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());