From 6195ea86bc4a18ea2f769a248f2104c96cac1e37 Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Tue, 12 May 2026 06:11:15 -0700 Subject: [PATCH] [vm] Remove irregular type arguments parameter from factories In the VM, factory constructors always had an extra "type arguments" parameter, even if class is not generic. Factory constructor bodies were using class type parameters instead of function type parameters. This results in extra code when calling non-generic factories which is slightly inefficient in terms of code size and performance. Also, it creates an additional complexity throughout the system as factories should be special cased in many places. This change removes artificial "type arguments" parameter, treating factory constructors basically as static methods. This matches kernel AST representation. TEST=ci Change-Id: I957583cb2ce9a3c408699880a04036e06b01dd31 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/501762 Reviewed-by: Slava Egorov Commit-Queue: Alexander Markov Reviewed-by: Ryan Macnak --- pkg/dart2bytecode/lib/bytecode_generator.dart | 78 ++++--------------- pkg/dart2bytecode/lib/constant_pool.dart | 12 +-- pkg/dart2bytecode/lib/local_vars.dart | 45 ++--------- pkg/dart2bytecode/lib/object_table.dart | 12 +-- .../testcases/closures.dart.expect | 6 +- pkg/dart2bytecode/testcases/ffi.dart.expect | 4 +- .../testcases/instance_creation.dart.expect | 48 ++++++------ .../testcases/literals.dart.expect | 4 +- .../testcases/type_ops.dart.expect | 29 ++++--- runtime/bin/io_natives.cc | 2 +- runtime/bin/socket.cc | 3 +- runtime/lib/array.cc | 11 ++- runtime/lib/bool.cc | 10 +-- runtime/lib/double.cc | 6 +- runtime/lib/growable_array.cc | 6 +- runtime/lib/integers.cc | 6 +- runtime/lib/isolate.cc | 17 ++-- runtime/lib/mirrors.cc | 58 +++++++++----- runtime/lib/profiler.cc | 6 +- runtime/lib/regexp.cc | 14 ++-- runtime/lib/simd128.cc | 26 +++---- runtime/lib/string.cc | 6 +- runtime/vm/bootstrap_natives.cc | 7 +- runtime/vm/bootstrap_natives.h | 38 ++++----- runtime/vm/bytecode_reader.cc | 20 +---- runtime/vm/compiler/backend/flow_graph.cc | 3 +- runtime/vm/compiler/backend/il.cc | 39 ++++------ .../vm/compiler/backend/type_propagator.cc | 8 +- runtime/vm/compiler/call_specializer.cc | 27 +++---- .../frontend/kernel_binary_flowgraph.cc | 52 +++---------- runtime/vm/compiler/frontend/kernel_to_il.cc | 53 ++++--------- .../frontend/kernel_translation_helper.cc | 61 +++------------ .../frontend/kernel_translation_helper.h | 5 -- runtime/vm/compiler/frontend/scope_builder.cc | 28 ++----- runtime/vm/compiler/frontend/scope_builder.h | 6 +- runtime/vm/compiler/method_recognizer.cc | 1 + runtime/vm/dart_api_impl.cc | 59 ++++++++------ runtime/vm/object.cc | 22 +++--- runtime/vm/runtime_entry.cc | 11 +-- 39 files changed, 310 insertions(+), 539 deletions(-) diff --git a/pkg/dart2bytecode/lib/bytecode_generator.dart b/pkg/dart2bytecode/lib/bytecode_generator.dart index 0bd74351554..c940fa656f1 100644 --- a/pkg/dart2bytecode/lib/bytecode_generator.dart +++ b/pkg/dart2bytecode/lib/bytecode_generator.dart @@ -949,9 +949,7 @@ class BytecodeGenerator extends RecursiveVisitor { void _genExternalCall(Member node) { final function = node.function!; - if (locals.hasFactoryTypeArgsVar) { - asm.emitPush(locals.getVarIndexInFrame(locals.factoryTypeArgsVar)); - } else if (locals.hasFunctionTypeArgsVar) { + if (locals.hasFunctionTypeArgsVar) { asm.emitPush(locals.functionTypeArgsVarIndexInFrame); } if (locals.hasReceiver) { @@ -1483,23 +1481,19 @@ class BytecodeGenerator extends RecursiveVisitor { Member target, Arguments args, { bool hasReceiver = false, - bool isFactory = false, bool isUnchecked = false, TreeNode? node, }) { final argDesc = objectTable.getArgDescHandleByArguments( args, hasReceiver: hasReceiver, - isFactory: isFactory, ); int totalArgCount = args.positional.length + args.named.length; if (hasReceiver) { totalArgCount++; } - if (args.types.isNotEmpty || isFactory) { - // VM needs type arguments for every invocation of a factory constructor. - // TODO(alexmarkov): Clean this up. + if (args.types.isNotEmpty) { totalArgCount++; } @@ -1573,17 +1567,9 @@ class BytecodeGenerator extends RecursiveVisitor { void _genPushInstantiatorTypeArguments() { if (instantiatorTypeArguments != null) { - if (locals.hasFactoryTypeArgsVar) { - assert( - enclosingMember is Procedure && - (enclosingMember as Procedure).isFactory, - ); - _genLoadVar(locals.factoryTypeArgsVar); - } else { - _genPushReceiver(); - final int cpIndex = cp.addTypeArgumentsField(enclosingClass!); - asm.emitLoadTypeArgumentsField(cpIndex); - } + _genPushReceiver(); + final int cpIndex = cp.addTypeArgumentsField(enclosingClass!); + asm.emitLoadTypeArgumentsField(cpIndex); } else { asm.emitPushNull(); } @@ -1844,22 +1830,15 @@ class BytecodeGenerator extends RecursiveVisitor { isClosure = false; hasErrors = false; staticTypeContext.enterMember(node); - final isFactory = node is Procedure && node.isFactory; - if (node.isInstanceMember || node is Constructor || isFactory) { + if (node.isInstanceMember || node is Constructor) { if (enclosingClass!.typeParameters.isNotEmpty) { - final classTypeParameters = this.classTypeParameters = - new Set.from(enclosingClass.typeParameters); - // Treat type arguments of factory constructors as class - // type parameters. - if (isFactory) { - classTypeParameters.addAll(node.function.typeParameters); - } + this.classTypeParameters = new Set.from( + enclosingClass.typeParameters, + ); } if (hasInstantiatorTypeArguments(enclosingClass)) { final typeParameters = getTypeParameterTypes( - isFactory - ? node.function.typeParameters - : enclosingClass.typeParameters, + enclosingClass.typeParameters, ); instantiatorTypeArguments = flattenInstantiatorTypeArguments( enclosingClass, @@ -2196,8 +2175,6 @@ class BytecodeGenerator extends RecursiveVisitor { } if (locals.hasFunctionTypeArgsVar && function!.typeParameters.isNotEmpty) { - assert(!(node is Procedure && node.isFactory)); - Label done = new Label(); if (isClosure) { @@ -2353,9 +2330,6 @@ class BytecodeGenerator extends RecursiveVisitor { if (locals.hasCapturedParameters) { // Copy captured parameters to their respective locations in the context. if (!isClosure) { - if (locals.hasFactoryTypeArgsVar) { - _copyParamIfCaptured(locals.factoryTypeArgsVar); - } if (locals.hasCapturedReceiverVar) { _genPushContextForVariable(locals.capturedReceiverVar); asm.emitPush(locals.getVarIndexInFrame(locals.receiverVar)); @@ -3385,11 +3359,8 @@ class BytecodeGenerator extends RecursiveVisitor { } } - // _GrowableList._literal is a factory constructor. - // Type arguments passed to a factory constructor are counted as a normal - // argument and not counted in number of type arguments. assert(growableListLiteral.isFactory); - _genDirectCall(growableListLiteral, objectTable.getArgDescHandle(2), 2); + _genDirectCall(growableListLiteral, objectTable.getArgDescHandle(1, 1), 2); } @override @@ -3451,11 +3422,8 @@ class BytecodeGenerator extends RecursiveVisitor { } } - // Map._fromLiteral is a factory constructor. - // Type arguments passed to a factory constructor are counted as a normal - // argument and not counted in number of type arguments. assert(mapFromLiteral.isFactory); - _genDirectCall(mapFromLiteral, objectTable.getArgDescHandle(2), 2); + _genDirectCall(mapFromLiteral, objectTable.getArgDescHandle(1, 2), 2); } void _genMethodInvocationUsingSpecializedBytecode( @@ -4025,28 +3993,8 @@ class BytecodeGenerator extends RecursiveVisitor { _generateFfiCall(args.positional.single); return; } - if (target.isFactory) { - final constructedClass = target.enclosingClass!; - if (hasInstantiatorTypeArguments(constructedClass)) { - _genTypeArguments(args.types, instantiatingClass: constructedClass); - } else { - assert(args.types.isEmpty); - // VM needs type arguments for every invocation of a factory - // constructor. TODO(alexmarkov): Clean this up. - asm.emitPushNull(); - } - args = new Arguments( - node.arguments.positional, - named: node.arguments.named, - )..parent = node; - } _genArguments(null, args); - _genDirectCallWithArgs( - target, - args, - isFactory: target.isFactory, - node: node, - ); + _genDirectCallWithArgs(target, args, node: node); if (target == debugger) { // The debugger needs a pause for the current source position right after // stepping out from the debugger function. diff --git a/pkg/dart2bytecode/lib/constant_pool.dart b/pkg/dart2bytecode/lib/constant_pool.dart index c2f520b6aed..dd8bc5d2959 100644 --- a/pkg/dart2bytecode/lib/constant_pool.dart +++ b/pkg/dart2bytecode/lib/constant_pool.dart @@ -692,17 +692,9 @@ class ConstantPool { ), ); - int addArgDescByArguments( - Arguments args, { - bool hasReceiver = false, - bool isFactory = false, - }) => _add( + int addArgDescByArguments(Arguments args, {bool hasReceiver = false}) => _add( new ConstantObjectRef( - objectTable.getArgDescHandleByArguments( - args, - hasReceiver: hasReceiver, - isFactory: isFactory, - ), + objectTable.getArgDescHandleByArguments(args, hasReceiver: hasReceiver), ), ); diff --git a/pkg/dart2bytecode/lib/local_vars.dart b/pkg/dart2bytecode/lib/local_vars.dart index 52953d4ff06..73696214902 100644 --- a/pkg/dart2bytecode/lib/local_vars.dart +++ b/pkg/dart2bytecode/lib/local_vars.dart @@ -120,12 +120,6 @@ class LocalVariables { bool get hasFunctionTypeArgsVar => _currentFrame.functionTypeArgsVar != null; - VariableDeclaration get factoryTypeArgsVar => - _currentFrame.factoryTypeArgsVar ?? - (throw 'FactoryTypeArgs variable is not declared in ${_currentFrame.function}'); - - bool get hasFactoryTypeArgsVar => _currentFrame.factoryTypeArgsVar != null; - VariableDeclaration get receiverVar => _currentFrame.receiverVar ?? (throw 'Receiver variable is not declared in ${_currentFrame.function}'); @@ -243,7 +237,6 @@ class Frame { VariableDeclaration? receiverVar; VariableDeclaration? capturedReceiverVar; VariableDeclaration? functionTypeArgsVar; - VariableDeclaration? factoryTypeArgsVar; VariableDeclaration? closureVar; VariableDeclaration? contextVar; VariableDeclaration? scratchVar; @@ -364,29 +357,15 @@ class _ScopeBuilder extends RecursiveVisitor { } } - if (node is Procedure && node.isFactory) { - assert(_currentFrame.parent == null); - _currentFrame.numTypeArguments = 0; - final factoryTypeArgsVar = _currentFrame.factoryTypeArgsVar = - VariableDeclaration(':type_arguments'); - _declareVariable(factoryTypeArgsVar); - } else { - _currentFrame.numTypeArguments = - (_currentFrame.parent?.numTypeArguments ?? 0) + - function.typeParameters.length; + _currentFrame.numTypeArguments = + (_currentFrame.parent?.numTypeArguments ?? 0) + + function.typeParameters.length; - if (_currentFrame.numTypeArguments > 0) { - final functionTypeArgsVar = _currentFrame.functionTypeArgsVar = - VariableDeclaration(':function_type_arguments_var') - ..fileOffset = function.fileOffset; - _declareVariable(functionTypeArgsVar); - } - - final parentFactoryTypeArgsVar = - _currentFrame.parent?.factoryTypeArgsVar; - if (parentFactoryTypeArgsVar != null) { - _currentFrame.factoryTypeArgsVar = parentFactoryTypeArgsVar; - } + if (_currentFrame.numTypeArguments > 0) { + final functionTypeArgsVar = _currentFrame.functionTypeArgsVar = + VariableDeclaration(':function_type_arguments_var') + ..fileOffset = function.fileOffset; + _declareVariable(functionTypeArgsVar); } if (_hasReceiverParameter(node)) { @@ -625,8 +604,6 @@ class _ScopeBuilder extends RecursiveVisitor { var parent = node.parameter.declaration; if (parent is Class) { _useThis(); - } else if (parent is Procedure && parent.isFactory) { - _useVariable(_currentFrame.factoryTypeArgsVar!); } node.visitChildren(this); } @@ -946,7 +923,6 @@ class _Allocator extends RecursiveVisitor { } void _allocateParameters(TreeNode node, FunctionNode function) { - final bool isFactory = node is Procedure && node.isFactory; final bool hasReceiver = _hasReceiverParameter(node); final bool hasClosureArg = node is FunctionDeclaration || node is FunctionExpression; @@ -954,7 +930,6 @@ class _Allocator extends RecursiveVisitor { _currentFrame.numParameters = function.positionalParameters.length + function.namedParameters.length + - (isFactory ? 1 : 0) + (hasReceiver ? 1 : 0) + (hasClosureArg ? 1 : 0); @@ -964,15 +939,11 @@ class _Allocator extends RecursiveVisitor { function.namedParameters.isNotEmpty; _currentFrame.hasCapturedParameters = - (isFactory && locals.isCaptured(_currentFrame.factoryTypeArgsVar!)) || (hasReceiver && _currentFrame.capturedReceiverVar != null) || function.positionalParameters.any(locals.isCaptured) || function.namedParameters.any(locals.isCaptured); int count = 0; - if (isFactory) { - _allocateParameter(_currentFrame.factoryTypeArgsVar!, count++); - } if (hasReceiver) { assert(!locals.isCaptured(_currentFrame.receiverVar!)); _allocateParameter(_currentFrame.receiverVar!, count++); diff --git a/pkg/dart2bytecode/lib/object_table.dart b/pkg/dart2bytecode/lib/object_table.dart index bda6a1dc557..9896d864557 100644 --- a/pkg/dart2bytecode/lib/object_table.dart +++ b/pkg/dart2bytecode/lib/object_table.dart @@ -1920,7 +1920,6 @@ class ObjectTable implements ObjectWriter, ObjectReader { ObjectHandle getArgDescHandleByArguments( Arguments args, { bool hasReceiver = false, - bool isFactory = false, }) { List<_PublicNameHandle> argNames = const <_PublicNameHandle>[]; final namedArguments = args.named; @@ -1931,15 +1930,8 @@ class ObjectTable implements ObjectWriter, ObjectReader { ); } final int numArguments = - args.positional.length + - args.named.length + - (hasReceiver ? 1 : 0) + - // VM expects that type arguments vector passed to a factory - // constructor is counted in numArguments, and not counted in - // numTypeArgs. - // TODO(alexmarkov): Clean this up. - (isFactory ? 1 : 0); - final int numTypeArguments = isFactory ? 0 : args.types.length; + args.positional.length + args.named.length + (hasReceiver ? 1 : 0); + final int numTypeArguments = args.types.length; return getOrAddObject( new _ArgDescHandle(numArguments, numTypeArguments, argNames), ); diff --git a/pkg/dart2bytecode/testcases/closures.dart.expect b/pkg/dart2bytecode/testcases/closures.dart.expect index 4d5116b5df3..77c780630b5 100644 --- a/pkg/dart2bytecode/testcases/closures.dart.expect +++ b/pkg/dart2bytecode/testcases/closures.dart.expect @@ -122,7 +122,7 @@ ConstantPool { [6] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::callWithArgs::TypeParam/5 [7] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::callWithArgs::TypeParam/6 [8] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::callWithArgs::TypeParam/7 - [9] = DirectCall 'dart:core::_GrowableList::_literal8 (constructor)', ArgDesc num-args 9, num-type-args 0, names [] + [9] = DirectCall 'dart:core::_GrowableList::_literal8 (constructor)', ArgDesc num-args 8, num-type-args 1, names [] [10] = Reserved [11] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] [12] = Reserved @@ -531,7 +531,7 @@ ConstantPool { [13] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::TypeParam/1 [14] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/0 [15] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/1 - [16] = DirectCall 'dart:core::_GrowableList::_literal8 (constructor)', ArgDesc num-args 9, num-type-args 0, names [] + [16] = DirectCall 'dart:core::_GrowableList::_literal8 (constructor)', ArgDesc num-args 8, num-type-args 1, names [] [17] = Reserved [18] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] [19] = Reserved @@ -1035,7 +1035,7 @@ L1: } ConstantPool { [0] = ObjectRef < dart:core::Function > - [1] = DirectCall 'dart:core::_GrowableList:: (constructor)', ArgDesc num-args 2, num-type-args 0, names [] + [1] = DirectCall 'dart:core::_GrowableList:: (constructor)', ArgDesc num-args 1, num-type-args 1, names [] [2] = Reserved [3] = ClosureFunction 0 [4] = EndClosureFunctionScope diff --git a/pkg/dart2bytecode/testcases/ffi.dart.expect b/pkg/dart2bytecode/testcases/ffi.dart.expect index d66075845b1..c61ecb02205 100644 --- a/pkg/dart2bytecode/testcases/ffi.dart.expect +++ b/pkg/dart2bytecode/testcases/ffi.dart.expect @@ -46,7 +46,7 @@ Bytecode { ConstantPool { [0] = ObjectRef < dart:ffi::NativeFunction < FunctionType () -> dart:ffi::Void > > [1] = ObjectRef const 3735928559 - [2] = DirectCall 'dart:ffi::Pointer::fromAddress (constructor)', ArgDesc num-args 2, num-type-args 0, names [] + [2] = DirectCall 'dart:ffi::Pointer::fromAddress (constructor)', ArgDesc num-args 1, num-type-args 1, names [] [3] = Reserved [4] = ClosureFunction 0 [5] = FfiCall @@ -107,7 +107,7 @@ Bytecode { ConstantPool { [0] = ObjectRef < dart:ffi::NativeFunction < FunctionType (dart:ffi::Int64) -> dart:ffi::Int32 > > [1] = ObjectRef const 3735928559 - [2] = DirectCall 'dart:ffi::Pointer::fromAddress (constructor)', ArgDesc num-args 2, num-type-args 0, names [] + [2] = DirectCall 'dart:ffi::Pointer::fromAddress (constructor)', ArgDesc num-args 1, num-type-args 1, names [] [3] = Reserved [4] = ClosureFunction 0 [5] = Type dart:core::int diff --git a/pkg/dart2bytecode/testcases/instance_creation.dart.expect b/pkg/dart2bytecode/testcases/instance_creation.dart.expect index 145220eb020..0543d62b053 100644 --- a/pkg/dart2bytecode/testcases/instance_creation.dart.expect +++ b/pkg/dart2bytecode/testcases/instance_creation.dart.expect @@ -115,7 +115,7 @@ Bytecode { } ConstantPool { [0] = ObjectRef < dart:core::int, dart:core::List < dart:core::String > > - [1] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::G::testFactory (constructor)', ArgDesc num-args 1, num-type-args 0, names [] + [1] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::G::testFactory (constructor)', ArgDesc num-args 0, num-type-args 2, names [] [2] = Reserved } @@ -127,20 +127,18 @@ Function 'foo5', static, reflectable, debuggable Bytecode { Entry 0 CheckStack 0 - PushNull - DirectCall CP#0, 1 + DirectCall CP#0, 0 Drop1 - PushNull PushInt 42 - DirectCall CP#2, 2 + DirectCall CP#2, 1 Drop1 PushNull ReturnTOS } ConstantPool { - [0] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::I::testFactory2 (constructor)', ArgDesc num-args 1, num-type-args 0, names [] + [0] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::I::testFactory2 (constructor)', ArgDesc num-args 0, num-type-args 0, names [] [1] = Reserved - [2] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::I::testFactory2 (constructor)', ArgDesc num-args 2, num-type-args 0, names ['param'] + [2] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::I::testFactory2 (constructor)', ArgDesc num-args 1, num-type-args 0, names ['param'] [3] = Reserved } @@ -158,7 +156,7 @@ Bytecode { } ConstantPool { [0] = ObjectRef < dart:core::String > - [1] = DirectCall 'dart:core::_List::empty (constructor)', ArgDesc num-args 1, num-type-args 0, names [] + [1] = DirectCall 'dart:core::_List::empty (constructor)', ArgDesc num-args 0, num-type-args 1, names [] [2] = Reserved } @@ -178,7 +176,7 @@ Bytecode { } ConstantPool { [0] = ObjectRef < dart:core::int > - [1] = DirectCall 'dart:core::_List::filled (constructor)', ArgDesc num-args 3, num-type-args 0, names [] + [1] = DirectCall 'dart:core::_List::filled (constructor)', ArgDesc num-args 2, num-type-args 1, names [] [2] = Reserved } @@ -427,7 +425,7 @@ Bytecode { } ConstantPool { [0] = TypeArgumentsField DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::E - [1] = DirectCall 'dart:core::Map:: (constructor)', ArgDesc num-args 1, num-type-args 0, names [] + [1] = DirectCall 'dart:core::Map:: (constructor)', ArgDesc num-args 0, num-type-args 2, names [] [2] = Reserved } @@ -469,7 +467,7 @@ Bytecode { } ConstantPool { [0] = TypeArgumentsField DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::F - [1] = DirectCall 'dart:core::Map:: (constructor)', ArgDesc num-args 1, num-type-args 0, names [] + [1] = DirectCall 'dart:core::Map:: (constructor)', ArgDesc num-args 0, num-type-args 2, names [] [2] = Reserved } @@ -503,15 +501,16 @@ Function 'testFactory', factory, static, reflectable, debuggable return-type DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::G < DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::G::testFactory (constructor)::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::G::testFactory (constructor)::TypeParam/1 > Bytecode { - Entry 1 + Entry 2 + CheckFunctionTypeArgs 2, r0 CheckStack 0 - Push FP[-5] PushNull + Push r0 InstantiateTypeArgumentsTOS 0, CP#1 PushConstant CP#0 AllocateT - StoreLocal r0 - Push r0 + StoreLocal r1 + Push r1 DirectCall CP#2, 1 Drop1 ReturnTOS @@ -574,15 +573,15 @@ Function 'testFactory2', factory, static, has-optional-named-params, reflectable return-type DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::I Bytecode { - EntryOptional 1, 0, 1 - LoadConstant r1, CP#0 - LoadConstant r1, CP#1 + EntryOptional 0, 0, 1 + LoadConstant r0, CP#0 + LoadConstant r0, CP#1 Frame 1 CheckStack 0 Allocate CP#2 - StoreLocal r2 - Push r2 + StoreLocal r1 Push r1 + Push r0 DirectCall CP#3, 2 Drop1 ReturnTOS @@ -649,13 +648,14 @@ Function '', factory, static, reflectable, debuggable return-type DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::L < DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::L:: (constructor)::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/instance_creation.dart::L:: (constructor)::TypeParam/1 > Bytecode { - Entry 1 + Entry 2 + CheckFunctionTypeArgs 2, r0 CheckStack 0 - Push FP[-5] + Push r0 PushConstant CP#0 AllocateT - StoreLocal r0 - Push r0 + StoreLocal r1 + Push r1 DirectCall CP#1, 1 Drop1 ReturnTOS diff --git a/pkg/dart2bytecode/testcases/literals.dart.expect b/pkg/dart2bytecode/testcases/literals.dart.expect index 3f4d2b75923..56642bf64dc 100644 --- a/pkg/dart2bytecode/testcases/literals.dart.expect +++ b/pkg/dart2bytecode/testcases/literals.dart.expect @@ -155,7 +155,7 @@ Bytecode { } ConstantPool { [0] = ObjectRef < dart:core::int > - [1] = DirectCall 'dart:core::_GrowableList::_literal3 (constructor)', ArgDesc num-args 4, num-type-args 0, names [] + [1] = DirectCall 'dart:core::_GrowableList::_literal3 (constructor)', ArgDesc num-args 3, num-type-args 1, names [] [2] = Reserved [3] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] [4] = Reserved @@ -256,7 +256,7 @@ Bytecode { ConstantPool { [0] = ObjectRef < dart:core::int, dart:core::int > [1] = ObjectRef < dynamic > - [2] = DirectCall 'dart:core::Map::_fromLiteral (constructor)', ArgDesc num-args 2, num-type-args 0, names [] + [2] = DirectCall 'dart:core::Map::_fromLiteral (constructor)', ArgDesc num-args 1, num-type-args 2, names [] [3] = Reserved [4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] [5] = Reserved diff --git a/pkg/dart2bytecode/testcases/type_ops.dart.expect b/pkg/dart2bytecode/testcases/type_ops.dart.expect index f021463ab07..4d68a5a8516 100644 --- a/pkg/dart2bytecode/testcases/type_ops.dart.expect +++ b/pkg/dart2bytecode/testcases/type_ops.dart.expect @@ -364,7 +364,7 @@ ConstantPool { [2] = Type dart:core::Map < DART_SDK/pkg/dart2bytecode/testcases/type_ops.dart::D::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/type_ops.dart::D::TypeParam/1 > [3] = ObjectRef '' [4] = SubtypeTestCache - [5] = DirectCall 'dart:core::_GrowableList::_literal1 (constructor)', ArgDesc num-args 2, num-type-args 0, names [] + [5] = DirectCall 'dart:core::_GrowableList::_literal1 (constructor)', ArgDesc num-args 1, num-type-args 1, names [] [6] = Reserved [7] = InterfaceCall 'dart:core::List::[]', ArgDesc num-args 2, num-type-args 0, names [] [8] = Reserved @@ -403,23 +403,28 @@ Function '', factory, static, reflectable, debuggable return-type DART_SDK/pkg/dart2bytecode/testcases/type_ops.dart::E < DART_SDK/pkg/dart2bytecode/testcases/type_ops.dart::E:: (constructor)::TypeParam/0 > Bytecode { - Entry 1 - CheckStack 0 - Push FP[-5] + Entry 2 + CheckFunctionTypeArgs 1, r0 + JumpIfNotZeroTypeArgs L1 PushConstant CP#0 - AllocateT - StoreLocal r0 + PopLocal r0 +L1: + CheckStack 0 Push r0 - DirectCall CP#1, 1 + PushConstant CP#1 + AllocateT + StoreLocal r1 + Push r1 + DirectCall CP#2, 1 Drop1 ReturnTOS } -Default function type arguments: CP#3 +Default function type arguments: CP#0 ConstantPool { - [0] = Class DART_SDK/pkg/dart2bytecode/testcases/type_ops.dart::E - [1] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/type_ops.dart::E::_ (constructor)', ArgDesc num-args 1, num-type-args 0, names [] - [2] = Reserved - [3] = ObjectRef < dart:core::String > + [0] = ObjectRef < dart:core::String > + [1] = Class DART_SDK/pkg/dart2bytecode/testcases/type_ops.dart::E + [2] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/type_ops.dart::E::_ (constructor)', ArgDesc num-args 1, num-type-args 0, names [] + [3] = Reserved } diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc index 8fe803c3d73..5093d9a1d96 100644 --- a/runtime/bin/io_natives.cc +++ b/runtime/bin/io_natives.cc @@ -173,7 +173,7 @@ namespace bin { V(Socket_SetSocketId, 3) \ V(Socket_WriteList, 4) \ V(Socket_HasPendingWrite, 1) \ - V(SocketControlMessage_fromHandles, 2) \ + V(SocketControlMessage_fromHandles, 1) \ V(SocketControlMessageImpl_extractHandles, 1) \ V(Stdin_ReadByte, 1) \ V(Stdin_GetEchoMode, 1) \ diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc index 5af1fc4de97..daddecfc0cd 100644 --- a/runtime/bin/socket.cc +++ b/runtime/bin/socket.cc @@ -1525,8 +1525,7 @@ void FUNCTION_NAME(SocketControlMessage_fromHandles)( DartUtils::NewDartUnsupportedError( "This is not supported on this operating system")); #else - ASSERT(Dart_IsNull(Dart_GetNativeArgument(args, 0))); - Dart_Handle handles_dart = Dart_GetNativeArgument(args, 1); + Dart_Handle handles_dart = Dart_GetNativeArgument(args, 0); if (Dart_IsNull(handles_dart)) { Dart_ThrowException( DartUtils::NewDartArgumentError("handles list can't be null")); diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc index 362e5865728..6cb12153925 100644 --- a/runtime/lib/array.cc +++ b/runtime/lib/array.cc @@ -10,7 +10,7 @@ namespace dart { -DEFINE_NATIVE_ENTRY(List_allocate, 0, 2) { +DEFINE_NATIVE_ENTRY(List_allocate, 1, 1) { // Implemented in FlowGraphBuilder::VisitNativeBody. UNREACHABLE(); return Object::null(); @@ -55,12 +55,11 @@ DEFINE_NATIVE_ENTRY(List_slice, 0, 4) { } // Private factory, expects correct arguments. -DEFINE_NATIVE_ENTRY(ImmutableList_from, 0, 4) { - // Ignore first argument of this factory (type argument). +DEFINE_NATIVE_ENTRY(ImmutableList_from, 1, 3) { const Array& from_array = - Array::CheckedHandle(zone, arguments->NativeArgAt(1)); - const Smi& smi_offset = Smi::CheckedHandle(zone, arguments->NativeArgAt(2)); - const Smi& smi_length = Smi::CheckedHandle(zone, arguments->NativeArgAt(3)); + Array::CheckedHandle(zone, arguments->NativeArgAt(0)); + const Smi& smi_offset = Smi::CheckedHandle(zone, arguments->NativeArgAt(1)); + const Smi& smi_length = Smi::CheckedHandle(zone, arguments->NativeArgAt(2)); const intptr_t length = smi_length.Value(); const intptr_t offset = smi_offset.Value(); const Array& result = Array::Handle(Array::New(length)); diff --git a/runtime/lib/bool.cc b/runtime/lib/bool.cc index c18a8c39e45..5b7b46f2999 100644 --- a/runtime/lib/bool.cc +++ b/runtime/lib/bool.cc @@ -16,9 +16,9 @@ namespace dart { -DEFINE_NATIVE_ENTRY(Bool_fromEnvironment, 0, 3) { - GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1)); - GET_NATIVE_ARGUMENT(Bool, default_value, arguments->NativeArgAt(2)); +DEFINE_NATIVE_ENTRY(Bool_fromEnvironment, 0, 2) { + GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0)); + GET_NATIVE_ARGUMENT(Bool, default_value, arguments->NativeArgAt(1)); // Call the embedder to supply us with the environment. const String& env_value = String::Handle(Api::GetEnvironmentValue(thread, name)); @@ -33,8 +33,8 @@ DEFINE_NATIVE_ENTRY(Bool_fromEnvironment, 0, 3) { return default_value.ptr(); } -DEFINE_NATIVE_ENTRY(Bool_hasEnvironment, 0, 2) { - GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1)); +DEFINE_NATIVE_ENTRY(Bool_hasEnvironment, 0, 1) { + GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0)); // Call the embedder to supply us with the environment. const String& env_value = String::Handle(Api::GetEnvironmentValue(thread, name)); diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc index d602adb42c9..f6b7600c769 100644 --- a/runtime/lib/double.cc +++ b/runtime/lib/double.cc @@ -18,10 +18,8 @@ namespace dart { -DEFINE_NATIVE_ENTRY(Double_doubleFromInteger, 0, 2) { - ASSERT( - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull()); - GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); +DEFINE_NATIVE_ENTRY(Double_doubleFromInteger, 0, 1) { + GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(0)); if (FLAG_trace_intrinsified_natives) { OS::PrintErr("Double_doubleFromInteger %s\n", value.ToCString()); } diff --git a/runtime/lib/growable_array.cc b/runtime/lib/growable_array.cc index 4d1518ecc67..0c20c29b770 100644 --- a/runtime/lib/growable_array.cc +++ b/runtime/lib/growable_array.cc @@ -12,10 +12,10 @@ namespace dart { -DEFINE_NATIVE_ENTRY(GrowableList_allocate, 0, 2) { +DEFINE_NATIVE_ENTRY(GrowableList_allocate, 1, 1) { const TypeArguments& type_arguments = - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)); - GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1)); + TypeArguments::CheckedHandle(zone, arguments->NativeTypeArgs()); + GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(0)); if (data.Length() < 0) { Exceptions::ThrowRangeError("length", Integer::Handle(Integer::New(data.Length())), diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc index 603b2957d5f..4d2ad40825d 100644 --- a/runtime/lib/integers.cc +++ b/runtime/lib/integers.cc @@ -185,9 +185,9 @@ DEFINE_NATIVE_ENTRY(Integer_parse, 0, 1) { return ParseInteger(value); } -DEFINE_NATIVE_ENTRY(Integer_fromEnvironment, 0, 3) { - GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1)); - GET_NATIVE_ARGUMENT(Integer, default_value, arguments->NativeArgAt(2)); +DEFINE_NATIVE_ENTRY(Integer_fromEnvironment, 0, 2) { + GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0)); + GET_NATIVE_ARGUMENT(Integer, default_value, arguments->NativeArgAt(1)); // Call the embedder to supply us with the environment. const String& env_value = String::Handle(Api::GetEnvironmentValue(thread, name)); diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc index 907828da43c..d4191b40570 100644 --- a/runtime/lib/isolate.cc +++ b/runtime/lib/isolate.cc @@ -31,9 +31,7 @@ namespace dart { -DEFINE_NATIVE_ENTRY(Capability_factory, 0, 1) { - ASSERT( - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull()); +DEFINE_NATIVE_ENTRY(Capability_factory, 0, 0) { // Keep capability IDs less than 2^53 so web clients of the service // protocol can process it properly. // @@ -57,10 +55,8 @@ DEFINE_NATIVE_ENTRY(Capability_get_hashcode, 0, 1) { return Smi::New(hash); } -DEFINE_NATIVE_ENTRY(RawReceivePort_factory, 0, 2) { - ASSERT( - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull()); - GET_NON_NULL_NATIVE_ARGUMENT(String, debug_name, arguments->NativeArgAt(1)); +DEFINE_NATIVE_ENTRY(RawReceivePort_factory, 0, 1) { + GET_NON_NULL_NATIVE_ARGUMENT(String, debug_name, arguments->NativeArgAt(0)); if (isolate == nullptr) { ThrowCantRunWithoutIsolateError(); UNREACHABLE(); @@ -1363,12 +1359,9 @@ static intptr_t GetTypedDataSizeOrThrow(const Instance& instance) { Exceptions::ThrowArgumentError(instance); } -DEFINE_NATIVE_ENTRY(TransferableTypedData_factory, 0, 2) { - ASSERT( - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull()); - +DEFINE_NATIVE_ENTRY(TransferableTypedData_factory, 0, 1) { GET_NON_NULL_NATIVE_ARGUMENT(Instance, array_instance, - arguments->NativeArgAt(1)); + arguments->NativeArgAt(0)); Array& array = Array::Handle(); intptr_t array_length; diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc index b24249fd0e4..48385a05b02 100644 --- a/runtime/lib/mirrors.cc +++ b/runtime/lib/mirrors.cc @@ -1405,19 +1405,32 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) { } ASSERT(!type.IsNull()); - TypeArguments& type_arguments = TypeArguments::Handle(); if (!type.IsInstantiated()) { // Must have been a declaration type. - const Type& rare_type = Type::Handle(klass.RareType()); - ASSERT(rare_type.IsInstantiated()); - type_arguments = rare_type.GetInstanceTypeArguments(thread); - } else { - type_arguments = type.GetInstanceTypeArguments(thread); + type = klass.RareType(); + ASSERT(type.IsInstantiated()); + } + + const bool is_generic_factory = + lookup_constructor.IsFactory() && lookup_constructor.IsGeneric(); + intptr_t type_args_len = 0; + TypeArguments& instantiator_type_arguments = TypeArguments::Handle(); + TypeArguments& function_type_arguments = TypeArguments::Handle(); + if (lookup_constructor.IsGenerativeConstructor()) { + instantiator_type_arguments = type.GetInstanceTypeArguments(thread); + } else if (is_generic_factory) { + function_type_arguments = type.arguments(); + type_args_len = lookup_constructor.NumTypeParameters(); + ASSERT(function_type_arguments.IsNull() || + function_type_arguments.Length() == type_args_len); } Class& redirected_klass = Class::Handle(klass.ptr()); const intptr_t num_explicit_args = explicit_args.Length(); - const intptr_t num_implicit_args = 1; + const intptr_t num_implicit_positional_args = + lookup_constructor.IsGenerativeConstructor() ? 1 : 0; + const intptr_t num_implicit_args = + ((type_args_len > 0) ? 1 : 0) + num_implicit_positional_args; const Array& args = Array::Handle(Array::New(num_implicit_args + num_explicit_args)); @@ -1427,10 +1440,14 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) { explicit_argument = explicit_args.At(i); args.SetAt(i + num_implicit_args, explicit_argument); } + if (is_generic_factory) { + args.SetAt(0, function_type_arguments); + } - const int kTypeArgsLen = 0; - const Array& args_descriptor_array = Array::Handle( - ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(), arg_names)); + const Array& args_descriptor_array = + Array::Handle(ArgumentsDescriptor::NewBoxed( + type_args_len, num_implicit_positional_args + num_explicit_args, + arg_names)); ArgumentsDescriptor args_descriptor(args_descriptor_array); if (!lookup_constructor.AreValidArguments(args_descriptor, nullptr)) { @@ -1442,14 +1459,18 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) { UNREACHABLE(); } #if defined(DEBUG) - // Make sure the receiver is the null value, so that DoArgumentTypesMatch does - // not attempt to retrieve the instantiator type arguments from the receiver. - explicit_argument = args.At(args_descriptor.FirstArgIndex()); - ASSERT(explicit_argument.IsNull()); + if (lookup_constructor.IsGenerativeConstructor()) { + // Make sure the receiver is the null value, so that DoArgumentTypesMatch + // does not attempt to retrieve the instantiator type arguments from + // the receiver. + explicit_argument = args.At(args_descriptor.FirstArgIndex()); + ASSERT(explicit_argument.IsNull()); + } #endif const Object& type_error = Object::Handle(lookup_constructor.DoArgumentTypesMatch( - args, args_descriptor, type_arguments)); + args, args_descriptor, instantiator_type_arguments, + function_type_arguments)); if (!type_error.IsNull()) { Exceptions::PropagateError(Error::Cast(type_error)); UNREACHABLE(); @@ -1461,16 +1482,13 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) { // Note we have delayed allocation until after the function // type and argument matching checks. new_object = Instance::New(redirected_klass); - if (!type_arguments.IsNull()) { + if (!instantiator_type_arguments.IsNull()) { // The type arguments will be null if the class has no type parameters, in // which case the following call would fail because there is no slot // reserved in the object for the type vector. - new_object.SetTypeArguments(type_arguments); + new_object.SetTypeArguments(instantiator_type_arguments); } args.SetAt(0, new_object); - } else { - // Factories get type arguments. - args.SetAt(0, type_arguments); } // Invoke the constructor and return the new object. diff --git a/runtime/lib/profiler.cc b/runtime/lib/profiler.cc index 939e88e7c8a..140d2407172 100644 --- a/runtime/lib/profiler.cc +++ b/runtime/lib/profiler.cc @@ -15,10 +15,8 @@ namespace dart { // Native implementations of the profiler parts of the dart:developer library. -DEFINE_NATIVE_ENTRY(UserTag_new, 0, 2) { - ASSERT( - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull()); - GET_NON_NULL_NATIVE_ARGUMENT(String, tag_label, arguments->NativeArgAt(1)); +DEFINE_NATIVE_ENTRY(UserTag_new, 0, 1) { + GET_NON_NULL_NATIVE_ARGUMENT(String, tag_label, arguments->NativeArgAt(0)); return UserTag::New(thread, tag_label); } diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc index 1d3404bf7ad..649806a5052 100644 --- a/runtime/lib/regexp.cc +++ b/runtime/lib/regexp.cc @@ -17,15 +17,13 @@ namespace dart { -DEFINE_NATIVE_ENTRY(RegExp_factory, 0, 6) { - ASSERT( - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull()); - GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1)); +DEFINE_NATIVE_ENTRY(RegExp_factory, 0, 5) { + GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(0)); - bool multi_line = arguments->NativeArgAt(2) == Bool::True().ptr(); - bool ignore_case = arguments->NativeArgAt(3) != Bool::True().ptr(); - bool unicode = arguments->NativeArgAt(4) == Bool::True().ptr(); - bool dot_all = arguments->NativeArgAt(5) == Bool::True().ptr(); + bool multi_line = arguments->NativeArgAt(1) == Bool::True().ptr(); + bool ignore_case = arguments->NativeArgAt(2) != Bool::True().ptr(); + bool unicode = arguments->NativeArgAt(3) == Bool::True().ptr(); + bool dot_all = arguments->NativeArgAt(4) == Bool::True().ptr(); RegExpFlags flags; flags |= RegExpFlag::kGlobal; // All dart regexps are global. diff --git a/runtime/lib/simd128.cc b/runtime/lib/simd128.cc index 9d8f6848565..45eab70be21 100644 --- a/runtime/lib/simd128.cc +++ b/runtime/lib/simd128.cc @@ -36,19 +36,17 @@ DEFINE_NATIVE_ENTRY(Float32x4_splat, 0, 1) { return Float32x4::New(_v, _v, _v, _v); } -DEFINE_NATIVE_ENTRY(Float32x4_zero, 0, 1) { - ASSERT( - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull()); +DEFINE_NATIVE_ENTRY(Float32x4_zero, 0, 0) { return Float32x4::New(0.0f, 0.0f, 0.0f, 0.0f); } -DEFINE_NATIVE_ENTRY(Float32x4_fromInt32x4Bits, 0, 2) { - GET_NON_NULL_NATIVE_ARGUMENT(Int32x4, v, arguments->NativeArgAt(1)); +DEFINE_NATIVE_ENTRY(Float32x4_fromInt32x4Bits, 0, 1) { + GET_NON_NULL_NATIVE_ARGUMENT(Int32x4, v, arguments->NativeArgAt(0)); return Float32x4::New(v.value()); } -DEFINE_NATIVE_ENTRY(Float32x4_fromFloat64x2, 0, 2) { - GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, v, arguments->NativeArgAt(1)); +DEFINE_NATIVE_ENTRY(Float32x4_fromFloat64x2, 0, 1) { + GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, v, arguments->NativeArgAt(0)); float _x = static_cast(v.x()); float _y = static_cast(v.y()); return Float32x4::New(_x, _y, 0.0f, 0.0f); @@ -433,8 +431,8 @@ DEFINE_NATIVE_ENTRY(Int32x4_fromBools, 0, 4) { return Int32x4::New(_x, _y, _z, _w); } -DEFINE_NATIVE_ENTRY(Int32x4_fromFloat32x4Bits, 0, 2) { - GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(1)); +DEFINE_NATIVE_ENTRY(Int32x4_fromFloat32x4Bits, 0, 1) { + GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(0)); return Int32x4::New(v.value()); } @@ -693,16 +691,12 @@ DEFINE_NATIVE_ENTRY(Float64x2_splat, 0, 1) { return Float64x2::New(v.value(), v.value()); } -DEFINE_NATIVE_ENTRY(Float64x2_zero, 0, 1) { - ASSERT( - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull()); +DEFINE_NATIVE_ENTRY(Float64x2_zero, 0, 0) { return Float64x2::New(0.0, 0.0); } -DEFINE_NATIVE_ENTRY(Float64x2_fromFloat32x4, 0, 2) { - ASSERT( - TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull()); - GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(1)); +DEFINE_NATIVE_ENTRY(Float64x2_fromFloat32x4, 0, 1) { + GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(0)); double _x = v.x(); double _y = v.y(); return Float64x2::New(_x, _y); diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc index e2da443eef0..05039e0dd71 100644 --- a/runtime/lib/string.cc +++ b/runtime/lib/string.cc @@ -16,9 +16,9 @@ namespace dart { -DEFINE_NATIVE_ENTRY(String_fromEnvironment, 0, 3) { - GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1)); - GET_NATIVE_ARGUMENT(String, default_value, arguments->NativeArgAt(2)); +DEFINE_NATIVE_ENTRY(String_fromEnvironment, 0, 2) { + GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0)); + GET_NATIVE_ARGUMENT(String, default_value, arguments->NativeArgAt(1)); // Call the embedder to supply us with the environment. const String& env_value = String::Handle(Api::GetEnvironmentValue(thread, name)); diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc index da421d01d69..a5c274486bd 100644 --- a/runtime/vm/bootstrap_natives.cc +++ b/runtime/vm/bootstrap_natives.cc @@ -59,8 +59,11 @@ Dart_NativeFunction BootstrapNatives::Lookup(Dart_Handle name, int num_entries = sizeof(BootStrapEntries) / sizeof(struct NativeEntries); for (int i = 0; i < num_entries; i++) { const struct NativeEntries* entry = &(BootStrapEntries[i]); - if ((strcmp(function_name, entry->name_) == 0) && - (entry->argument_count_ == argument_count)) { + if (strcmp(function_name, entry->name_) == 0) { + if (entry->argument_count_ != argument_count) { + FATAL("Wrong number of arguments of %s (expected %d, actual %d)", + function_name, argument_count, entry->argument_count_); + } return reinterpret_cast(entry->function_); } } diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h index 2b6a201e309..11f8512c9f1 100644 --- a/runtime/vm/bootstrap_natives.h +++ b/runtime/vm/bootstrap_natives.h @@ -45,18 +45,18 @@ namespace dart { V(Integer_moduloFromInteger, 2) \ V(Integer_greaterThanFromInteger, 2) \ V(Integer_equalToInteger, 2) \ - V(Integer_fromEnvironment, 3) \ + V(Integer_fromEnvironment, 2) \ V(Integer_parse, 1) \ V(Integer_shlFromInteger, 2) \ V(Integer_shrFromInteger, 2) \ V(Integer_ushrFromInteger, 2) \ - V(Bool_fromEnvironment, 3) \ - V(Bool_hasEnvironment, 2) \ - V(Capability_factory, 1) \ + V(Bool_fromEnvironment, 2) \ + V(Bool_hasEnvironment, 1) \ + V(Capability_factory, 0) \ V(Capability_equals, 2) \ V(Capability_get_hashcode, 1) \ V(createConstMapFromMapOfDeeplyImmutables, 1) \ - V(RawReceivePort_factory, 2) \ + V(RawReceivePort_factory, 1) \ V(RawReceivePort_get_id, 1) \ V(RawReceivePort_closeInternal, 1) \ V(RawReceivePort_setActive, 2) \ @@ -99,14 +99,14 @@ namespace dart { V(Double_equalToInteger, 2) \ V(Double_greaterThan, 2) \ V(Double_equal, 2) \ - V(Double_doubleFromInteger, 2) \ + V(Double_doubleFromInteger, 1) \ V(Double_parse, 3) \ V(Double_toString, 1) \ V(Double_toStringAsFixed, 2) \ V(Double_toStringAsExponential, 2) \ V(Double_toStringAsPrecision, 2) \ V(Double_flipSignBit, 1) \ - V(RegExp_factory, 6) \ + V(RegExp_factory, 5) \ V(RegExp_getPattern, 1) \ V(RegExp_getIsMultiLine, 1) \ V(RegExp_getIsCaseSensitive, 1) \ @@ -116,11 +116,11 @@ namespace dart { V(RegExp_getGroupNameMap, 1) \ V(RegExp_ExecuteMatch, 3) \ V(RegExp_ExecuteMatchSticky, 3) \ - V(List_allocate, 2) \ + V(List_allocate, 1) \ V(List_setIndexed, 3) \ V(List_getLength, 1) \ V(List_slice, 4) \ - V(ImmutableList_from, 4) \ + V(ImmutableList_from, 3) \ V(StringBase_createFromCodePoints, 3) \ V(StringBase_substringUnchecked, 3) \ V(StringBase_joinReplaceAllResult, 4) \ @@ -133,7 +133,7 @@ namespace dart { V(String_getLength, 1) \ V(String_charAt, 2) \ V(String_concat, 2) \ - V(String_fromEnvironment, 3) \ + V(String_fromEnvironment, 2) \ V(String_toLowerCase, 1) \ V(String_toUpperCase, 1) \ V(String_concatRange, 3) \ @@ -172,9 +172,9 @@ namespace dart { V(TypedDataView_typedData, 1) \ V(Float32x4_fromDoubles, 4) \ V(Float32x4_splat, 1) \ - V(Float32x4_fromInt32x4Bits, 2) \ - V(Float32x4_fromFloat64x2, 2) \ - V(Float32x4_zero, 1) \ + V(Float32x4_fromInt32x4Bits, 1) \ + V(Float32x4_fromFloat64x2, 1) \ + V(Float32x4_zero, 0) \ V(Float32x4_add, 2) \ V(Float32x4_negate, 1) \ V(Float32x4_sub, 2) \ @@ -207,8 +207,8 @@ namespace dart { V(Float32x4_reciprocalSqrt, 1) \ V(Float64x2_fromDoubles, 2) \ V(Float64x2_splat, 1) \ - V(Float64x2_zero, 1) \ - V(Float64x2_fromFloat32x4, 2) \ + V(Float64x2_zero, 0) \ + V(Float64x2_fromFloat32x4, 1) \ V(Float64x2_add, 2) \ V(Float64x2_negate, 1) \ V(Float64x2_sub, 2) \ @@ -227,7 +227,7 @@ namespace dart { V(Float64x2_sqrt, 1) \ V(Int32x4_fromInts, 4) \ V(Int32x4_fromBools, 4) \ - V(Int32x4_fromFloat32x4Bits, 2) \ + V(Int32x4_fromFloat32x4Bits, 1) \ V(Int32x4_or, 2) \ V(Int32x4_and, 2) \ V(Int32x4_xor, 2) \ @@ -260,7 +260,7 @@ namespace dart { V(Isolate_sendOOB, 2) \ V(Isolate_spawnFunction, 10) \ V(Isolate_spawnUri, 12) \ - V(GrowableList_allocate, 2) \ + V(GrowableList_allocate, 1) \ V(GrowableList_setIndexed, 3) \ V(GrowableList_getLength, 1) \ V(GrowableList_getCapacity, 1) \ @@ -290,7 +290,7 @@ namespace dart { V(ThreadLocal_hasValue, 1) \ V(ThreadLocal_setValue, 2) \ V(Uri_isWindowsPlatform, 0) \ - V(UserTag_new, 2) \ + V(UserTag_new, 1) \ V(UserTag_label, 1) \ V(UserTag_makeCurrent, 1) \ V(VMService_SendIsolateServiceMessage, 2) \ @@ -322,7 +322,7 @@ namespace dart { V(DartApiDLMajorVersion, 0) \ V(DartApiDLMinorVersion, 0) \ V(DartNativeApiFunctionPointer, 1) \ - V(TransferableTypedData_factory, 2) \ + V(TransferableTypedData_factory, 1) \ V(TransferableTypedData_materialize, 1) \ V(Timer_postTimerEvent, 1) diff --git a/runtime/vm/bytecode_reader.cc b/runtime/vm/bytecode_reader.cc index 1b08baaed73..e971f56e4ea 100644 --- a/runtime/vm/bytecode_reader.cc +++ b/runtime/vm/bytecode_reader.cc @@ -1528,16 +1528,8 @@ ObjectPtr BytecodeReaderHelper::ReadType(intptr_t tag, type = Class::Cast(parent).TypeParameterAt(index_in_parent, nullability); } else if (parent.IsFunction()) { - if (Function::Cast(parent).IsFactory()) { - // For factory constructors VM uses type parameters of a class - // instead of constructor's type parameters. - parent = Function::Cast(parent).Owner(); - type = - Class::Cast(parent).TypeParameterAt(index_in_parent, nullability); - } else { - type = Function::Cast(parent).TypeParameterAt(index_in_parent, - nullability); - } + type = Function::Cast(parent).TypeParameterAt(index_in_parent, + nullability); } else if (parent.IsNull()) { ASSERT(!enclosing_function_types_.is_empty()); for (intptr_t i = enclosing_function_types_.length() - 1; i >= 0; --i) { @@ -2124,7 +2116,6 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) { intptr_t flags = reader_.ReadUInt(); const bool is_static = (flags & kIsStaticFlag) != 0; - const bool is_factory = (flags & kIsFactoryFlag) != 0; const bool is_native = (flags & kIsNativeFlag) != 0; const bool has_pragma = (flags & kHasPragmaFlag) != 0; const bool is_extension_member = (flags & kIsExtensionMemberFlag) != 0; @@ -2204,7 +2195,7 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) { ReadTypeParametersDeclaration(Class::Handle(Z), signature); } - const intptr_t num_implicit_params = (!is_static || is_factory) ? 1 : 0; + const intptr_t num_implicit_params = (!is_static) ? 1 : 0; const intptr_t num_params = num_implicit_params + reader_.ReadUInt(); const bool has_optional_named_params = ((flags & kHasOptionalNamedParamsFlag) != 0); @@ -2241,11 +2232,6 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) { NOT_IN_PRECOMPILED( function.SetParameterNameAt(param_index, Symbols::This())); ++param_index; - } else if (is_factory) { - signature.SetParameterTypeAt(param_index, AbstractType::dynamic_type()); - NOT_IN_PRECOMPILED(function.SetParameterNameAt( - param_index, Symbols::TypeArgumentsParameter())); - ++param_index; } for (; param_index < num_params; ++param_index) { diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc index 732b6df5c5b..3a8dd1871ca 100644 --- a/runtime/vm/compiler/backend/flow_graph.cc +++ b/runtime/vm/compiler/backend/flow_graph.cc @@ -1477,8 +1477,7 @@ intptr_t FlowGraph::ComputeLocationsOfFixedParameters( compiler::ParameterInfoArray* parameter_info /* = nullptr */) { return compiler::ComputeCallingConvention( zone, function, function.num_fixed_parameters(), - [&](intptr_t i) { - const intptr_t index = (function.IsFactory() ? (i - 1) : i); + [&](intptr_t index) { return index >= 0 ? ParameterRepresentationAt(function, index) : kTagged; }, diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index b12dbdd23ec..7f888242bc8 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -2852,22 +2852,21 @@ Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) { // argument passed to the constructor. if (call->is_known_list_constructor() && IsFixedLengthArrayCid(call->Type()->ToCid())) { - return call->ArgumentAt(1); + return call->ArgumentAt(call->FirstArgIndex()); } else if (call->function().recognized_kind() == MethodRecognizer::kByteDataFactory) { // Similarly, we check for the ByteData constructor and forward its // explicit length argument appropriately. - return call->ArgumentAt(1); + return call->ArgumentAt(call->FirstArgIndex()); } else if (IsTypedDataViewFactory(call->function())) { - // Typed data view factories all take three arguments (after - // the implicit type arguments parameter): + // Typed data view factories all take three arguments: // // 1) _TypedList buffer -- the underlying data for the view // 2) int offsetInBytes -- the offset into the buffer to start viewing // 3) int length -- the number of elements in the view // // Here, we forward the third. - return call->ArgumentAt(3); + return call->ArgumentAt(call->FirstArgIndex() + 2); } } else if (LoadFieldInstr* load_array = orig_instance->AsLoadField()) { // For arrays with guarded lengths, replace the length load @@ -2901,7 +2900,7 @@ Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) { if (StaticCallInstr* call = orig_instance->AsStaticCall()) { if (IsTypedDataViewFactory(call->function()) || IsUnmodifiableTypedDataViewFactory(call->function())) { - return call->ArgumentAt(1); + return call->ArgumentAt(call->FirstArgIndex()); } } break; @@ -2911,7 +2910,7 @@ Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) { ASSERT(!calls_initializer()); if (StaticCallInstr* call = orig_instance->AsStaticCall()) { if (IsTypedDataViewFactory(call->function())) { - return call->ArgumentAt(2); + return call->ArgumentAt(call->FirstArgIndex() + 1); } else if (call->function().recognized_kind() == MethodRecognizer::kByteDataFactory) { // A _ByteDataView returned from the ByteData constructor always @@ -2944,7 +2943,8 @@ Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) { } if (StaticCallInstr* call = orig_instance->AsStaticCall()) { if (call->is_known_list_constructor()) { - return call->ArgumentAt(0); + return (call->type_args_len() > 0) ? call->ArgumentAt(0) + : flow_graph->constant_null(); } else if (IsTypedDataViewFactory(call->function()) || IsUnmodifiableTypedDataViewFactory(call->function())) { return flow_graph->constant_null(); @@ -3942,12 +3942,12 @@ Instruction* GuardFieldLengthInstr::Canonicalize(FlowGraph* flow_graph) { ConstantInstr* length = nullptr; if (call->is_known_list_constructor() && LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) { - length = call->ArgumentAt(1)->AsConstant(); + length = call->ArgumentAt(call->FirstArgIndex())->AsConstant(); } else if (call->function().recognized_kind() == MethodRecognizer::kByteDataFactory) { - length = call->ArgumentAt(1)->AsConstant(); + length = call->ArgumentAt(call->FirstArgIndex())->AsConstant(); } else if (LoadFieldInstr::IsTypedDataViewFactory(call->function())) { - length = call->ArgumentAt(3)->AsConstant(); + length = call->ArgumentAt(call->FirstArgIndex() + 2)->AsConstant(); } if ((length != nullptr) && length->value().IsSmi() && Smi::Cast(length->value()).Value() == expected_length) { @@ -5471,7 +5471,7 @@ Representation StaticCallInstr::RequiredInputRepresentation( intptr_t idx) const { // The first input is the array of types // for generic functions - if (type_args_len() > 0 || function().IsFactory()) { + if (type_args_len() > 0) { if (idx == 0) { return kTagged; } @@ -5954,14 +5954,6 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { compiler->GenerateStaticCall(deopt_id(), source(), function(), args_info, locs(), *call_ic_data, rebind_rule_, entry_kind()); - if (function().IsFactory()) { - TypeUsageInfo* type_usage_info = compiler->thread()->type_usage_info(); - if (type_usage_info != nullptr) { - const Class& klass = Class::Handle(function().Owner()); - RegisterTypeArgumentsUse(compiler->function(), type_usage_info, klass, - ArgumentAt(0)); - } - } } CachableIdempotentCallInstr::CachableIdempotentCallInstr( @@ -5997,7 +5989,7 @@ CachableIdempotentCallInstr::CachableIdempotentCallInstr( Representation CachableIdempotentCallInstr::RequiredInputRepresentation( intptr_t idx) const { // The first input is the array of types for generic functions. - if (type_args_len() > 0 || function().IsFactory()) { + if (type_args_len() > 0) { if (idx == 0) { return kTagged; } @@ -8684,11 +8676,10 @@ SimdOpInstr* SimdOpInstr::CreateFromFactoryCall(Zone* zone, Instruction* call) { SimdOpInstr* op = new (zone) SimdOpInstr(KindForMethod(kind), call->deopt_id()); + ASSERT(call->ArgumentCount() == op->InputCount()); for (intptr_t i = 0; i < op->InputCount(); i++) { - // Note: ArgumentAt(0) is type arguments which we don't need. - op->SetInputAt(i, call->ArgumentValueAt(i + 1)->CopyWithType(zone)); + op->SetInputAt(i, call->ArgumentValueAt(i)->CopyWithType(zone)); } - ASSERT(call->ArgumentCount() == (op->InputCount() + 1)); return op; } diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc index 9b008a10ec7..eefab78184f 100644 --- a/runtime/vm/compiler/backend/type_propagator.cc +++ b/runtime/vm/compiler/backend/type_propagator.cc @@ -1507,13 +1507,14 @@ static CompileType ComputeListFactoryType(CompileType* inferred_type, ASSERT(cid != kDynamicCid); if ((cid == kGrowableObjectArrayCid || cid == kArrayCid || cid == kImmutableArrayCid) && - type_args_value->BindsToConstant()) { + ((type_args_value == nullptr) || type_args_value->BindsToConstant())) { Thread* thread = Thread::Current(); Zone* zone = thread->zone(); const Class& cls = Class::Handle(zone, thread->isolate_group()->class_table()->At(cid)); auto& type_args = TypeArguments::Handle(zone); - if (!type_args_value->BoundConstant().IsNull()) { + if (type_args_value != nullptr && + !type_args_value->BoundConstant().IsNull()) { type_args ^= type_args_value->BoundConstant().ptr(); ASSERT(type_args.Length() >= cls.NumTypeArguments()); type_args = type_args.FromInstanceTypeArguments(thread, cls); @@ -1533,7 +1534,8 @@ CompileType StaticCallInstr::ComputeType() const { // (in optimized mode) and avoid keeping separate result_type. CompileType* const inferred_type = result_type(); if (is_known_list_constructor()) { - return ComputeListFactoryType(inferred_type, ArgumentValueAt(0)); + Value* type_args_value = type_args_len() > 0 ? ArgumentValueAt(0) : nullptr; + return ComputeListFactoryType(inferred_type, type_args_value); } intptr_t inferred_cid = kDynamicCid; diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc index a562faae4e6..e5e7fe9c030 100644 --- a/runtime/vm/compiler/call_specializer.cc +++ b/runtime/vm/compiler/call_specializer.cc @@ -1325,14 +1325,14 @@ void CallSpecializer::VisitStaticCall(StaticCallInstr* call) { if (call->HasICData() && targets.IsMonomorphic() && (call->FirstArgIndex() == 0)) { if (binary_feedback.ArgumentIs(kSmiCid)) { - Definition* arg = call->ArgumentAt(1); + Definition* arg = call->ArgumentAt(0); AddCheckSmi(arg, call->deopt_id(), call->env(), call); ReplaceCall(call, new (Z) SmiToDoubleInstr(new (Z) Value(arg), call->source())); return; } else if (binary_feedback.ArgumentIs(kMintCid) && CanConvertInt64ToDouble()) { - Definition* arg = call->ArgumentAt(1); + Definition* arg = call->ArgumentAt(0); ReplaceCall(call, new (Z) Int64ToDoubleInstr(new (Z) Value(arg), call->deopt_id())); return; @@ -2688,24 +2688,24 @@ class SimdLowering : public ValueObject { // Mixed case MethodRecognizer::kFloat32x4ToFloat64x2: { - UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1); + UnboxVector(0, kUnboxedFloat, kDoubleCid, 4); Float32x4ToFloat64x2(); BoxVector(kUnboxedDouble, 2); return true; } case MethodRecognizer::kFloat64x2ToFloat32x4: { - UnboxVector(0, kUnboxedDouble, kDoubleCid, 2, 1); + UnboxVector(0, kUnboxedDouble, kDoubleCid, 2); Float64x2ToFloat32x4(); BoxVector(kUnboxedFloat, 4); return true; } case MethodRecognizer::kInt32x4ToFloat32x4: - UnboxVector(0, kUnboxedInt32, kMintCid, 4, 1); + UnboxVector(0, kUnboxedInt32, kMintCid, 4); Int32x4ToFloat32x4(); BoxVector(kUnboxedFloat, 4); return true; case MethodRecognizer::kFloat32x4ToInt32x4: - UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1); + UnboxVector(0, kUnboxedFloat, kDoubleCid, 4); Float32x4ToInt32x4(); BoxVector(kUnboxedInt32, 4); return true; @@ -2744,12 +2744,8 @@ class SimdLowering : public ValueObject { BoxVector(kUnboxedDouble, 2); } - void UnboxVector(intptr_t i, - Representation rep, - intptr_t cid, - intptr_t n, - intptr_t type_args = 0) { - Definition* arg = call_->ArgumentAt(i + type_args); + void UnboxVector(intptr_t i, Representation rep, intptr_t cid, intptr_t n) { + Definition* arg = call_->ArgumentAt(i); if (CompilerState::Current().is_aot()) { // Add null-checks in case of the arguments are known to be compatible // but they are possibly nullable. @@ -2765,11 +2761,8 @@ class SimdLowering : public ValueObject { } } - void UnboxScalar(intptr_t i, - Representation rep, - intptr_t n, - intptr_t type_args = 0) { - Definition* arg = call_->ArgumentAt(i + type_args); + void UnboxScalar(intptr_t i, Representation rep, intptr_t n) { + Definition* arg = call_->ArgumentAt(i); if (CompilerState::Current().is_aot()) { // Add null-checks in case of the arguments are known to be compatible // but they are possibly nullable. diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index c259aacfb5f..d38e5578ec2 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -3415,12 +3415,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) { return instructions; } - const Class& klass = Class::ZoneHandle(Z, target.Owner()); - if (target.IsGenerativeConstructor() || target.IsFactory()) { - // The VM requires a TypeArguments object as first parameter for - // every factory constructor. - ++argument_count; - } + ASSERT(!target.IsGenerativeConstructor()); if (target.IsCachableIdempotent()) { return BuildCachableIdempotentCall(position, target); @@ -3469,7 +3464,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) { } Fragment instructions; - LocalVariable* instance_variable = nullptr; + const Class& klass = Class::ZoneHandle(Z, target.Owner()); const bool special_case_unchecked_cast = klass.IsTopLevel() && (klass.library() == Library::InternalLibrary()) && @@ -3482,38 +3477,8 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) { const bool special_case = special_case_identical || special_case_unchecked_cast; - // If we cross the Kernel -> VM core library boundary, a [StaticInvocation] - // can appear, but the thing we're calling is not a static method, but a - // factory constructor. - // The `H.LookupStaticmethodByKernelProcedure` will potentially resolve to the - // forwarded constructor. - // In that case we'll make an instance and pass it as first argument. - // - // TODO(27590): Get rid of this after we're using core libraries compiled - // into Kernel. intptr_t type_args_len = 0; - if (target.IsGenerativeConstructor()) { - if (klass.NumTypeArguments() > 0) { - const TypeArguments& type_arguments = - PeekArgumentsInstantiatedType(klass); - instructions += TranslateInstantiatedTypeArguments(type_arguments); - instructions += AllocateObject(position, klass, 1); - } else { - instructions += AllocateObject(position, klass, 0); - } - - instance_variable = MakeTemporary(); - - instructions += LoadLocal(instance_variable); - } else if (target.IsFactory()) { - // The VM requires currently a TypeArguments object as first parameter for - // every factory constructor :-/ ! - // - // TODO(27590): Get rid of this after we're using core libraries compiled - // into Kernel. - const TypeArguments& type_arguments = PeekArgumentsInstantiatedType(klass); - instructions += TranslateInstantiatedTypeArguments(type_arguments); - } else if (!special_case) { + if (!special_case) { AlternativeReadingScope alt(&reader_); ReadUInt(); // read argument count. intptr_t list_length = ReadListLength(); // read types list length. @@ -4161,7 +4126,10 @@ Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) { Symbols::_GrowableListLiteralFactory())); ASSERT(!factory_method.IsNull()); - instructions += StaticCall(position, factory_method, 2, ICData::kStatic); + instructions += StaticCall(position, factory_method, + /*argument_count=*/1, Array::null_array(), + ICData::kStatic, /*result_type=*/nullptr, + /*type_args_len=*/1); instructions += DropTempsPreserveTop(1); // Instantiated type_arguments. return instructions; } @@ -4211,8 +4179,10 @@ Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition* p) { Library::PrivateCoreLibName(Symbols::MapLiteralFactory())); } - return instructions + - StaticCall(position, factory_method, 2, ICData::kStatic); + return instructions + StaticCall(position, factory_method, + /*argument_count=*/1, Array::null_array(), + ICData::kStatic, /*result_type=*/nullptr, + /*type_args_len=*/2); } Fragment StreamingFlowGraphBuilder::BuildRecordLiteral(TokenPosition* p) { diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 2daf19e0735..d3f4c74ea7f 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -164,18 +164,8 @@ Fragment FlowGraphBuilder::PopContext() { Fragment FlowGraphBuilder::LoadInstantiatorTypeArguments() { // TODO(27590): We could use `active_class_->IsGeneric()`. Fragment instructions; - if (scopes_ != nullptr && scopes_->type_arguments_variable != nullptr) { -#ifdef DEBUG - Function& function = - Function::Handle(Z, parsed_function_->function().ptr()); - while (function.IsClosureFunction()) { - function = function.parent_function(); - } - ASSERT(function.IsFactory()); -#endif - instructions += LoadLocal(scopes_->type_arguments_variable); - } else if (parsed_function_->has_receiver_var() && - active_class_.ClassNumTypeArguments() > 0) { + if (parsed_function_->has_receiver_var() && + active_class_.ClassNumTypeArguments() > 0) { ASSERT(!parsed_function_->function().IsFactory()); instructions += LoadLocal(parsed_function_->receiver_var()); instructions += LoadNativeField( @@ -1466,14 +1456,14 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( break; case MethodRecognizer::kGrowableArrayAllocateWithData: { ASSERT(function.IsFactory()); - ASSERT_EQUAL(function.NumParameters(), 2); + ASSERT_EQUAL(function.NumParameters(), 1); const Class& cls = Class::ZoneHandle(Z, compiler::GrowableObjectArrayClass().ptr()); - body += LoadLocal(parsed_function_->RawParameterVariable(0)); + body += LoadLocal(parsed_function_->function_type_arguments()); body += AllocateObject(TokenPosition::kNoSource, cls, 1); LocalVariable* object = MakeTemporary(); body += LoadLocal(object); - body += LoadLocal(parsed_function_->RawParameterVariable(1)); + body += LoadLocal(parsed_function_->RawParameterVariable(0)); body += StoreNativeField(Slot::GrowableObjectArray_data(), StoreFieldInstr::Kind::kInitializing, kNoStoreBarrier); @@ -1494,9 +1484,9 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( body += Constant(Object::mutable_empty_array()); break; case MethodRecognizer::kObjectArrayAllocate: - ASSERT(function.IsFactory() && (function.NumParameters() == 2)); + ASSERT(function.IsFactory() && (function.NumParameters() == 1)); + body += LoadLocal(parsed_function_->function_type_arguments()); body += LoadLocal(parsed_function_->RawParameterVariable(0)); - body += LoadLocal(parsed_function_->RawParameterVariable(1)); body += CreateArray(); break; case MethodRecognizer::kCopyRangeFromUint8ListToOneByteString: @@ -1693,7 +1683,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( const auto& type_arguments = TypeArguments::ZoneHandle( Z, IG->object_store()->type_argument_never()); - ASSERT(function.NumTypeParameters() == 1); ASSERT_EQUAL(function.NumParameters(), 1); body += Constant(type_arguments); body += AllocateObject(TokenPosition::kNoSource, pointer_class, 1); @@ -2013,10 +2002,10 @@ Fragment FlowGraphBuilder::BuildTypedDataViewFactoryConstructor( ASSERT(class_table->HasValidClassAt(cid)); const auto& view_class = Class::ZoneHandle(H.zone(), class_table->At(cid)); - ASSERT(function.IsFactory() && (function.NumParameters() == 4)); - LocalVariable* typed_data = parsed_function_->RawParameterVariable(1); - LocalVariable* offset_in_bytes = parsed_function_->RawParameterVariable(2); - LocalVariable* length = parsed_function_->RawParameterVariable(3); + ASSERT(function.IsFactory() && (function.NumParameters() == 3)); + LocalVariable* typed_data = parsed_function_->RawParameterVariable(0); + LocalVariable* offset_in_bytes = parsed_function_->RawParameterVariable(1); + LocalVariable* length = parsed_function_->RawParameterVariable(2); Fragment body; @@ -2265,8 +2254,8 @@ Fragment FlowGraphBuilder::BuildTypedDataFactoryConstructor( ASSERT( Thread::Current()->isolate_group()->class_table()->HasValidClassAt(cid)); - ASSERT(function.IsFactory() && (function.NumParameters() == 2)); - LocalVariable* length = parsed_function_->RawParameterVariable(1); + ASSERT(function.IsFactory() && (function.NumParameters() == 1)); + LocalVariable* length = parsed_function_->RawParameterVariable(0); Fragment instructions; instructions += LoadLocal(length); @@ -2423,12 +2412,8 @@ void FlowGraphBuilder::BuildTypeArgumentTypeChecks(TypeChecksToBuild mode, ASSERT(!forwarding_target->IsNull()); } - TypeParameters& type_parameters = TypeParameters::Handle(Z); - if (dart_function.IsFactory()) { - type_parameters = Class::Handle(Z, dart_function.Owner()).type_parameters(); - } else { - type_parameters = dart_function.type_parameters(); - } + TypeParameters& type_parameters = + TypeParameters::Handle(Z, dart_function.type_parameters()); const intptr_t num_type_params = type_parameters.Length(); if (num_type_params == 0) return; // Check type parameter bounds against forwarding stub target, if any. @@ -2471,8 +2456,6 @@ void FlowGraphBuilder::BuildTypeArgumentTypeChecks(TypeChecksToBuild mode, if (forwarding_target != nullptr) { type_param = forwarding_target->TypeParameterAt(i); - } else if (dart_function.IsFactory()) { - type_param = Class::Handle(Z, dart_function.Owner()).TypeParameterAt(i); } else { type_param = dart_function.TypeParameterAt(i); } @@ -4351,7 +4334,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction( intptr_t type_args_len = 0; if (function.IsGeneric()) { - if (target.IsConstructor()) { + if (target.IsGenerativeConstructor()) { const auto& result_type = AbstractType::Handle(Z, function.result_type()); ASSERT(result_type.IsFinalized()); // Instantiate a flattened type arguments vector which @@ -4368,10 +4351,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction( ASSERT(parsed_function_->function_type_arguments() != nullptr); closure += LoadLocal(parsed_function_->function_type_arguments()); } - } else if (target.IsFactory()) { - // Factories always take an extra implicit argument for - // type arguments even if their classes don't have type parameters. - closure += NullConstant(); } // Push receiver. diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc index 4d22555ecff..c902d0cc0fd 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc @@ -3204,9 +3204,7 @@ TypedDataViewPtr KernelReaderHelper::GetConstantCoverageFor(intptr_t index) { intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) { ASSERT(member != nullptr); - if (member->IsFactory()) { - return klass->NumTypeParameters(); - } else if (member->IsMethodExtractor()) { + if (member->IsMethodExtractor()) { Function& extracted = Function::Handle(zone, member->extracted_method_closure()); return extracted.NumTypeParameters(); @@ -3601,35 +3599,8 @@ void TypeTranslator::BuildTypeParameterType() { parameter_index -= class_type_parameter_count; if (active_class_->HasMember()) { - if (active_class_->MemberIsFactoryProcedure()) { - // - // WARNING: This is a little hackish: - // - // We have a static factory constructor. The kernel IR gives the factory - // constructor function its own type parameters (which are equal in name - // and number to the ones of the enclosing class). I.e., - // - // class A { - // factory A.x() { return new B(); } - // } - // - // is basically translated to this: - // - // class A { - // static A.x() { return new B(); } - // } - // - if (class_type_parameter_count > parameter_index) { - result_ = active_class_->klass->TypeParameterAt(parameter_index, - nullability); - return; - } - parameter_index -= class_type_parameter_count; - } - // Factory function should not be considered as procedure. const intptr_t procedure_type_parameter_count = - (active_class_->MemberIsProcedure() && - !active_class_->MemberIsFactoryProcedure()) + active_class_->MemberIsProcedure() ? active_class_->MemberTypeParameterCount(Z) : 0; if (procedure_type_parameter_count > 0) { @@ -3937,26 +3908,20 @@ void TypeTranslator::SetupFunctionParameters( bool is_closure, FunctionNodeHelper* function_node_helper) { ASSERT(!(is_method && is_closure)); - bool is_factory = function.IsFactory(); - intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0; + intptr_t extra_parameters = (is_method || is_closure) ? 1 : 0; const FunctionType& signature = FunctionType::Handle(Z, function.signature()); ASSERT(!signature.IsNull()); - intptr_t type_parameter_count = 0; - if (!is_factory) { - type_parameter_count = helper_->ReadListLength(); - LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z), - signature, type_parameter_count); - function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters); - } + intptr_t type_parameter_count = helper_->ReadListLength(); + LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z), + signature, type_parameter_count); + function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters); ActiveTypeParametersScope scope(active_class_, function, &signature, Z); - if (!is_factory) { - LoadAndSetupBounds(active_class_, function, Class::Handle(Z), signature, - type_parameter_count); - function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters); - } + LoadAndSetupBounds(active_class_, function, Class::Handle(Z), signature, + type_parameter_count); + function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters); function_node_helper->ReadUntilExcluding( FunctionNodeHelper::kPositionalParameters); @@ -3996,13 +3961,9 @@ void TypeTranslator::SetupFunctionParameters( signature.SetParameterTypeAt(pos, AbstractType::dynamic_type()); function.SetParameterNameAt(pos, Symbols::ClosureParameter()); pos++; - } else if (is_factory) { - signature.SetParameterTypeAt(pos, AbstractType::dynamic_type()); - function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter()); - pos++; } } else { - ASSERT(!is_method && !is_closure && !is_factory); + ASSERT(!is_method && !is_closure); } const Library& lib = Library::Handle(Z, active_class_->klass->library()); diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h index 12318394927..4ee60a264f4 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.h +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h @@ -1429,11 +1429,6 @@ class ActiveClass { member->IsFactory(); } - bool MemberIsFactoryProcedure() { - ASSERT(member != nullptr); - return member->IsFactory(); - } - intptr_t MemberTypeParameterCount(Zone* zone); intptr_t ClassNumTypeArguments() { diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc index 368eb19f606..ab7f04e0817 100644 --- a/runtime/vm/compiler/frontend/scope_builder.cc +++ b/runtime/vm/compiler/frontend/scope_builder.cc @@ -224,12 +224,6 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() { } } } - } else if (function.IsFactory()) { - LocalVariable* variable = MakeVariable( - TokenPosition::kNoSource, TokenPosition::kNoSource, - Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type()); - scope_->InsertParameterAt(pos++, variable); - result_->type_arguments_variable = variable; } ParameterTypeCheckMode type_check_mode = @@ -1570,21 +1564,13 @@ void ScopeBuilder::VisitTypeParameterType() { function = function.parent_function(); } - if (function.IsFactory()) { - // The type argument vector is passed as the very first argument to the - // factory constructor function. - HandleSpecialLoad(&result_->type_arguments_variable, - Symbols::TypeArgumentsParameter(), - LocalVariable::kNoKernelOffset); - } else { - // If the type parameter is a parameter to this or an enclosing function, - // we can read it directly from the function type arguments vector later. - // Otherwise, the type arguments vector we need is stored on the instance - // object, so we need to capture 'this'. - Class& parent_class = Class::Handle(Z, function.Owner()); - if (index < parent_class.NumTypeParameters()) { - HandleLoadReceiver(); - } + // If the type parameter is a parameter to this or an enclosing function, + // we can read it directly from the function type arguments vector later. + // Otherwise, the type arguments vector we need is stored on the instance + // object, so we need to capture 'this'. + Class& parent_class = Class::Handle(Z, function.Owner()); + if (index < parent_class.NumTypeParameters()) { + HandleLoadReceiver(); } } } diff --git a/runtime/vm/compiler/frontend/scope_builder.h b/runtime/vm/compiler/frontend/scope_builder.h index f319acc8bf5..4052e90d9e4 100644 --- a/runtime/vm/compiler/frontend/scope_builder.h +++ b/runtime/vm/compiler/frontend/scope_builder.h @@ -181,8 +181,7 @@ struct FunctionScope { class ScopeBuildingResult : public ZoneObject { public: ScopeBuildingResult() - : type_arguments_variable(nullptr), - switch_variable(nullptr), + : switch_variable(nullptr), finally_return_variable(nullptr), setter_value(nullptr), raw_variable_counter_(0) {} @@ -200,9 +199,6 @@ class ScopeBuildingResult : public ZoneObject { IntMap scopes; GrowableArray function_scopes; - // Only non-null for factory constructor functions. - LocalVariable* type_arguments_variable; - // Non-nullptr when the function contains a switch statement. LocalVariable* switch_variable; diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc index 9a80dd6bd67..fe720892e4e 100644 --- a/runtime/vm/compiler/method_recognizer.cc +++ b/runtime/vm/compiler/method_recognizer.cc @@ -15,6 +15,7 @@ intptr_t MethodRecognizer::NumArgsCheckedForStaticCall( const Function& function) { switch (function.recognized_kind()) { case MethodRecognizer::kDoubleFromInteger: + return 1; case MethodRecognizer::kMathMin: case MethodRecognizer::kMathMax: return 2; diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 55dca4bfd3f..2fced2968c7 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -3205,11 +3205,14 @@ DART_EXPORT Dart_Handle Dart_NewMap(Dart_Handle keys_type, Function& factory_method = Function::ZoneHandle(Z); factory_method = map_class.LookupFactoryAllowPrivate( Library::PrivateCoreLibName(Symbols::MapKeyValuesFactory())); + const Array& arguments_descriptor = + Array::Handle(Z, ArgumentsDescriptor::NewBoxed(2, 2)); const Array& args = Array::Handle(Z, Array::New(3)); args.SetAt(0, type_arguments); args.SetAt(1, keys_obj); args.SetAt(2, values_obj); - return Api::NewHandle(T, DartEntry::InvokeFunction(factory_method, args)); + return Api::NewHandle( + T, DartEntry::InvokeFunction(factory_method, args, arguments_descriptor)); } DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type, @@ -3427,7 +3430,7 @@ DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list, static ObjectPtr ResolveConstructor(const char* current_func, const Class& cls, const String& class_name, - const String& dotted_name, + const String& constr_name, int num_args); static ObjectPtr ThrowArgumentError(const char* exception_message) { @@ -4079,13 +4082,12 @@ DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data) { ASSERT(result.IsFunction()); const Function& factory = Function::Cast(result); ASSERT(!factory.IsGenerativeConstructor()); + ASSERT(factory.NumParameters() == 1); // Create the argument list. - const Array& args = Array::Handle(Z, Array::New(2)); - // Factories get type arguments. - args.SetAt(0, Object::null_type_arguments()); + const Array& args = Array::Handle(Z, Array::New(1)); const Object& obj = Object::Handle(Z, Api::UnwrapHandle(typed_data)); - args.SetAt(1, obj); + args.SetAt(0, obj); // Invoke the factory constructor and return the new object. result = DartEntry::InvokeFunction(factory, args); @@ -4297,10 +4299,11 @@ static ObjectPtr ResolveConstructor(const char* current_func, return ApiError::New(message); } } - const int kTypeArgsLen = 0; - const int extra_args = 1; + const int type_args_len = + constructor.IsGenerativeConstructor() ? 0 : cls.NumTypeParameters(); + const int extra_args = constructor.IsGenerativeConstructor() ? 1 : 0; String& error_message = String::Handle(); - if (!constructor.AreValidArgumentCounts(kTypeArgsLen, num_args + extra_args, + if (!constructor.AreValidArgumentCounts(type_args_len, num_args + extra_args, 0, &error_message)) { const String& message = String::Handle(String::NewFormatted( "%s: wrong argument count for " @@ -4344,9 +4347,6 @@ DART_EXPORT Dart_Handle Dart_New(Dart_Handle type, Class& cls = Class::Handle(Z, type_obj.type_class()); CHECK_ERROR_HANDLE(cls.EnsureIsAllocateFinalized(T)); - TypeArguments& type_arguments = - TypeArguments::Handle(Z, type_obj.GetInstanceTypeArguments(T)); - const String& base_constructor_name = String::Handle(Z, cls.Name()); // And get the name of the constructor to invoke. @@ -4388,22 +4388,33 @@ DART_EXPORT Dart_Handle Dart_New(Dart_Handle type, } // Create the argument list. + const intptr_t type_args_len = + constructor.IsGenerativeConstructor() ? 0 : cls.NumTypeParameters(); + const intptr_t num_implicit_positional_args = + constructor.IsGenerativeConstructor() ? 1 : 0; intptr_t arg_index = 0; - int extra_args = 1; - const Array& args = - Array::Handle(Z, Array::New(number_of_arguments + extra_args)); + Array& args = Array::Handle(Z); + TypeArguments& instantiator_type_arguments = TypeArguments::Handle(Z); + TypeArguments& function_type_arguments = TypeArguments::Handle(Z); if (constructor.IsGenerativeConstructor()) { // Constructors get the uninitialized object. - if (!type_arguments.IsNull()) { + args = Array::New(number_of_arguments + num_implicit_positional_args); + instantiator_type_arguments = type_obj.GetInstanceTypeArguments(T); + if (!instantiator_type_arguments.IsNull()) { // The type arguments will be null if the class has no type parameters, in // which case the following call would fail because there is no slot // reserved in the object for the type vector. - new_object.SetTypeArguments(type_arguments); + new_object.SetTypeArguments(instantiator_type_arguments); } args.SetAt(arg_index++, new_object); } else { - // Factories get type arguments. - args.SetAt(arg_index++, type_arguments); + args = Array::New(number_of_arguments + ((type_args_len > 0) ? 1 : 0)); + if (type_args_len > 0) { + function_type_arguments = type_obj.arguments(); + ASSERT(function_type_arguments.IsNull() || + function_type_arguments.Length() == type_args_len); + args.SetAt(arg_index++, function_type_arguments); + } } Object& argument = Object::Handle(Z); for (int i = 0; i < number_of_arguments; i++) { @@ -4420,19 +4431,21 @@ DART_EXPORT Dart_Handle Dart_New(Dart_Handle type, args.SetAt(arg_index++, argument); } - const int kTypeArgsLen = 0; Array& args_descriptor_array = Array::Handle( - Z, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length())); + Z, + ArgumentsDescriptor::NewBoxed( + type_args_len, number_of_arguments + num_implicit_positional_args)); ArgumentsDescriptor args_descriptor(args_descriptor_array); ObjectPtr type_error = constructor.DoArgumentTypesMatch( - args, args_descriptor, type_arguments, Object::empty_type_arguments()); + args, args_descriptor, instantiator_type_arguments, + function_type_arguments); if (type_error != Error::null()) { return Api::NewHandle(T, type_error); } // Invoke the constructor and return the new object. - result = DartEntry::InvokeFunction(constructor, args); + result = DartEntry::InvokeFunction(constructor, args, args_descriptor_array); if (result.IsError()) { return Api::NewHandle(T, result.ptr()); } diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index a64a849affb..29c6933454b 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -9713,10 +9713,6 @@ bool Function::CanBeInlined() const { intptr_t Function::NumImplicitParameters() const { const UntaggedFunction::Kind k = kind(); - if (k == UntaggedFunction::kConstructor) { - // Type arguments for factory; instance for generative constructor. - return 1; - } if ((k == UntaggedFunction::kClosureFunction) || (k == UntaggedFunction::kImplicitClosureFunction) || (k == UntaggedFunction::kFfiTrampoline)) { @@ -10910,7 +10906,7 @@ FunctionPtr Function::ImplicitClosureFunction() const { } const intptr_t num_type_params = - IsConstructor() ? cls.NumTypeParameters() : NumTypeParameters(); + IsGenerativeConstructor() ? cls.NumTypeParameters() : NumTypeParameters(); TypeArguments& instantiator_type_arguments = TypeArguments::Handle(zone); TypeArguments& function_type_arguments = TypeArguments::Handle(zone); @@ -10922,7 +10918,7 @@ FunctionPtr Function::ImplicitClosureFunction() const { auto transform_type = [&](AbstractType& type) { if (num_type_params > 0) { - if (IsConstructor()) { + if (IsGenerativeConstructor()) { type = type.UpdateFunctionTypes(num_type_params, kAllFree, Heap::kOld, nullptr); if (!type.IsInstantiated(kCurrentClass)) { @@ -10940,7 +10936,7 @@ FunctionPtr Function::ImplicitClosureFunction() const { auto transform_type_args = [&](TypeArguments& type_args) { ASSERT(num_type_params > 0); if (!type_args.IsNull()) { - if (IsConstructor()) { + if (IsGenerativeConstructor()) { type_args = type_args.UpdateFunctionTypes(num_type_params, kAllFree, Heap::kOld, nullptr); if (!type_args.IsInstantiated(kCurrentClass)) { @@ -10958,7 +10954,8 @@ FunctionPtr Function::ImplicitClosureFunction() const { // Set closure function's type parameters. if (num_type_params > 0) { const TypeParameters& old_type_params = TypeParameters::Handle( - zone, IsConstructor() ? cls.type_parameters() : type_parameters()); + zone, + IsGenerativeConstructor() ? cls.type_parameters() : type_parameters()); const TypeParameters& new_type_params = TypeParameters::Handle(zone, TypeParameters::New()); // No need to set names that are ignored in a signature, however, the @@ -10977,7 +10974,7 @@ FunctionPtr Function::ImplicitClosureFunction() const { type_args.SetTypeAt(i, type_param); } - if (IsConstructor()) { + if (IsGenerativeConstructor()) { instantiator_type_arguments = type_args.ToInstantiatorTypeArguments(thread, cls); } else { @@ -10996,7 +10993,7 @@ FunctionPtr Function::ImplicitClosureFunction() const { // Set closure function's result type. AbstractType& result_type = AbstractType::Handle(zone); - if (IsConstructor()) { + if (IsGenerativeConstructor()) { result_type = cls.DeclarationType(); } else { result_type = this->result_type(); @@ -18123,14 +18120,13 @@ ICDataPtr ICData::NewForStaticCall(const Function& owner, intptr_t num_args_tested, RebindRule rebind_rule) { // See `MethodRecognizer::NumArgsCheckedForStaticCall`. - ASSERT(num_args_tested == 0 || num_args_tested == 2); + ASSERT(num_args_tested == 0 || num_args_tested == 1 || num_args_tested == 2); ASSERT(!target.IsNull()); Zone* zone = Thread::Current()->zone(); const auto& target_name = String::Handle(zone, target.name()); GrowableArray cids(num_args_tested); - if (num_args_tested == 2) { - cids.Add(kObjectCid); + for (intptr_t i = 0; i < num_args_tested; ++i) { cids.Add(kObjectCid); } return ICData::NewWithCheck(owner, target_name, arguments_descriptor, diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index f974fc91912..8e2bb3dbfd6 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -1064,13 +1064,8 @@ DEFINE_RUNTIME_ENTRY(AdjustArgumentsDesciptorForImplicitClosure, 3) { intptr_t num_arguments = args_desc.Count(); if (target.is_static()) { - if (target.IsFactory()) { - // Factory always takes type arguments via a positional parameter. - type_args_len = 0; - } else { - // Drop closure receiver. - --num_arguments; - } + // Drop closure receiver. + --num_arguments; } else { if (target.IsGenerativeConstructor()) { // Type arguments are not passed to a generative constructor. @@ -2496,7 +2491,7 @@ DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) { const Instance& arg = Instance::CheckedHandle(zone, arguments.ArgAt(0)); const ICData& ic_data = ICData::CheckedHandle(zone, arguments.ArgAt(1)); // IC data for static call is prepopulated with the statically known target. - ASSERT(ic_data.NumberOfChecksIs(1)); + ASSERT(!ic_data.NumberOfChecksIs(0)); const Function& target = Function::Handle(zone, ic_data.GetTargetAt(0)); target.EnsureHasCode(); ASSERT(!target.IsNull() && target.HasCode());