[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 <vegorov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
66b54232ee
commit
6195ea86bc
@@ -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<TypeParameter>.from(enclosingClass.typeParameters);
|
||||
// Treat type arguments of factory constructors as class
|
||||
// type parameters.
|
||||
if (isFactory) {
|
||||
classTypeParameters.addAll(node.function.typeParameters);
|
||||
}
|
||||
this.classTypeParameters = new Set<TypeParameter>.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.
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -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++);
|
||||
|
||||
@@ -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),
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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));
|
||||
|
||||
+5
-5
@@ -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));
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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())),
|
||||
|
||||
@@ -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));
|
||||
|
||||
+5
-12
@@ -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;
|
||||
|
||||
+38
-20
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
+10
-16
@@ -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<float>(v.x());
|
||||
float _y = static_cast<float>(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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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<Dart_NativeFunction>(entry->function_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<T> {
|
||||
// factory A.x() { return new B<T>(); }
|
||||
// }
|
||||
//
|
||||
// is basically translated to this:
|
||||
//
|
||||
// class A<T> {
|
||||
// static A.x<T'>() { return new B<T'>(); }
|
||||
// }
|
||||
//
|
||||
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());
|
||||
|
||||
@@ -1429,11 +1429,6 @@ class ActiveClass {
|
||||
member->IsFactory();
|
||||
}
|
||||
|
||||
bool MemberIsFactoryProcedure() {
|
||||
ASSERT(member != nullptr);
|
||||
return member->IsFactory();
|
||||
}
|
||||
|
||||
intptr_t MemberTypeParameterCount(Zone* zone);
|
||||
|
||||
intptr_t ClassNumTypeArguments() {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<LocalScope*> scopes;
|
||||
GrowableArray<FunctionScope> 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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+36
-23
@@ -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());
|
||||
}
|
||||
|
||||
+9
-13
@@ -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<intptr_t> 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,
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user