mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
Pass type argument vector to generic functions (if --reify-generic-functions is
true, still false per default). Work in progress, not functional yet (passed vector is still ignored in callee). R=vegorov@google.com, zra@google.com Review-Url: https://codereview.chromium.org/2859673002 .
This commit is contained in:
parent
59e6c332ea
commit
9aafded095
|
@ -281,6 +281,7 @@ class SuperCallResolutionTransformer extends Transformer {
|
|||
// The _InvocationMirror constructor takes the following arguments:
|
||||
// * Method name (a string).
|
||||
// * An arguments descriptor - a list consisting of:
|
||||
// - length of passed type argument vector, 0 if none passed.
|
||||
// - number of arguments (including receiver).
|
||||
// - number of positional arguments (including receiver).
|
||||
// - pairs (2 entries in the list) of
|
||||
|
@ -289,9 +290,11 @@ class SuperCallResolutionTransformer extends Transformer {
|
|||
// * A list of arguments, where the first ones are the positional arguments.
|
||||
// * Whether it's a super invocation or not.
|
||||
|
||||
int typeArgsLen = 0; // TODO(regis): Type arguments of generic function.
|
||||
int numPositionalArguments = callArguments.positional.length + 1;
|
||||
int numArguments = numPositionalArguments + callArguments.named.length;
|
||||
List<Expression> argumentsDescriptor = [
|
||||
new IntLiteral(typeArgsLen),
|
||||
new IntLiteral(numArguments),
|
||||
new IntLiteral(numPositionalArguments)
|
||||
];
|
||||
|
|
|
@ -14,12 +14,16 @@
|
|||
namespace dart {
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Function_apply, 2) {
|
||||
const Array& fun_arguments = Array::CheckedHandle(arguments->NativeArgAt(0));
|
||||
const Array& fun_arg_names = Array::CheckedHandle(arguments->NativeArgAt(1));
|
||||
const int kTypeArgsLen = 0; // TODO(regis): Add support for generic function.
|
||||
const Array& fun_arguments =
|
||||
Array::CheckedHandle(zone, arguments->NativeArgAt(0));
|
||||
const Array& fun_arg_names =
|
||||
Array::CheckedHandle(zone, arguments->NativeArgAt(1));
|
||||
const Array& fun_args_desc = Array::Handle(
|
||||
ArgumentsDescriptor::New(fun_arguments.Length(), fun_arg_names));
|
||||
const Object& result =
|
||||
Object::Handle(DartEntry::InvokeClosure(fun_arguments, fun_args_desc));
|
||||
zone, ArgumentsDescriptor::New(kTypeArgsLen, fun_arguments.Length(),
|
||||
fun_arg_names));
|
||||
const Object& result = Object::Handle(
|
||||
zone, DartEntry::InvokeClosure(fun_arguments, fun_args_desc));
|
||||
if (result.IsError()) {
|
||||
Exceptions::PropagateError(Error::Cast(result));
|
||||
}
|
||||
|
@ -34,26 +38,27 @@ DEFINE_NATIVE_ENTRY(Closure_equals, 2) {
|
|||
ASSERT(!other.IsNull());
|
||||
if (receiver.raw() == other.raw()) return Bool::True().raw();
|
||||
if (other.IsClosure()) {
|
||||
const Function& func_a = Function::Handle(receiver.function());
|
||||
const Function& func_b = Function::Handle(Closure::Cast(other).function());
|
||||
const Function& func_a = Function::Handle(zone, receiver.function());
|
||||
const Function& func_b =
|
||||
Function::Handle(zone, Closure::Cast(other).function());
|
||||
if (func_a.raw() == func_b.raw()) {
|
||||
ASSERT(!func_a.IsImplicitStaticClosureFunction());
|
||||
if (func_a.IsImplicitInstanceClosureFunction()) {
|
||||
const Context& context_a = Context::Handle(receiver.context());
|
||||
const Context& context_a = Context::Handle(zone, receiver.context());
|
||||
const Context& context_b =
|
||||
Context::Handle(Closure::Cast(other).context());
|
||||
const Object& receiver_a = Object::Handle(context_a.At(0));
|
||||
const Object& receiver_b = Object::Handle(context_b.At(0));
|
||||
Context::Handle(zone, Closure::Cast(other).context());
|
||||
const Object& receiver_a = Object::Handle(zone, context_a.At(0));
|
||||
const Object& receiver_b = Object::Handle(zone, context_b.At(0));
|
||||
if (receiver_a.raw() == receiver_b.raw()) return Bool::True().raw();
|
||||
}
|
||||
} else if (func_a.IsImplicitInstanceClosureFunction() &&
|
||||
func_b.IsImplicitInstanceClosureFunction()) {
|
||||
// TODO(rmacnak): Patch existing tears off during reload instead.
|
||||
const Context& context_a = Context::Handle(receiver.context());
|
||||
const Context& context_a = Context::Handle(zone, receiver.context());
|
||||
const Context& context_b =
|
||||
Context::Handle(Closure::Cast(other).context());
|
||||
const Object& receiver_a = Object::Handle(context_a.At(0));
|
||||
const Object& receiver_b = Object::Handle(context_b.At(0));
|
||||
Context::Handle(zone, Closure::Cast(other).context());
|
||||
const Object& receiver_a = Object::Handle(zone, context_a.At(0));
|
||||
const Object& receiver_b = Object::Handle(zone, context_b.At(0));
|
||||
if ((receiver_a.raw() == receiver_b.raw()) &&
|
||||
(func_a.name() == func_b.name()) &&
|
||||
(func_a.Owner() == func_b.Owner())) {
|
||||
|
@ -68,7 +73,7 @@ DEFINE_NATIVE_ENTRY(Closure_equals, 2) {
|
|||
DEFINE_NATIVE_ENTRY(Closure_hashCode, 1) {
|
||||
const Closure& receiver =
|
||||
Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
|
||||
const Function& func = Function::Handle(receiver.function());
|
||||
const Function& func = Function::Handle(zone, receiver.function());
|
||||
return func.GetClosureHashCode();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,12 @@ class _InvocationMirror implements Invocation {
|
|||
static const int _CALL_BITS = 3;
|
||||
static const int _CALL_MASK = (1 << _CALL_BITS) - 1;
|
||||
|
||||
// ArgumentsDescriptor layout. Keep in sync with enum in dart_entry.h.
|
||||
static const int _TYPE_ARGS_LEN = 0;
|
||||
static const int _COUNT = 1;
|
||||
static const int _POSITIONAL_COUNT = 2;
|
||||
static const int _FIRST_NAMED_ENTRY = 3;
|
||||
|
||||
// Internal representation of the invocation mirror.
|
||||
final String _functionName;
|
||||
final List _argumentsDescriptor;
|
||||
|
@ -60,7 +66,7 @@ class _InvocationMirror implements Invocation {
|
|||
|
||||
List get positionalArguments {
|
||||
if (_positionalArguments == null) {
|
||||
int numPositionalArguments = _argumentsDescriptor[1];
|
||||
int numPositionalArguments = _argumentsDescriptor[_POSITIONAL_COUNT];
|
||||
// Don't count receiver.
|
||||
if (numPositionalArguments == 1) {
|
||||
return _positionalArguments = const [];
|
||||
|
@ -74,16 +80,17 @@ class _InvocationMirror implements Invocation {
|
|||
|
||||
Map<Symbol, dynamic> get namedArguments {
|
||||
if (_namedArguments == null) {
|
||||
int numArguments = _argumentsDescriptor[0] - 1; // Exclude receiver.
|
||||
int numPositionalArguments = _argumentsDescriptor[1] - 1;
|
||||
int numArguments = _argumentsDescriptor[_COUNT] - 1; // Exclude receiver.
|
||||
int numPositionalArguments = _argumentsDescriptor[_POSITIONAL_COUNT] - 1;
|
||||
int numNamedArguments = numArguments - numPositionalArguments;
|
||||
if (numNamedArguments == 0) {
|
||||
return _namedArguments = const {};
|
||||
}
|
||||
_namedArguments = new Map<Symbol, dynamic>();
|
||||
for (int i = 0; i < numNamedArguments; i++) {
|
||||
String arg_name = _argumentsDescriptor[2 + 2 * i];
|
||||
var arg_value = _arguments[_argumentsDescriptor[3 + 2 * i]];
|
||||
int namedEntryIndex = _FIRST_NAMED_ENTRY + 2 * i;
|
||||
String arg_name = _argumentsDescriptor[namedEntryIndex];
|
||||
var arg_value = _arguments[_argumentsDescriptor[namedEntryIndex + 1]];
|
||||
_namedArguments[new internal.Symbol.unvalidated(arg_name)] = arg_value;
|
||||
}
|
||||
_namedArguments = new Map.unmodifiable(_namedArguments);
|
||||
|
|
|
@ -1343,8 +1343,10 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 5) {
|
|||
Function& function = Function::Handle(
|
||||
zone, Resolver::ResolveDynamicAnyArgs(zone, klass, function_name));
|
||||
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(zone, ArgumentsDescriptor::New(args.Length(), arg_names));
|
||||
// TODO(regis): Support invocation of generic functions with type arguments.
|
||||
const int kTypeArgsLen = 0;
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
|
||||
|
||||
if (function.IsNull()) {
|
||||
// Didn't find a method: try to find a getter and invoke call on its result.
|
||||
|
@ -1357,8 +1359,8 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 5) {
|
|||
const int kNumArgs = 1;
|
||||
const Array& getter_args = Array::Handle(zone, Array::New(kNumArgs));
|
||||
getter_args.SetAt(0, reflectee);
|
||||
const Array& getter_args_descriptor =
|
||||
Array::Handle(zone, ArgumentsDescriptor::New(getter_args.Length()));
|
||||
const Array& getter_args_descriptor = Array::Handle(
|
||||
zone, ArgumentsDescriptor::New(kTypeArgsLen, getter_args.Length()));
|
||||
const Instance& getter_result = Instance::Handle(
|
||||
zone, InvokeDynamicFunction(reflectee, function, getter_name,
|
||||
getter_args, getter_args_descriptor));
|
||||
|
@ -1404,11 +1406,12 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invokeGetter, 3) {
|
|||
}
|
||||
}
|
||||
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArgs = 1;
|
||||
const Array& args = Array::Handle(zone, Array::New(kNumArgs));
|
||||
args.SetAt(0, reflectee);
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(zone, ArgumentsDescriptor::New(args.Length()));
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length()));
|
||||
|
||||
// InvokeDynamic invokes NoSuchMethod if the provided function is null.
|
||||
return InvokeDynamicFunction(reflectee, function, internal_getter_name, args,
|
||||
|
@ -1430,12 +1433,13 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invokeSetter, 4) {
|
|||
const Function& setter = Function::Handle(
|
||||
zone, Resolver::ResolveDynamicAnyArgs(zone, klass, internal_setter_name));
|
||||
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArgs = 2;
|
||||
const Array& args = Array::Handle(zone, Array::New(kNumArgs));
|
||||
args.SetAt(0, reflectee);
|
||||
args.SetAt(1, value);
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(zone, ArgumentsDescriptor::New(args.Length()));
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length()));
|
||||
|
||||
return InvokeDynamicFunction(reflectee, setter, internal_setter_name, args,
|
||||
args_descriptor);
|
||||
|
@ -1497,6 +1501,8 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 5) {
|
|||
GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
|
||||
|
||||
// TODO(regis): Support invocation of generic functions with type arguments.
|
||||
const int kTypeArgsLen = 0;
|
||||
const Error& error = Error::Handle(zone, klass.EnsureIsFinalized(thread));
|
||||
if (!error.IsNull()) {
|
||||
Exceptions::PropagateError(error);
|
||||
|
@ -1520,16 +1526,17 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 5) {
|
|||
UNREACHABLE();
|
||||
}
|
||||
// Make room for the closure (receiver) in the argument list.
|
||||
intptr_t numArgs = args.Length();
|
||||
const Array& call_args = Array::Handle(Array::New(numArgs + 1));
|
||||
const intptr_t num_args = args.Length();
|
||||
const Array& call_args = Array::Handle(Array::New(num_args + 1));
|
||||
Object& temp = Object::Handle();
|
||||
for (int i = 0; i < numArgs; i++) {
|
||||
for (int i = 0; i < num_args; i++) {
|
||||
temp = args.At(i);
|
||||
call_args.SetAt(i + 1, temp);
|
||||
}
|
||||
call_args.SetAt(0, getter_result);
|
||||
const Array& call_args_descriptor_array = Array::Handle(
|
||||
ArgumentsDescriptor::New(call_args.Length(), arg_names));
|
||||
const Array& call_args_descriptor_array =
|
||||
Array::Handle(ArgumentsDescriptor::New(
|
||||
kTypeArgsLen, call_args.Length(), arg_names));
|
||||
// Call the closure.
|
||||
const Object& call_result = Object::Handle(
|
||||
DartEntry::InvokeClosure(call_args, call_args_descriptor_array));
|
||||
|
@ -1541,8 +1548,8 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 5) {
|
|||
}
|
||||
}
|
||||
|
||||
const Array& args_descriptor_array =
|
||||
Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
|
||||
const Array& args_descriptor_array = Array::Handle(
|
||||
ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
|
||||
|
||||
ArgumentsDescriptor args_descriptor(args_descriptor_array);
|
||||
|
||||
|
@ -1743,8 +1750,9 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 5) {
|
|||
args.SetAt(i + num_implicit_args, explicit_argument);
|
||||
}
|
||||
|
||||
const Array& args_descriptor_array =
|
||||
Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
|
||||
const int kTypeArgsLen = 0;
|
||||
const Array& args_descriptor_array = Array::Handle(
|
||||
ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
|
||||
|
||||
ArgumentsDescriptor args_descriptor(args_descriptor_array);
|
||||
if (!redirected_constructor.AreValidArguments(args_descriptor, NULL)) {
|
||||
|
@ -1804,6 +1812,8 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 5) {
|
|||
GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
|
||||
|
||||
// TODO(regis): Support invocation of generic functions with type arguments.
|
||||
const int kTypeArgsLen = 0;
|
||||
Function& function =
|
||||
Function::Handle(library.LookupLocalFunction(function_name));
|
||||
|
||||
|
@ -1821,8 +1831,9 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 5) {
|
|||
call_args.SetAt(i + 1, temp);
|
||||
}
|
||||
call_args.SetAt(0, getter_result);
|
||||
const Array& call_args_descriptor_array = Array::Handle(
|
||||
ArgumentsDescriptor::New(call_args.Length(), arg_names));
|
||||
const Array& call_args_descriptor_array =
|
||||
Array::Handle(ArgumentsDescriptor::New(
|
||||
kTypeArgsLen, call_args.Length(), arg_names));
|
||||
// Call closure.
|
||||
const Object& call_result = Object::Handle(
|
||||
DartEntry::InvokeClosure(call_args, call_args_descriptor_array));
|
||||
|
@ -1834,8 +1845,8 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 5) {
|
|||
}
|
||||
}
|
||||
|
||||
const Array& args_descriptor_array =
|
||||
Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
|
||||
const Array& args_descriptor_array = Array::Handle(
|
||||
ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
|
||||
ArgumentsDescriptor args_descriptor(args_descriptor_array);
|
||||
|
||||
if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
|
||||
|
|
|
@ -113,22 +113,18 @@ bool AotOptimizer::RecognizeRuntimeTypeGetter(InstanceCallInstr* call) {
|
|||
// There is only a single function Object.get:runtimeType that can be invoked
|
||||
// by this call. Convert dynamic invocation to a static one.
|
||||
const Class& cls = Class::Handle(Z, I->object_store()->object_class());
|
||||
const Array& args_desc_array = Array::Handle(
|
||||
Z,
|
||||
ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names()));
|
||||
ArgumentsDescriptor args_desc(args_desc_array);
|
||||
const Function& function =
|
||||
Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass(
|
||||
cls, call->function_name(), args_desc));
|
||||
Function::Handle(Z, call->ResolveForReceiverClass(cls));
|
||||
ASSERT(!function.IsNull());
|
||||
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
ASSERT(call->type_args_len() == kTypeArgsLen);
|
||||
ZoneGrowableArray<PushArgumentInstr*>* args =
|
||||
new (Z) ZoneGrowableArray<PushArgumentInstr*>(call->ArgumentCount());
|
||||
for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
|
||||
args->Add(call->PushArgumentAt(i));
|
||||
}
|
||||
StaticCallInstr* static_call = new (Z) StaticCallInstr(
|
||||
call->token_pos(), Function::ZoneHandle(Z, function.raw()),
|
||||
call->token_pos(), Function::ZoneHandle(Z, function.raw()), kTypeArgsLen,
|
||||
call->argument_names(), args, call->deopt_id());
|
||||
static_call->set_result_cid(kTypeCid);
|
||||
call->ReplaceWith(static_call, current_iterator());
|
||||
|
@ -178,9 +174,12 @@ bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
|||
return false;
|
||||
}
|
||||
GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
|
||||
ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount());
|
||||
const intptr_t receiver_idx = call->FirstParamIndex();
|
||||
ASSERT(call->ic_data()->NumArgsTested() <=
|
||||
call->ArgumentCountWithoutTypeArgs());
|
||||
for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
|
||||
class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid());
|
||||
class_ids.Add(
|
||||
call->PushArgumentAt(receiver_idx + i)->value()->Type()->ToCid());
|
||||
}
|
||||
|
||||
const Token::Kind op_kind = call->token_kind();
|
||||
|
@ -222,13 +221,8 @@ bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
|||
// finalized yet.
|
||||
return false;
|
||||
}
|
||||
const Array& args_desc_array =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(call->ArgumentCount(),
|
||||
call->argument_names()));
|
||||
ArgumentsDescriptor args_desc(args_desc_array);
|
||||
const Function& function = Function::Handle(
|
||||
Z, Resolver::ResolveDynamicForReceiverClass(
|
||||
receiver_class, call->function_name(), args_desc));
|
||||
const Function& function =
|
||||
Function::Handle(Z, call->ResolveForReceiverClass(receiver_class));
|
||||
if (function.IsNull()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -253,11 +247,18 @@ bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
|||
// Check if the target is unique.
|
||||
Function& target_function = Function::Handle(Z);
|
||||
GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function);
|
||||
// Calls with named arguments must be resolved/checked at runtime.
|
||||
// Calls passing named arguments and calls to a function taking named
|
||||
// arguments must be resolved/checked at runtime.
|
||||
// Calls passing a type argument vector and calls to a generic function must
|
||||
// be resolved/checked at runtime.
|
||||
if (!target_function.IsNull() &&
|
||||
!target_function.HasOptionalNamedParameters() &&
|
||||
target_function.AreValidArgumentCounts(call->ArgumentCount(), 0,
|
||||
/* error_message = */ NULL)) {
|
||||
!target_function.IsGeneric() &&
|
||||
target_function.AreValidArgumentCounts(
|
||||
call->type_args_len(), call->ArgumentCountWithoutTypeArgs(),
|
||||
call->argument_names().IsNull() ? 0
|
||||
: call->argument_names().Length(),
|
||||
/* error_message = */ NULL)) {
|
||||
const Class& cls = Class::Handle(Z, target_function.Owner());
|
||||
if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) {
|
||||
const ICData& ic_data =
|
||||
|
@ -613,6 +614,7 @@ bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) {
|
|||
const ICData& ic_data = *call->ic_data();
|
||||
ASSERT(ic_data.NumArgsTested() == 2);
|
||||
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
ASSERT(call->ArgumentCount() == 2);
|
||||
Definition* left = call->ArgumentAt(0);
|
||||
Definition* right = call->ArgumentAt(1);
|
||||
|
@ -634,10 +636,12 @@ bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) {
|
|||
arg = new (Z) PushArgumentInstr(new (Z) Value(right->ArgumentAt(0)));
|
||||
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
|
||||
args->Add(arg);
|
||||
StaticCallInstr* static_call =
|
||||
new (Z) StaticCallInstr(call->token_pos(), have_same_runtime_type,
|
||||
Object::null_array(), // argument_names
|
||||
args, call->deopt_id());
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
ASSERT(call->type_args_len() == kTypeArgsLen);
|
||||
StaticCallInstr* static_call = new (Z)
|
||||
StaticCallInstr(call->token_pos(), have_same_runtime_type, kTypeArgsLen,
|
||||
Object::null_array(), // argument_names
|
||||
args, call->deopt_id());
|
||||
static_call->set_result_cid(kBoolCid);
|
||||
ReplaceCall(call, static_call);
|
||||
return true;
|
||||
|
@ -652,6 +656,7 @@ bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
|
|||
const ICData& ic_data = *call->ic_data();
|
||||
ASSERT(ic_data.NumArgsTested() == 2);
|
||||
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
ASSERT(call->ArgumentCount() == 2);
|
||||
Definition* const left = call->ArgumentAt(0);
|
||||
Definition* const right = call->ArgumentAt(1);
|
||||
|
@ -734,6 +739,7 @@ bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
|
|||
const ICData& ic_data = *call->ic_data();
|
||||
ASSERT(ic_data.NumArgsTested() == 2);
|
||||
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
ASSERT(call->ArgumentCount() == 2);
|
||||
Definition* left = call->ArgumentAt(0);
|
||||
Definition* right = call->ArgumentAt(1);
|
||||
|
@ -883,6 +889,7 @@ bool AotOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
ASSERT(call->ArgumentCount() == 2);
|
||||
Definition* left = call->ArgumentAt(0);
|
||||
Definition* right = call->ArgumentAt(1);
|
||||
|
@ -971,6 +978,7 @@ bool AotOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
|||
|
||||
bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
|
||||
Token::Kind op_kind) {
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
ASSERT(call->ArgumentCount() == 1);
|
||||
Definition* input = call->ArgumentAt(0);
|
||||
Definition* unary_op = NULL;
|
||||
|
@ -1057,6 +1065,7 @@ bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
|
|||
if (!ShouldInlineSimd()) {
|
||||
return false;
|
||||
}
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
ASSERT(call->ArgumentCount() == 2);
|
||||
Definition* const left = call->ArgumentAt(0);
|
||||
Definition* const right = call->ArgumentAt(1);
|
||||
|
@ -1077,6 +1086,7 @@ bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
|
|||
if (!ShouldInlineSimd()) {
|
||||
return false;
|
||||
}
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
ASSERT(call->ArgumentCount() == 2);
|
||||
Definition* const left = call->ArgumentAt(0);
|
||||
Definition* const right = call->ArgumentAt(1);
|
||||
|
@ -1096,6 +1106,7 @@ bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
|
|||
if (!ShouldInlineSimd()) {
|
||||
return false;
|
||||
}
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
ASSERT(call->ArgumentCount() == 2);
|
||||
Definition* const left = call->ArgumentAt(0);
|
||||
Definition* const right = call->ArgumentAt(1);
|
||||
|
@ -1138,6 +1149,7 @@ bool AotOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
|
|||
void AotOptimizer::ReplaceWithMathCFunction(
|
||||
InstanceCallInstr* call,
|
||||
MethodRecognizer::Kind recognized_kind) {
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
AddReceiverCheck(call);
|
||||
ZoneGrowableArray<Value*>* args =
|
||||
new (Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
|
||||
|
@ -1418,6 +1430,7 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
|
|||
Definition* instantiator_type_args = NULL;
|
||||
Definition* function_type_args = NULL;
|
||||
AbstractType& type = AbstractType::ZoneHandle(Z);
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
if (call->ArgumentCount() == 2) {
|
||||
instantiator_type_args = flow_graph()->constant_null();
|
||||
function_type_args = flow_graph()->constant_null();
|
||||
|
@ -1481,8 +1494,9 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
|
|||
ASSERT(!target.IsNull());
|
||||
ASSERT(target.IsRecognized() && target.always_inline());
|
||||
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
StaticCallInstr* new_call =
|
||||
new (Z) StaticCallInstr(call->token_pos(), target,
|
||||
new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
|
||||
Object::null_array(), // argument_names
|
||||
args, call->deopt_id());
|
||||
Environment* copy = call->env()->DeepCopy(
|
||||
|
@ -1530,6 +1544,7 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
|
|||
// TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids).
|
||||
void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
|
||||
ASSERT(Token::IsTypeCastOperator(call->token_kind()));
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
Definition* left = call->ArgumentAt(0);
|
||||
Definition* instantiator_type_args = call->ArgumentAt(1);
|
||||
Definition* function_type_args = call->ArgumentAt(2);
|
||||
|
@ -1573,8 +1588,9 @@ void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
|
|||
ASSERT(target.IsRecognized());
|
||||
ASSERT(target.always_inline());
|
||||
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
StaticCallInstr* new_call =
|
||||
new (Z) StaticCallInstr(call->token_pos(), target,
|
||||
new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
|
||||
Object::null_array(), // argument_names
|
||||
args, call->deopt_id());
|
||||
Environment* copy =
|
||||
|
@ -1636,8 +1652,9 @@ void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
|
|||
ASSERT(target.IsRecognized());
|
||||
ASSERT(target.always_inline());
|
||||
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
StaticCallInstr* new_call =
|
||||
new (Z) StaticCallInstr(call->token_pos(), target,
|
||||
new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
|
||||
Object::null_array(), // argument_names
|
||||
args, call->deopt_id());
|
||||
Environment* copy = call->env()->DeepCopy(
|
||||
|
@ -1697,6 +1714,7 @@ bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) {
|
|||
|
||||
|
||||
static bool HasLikelySmiOperand(InstanceCallInstr* instr) {
|
||||
ASSERT(instr->type_args_len() == 0);
|
||||
// Phis with at least one known smi are // guessed to be likely smi as well.
|
||||
for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) {
|
||||
PhiInstr* phi = instr->ArgumentAt(i)->AsPhi();
|
||||
|
@ -1868,14 +1886,8 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
|
|||
if (receiver_cid != kDynamicCid) {
|
||||
const Class& receiver_class =
|
||||
Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
|
||||
|
||||
const Array& args_desc_array =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(),
|
||||
instr->argument_names()));
|
||||
ArgumentsDescriptor args_desc(args_desc_array);
|
||||
Function& function = Function::Handle(
|
||||
Z, Resolver::ResolveDynamicForReceiverClass(
|
||||
receiver_class, instr->function_name(), args_desc));
|
||||
const Function& function =
|
||||
Function::Handle(Z, instr->ResolveForReceiverClass(receiver_class));
|
||||
if (!function.IsNull()) {
|
||||
CallTargets* targets = new (Z) CallTargets(Z);
|
||||
Function& target = Function::ZoneHandle(Z, function.raw());
|
||||
|
@ -1919,20 +1931,14 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
|
|||
// targets with appropriate checks.
|
||||
Function& single_target = Function::Handle(Z);
|
||||
ICData& ic_data = ICData::Handle(Z);
|
||||
|
||||
const Array& args_desc_array =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(),
|
||||
instr->argument_names()));
|
||||
ArgumentsDescriptor args_desc(args_desc_array);
|
||||
|
||||
Array::Handle(Z, instr->GetArgumentsDescriptor());
|
||||
Function& target = Function::Handle(Z);
|
||||
Class& cls = Class::Handle(Z);
|
||||
for (intptr_t i = 0; i < class_ids.length(); i++) {
|
||||
const intptr_t cid = class_ids[i];
|
||||
cls = isolate()->class_table()->At(cid);
|
||||
target = Resolver::ResolveDynamicForReceiverClass(
|
||||
cls, instr->function_name(), args_desc);
|
||||
|
||||
target = instr->ResolveForReceiverClass(cls);
|
||||
if (target.IsNull()) {
|
||||
// Can't resolve the target. It might be a noSuchMethod,
|
||||
// call through getter or closurization.
|
||||
|
@ -2000,7 +2006,8 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
|
|||
}
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()),
|
||||
instr->argument_names(), args, instr->deopt_id());
|
||||
instr->type_args_len(), instr->argument_names(), args,
|
||||
instr->deopt_id());
|
||||
instr->ReplaceWith(call, current_iterator());
|
||||
return;
|
||||
} else if ((ic_data.raw() != ICData::null()) &&
|
||||
|
@ -2041,15 +2048,8 @@ void AotOptimizer::VisitPolymorphicInstanceCall(
|
|||
if (receiver_cid != kDynamicCid) {
|
||||
const Class& receiver_class =
|
||||
Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
|
||||
|
||||
const Array& args_desc_array = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(call->ArgumentCount(),
|
||||
call->instance_call()->argument_names()));
|
||||
ArgumentsDescriptor args_desc(args_desc_array);
|
||||
const Function& function = Function::Handle(
|
||||
Z, Resolver::ResolveDynamicForReceiverClass(
|
||||
receiver_class, call->instance_call()->function_name(),
|
||||
args_desc));
|
||||
Z, call->instance_call()->ResolveForReceiverClass(receiver_class));
|
||||
if (!function.IsNull()) {
|
||||
call->set_with_checks(false);
|
||||
}
|
||||
|
|
|
@ -14,9 +14,11 @@ namespace dart {
|
|||
static RawObject* ExecuteTest(const Code& code) {
|
||||
Thread* thread = Thread::Current();
|
||||
TransitionToGenerated transition(thread);
|
||||
return Simulator::Current()->Call(code,
|
||||
Array::Handle(ArgumentsDescriptor::New(0)),
|
||||
Array::Handle(Array::New(0)), thread);
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 0;
|
||||
return Simulator::Current()->Call(
|
||||
code, Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)),
|
||||
Array::Handle(Array::New(0)), thread);
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,8 +81,10 @@ static void MakeDummyInstanceCall(Assembler* assembler, const Object& result) {
|
|||
dummy_instance_function.AttachCode(code);
|
||||
|
||||
// Make a dummy ICData.
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 2;
|
||||
const Array& dummy_arguments_descriptor =
|
||||
Array::Handle(ArgumentsDescriptor::New(2));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs));
|
||||
const ICData& ic_data = ICData::Handle(ICData::New(
|
||||
dummy_instance_function, String::Handle(dummy_instance_function.name()),
|
||||
dummy_arguments_descriptor, Thread::kNoDeoptId, 2,
|
||||
|
|
|
@ -285,12 +285,45 @@ class CloneContextNode : public AstNode {
|
|||
class ArgumentListNode : public AstNode {
|
||||
public:
|
||||
explicit ArgumentListNode(TokenPosition token_pos)
|
||||
: AstNode(token_pos), nodes_(4), names_(Array::ZoneHandle()) {}
|
||||
: AstNode(token_pos),
|
||||
type_args_var_(NULL),
|
||||
type_arguments_(TypeArguments::ZoneHandle()),
|
||||
type_args_len_(0),
|
||||
nodes_(4),
|
||||
names_(Array::ZoneHandle()) {}
|
||||
|
||||
ArgumentListNode(TokenPosition token_pos, const TypeArguments& type_arguments)
|
||||
: AstNode(token_pos),
|
||||
type_args_var_(NULL),
|
||||
type_arguments_(type_arguments),
|
||||
type_args_len_(type_arguments.Length()),
|
||||
nodes_(4),
|
||||
names_(Array::ZoneHandle()) {
|
||||
ASSERT(type_arguments_.IsZoneHandle());
|
||||
}
|
||||
|
||||
ArgumentListNode(TokenPosition token_pos,
|
||||
LocalVariable* type_args_var,
|
||||
intptr_t type_args_len)
|
||||
: AstNode(token_pos),
|
||||
type_args_var_(type_args_var),
|
||||
type_arguments_(TypeArguments::ZoneHandle()),
|
||||
type_args_len_(type_args_len),
|
||||
nodes_(4),
|
||||
names_(Array::ZoneHandle()) {
|
||||
ASSERT((type_args_var_ == NULL) == (type_args_len_ == 0));
|
||||
}
|
||||
|
||||
void VisitChildren(AstNodeVisitor* visitor) const;
|
||||
|
||||
LocalVariable* type_args_var() const { return type_args_var_; }
|
||||
const TypeArguments& type_arguments() const { return type_arguments_; }
|
||||
intptr_t type_args_len() const { return type_args_len_; }
|
||||
void Add(AstNode* node) { nodes_.Add(node); }
|
||||
intptr_t length() const { return nodes_.length(); }
|
||||
intptr_t LengthWithTypeArgs() const {
|
||||
return length() + (type_args_len() > 0 ? 1 : 0);
|
||||
}
|
||||
AstNode* NodeAt(intptr_t index) const { return nodes_[index]; }
|
||||
void SetNodeAt(intptr_t index, AstNode* node) { nodes_[index] = node; }
|
||||
const Array& names() const { return names_; }
|
||||
|
@ -300,6 +333,10 @@ class ArgumentListNode : public AstNode {
|
|||
DECLARE_COMMON_NODE_FUNCTIONS(ArgumentListNode);
|
||||
|
||||
private:
|
||||
// At most one of type_args_var_ and type_arguments_ can be set, not both.
|
||||
LocalVariable* type_args_var_;
|
||||
const TypeArguments& type_arguments_;
|
||||
intptr_t type_args_len_;
|
||||
GrowableArray<AstNode*> nodes_;
|
||||
Array& names_;
|
||||
|
||||
|
|
|
@ -33,8 +33,10 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
|
|||
false, owner_class, TokenPosition::kNoSource));
|
||||
|
||||
const String& target_name = String::Handle(String::New("targetFunction"));
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 1;
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs, Object::null_array()));
|
||||
const ICData& ic_data = ICData::ZoneHandle(
|
||||
ICData::New(function, target_name, args_descriptor, 15, 1, false));
|
||||
|
||||
|
|
|
@ -33,8 +33,10 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
|
|||
false, owner_class, TokenPosition::kNoSource));
|
||||
|
||||
const String& target_name = String::Handle(String::New("targetFunction"));
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 1;
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs, Object::null_array()));
|
||||
const ICData& ic_data = ICData::ZoneHandle(
|
||||
ICData::New(function, target_name, args_descriptor, 15, 1, false));
|
||||
|
||||
|
|
|
@ -33,8 +33,10 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
|
|||
false, owner_class, TokenPosition::kNoSource));
|
||||
|
||||
const String& target_name = String::Handle(String::New("targetFunction"));
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 1;
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs, Object::null_array()));
|
||||
const ICData& ic_data = ICData::ZoneHandle(
|
||||
ICData::New(function, target_name, args_descriptor, 15, 1, false));
|
||||
|
||||
|
|
|
@ -33,8 +33,10 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
|
|||
false, owner_class, TokenPosition::kNoSource));
|
||||
|
||||
const String& target_name = String::Handle(String::New("targetFunction"));
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 1;
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs, Object::null_array()));
|
||||
const ICData& ic_data = ICData::ZoneHandle(
|
||||
ICData::New(function, target_name, args_descriptor, 15, 1, false));
|
||||
|
||||
|
|
|
@ -33,8 +33,10 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
|
|||
false, owner_class, TokenPosition::kNoSource));
|
||||
|
||||
const String& target_name = String::Handle(String::New("targetFunction"));
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 1;
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs, Object::null_array()));
|
||||
const ICData& ic_data = ICData::ZoneHandle(
|
||||
ICData::New(function, target_name, args_descriptor, 15, 1, false));
|
||||
|
||||
|
|
|
@ -354,9 +354,10 @@ Heap::Space SpaceForExternal(Thread* thread, intptr_t size) {
|
|||
|
||||
|
||||
static RawObject* Send0Arg(const Instance& receiver, const String& selector) {
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 1;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
|
||||
const Function& function =
|
||||
Function::Handle(Resolver::ResolveDynamic(receiver, selector, args_desc));
|
||||
if (function.IsNull()) {
|
||||
|
@ -371,9 +372,10 @@ static RawObject* Send0Arg(const Instance& receiver, const String& selector) {
|
|||
static RawObject* Send1Arg(const Instance& receiver,
|
||||
const String& selector,
|
||||
const Instance& argument) {
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 2;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
|
||||
const Function& function =
|
||||
Function::Handle(Resolver::ResolveDynamic(receiver, selector, args_desc));
|
||||
if (function.IsNull()) {
|
||||
|
@ -2725,9 +2727,10 @@ DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* len) {
|
|||
return Api::NewError("Object does not implement the List interface");
|
||||
}
|
||||
const String& name = String::Handle(Z, Field::GetterName(Symbols::Length()));
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArgs = 1;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kNumArgs)));
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
|
||||
const Function& function =
|
||||
Function::Handle(Z, Resolver::ResolveDynamic(instance, name, args_desc));
|
||||
if (function.IsNull()) {
|
||||
|
@ -2831,9 +2834,10 @@ DART_EXPORT Dart_Handle Dart_ListGetRange(Dart_Handle list,
|
|||
// Check and handle a dart object that implements the List interface.
|
||||
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
|
||||
if (!instance.IsNull()) {
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 2;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
|
||||
const Function& function = Function::Handle(
|
||||
Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
|
||||
args_desc));
|
||||
|
@ -2889,9 +2893,10 @@ DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list,
|
|||
// Check and handle a dart object that implements the List interface.
|
||||
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
|
||||
if (!instance.IsNull()) {
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 3;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
|
||||
const Function& function = Function::Handle(
|
||||
Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
|
||||
args_desc));
|
||||
|
@ -3075,9 +3080,10 @@ DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list,
|
|||
// Check and handle a dart object that implements the List interface.
|
||||
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
|
||||
if (!instance.IsNull()) {
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArgs = 2;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
|
||||
const Function& function = Function::Handle(
|
||||
Z,
|
||||
Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc));
|
||||
|
@ -3162,9 +3168,10 @@ DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list,
|
|||
// Check and handle a dart object that implements the List interface.
|
||||
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
|
||||
if (!instance.IsNull()) {
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArgs = 3;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
|
||||
const Function& function = Function::Handle(
|
||||
Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
|
||||
args_desc));
|
||||
|
@ -3792,10 +3799,11 @@ static RawObject* ResolveConstructor(const char* current_func,
|
|||
return ApiError::New(message);
|
||||
}
|
||||
}
|
||||
int extra_args = 1;
|
||||
const int kTypeArgsLen = 0;
|
||||
const int extra_args = 1;
|
||||
String& error_message = String::Handle();
|
||||
if (!constructor.AreValidArgumentCounts(num_args + extra_args, 0,
|
||||
&error_message)) {
|
||||
if (!constructor.AreValidArgumentCounts(kTypeArgsLen, num_args + extra_args,
|
||||
0, &error_message)) {
|
||||
const String& message = String::Handle(String::NewFormatted(
|
||||
"%s: wrong argument count for "
|
||||
"constructor '%s': %s.",
|
||||
|
@ -4108,10 +4116,11 @@ DART_EXPORT Dart_Handle Dart_InvokeConstructor(Dart_Handle object,
|
|||
TypeArguments::Handle(Z, type_obj.arguments());
|
||||
const Function& constructor =
|
||||
Function::Handle(Z, cls.LookupFunctionAllowPrivate(dot_name));
|
||||
const int kTypeArgsLen = 0;
|
||||
const int extra_args = 1;
|
||||
if (!constructor.IsNull() && constructor.IsGenerativeConstructor() &&
|
||||
constructor.AreValidArgumentCounts(number_of_arguments + extra_args, 0,
|
||||
NULL)) {
|
||||
constructor.AreValidArgumentCounts(
|
||||
kTypeArgsLen, number_of_arguments + extra_args, 0, NULL)) {
|
||||
// Create the argument list.
|
||||
// Constructors get the uninitialized object.
|
||||
if (!type_arguments.IsNull()) {
|
||||
|
@ -4165,6 +4174,7 @@ DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
|
|||
}
|
||||
Dart_Handle result;
|
||||
Array& args = Array::Handle(Z);
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
if (obj.IsType()) {
|
||||
if (!Type::Cast(obj).IsFinalized()) {
|
||||
return Api::NewError(
|
||||
|
@ -4173,9 +4183,10 @@ DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
|
|||
}
|
||||
|
||||
const Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
|
||||
const Function& function = Function::Handle(
|
||||
Z, Resolver::ResolveStaticAllowPrivate(
|
||||
cls, function_name, number_of_arguments, Object::empty_array()));
|
||||
const Function& function =
|
||||
Function::Handle(Z, Resolver::ResolveStaticAllowPrivate(
|
||||
cls, function_name, kTypeArgsLen,
|
||||
number_of_arguments, Object::empty_array()));
|
||||
if (function.IsNull()) {
|
||||
const String& cls_name = String::Handle(Z, cls.Name());
|
||||
return Api::NewError("%s: did not find static method '%s.%s'.",
|
||||
|
@ -4202,8 +4213,8 @@ DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
|
|||
// to check here.
|
||||
Instance& instance = Instance::Handle(Z);
|
||||
instance ^= obj.raw();
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(number_of_arguments + 1)));
|
||||
ArgumentsDescriptor args_desc(Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(kTypeArgsLen, number_of_arguments + 1)));
|
||||
const Function& function = Function::Handle(
|
||||
Z, Resolver::ResolveDynamic(instance, function_name, args_desc));
|
||||
if (function.IsNull()) {
|
||||
|
@ -4211,8 +4222,8 @@ DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
|
|||
result = SetupArguments(T, number_of_arguments, arguments, 1, &args);
|
||||
if (!::Dart_IsError(result)) {
|
||||
args.SetAt(0, instance);
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(args.Length()));
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(kTypeArgsLen, args.Length()));
|
||||
result = Api::NewHandle(
|
||||
T, DartEntry::InvokeNoSuchMethod(instance, function_name, args,
|
||||
args_descriptor));
|
||||
|
@ -4265,7 +4276,7 @@ DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
|
|||
// LookupFunctionAllowPrivate does not check argument arity, so we
|
||||
// do it here.
|
||||
String& error_message = String::Handle(Z);
|
||||
if (!function.AreValidArgumentCounts(number_of_arguments, 0,
|
||||
if (!function.AreValidArgumentCounts(kTypeArgsLen, number_of_arguments, 0,
|
||||
&error_message)) {
|
||||
return Api::NewError("%s: wrong argument count for function '%s': %s.",
|
||||
CURRENT_FUNC, function_name.ToCString(),
|
||||
|
@ -4395,12 +4406,13 @@ DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name) {
|
|||
#endif // !defined(PRODUCT)
|
||||
|
||||
// Invoke the getter and return the result.
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArgs = 1;
|
||||
const Array& args = Array::Handle(Z, Array::New(kNumArgs));
|
||||
args.SetAt(0, instance);
|
||||
if (getter.IsNull()) {
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(args.Length()));
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(kTypeArgsLen, args.Length()));
|
||||
return Api::NewHandle(
|
||||
T, DartEntry::InvokeNoSuchMethod(instance, getter_name, args,
|
||||
args_descriptor));
|
||||
|
@ -4551,13 +4563,14 @@ DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container,
|
|||
}
|
||||
|
||||
// Invoke the setter and return the result.
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArgs = 2;
|
||||
const Array& args = Array::Handle(Z, Array::New(kNumArgs));
|
||||
args.SetAt(0, instance);
|
||||
args.SetAt(1, value_instance);
|
||||
if (setter.IsNull()) {
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(args.Length()));
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(kTypeArgsLen, args.Length()));
|
||||
return Api::NewHandle(
|
||||
T, DartEntry::InvokeNoSuchMethod(instance, setter_name, args,
|
||||
args_descriptor));
|
||||
|
|
|
@ -24,8 +24,9 @@ RawArray* ArgumentsDescriptor::cached_args_descriptors_[kCachedDescriptorCount];
|
|||
RawObject* DartEntry::InvokeFunction(const Function& function,
|
||||
const Array& arguments) {
|
||||
ASSERT(Thread::Current()->IsMutatorThread());
|
||||
const int kTypeArgsLen = 0; // No support to pass type args to generic func.
|
||||
const Array& arguments_descriptor =
|
||||
Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length()));
|
||||
return InvokeFunction(function, arguments, arguments_descriptor);
|
||||
}
|
||||
|
||||
|
@ -128,8 +129,9 @@ RawObject* DartEntry::InvokeFunction(const Function& function,
|
|||
|
||||
|
||||
RawObject* DartEntry::InvokeClosure(const Array& arguments) {
|
||||
const int kTypeArgsLen = 0; // No support to pass type args to generic func.
|
||||
const Array& arguments_descriptor =
|
||||
Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length()));
|
||||
return InvokeClosure(arguments, arguments_descriptor);
|
||||
}
|
||||
|
||||
|
@ -147,7 +149,8 @@ RawObject* DartEntry::InvokeClosure(const Array& arguments,
|
|||
if (instance.IsCallable(&function)) {
|
||||
// Only invoke the function if its arguments are compatible.
|
||||
const ArgumentsDescriptor args_desc(arguments_descriptor);
|
||||
if (function.AreValidArgumentCounts(args_desc.Count(),
|
||||
if (function.AreValidArgumentCounts(args_desc.TypeArgsLen(),
|
||||
args_desc.Count(),
|
||||
args_desc.NamedCount(), NULL)) {
|
||||
// The closure or non-closure object (receiver) is passed as implicit
|
||||
// first argument. It is already included in the arguments array.
|
||||
|
@ -237,9 +240,10 @@ RawObject* DartEntry::InvokeNoSuchMethod(const Instance& receiver,
|
|||
}
|
||||
|
||||
// Now use the invocation mirror object and invoke NoSuchMethod.
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 2;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
Function& function = Function::Handle(
|
||||
Resolver::ResolveDynamic(receiver, Symbols::NoSuchMethod(), args_desc));
|
||||
if (function.IsNull()) {
|
||||
|
@ -261,6 +265,10 @@ RawObject* DartEntry::InvokeNoSuchMethod(const Instance& receiver,
|
|||
|
||||
ArgumentsDescriptor::ArgumentsDescriptor(const Array& array) : array_(array) {}
|
||||
|
||||
intptr_t ArgumentsDescriptor::TypeArgsLen() const {
|
||||
return Smi::Cast(Object::Handle(array_.At(kTypeArgsLenIndex))).Value();
|
||||
}
|
||||
|
||||
|
||||
intptr_t ArgumentsDescriptor::Count() const {
|
||||
return Smi::Cast(Object::Handle(array_.At(kCountIndex))).Value();
|
||||
|
@ -294,6 +302,11 @@ bool ArgumentsDescriptor::MatchesNameAt(intptr_t index,
|
|||
}
|
||||
|
||||
|
||||
intptr_t ArgumentsDescriptor::type_args_len_offset() {
|
||||
return Array::element_offset(kTypeArgsLenIndex);
|
||||
}
|
||||
|
||||
|
||||
intptr_t ArgumentsDescriptor::count_offset() {
|
||||
return Array::element_offset(kCountIndex);
|
||||
}
|
||||
|
@ -309,25 +322,31 @@ intptr_t ArgumentsDescriptor::first_named_entry_offset() {
|
|||
}
|
||||
|
||||
|
||||
RawArray* ArgumentsDescriptor::New(intptr_t num_arguments,
|
||||
RawArray* ArgumentsDescriptor::New(intptr_t type_args_len,
|
||||
intptr_t num_arguments,
|
||||
const Array& optional_arguments_names) {
|
||||
const intptr_t num_named_args =
|
||||
optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length();
|
||||
if (num_named_args == 0) {
|
||||
return ArgumentsDescriptor::New(num_arguments);
|
||||
return ArgumentsDescriptor::New(type_args_len, num_arguments);
|
||||
}
|
||||
ASSERT(type_args_len >= 0);
|
||||
ASSERT(num_arguments >= 0);
|
||||
const intptr_t num_pos_args = num_arguments - num_named_args;
|
||||
|
||||
// Build the arguments descriptor array, which consists of the total
|
||||
// argument count; the positional argument count; a sequence of (name,
|
||||
// position) pairs, sorted by name, for each named optional argument; and
|
||||
// a terminating null to simplify iterating in generated code.
|
||||
// Build the arguments descriptor array, which consists of the the type
|
||||
// argument vector length (0 if none); total argument count; the positional
|
||||
// argument count; a sequence of (name, position) pairs, sorted by name, for
|
||||
// each named optional argument; and a terminating null to simplify iterating
|
||||
// in generated code.
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
const intptr_t descriptor_len = LengthFor(num_named_args);
|
||||
Array& descriptor =
|
||||
Array::Handle(zone, Array::New(descriptor_len, Heap::kOld));
|
||||
|
||||
// Set length of type argument vector.
|
||||
descriptor.SetAt(kTypeArgsLenIndex, Smi::Handle(Smi::New(type_args_len)));
|
||||
// Set total number of passed arguments.
|
||||
descriptor.SetAt(kCountIndex, Smi::Handle(Smi::New(num_arguments)));
|
||||
// Set number of positional arguments.
|
||||
|
@ -368,7 +387,9 @@ RawArray* ArgumentsDescriptor::New(intptr_t num_arguments,
|
|||
}
|
||||
|
||||
|
||||
RawArray* ArgumentsDescriptor::New(intptr_t num_arguments) {
|
||||
RawArray* ArgumentsDescriptor::New(intptr_t type_args_len,
|
||||
intptr_t num_arguments) {
|
||||
ASSERT(type_args_len >= 0);
|
||||
ASSERT(num_arguments >= 0);
|
||||
if (num_arguments < kCachedDescriptorCount) {
|
||||
return cached_args_descriptors_[num_arguments];
|
||||
|
@ -379,9 +400,9 @@ RawArray* ArgumentsDescriptor::New(intptr_t num_arguments) {
|
|||
|
||||
RawArray* ArgumentsDescriptor::NewNonCached(intptr_t num_arguments,
|
||||
bool canonicalize) {
|
||||
// Build the arguments descriptor array, which consists of the total
|
||||
// argument count; the positional argument count; and
|
||||
// a terminating null to simplify iterating in generated code.
|
||||
// Build the arguments descriptor array, which consists of the zero length
|
||||
// type argument vector, total argument count; the positional argument count;
|
||||
// and a terminating null to simplify iterating in generated code.
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
const intptr_t descriptor_len = LengthFor(0);
|
||||
|
@ -389,6 +410,9 @@ RawArray* ArgumentsDescriptor::NewNonCached(intptr_t num_arguments,
|
|||
Array::Handle(zone, Array::New(descriptor_len, Heap::kOld));
|
||||
const Smi& arg_count = Smi::Handle(zone, Smi::New(num_arguments));
|
||||
|
||||
// Set zero length type argument vector.
|
||||
descriptor.SetAt(kTypeArgsLenIndex, Smi::Handle(zone, Smi::New(0)));
|
||||
|
||||
// Set total number of passed arguments.
|
||||
descriptor.SetAt(kCountIndex, arg_count);
|
||||
|
||||
|
@ -449,9 +473,10 @@ RawObject* DartLibraryCalls::InstanceCreate(const Library& lib,
|
|||
|
||||
|
||||
RawObject* DartLibraryCalls::ToString(const Instance& receiver) {
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 1; // Receiver.
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
const Function& function = Function::Handle(
|
||||
Resolver::ResolveDynamic(receiver, Symbols::toString(), args_desc));
|
||||
ASSERT(!function.IsNull());
|
||||
|
@ -465,9 +490,10 @@ RawObject* DartLibraryCalls::ToString(const Instance& receiver) {
|
|||
|
||||
|
||||
RawObject* DartLibraryCalls::HashCode(const Instance& receiver) {
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 1; // Receiver.
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
const Function& function = Function::Handle(
|
||||
Resolver::ResolveDynamic(receiver, Symbols::hashCode(), args_desc));
|
||||
ASSERT(!function.IsNull());
|
||||
|
@ -482,9 +508,10 @@ RawObject* DartLibraryCalls::HashCode(const Instance& receiver) {
|
|||
|
||||
RawObject* DartLibraryCalls::Equals(const Instance& left,
|
||||
const Instance& right) {
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 2;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
const Function& function = Function::Handle(
|
||||
Resolver::ResolveDynamic(left, Symbols::EqualOperator(), args_desc));
|
||||
ASSERT(!function.IsNull());
|
||||
|
@ -501,25 +528,28 @@ RawObject* DartLibraryCalls::Equals(const Instance& left,
|
|||
|
||||
RawObject* DartLibraryCalls::LookupHandler(Dart_Port port_id) {
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
Function& function = Function::Handle(
|
||||
thread->zone(), thread->isolate()->object_store()->lookup_port_handler());
|
||||
zone, thread->isolate()->object_store()->lookup_port_handler());
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 1;
|
||||
if (function.IsNull()) {
|
||||
Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
|
||||
Library& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
|
||||
ASSERT(!isolate_lib.IsNull());
|
||||
const String& class_name =
|
||||
String::Handle(isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
|
||||
const String& function_name =
|
||||
String::Handle(isolate_lib.PrivateName(Symbols::_lookupHandler()));
|
||||
const String& class_name = String::Handle(
|
||||
zone, isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
|
||||
const String& function_name = String::Handle(
|
||||
zone, isolate_lib.PrivateName(Symbols::_lookupHandler()));
|
||||
function = Resolver::ResolveStatic(isolate_lib, class_name, function_name,
|
||||
kNumArguments, Object::empty_array());
|
||||
kTypeArgsLen, kNumArguments,
|
||||
Object::empty_array());
|
||||
ASSERT(!function.IsNull());
|
||||
thread->isolate()->object_store()->set_lookup_port_handler(function);
|
||||
}
|
||||
const Array& args = Array::Handle(Array::New(kNumArguments));
|
||||
args.SetAt(0, Integer::Handle(Integer::New(port_id)));
|
||||
const Array& args = Array::Handle(zone, Array::New(kNumArguments));
|
||||
args.SetAt(0, Integer::Handle(zone, Integer::New(port_id)));
|
||||
const Object& result =
|
||||
Object::Handle(DartEntry::InvokeFunction(function, args));
|
||||
Object::Handle(zone, DartEntry::InvokeFunction(function, args));
|
||||
return result.raw();
|
||||
}
|
||||
|
||||
|
@ -531,6 +561,7 @@ RawObject* DartLibraryCalls::HandleMessage(const Object& handler,
|
|||
Isolate* isolate = thread->isolate();
|
||||
Function& function = Function::Handle(
|
||||
zone, isolate->object_store()->handle_message_function());
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 2;
|
||||
if (function.IsNull()) {
|
||||
Library& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
|
||||
|
@ -540,7 +571,8 @@ RawObject* DartLibraryCalls::HandleMessage(const Object& handler,
|
|||
const String& function_name = String::Handle(
|
||||
zone, isolate_lib.PrivateName(Symbols::_handleMessage()));
|
||||
function = Resolver::ResolveStatic(isolate_lib, class_name, function_name,
|
||||
kNumArguments, Object::empty_array());
|
||||
kTypeArgsLen, kNumArguments,
|
||||
Object::empty_array());
|
||||
ASSERT(!function.IsNull());
|
||||
isolate->object_store()->set_handle_message_function(function);
|
||||
}
|
||||
|
@ -577,9 +609,10 @@ RawObject* DartLibraryCalls::DrainMicrotaskQueue() {
|
|||
RawObject* DartLibraryCalls::MapSetAt(const Instance& map,
|
||||
const Instance& key,
|
||||
const Instance& value) {
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 3;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
const Function& function = Function::Handle(
|
||||
Resolver::ResolveDynamic(map, Symbols::AssignIndexToken(), args_desc));
|
||||
ASSERT(!function.IsNull());
|
||||
|
|
|
@ -24,7 +24,8 @@ class RawObject;
|
|||
class RawString;
|
||||
class String;
|
||||
|
||||
// An arguments descriptor array consists of the total argument count; the
|
||||
// An arguments descriptor array consists of the type argument vector length (0
|
||||
// if none); total argument count (not counting type argument vector); the
|
||||
// positional argument count; a sequence of (name, position) pairs, sorted
|
||||
// by name, for each named optional argument; and a terminating null to
|
||||
// simplify iterating in generated code.
|
||||
|
@ -33,6 +34,7 @@ class ArgumentsDescriptor : public ValueObject {
|
|||
explicit ArgumentsDescriptor(const Array& array);
|
||||
|
||||
// Accessors.
|
||||
intptr_t TypeArgsLen() const;
|
||||
intptr_t Count() const;
|
||||
intptr_t PositionalCount() const;
|
||||
intptr_t NamedCount() const { return Count() - PositionalCount(); }
|
||||
|
@ -41,6 +43,7 @@ class ArgumentsDescriptor : public ValueObject {
|
|||
bool MatchesNameAt(intptr_t i, const String& other) const;
|
||||
|
||||
// Generated code support.
|
||||
static intptr_t type_args_len_offset();
|
||||
static intptr_t count_offset();
|
||||
static intptr_t positional_count_offset();
|
||||
static intptr_t first_named_entry_offset();
|
||||
|
@ -49,13 +52,19 @@ class ArgumentsDescriptor : public ValueObject {
|
|||
static intptr_t named_entry_size() { return kNamedEntrySize * kWordSize; }
|
||||
|
||||
// Allocate and return an arguments descriptor. The first
|
||||
// (count - optional_arguments_names.Length()) arguments are
|
||||
// (num_arguments - optional_arguments_names.Length()) arguments are
|
||||
// positional and the remaining ones are named optional arguments.
|
||||
static RawArray* New(intptr_t count, const Array& optional_arguments_names);
|
||||
// The presence of a type argument vector as first argument (not counted in
|
||||
// num_arguments) is indicated by a non-zero type_args_len.
|
||||
static RawArray* New(intptr_t type_args_len,
|
||||
intptr_t num_arguments,
|
||||
const Array& optional_arguments_names);
|
||||
|
||||
// Allocate and return an arguments descriptor that has no optional
|
||||
// arguments. All arguments are positional.
|
||||
static RawArray* New(intptr_t count);
|
||||
// arguments. All arguments are positional. The presence of a type argument
|
||||
// vector as first argument (not counted in num_arguments) is indicated
|
||||
// by a non-zero type_args_len.
|
||||
static RawArray* New(intptr_t type_args_len, intptr_t num_arguments);
|
||||
|
||||
// Initialize the preallocated fixed length arguments descriptors cache.
|
||||
static void InitOnce();
|
||||
|
@ -64,7 +73,9 @@ class ArgumentsDescriptor : public ValueObject {
|
|||
|
||||
private:
|
||||
// Absolute indexes into the array.
|
||||
// Keep these in sync with the constants in invocation_mirror_patch.dart.
|
||||
enum {
|
||||
kTypeArgsLenIndex,
|
||||
kCountIndex,
|
||||
kPositionalCountIndex,
|
||||
kFirstNamedEntryIndex,
|
||||
|
@ -77,12 +88,13 @@ class ArgumentsDescriptor : public ValueObject {
|
|||
kNamedEntrySize,
|
||||
};
|
||||
|
||||
static intptr_t LengthFor(intptr_t count) {
|
||||
static intptr_t LengthFor(intptr_t num_named_arguments) {
|
||||
// Add 1 for the terminating null.
|
||||
return kFirstNamedEntryIndex + (kNamedEntrySize * count) + 1;
|
||||
return kFirstNamedEntryIndex + (kNamedEntrySize * num_named_arguments) + 1;
|
||||
}
|
||||
|
||||
static RawArray* NewNonCached(intptr_t count, bool canonicalize = true);
|
||||
static RawArray* NewNonCached(intptr_t num_arguments,
|
||||
bool canonicalize = true);
|
||||
|
||||
// Used by Simulator to parse argument descriptors.
|
||||
static intptr_t name_index(intptr_t index) {
|
||||
|
@ -120,7 +132,8 @@ class DartEntry : public AllStatic {
|
|||
// Invokes the specified instance function or static function.
|
||||
// The first argument of an instance function is the receiver.
|
||||
// On success, returns a RawInstance. On failure, a RawError.
|
||||
// This is used when there are no named arguments in the call.
|
||||
// This is used when there is no type argument vector and
|
||||
// no named arguments in the call.
|
||||
static RawObject* InvokeFunction(const Function& function,
|
||||
const Array& arguments);
|
||||
|
||||
|
@ -134,7 +147,8 @@ class DartEntry : public AllStatic {
|
|||
|
||||
// Invokes the closure object given as the first argument.
|
||||
// On success, returns a RawInstance. On failure, a RawError.
|
||||
// This is used when there are no named arguments in the call.
|
||||
// This is used when there is no type argument vector and
|
||||
// no named arguments in the call.
|
||||
static RawObject* InvokeClosure(const Array& arguments);
|
||||
|
||||
// Invokes the closure object given as the first argument.
|
||||
|
|
|
@ -1140,10 +1140,12 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
|
|||
Z, isolate()->object_store()->async_clear_thread_stack_trace());
|
||||
ZoneGrowableArray<PushArgumentInstr*>* no_arguments =
|
||||
new (Z) ZoneGrowableArray<PushArgumentInstr*>(0);
|
||||
StaticCallInstr* call_async_clear_thread_stack_trace = new (Z)
|
||||
StaticCallInstr(node->token_pos().ToSynthetic(),
|
||||
async_clear_thread_stack_trace, Object::null_array(),
|
||||
no_arguments, owner()->ic_data_array());
|
||||
const int kTypeArgsLen = 0;
|
||||
StaticCallInstr* call_async_clear_thread_stack_trace =
|
||||
new (Z) StaticCallInstr(node->token_pos().ToSynthetic(),
|
||||
async_clear_thread_stack_trace, kTypeArgsLen,
|
||||
Object::null_array(), no_arguments,
|
||||
owner()->ic_data_array());
|
||||
Do(call_async_clear_thread_stack_trace);
|
||||
}
|
||||
|
||||
|
@ -1175,8 +1177,9 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
|
|||
const Function& complete_on_async_return = Function::ZoneHandle(
|
||||
Z, isolate()->object_store()->complete_on_async_return());
|
||||
ASSERT(!complete_on_async_return.IsNull());
|
||||
const int kTypeArgsLen = 0;
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
node->token_pos().ToSynthetic(), complete_on_async_return,
|
||||
node->token_pos().ToSynthetic(), complete_on_async_return, kTypeArgsLen,
|
||||
Object::null_array(), arguments, owner()->ic_data_array());
|
||||
Do(call);
|
||||
|
||||
|
@ -1363,10 +1366,11 @@ void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
|
|||
arguments->Add(push_left);
|
||||
arguments->Add(push_right);
|
||||
const String& name = Symbols::Token(node->kind());
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 2;
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), name, node->kind(), arguments, Object::null_array(),
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
node->token_pos(), name, node->kind(), arguments, kTypeArgsLen,
|
||||
Object::null_array(), kNumArgsChecked, owner()->ic_data_array());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
|
||||
|
@ -1524,11 +1528,12 @@ void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
|
|||
arguments->Add(push_left);
|
||||
Value* type_const = Bind(new (Z) ConstantInstr(type));
|
||||
arguments->Add(PushArgument(type_const));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 2;
|
||||
Definition* result = new (Z) InstanceCallInstr(
|
||||
node->token_pos(),
|
||||
Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), node->kind(),
|
||||
arguments,
|
||||
arguments, kTypeArgsLen,
|
||||
Object::null_array(), // No argument names.
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
if (negate_result) {
|
||||
|
@ -1549,10 +1554,11 @@ void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
|
|||
arguments->Add(push_function_type_args);
|
||||
Value* type_const = Bind(new (Z) ConstantInstr(type));
|
||||
arguments->Add(PushArgument(type_const));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 1;
|
||||
Definition* result = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), Library::PrivateCoreLibName(Symbols::_instanceOf()),
|
||||
node->kind(), arguments,
|
||||
node->kind(), arguments, kTypeArgsLen,
|
||||
Object::null_array(), // No argument names.
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
if (negate_result) {
|
||||
|
@ -1587,10 +1593,11 @@ void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) {
|
|||
arguments->Add(push_function_type_args);
|
||||
Value* type_arg = Bind(new (Z) ConstantInstr(type));
|
||||
arguments->Add(PushArgument(type_arg));
|
||||
const int kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 1;
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), Library::PrivateCoreLibName(Symbols::_as()),
|
||||
node->kind(), arguments,
|
||||
node->kind(), arguments, kTypeArgsLen,
|
||||
Object::null_array(), // No argument names.
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
ReturnDefinition(call);
|
||||
|
@ -1664,12 +1671,13 @@ void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
|
|||
PushArgumentInstr* push_right = PushArgument(for_right_value.value());
|
||||
arguments->Add(push_right);
|
||||
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 2;
|
||||
Definition* result = new (Z)
|
||||
InstanceCallInstr(node->token_pos(), Symbols::EqualOperator(),
|
||||
Token::kEQ, // Result is negated later for kNE.
|
||||
arguments, Object::null_array(), kNumArgsChecked,
|
||||
owner()->ic_data_array());
|
||||
arguments, kTypeArgsLen, Object::null_array(),
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
if (node->kind() == Token::kNE) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
if (isolate->type_checks() || isolate->asserts()) {
|
||||
|
@ -1699,9 +1707,10 @@ void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
|
|||
arguments->Add(push_right);
|
||||
|
||||
ASSERT(Token::IsRelationalOperator(node->kind()));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
InstanceCallInstr* comp = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments,
|
||||
Object::null_array(), 2, owner()->ic_data_array());
|
||||
kTypeArgsLen, Object::null_array(), 2, owner()->ic_data_array());
|
||||
ReturnDefinition(comp);
|
||||
}
|
||||
|
||||
|
@ -1730,9 +1739,10 @@ void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) {
|
|||
ZoneGrowableArray<PushArgumentInstr*>* arguments =
|
||||
new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
|
||||
arguments->Add(push_value);
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments,
|
||||
Object::null_array(), 1, owner()->ic_data_array());
|
||||
kTypeArgsLen, Object::null_array(), 1, owner()->ic_data_array());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
|
||||
|
@ -2279,6 +2289,7 @@ void EffectGraphVisitor::VisitStringInterpolateNode(
|
|||
Append(for_argument);
|
||||
PushArgumentInstr* push_arg = PushArgument(for_argument.value());
|
||||
values->Add(push_arg);
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
const Class& cls =
|
||||
|
@ -2287,10 +2298,10 @@ void EffectGraphVisitor::VisitStringInterpolateNode(
|
|||
const Function& function = Function::ZoneHandle(
|
||||
Z, Resolver::ResolveStatic(
|
||||
cls, Library::PrivateCoreLibName(Symbols::InterpolateSingle()),
|
||||
kNumberOfArguments, kNoArgumentNames));
|
||||
StaticCallInstr* call =
|
||||
new (Z) StaticCallInstr(node->token_pos(), function, kNoArgumentNames,
|
||||
values, owner()->ic_data_array());
|
||||
kTypeArgsLen, kNumberOfArguments, kNoArgumentNames));
|
||||
StaticCallInstr* call = new (Z)
|
||||
StaticCallInstr(node->token_pos(), function, kTypeArgsLen,
|
||||
kNoArgumentNames, values, owner()->ic_data_array());
|
||||
ReturnDefinition(call);
|
||||
return;
|
||||
}
|
||||
|
@ -2421,6 +2432,27 @@ void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
|
|||
}
|
||||
|
||||
|
||||
void EffectGraphVisitor::BuildPushTypeArguments(
|
||||
const ArgumentListNode& node,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* values) {
|
||||
if (node.type_args_len() > 0) {
|
||||
Value* type_args_val;
|
||||
if (node.type_args_var() != NULL) {
|
||||
type_args_val =
|
||||
Bind(new (Z) LoadLocalInstr(*node.type_args_var(), node.token_pos()));
|
||||
} else {
|
||||
const TypeArguments& type_args = node.type_arguments();
|
||||
ASSERT(!type_args.IsNull() &&
|
||||
(type_args.Length() == node.type_args_len()));
|
||||
type_args_val =
|
||||
BuildInstantiatedTypeArguments(node.token_pos(), type_args);
|
||||
}
|
||||
PushArgumentInstr* push_type_args = PushArgument(type_args_val);
|
||||
values->Add(push_type_args);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EffectGraphVisitor::BuildPushArguments(
|
||||
const ArgumentListNode& node,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* values) {
|
||||
|
@ -2478,22 +2510,27 @@ void ValueGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
|
|||
|
||||
|
||||
void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
|
||||
ValueGraphVisitor for_receiver(owner());
|
||||
node->receiver()->Visit(&for_receiver);
|
||||
Append(for_receiver);
|
||||
if (node->is_conditional()) {
|
||||
ValueGraphVisitor for_receiver(owner());
|
||||
node->receiver()->Visit(&for_receiver);
|
||||
Append(for_receiver);
|
||||
Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos()));
|
||||
BuildInstanceCallConditional(node);
|
||||
} else {
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments =
|
||||
new (Z) ZoneGrowableArray<PushArgumentInstr*>(
|
||||
node->arguments()->LengthWithTypeArgs() + 1);
|
||||
BuildPushTypeArguments(*node->arguments(), arguments);
|
||||
ValueGraphVisitor for_receiver(owner());
|
||||
node->receiver()->Visit(&for_receiver);
|
||||
Append(for_receiver);
|
||||
PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments = new (Z)
|
||||
ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length() + 1);
|
||||
arguments->Add(push_receiver);
|
||||
|
||||
BuildPushArguments(*node->arguments(), arguments);
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), node->function_name(), Token::kILLEGAL, arguments,
|
||||
node->arguments()->names(), 1, owner()->ic_data_array());
|
||||
node->arguments()->type_args_len(), node->arguments()->names(), 1,
|
||||
owner()->ic_data_array());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
}
|
||||
|
@ -2502,12 +2539,14 @@ void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
|
|||
// <Expression> ::= StaticCall { function: Function
|
||||
// arguments: <ArgumentList> }
|
||||
void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) {
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments = new (Z)
|
||||
ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length());
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments =
|
||||
new (Z) ZoneGrowableArray<PushArgumentInstr*>(
|
||||
node->arguments()->LengthWithTypeArgs());
|
||||
BuildPushTypeArguments(*node->arguments(), arguments);
|
||||
BuildPushArguments(*node->arguments(), arguments);
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
node->token_pos(), node->function(), node->arguments()->names(),
|
||||
arguments, owner()->ic_data_array());
|
||||
node->token_pos(), node->function(), node->arguments()->type_args_len(),
|
||||
node->arguments()->names(), arguments, owner()->ic_data_array());
|
||||
if (node->function().recognized_kind() != MethodRecognizer::kUnknown) {
|
||||
call->set_result_cid(MethodRecognizer::ResultCid(node->function()));
|
||||
}
|
||||
|
@ -2517,15 +2556,17 @@ void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) {
|
|||
|
||||
void EffectGraphVisitor::BuildClosureCall(ClosureCallNode* node,
|
||||
bool result_needed) {
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments =
|
||||
new (Z) ZoneGrowableArray<PushArgumentInstr*>(
|
||||
node->arguments()->LengthWithTypeArgs() + 1);
|
||||
BuildPushTypeArguments(*node->arguments(), arguments);
|
||||
|
||||
ValueGraphVisitor for_closure(owner());
|
||||
node->closure()->Visit(&for_closure);
|
||||
Append(for_closure);
|
||||
|
||||
Value* closure_value = for_closure.value();
|
||||
LocalVariable* tmp_var = EnterTempLocalScope(closure_value);
|
||||
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments = new (Z)
|
||||
ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length());
|
||||
Value* closure_val =
|
||||
Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos()));
|
||||
PushArgumentInstr* push_closure = PushArgument(closure_val);
|
||||
|
@ -2603,9 +2644,10 @@ void EffectGraphVisitor::BuildConstructorCall(
|
|||
arguments->Add(push_alloc_value);
|
||||
|
||||
BuildPushArguments(*node->arguments(), arguments);
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
Do(new (Z) StaticCallInstr(node->token_pos(), node->constructor(),
|
||||
node->arguments()->names(), arguments,
|
||||
owner()->ic_data_array()));
|
||||
kTypeArgsLen, node->arguments()->names(),
|
||||
arguments, owner()->ic_data_array()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2643,9 +2685,10 @@ void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) {
|
|||
arguments->Add(push_type_arguments);
|
||||
ASSERT(arguments->length() == 1);
|
||||
BuildPushArguments(*node->arguments(), arguments);
|
||||
const int kTypeArgsLen = 0;
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
node->token_pos(), node->constructor(), node->arguments()->names(),
|
||||
arguments, owner()->ic_data_array());
|
||||
node->token_pos(), node->constructor(), kTypeArgsLen,
|
||||
node->arguments()->names(), arguments, owner()->ic_data_array());
|
||||
const intptr_t result_cid = GetResultCidOfListFactory(node);
|
||||
if (result_cid != kDynamicCid) {
|
||||
call->set_result_cid(result_cid);
|
||||
|
@ -2875,9 +2918,10 @@ void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) {
|
|||
arguments->Add(push_receiver);
|
||||
const String& name =
|
||||
String::ZoneHandle(Z, Field::GetterSymbol(node->field_name()));
|
||||
InstanceCallInstr* call = new (Z)
|
||||
InstanceCallInstr(node->token_pos(), name, Token::kGET, arguments,
|
||||
Object::null_array(), 1, owner()->ic_data_array());
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), name, Token::kGET, arguments, kTypeArgsLen,
|
||||
Object::null_array(), 1, owner()->ic_data_array());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
}
|
||||
|
@ -2937,10 +2981,11 @@ void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
|
|||
BuildInstanceSetterArguments(node, arguments, kResultNotNeeded);
|
||||
const String& name =
|
||||
String::ZoneHandle(Z, Field::SetterSymbol(node->field_name()));
|
||||
const int kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 1; // Do not check value type.
|
||||
InstanceCallInstr* call = new (Z) InstanceCallInstr(
|
||||
token_pos, name, Token::kSET, arguments, Object::null_array(),
|
||||
kNumArgsChecked, owner()->ic_data_array());
|
||||
token_pos, name, Token::kSET, arguments, kTypeArgsLen,
|
||||
Object::null_array(), kNumArgsChecked, owner()->ic_data_array());
|
||||
ReturnDefinition(call);
|
||||
}
|
||||
|
||||
|
@ -2981,10 +3026,11 @@ void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
|
|||
BuildInstanceSetterArguments(node, arguments, kResultNeeded);
|
||||
const String& name =
|
||||
String::ZoneHandle(Z, Field::SetterSymbol(node->field_name()));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgsChecked = 1; // Do not check value type.
|
||||
Do(new (Z) InstanceCallInstr(token_pos, name, Token::kSET, arguments,
|
||||
Object::null_array(), kNumArgsChecked,
|
||||
owner()->ic_data_array()));
|
||||
kTypeArgsLen, Object::null_array(),
|
||||
kNumArgsChecked, owner()->ic_data_array()));
|
||||
ReturnDefinition(BuildLoadExprTemp(token_pos));
|
||||
}
|
||||
|
||||
|
@ -3046,8 +3092,9 @@ void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) {
|
|||
}
|
||||
}
|
||||
ASSERT(!getter_function.IsNull());
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
StaticCallInstr* call =
|
||||
new (Z) StaticCallInstr(node->token_pos(), getter_function,
|
||||
new (Z) StaticCallInstr(node->token_pos(), getter_function, kTypeArgsLen,
|
||||
Object::null_array(), // No names
|
||||
arguments, owner()->ic_data_array());
|
||||
ReturnDefinition(call);
|
||||
|
@ -3108,8 +3155,8 @@ void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node,
|
|||
value = for_value.value();
|
||||
}
|
||||
arguments->Add(PushArgument(value));
|
||||
|
||||
call = new (Z) StaticCallInstr(token_pos, setter_function,
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
call = new (Z) StaticCallInstr(token_pos, setter_function, kTypeArgsLen,
|
||||
Object::null_array(), // No names.
|
||||
arguments, owner()->ic_data_array());
|
||||
}
|
||||
|
@ -3555,18 +3602,20 @@ void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) {
|
|||
Append(for_index);
|
||||
arguments->Add(PushArgument(for_index.value()));
|
||||
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
if (super_function != NULL) {
|
||||
// Generate static call to super operator.
|
||||
StaticCallInstr* load = new (Z) StaticCallInstr(
|
||||
node->token_pos(), *super_function, Object::null_array(), arguments,
|
||||
owner()->ic_data_array());
|
||||
node->token_pos(), *super_function, kTypeArgsLen, Object::null_array(),
|
||||
arguments, owner()->ic_data_array());
|
||||
ReturnDefinition(load);
|
||||
} else {
|
||||
// Generate dynamic call to index operator.
|
||||
const intptr_t checked_argument_count = 1;
|
||||
InstanceCallInstr* load = new (Z) InstanceCallInstr(
|
||||
node->token_pos(), Symbols::IndexToken(), Token::kINDEX, arguments,
|
||||
Object::null_array(), checked_argument_count, owner()->ic_data_array());
|
||||
kTypeArgsLen, Object::null_array(), checked_argument_count,
|
||||
owner()->ic_data_array());
|
||||
ReturnDefinition(load);
|
||||
}
|
||||
}
|
||||
|
@ -3626,12 +3675,13 @@ Definition* EffectGraphVisitor::BuildStoreIndexedValues(StoreIndexedNode* node,
|
|||
}
|
||||
arguments->Add(PushArgument(value));
|
||||
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
if (super_function != NULL) {
|
||||
// Generate static call to super operator []=.
|
||||
|
||||
StaticCallInstr* store = new (Z)
|
||||
StaticCallInstr(token_pos, *super_function, Object::null_array(),
|
||||
arguments, owner()->ic_data_array());
|
||||
StaticCallInstr* store = new (Z) StaticCallInstr(
|
||||
token_pos, *super_function, kTypeArgsLen, Object::null_array(),
|
||||
arguments, owner()->ic_data_array());
|
||||
if (result_is_needed) {
|
||||
Do(store);
|
||||
return BuildLoadExprTemp(token_pos);
|
||||
|
@ -3643,7 +3693,8 @@ Definition* EffectGraphVisitor::BuildStoreIndexedValues(StoreIndexedNode* node,
|
|||
const intptr_t checked_argument_count = 2; // Do not check for value type.
|
||||
InstanceCallInstr* store = new (Z) InstanceCallInstr(
|
||||
token_pos, Symbols::AssignIndexToken(), Token::kASSIGN_INDEX, arguments,
|
||||
Object::null_array(), checked_argument_count, owner()->ic_data_array());
|
||||
kTypeArgsLen, Object::null_array(), checked_argument_count,
|
||||
owner()->ic_data_array());
|
||||
if (result_is_needed) {
|
||||
Do(store);
|
||||
return BuildLoadExprTemp(token_pos);
|
||||
|
@ -3813,10 +3864,12 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
|||
Z, isolate()->object_store()->async_set_thread_stack_trace());
|
||||
ASSERT(!async_set_thread_stack_trace.IsNull());
|
||||
// Call _asyncSetThreadStackTrace
|
||||
StaticCallInstr* call_async_set_thread_stack_trace = new (Z)
|
||||
StaticCallInstr(node->token_pos().ToSynthetic(),
|
||||
async_set_thread_stack_trace, Object::null_array(),
|
||||
arguments, owner()->ic_data_array());
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
StaticCallInstr* call_async_set_thread_stack_trace =
|
||||
new (Z) StaticCallInstr(node->token_pos().ToSynthetic(),
|
||||
async_set_thread_stack_trace, kTypeArgsLen,
|
||||
Object::null_array(), arguments,
|
||||
owner()->ic_data_array());
|
||||
Do(call_async_set_thread_stack_trace);
|
||||
}
|
||||
|
||||
|
@ -4150,9 +4203,10 @@ StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall(
|
|||
args_pos, method_name, *method_arguments, temp, is_super_invocation);
|
||||
// Make sure we resolve to a compatible noSuchMethod, otherwise call
|
||||
// noSuchMethod of class Object.
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 2;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::ZoneHandle(Z, ArgumentsDescriptor::New(kNumArguments)));
|
||||
ArgumentsDescriptor args_desc(Array::ZoneHandle(
|
||||
Z, ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
Function& no_such_method_func = Function::ZoneHandle(
|
||||
Z, Resolver::ResolveDynamicForReceiverClass(
|
||||
target_class, Symbols::NoSuchMethod(), args_desc));
|
||||
|
@ -4167,9 +4221,9 @@ StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall(
|
|||
ZoneGrowableArray<PushArgumentInstr*>* push_arguments =
|
||||
new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
|
||||
BuildPushArguments(*args, push_arguments);
|
||||
return new (Z)
|
||||
StaticCallInstr(args_pos, no_such_method_func, Object::null_array(),
|
||||
push_arguments, owner()->ic_data_array());
|
||||
return new (Z) StaticCallInstr(args_pos, no_such_method_func, kTypeArgsLen,
|
||||
Object::null_array(), push_arguments,
|
||||
owner()->ic_data_array());
|
||||
}
|
||||
|
||||
|
||||
|
@ -4227,12 +4281,13 @@ StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError(
|
|||
const Class& cls =
|
||||
Class::Handle(Z, core_lib.LookupClass(Symbols::NoSuchMethodError()));
|
||||
ASSERT(!cls.IsNull());
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const Function& func = Function::ZoneHandle(
|
||||
Z, Resolver::ResolveStatic(
|
||||
cls, Library::PrivateCoreLibName(Symbols::ThrowNew()),
|
||||
arguments->length(), Object::null_array()));
|
||||
kTypeArgsLen, arguments->length(), Object::null_array()));
|
||||
ASSERT(!func.IsNull());
|
||||
return new (Z) StaticCallInstr(token_pos, func,
|
||||
return new (Z) StaticCallInstr(token_pos, func, kTypeArgsLen,
|
||||
Object::null_array(), // No names.
|
||||
arguments, owner()->ic_data_array());
|
||||
}
|
||||
|
|
|
@ -316,6 +316,8 @@ class EffectGraphVisitor : public AstNodeVisitor {
|
|||
StoreBarrierType emit_store_barrier);
|
||||
|
||||
// Helpers for translating parts of the AST.
|
||||
void BuildPushTypeArguments(const ArgumentListNode& node,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* values);
|
||||
void BuildPushArguments(const ArgumentListNode& node,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* values);
|
||||
|
||||
|
|
|
@ -1197,20 +1197,18 @@ void FlowGraphCompiler::GenerateInstanceCall(intptr_t deopt_id,
|
|||
void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id,
|
||||
TokenPosition token_pos,
|
||||
const Function& function,
|
||||
intptr_t argument_count,
|
||||
const Array& argument_names,
|
||||
ArgumentsInfo args_info,
|
||||
LocationSummary* locs,
|
||||
const ICData& ic_data_in) {
|
||||
const ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original());
|
||||
const Array& arguments_descriptor =
|
||||
Array::ZoneHandle(ic_data.IsNull() ? ArgumentsDescriptor::New(
|
||||
argument_count, argument_names)
|
||||
: ic_data.arguments_descriptor());
|
||||
const Array& arguments_descriptor = Array::ZoneHandle(
|
||||
zone(), ic_data.IsNull() ? args_info.ToArgumentsDescriptor()
|
||||
: ic_data.arguments_descriptor());
|
||||
if (is_optimizing()) {
|
||||
EmitOptimizedStaticCall(function, arguments_descriptor, argument_count,
|
||||
deopt_id, token_pos, locs);
|
||||
EmitOptimizedStaticCall(function, arguments_descriptor,
|
||||
args_info.pushed_argc, deopt_id, token_pos, locs);
|
||||
} else {
|
||||
ICData& call_ic_data = ICData::ZoneHandle(ic_data.raw());
|
||||
ICData& call_ic_data = ICData::ZoneHandle(zone(), ic_data.raw());
|
||||
if (call_ic_data.IsNull()) {
|
||||
const intptr_t kNumArgsChecked = 0;
|
||||
call_ic_data =
|
||||
|
@ -1219,7 +1217,7 @@ void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id,
|
|||
->raw();
|
||||
}
|
||||
AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id, token_pos);
|
||||
EmitUnoptimizedStaticCall(argument_count, deopt_id, token_pos, locs,
|
||||
EmitUnoptimizedStaticCall(args_info.pushed_argc, deopt_id, token_pos, locs,
|
||||
call_ic_data);
|
||||
}
|
||||
}
|
||||
|
@ -1793,8 +1791,7 @@ bool FlowGraphCompiler::LookupMethodFor(int class_id,
|
|||
void FlowGraphCompiler::EmitPolymorphicInstanceCall(
|
||||
const CallTargets& targets,
|
||||
const InstanceCallInstr& original_call,
|
||||
intptr_t argument_count,
|
||||
const Array& argument_names,
|
||||
ArgumentsInfo args_info,
|
||||
intptr_t deopt_id,
|
||||
TokenPosition token_pos,
|
||||
LocationSummary* locs,
|
||||
|
@ -1804,8 +1801,7 @@ void FlowGraphCompiler::EmitPolymorphicInstanceCall(
|
|||
Label* deopt =
|
||||
AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail);
|
||||
Label ok;
|
||||
EmitTestAndCall(targets, original_call.function_name(), argument_count,
|
||||
argument_names,
|
||||
EmitTestAndCall(targets, original_call.function_name(), args_info,
|
||||
deopt, // No cid match.
|
||||
&ok, // Found cid.
|
||||
deopt_id, token_pos, locs, complete, total_ic_calls);
|
||||
|
@ -1813,8 +1809,7 @@ void FlowGraphCompiler::EmitPolymorphicInstanceCall(
|
|||
} else {
|
||||
if (complete) {
|
||||
Label ok;
|
||||
EmitTestAndCall(targets, original_call.function_name(), argument_count,
|
||||
argument_names,
|
||||
EmitTestAndCall(targets, original_call.function_name(), args_info,
|
||||
NULL, // No cid match.
|
||||
&ok, // Found cid.
|
||||
deopt_id, token_pos, locs, true, total_ic_calls);
|
||||
|
@ -1822,7 +1817,7 @@ void FlowGraphCompiler::EmitPolymorphicInstanceCall(
|
|||
} else {
|
||||
const ICData& unary_checks = ICData::ZoneHandle(
|
||||
zone(), original_call.ic_data()->AsUnaryClassChecks());
|
||||
EmitSwitchableInstanceCall(unary_checks, argument_count, deopt_id,
|
||||
EmitSwitchableInstanceCall(unary_checks, args_info.pushed_argc, deopt_id,
|
||||
token_pos, locs);
|
||||
}
|
||||
}
|
||||
|
@ -1832,8 +1827,7 @@ void FlowGraphCompiler::EmitPolymorphicInstanceCall(
|
|||
#define __ assembler()->
|
||||
void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets,
|
||||
const String& function_name,
|
||||
intptr_t argument_count,
|
||||
const Array& argument_names,
|
||||
ArgumentsInfo args_info,
|
||||
Label* failed,
|
||||
Label* match_found,
|
||||
intptr_t deopt_id,
|
||||
|
@ -1843,10 +1837,9 @@ void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets,
|
|||
intptr_t total_ic_calls) {
|
||||
ASSERT(is_optimizing());
|
||||
|
||||
const Array& arguments_descriptor = Array::ZoneHandle(
|
||||
zone(), ArgumentsDescriptor::New(argument_count, argument_names));
|
||||
|
||||
EmitTestAndCallLoadReceiver(argument_count, arguments_descriptor);
|
||||
const Array& arguments_descriptor =
|
||||
Array::ZoneHandle(zone(), args_info.ToArgumentsDescriptor());
|
||||
EmitTestAndCallLoadReceiver(args_info.pushed_argc, arguments_descriptor);
|
||||
|
||||
static const int kNoCase = -1;
|
||||
int smi_case = kNoCase;
|
||||
|
@ -1885,7 +1878,7 @@ void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets,
|
|||
GenerateStaticDartCall(deopt_id, token_index,
|
||||
*StubCode::CallStaticFunction_entry(),
|
||||
RawPcDescriptors::kOther, locs, function);
|
||||
__ Drop(argument_count);
|
||||
__ Drop(args_info.pushed_argc);
|
||||
if (match_found != NULL) {
|
||||
__ Jump(match_found);
|
||||
}
|
||||
|
@ -1934,7 +1927,7 @@ void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets,
|
|||
GenerateStaticDartCall(deopt_id, token_index,
|
||||
*StubCode::CallStaticFunction_entry(),
|
||||
RawPcDescriptors::kOther, locs, function);
|
||||
__ Drop(argument_count);
|
||||
__ Drop(args_info.pushed_argc);
|
||||
if (!is_last_check || add_megamorphic_call) {
|
||||
__ Jump(match_found);
|
||||
}
|
||||
|
@ -1943,8 +1936,8 @@ void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets,
|
|||
if (add_megamorphic_call) {
|
||||
int try_index = CatchClauseNode::kInvalidTryIndex;
|
||||
EmitMegamorphicInstanceCall(function_name, arguments_descriptor,
|
||||
argument_count, deopt_id, token_index, locs,
|
||||
try_index);
|
||||
args_info.pushed_argc, deopt_id, token_index,
|
||||
locs, try_index);
|
||||
}
|
||||
}
|
||||
#undef __
|
||||
|
|
|
@ -390,8 +390,7 @@ class FlowGraphCompiler : public ValueObject {
|
|||
void GenerateStaticCall(intptr_t deopt_id,
|
||||
TokenPosition token_pos,
|
||||
const Function& function,
|
||||
intptr_t argument_count,
|
||||
const Array& argument_names,
|
||||
ArgumentsInfo args_info,
|
||||
LocationSummary* locs,
|
||||
const ICData& ic_data);
|
||||
|
||||
|
@ -421,8 +420,7 @@ class FlowGraphCompiler : public ValueObject {
|
|||
void EmitPolymorphicInstanceCall(
|
||||
const CallTargets& targets,
|
||||
const InstanceCallInstr& original_instruction,
|
||||
intptr_t argument_count,
|
||||
const Array& argument_names,
|
||||
ArgumentsInfo args_info,
|
||||
intptr_t deopt_id,
|
||||
TokenPosition token_pos,
|
||||
LocationSummary* locs,
|
||||
|
@ -447,8 +445,7 @@ class FlowGraphCompiler : public ValueObject {
|
|||
|
||||
void EmitTestAndCall(const CallTargets& targets,
|
||||
const String& function_name,
|
||||
intptr_t arg_count,
|
||||
const Array& arg_names,
|
||||
ArgumentsInfo args_info,
|
||||
Label* failed,
|
||||
Label* match_found,
|
||||
intptr_t deopt_id,
|
||||
|
|
|
@ -863,7 +863,16 @@ class CallSiteInliner : public ValueObject {
|
|||
|
||||
// After treating optional parameters the actual/formal count must
|
||||
// match.
|
||||
ASSERT(arguments->length() == function.NumParameters());
|
||||
// TODO(regis): Consider type arguments in arguments.
|
||||
if (arguments->length() != function.NumParameters()) {
|
||||
ASSERT(function.IsGeneric());
|
||||
ASSERT(arguments->length() == function.NumParameters() + 1);
|
||||
TRACE_INLINING(
|
||||
THR_Print(" Bailout: unsupported type arguments\n"));
|
||||
PRINT_INLINING_TREE("Unsupported type arguments", &call_data->caller,
|
||||
&function, call_data->call);
|
||||
return false;
|
||||
}
|
||||
ASSERT(param_stubs->length() == callee_graph->parameter_count());
|
||||
|
||||
// Update try-index of the callee graph.
|
||||
|
@ -1341,6 +1350,7 @@ class CallSiteInliner : public ValueObject {
|
|||
ASSERT(!function.HasOptionalPositionalParameters() ||
|
||||
!function.HasOptionalNamedParameters());
|
||||
|
||||
// TODO(regis): Consider type arguments in arguments.
|
||||
intptr_t arg_count = arguments->length();
|
||||
intptr_t param_count = function.NumParameters();
|
||||
intptr_t fixed_param_count = function.num_fixed_parameters();
|
||||
|
|
|
@ -3266,8 +3266,8 @@ void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
const ICData* call_ic_data = NULL;
|
||||
if (!FLAG_propagate_ic_data || !compiler->is_optimizing() ||
|
||||
(ic_data() == NULL)) {
|
||||
const Array& arguments_descriptor = Array::Handle(
|
||||
zone, ArgumentsDescriptor::New(ArgumentCount(), argument_names()));
|
||||
const Array& arguments_descriptor =
|
||||
Array::Handle(zone, GetArgumentsDescriptor());
|
||||
call_ic_data = compiler->GetOrAddInstanceCallICData(
|
||||
deopt_id(), function_name(), arguments_descriptor,
|
||||
checked_argument_count());
|
||||
|
@ -3357,6 +3357,14 @@ bool InstanceCallInstr::MatchesCoreName(const String& name) {
|
|||
}
|
||||
|
||||
|
||||
RawFunction* InstanceCallInstr::ResolveForReceiverClass(const Class& cls) {
|
||||
const Array& args_desc_array = Array::Handle(GetArgumentsDescriptor());
|
||||
ArgumentsDescriptor args_desc(args_desc_array);
|
||||
return Resolver::ResolveDynamicForReceiverClass(cls, function_name(),
|
||||
args_desc);
|
||||
}
|
||||
|
||||
|
||||
bool CallTargets::HasSingleRecognizedTarget() const {
|
||||
if (!HasSingleTarget()) return false;
|
||||
return MethodRecognizer::RecognizeKind(FirstTarget()) !=
|
||||
|
@ -3422,19 +3430,19 @@ intptr_t PolymorphicInstanceCallInstr::CallCount() const {
|
|||
// PolymorphicInstanceCallInstr.
|
||||
#if !defined(TARGET_ARCH_DBC)
|
||||
void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ArgumentsInfo args_info(instance_call()->type_args_len(),
|
||||
instance_call()->ArgumentCount(),
|
||||
instance_call()->argument_names());
|
||||
if (!with_checks()) {
|
||||
ASSERT(targets().HasSingleTarget());
|
||||
const Function& target = targets().FirstTarget();
|
||||
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(),
|
||||
target, instance_call()->ArgumentCount(),
|
||||
instance_call()->argument_names(), locs(),
|
||||
ICData::Handle());
|
||||
target, args_info, locs(), ICData::Handle());
|
||||
return;
|
||||
}
|
||||
|
||||
compiler->EmitPolymorphicInstanceCall(
|
||||
targets_, *instance_call(), instance_call()->ArgumentCount(),
|
||||
instance_call()->argument_names(), deopt_id(),
|
||||
targets_, *instance_call(), args_info, deopt_id(),
|
||||
instance_call()->token_pos(), locs(), complete(), total_call_count());
|
||||
}
|
||||
#endif
|
||||
|
@ -3550,11 +3558,12 @@ LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone,
|
|||
|
||||
|
||||
void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Zone* zone = compiler->zone();
|
||||
const ICData* call_ic_data = NULL;
|
||||
if (!FLAG_propagate_ic_data || !compiler->is_optimizing() ||
|
||||
(ic_data() == NULL)) {
|
||||
const Array& arguments_descriptor = Array::Handle(
|
||||
ArgumentsDescriptor::New(ArgumentCount(), argument_names()));
|
||||
const Array& arguments_descriptor =
|
||||
Array::Handle(zone, GetArgumentsDescriptor());
|
||||
MethodRecognizer::Kind recognized_kind =
|
||||
MethodRecognizer::RecognizeKind(function());
|
||||
int num_args_checked = 0;
|
||||
|
@ -3574,14 +3583,13 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
}
|
||||
|
||||
#if !defined(TARGET_ARCH_DBC)
|
||||
compiler->GenerateStaticCall(deopt_id(), token_pos(), function(),
|
||||
ArgumentCount(), argument_names(), locs(),
|
||||
*call_ic_data);
|
||||
ArgumentsInfo args_info(type_args_len(), ArgumentCount(), argument_names());
|
||||
compiler->GenerateStaticCall(deopt_id(), token_pos(), function(), args_info,
|
||||
locs(), *call_ic_data);
|
||||
#else
|
||||
const Array& arguments_descriptor =
|
||||
(ic_data() == NULL) ? Array::Handle(ArgumentsDescriptor::New(
|
||||
ArgumentCount(), argument_names()))
|
||||
: Array::Handle(ic_data()->arguments_descriptor());
|
||||
const Array& arguments_descriptor = Array::Handle(
|
||||
zone, (ic_data() == NULL) ? GetArgumentsDescriptor()
|
||||
: ic_data()->arguments_descriptor());
|
||||
const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
|
||||
|
||||
compiler->AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id(),
|
||||
|
@ -3908,13 +3916,14 @@ intptr_t CheckArrayBoundInstr::LengthOffsetFor(intptr_t class_id) {
|
|||
|
||||
const Function& StringInterpolateInstr::CallFunction() const {
|
||||
if (function_.IsNull()) {
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
const Class& cls =
|
||||
Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
|
||||
ASSERT(!cls.IsNull());
|
||||
function_ = Resolver::ResolveStatic(
|
||||
cls, Library::PrivateCoreLibName(Symbols::Interpolate()),
|
||||
cls, Library::PrivateCoreLibName(Symbols::Interpolate()), kTypeArgsLen,
|
||||
kNumberOfArguments, kNoArgumentNames);
|
||||
}
|
||||
ASSERT(!function_.IsNull());
|
||||
|
|
|
@ -2753,39 +2753,99 @@ class CurrentContextInstr : public TemplateDefinition<0, NoThrow> {
|
|||
};
|
||||
|
||||
|
||||
class ClosureCallInstr : public TemplateDefinition<1, Throws> {
|
||||
struct ArgumentsInfo {
|
||||
ArgumentsInfo(intptr_t type_args_len,
|
||||
intptr_t pushed_argc,
|
||||
const Array& argument_names)
|
||||
: type_args_len(type_args_len),
|
||||
pushed_argc(pushed_argc),
|
||||
argument_names(argument_names) {}
|
||||
|
||||
RawArray* ToArgumentsDescriptor() const {
|
||||
return ArgumentsDescriptor::New(type_args_len,
|
||||
pushed_argc - (type_args_len > 0 ? 1 : 0),
|
||||
argument_names);
|
||||
}
|
||||
|
||||
intptr_t type_args_len;
|
||||
intptr_t pushed_argc;
|
||||
const Array& argument_names;
|
||||
};
|
||||
|
||||
|
||||
template <intptr_t kInputCount>
|
||||
class TemplateDartCall : public TemplateDefinition<kInputCount, Throws> {
|
||||
public:
|
||||
TemplateDartCall(intptr_t deopt_id,
|
||||
intptr_t type_args_len,
|
||||
const Array& argument_names,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments,
|
||||
TokenPosition token_pos)
|
||||
: TemplateDefinition<kInputCount, Throws>(deopt_id),
|
||||
type_args_len_(type_args_len),
|
||||
argument_names_(argument_names),
|
||||
arguments_(arguments),
|
||||
token_pos_(token_pos) {
|
||||
ASSERT(argument_names.IsZoneHandle() || argument_names.InVMHeap());
|
||||
}
|
||||
|
||||
intptr_t FirstParamIndex() const { return type_args_len() > 0 ? 1 : 0; }
|
||||
intptr_t ArgumentCountWithoutTypeArgs() const {
|
||||
return arguments_->length() - FirstParamIndex();
|
||||
}
|
||||
// ArgumentCount() includes the type argument vector if any.
|
||||
virtual intptr_t ArgumentCount() const { return arguments_->length(); }
|
||||
virtual PushArgumentInstr* PushArgumentAt(intptr_t index) const {
|
||||
return (*arguments_)[index];
|
||||
}
|
||||
intptr_t type_args_len() const { return type_args_len_; }
|
||||
const Array& argument_names() const { return argument_names_; }
|
||||
virtual TokenPosition token_pos() const { return token_pos_; }
|
||||
RawArray* GetArgumentsDescriptor() const {
|
||||
return ArgumentsDescriptor::New(
|
||||
type_args_len(), ArgumentCountWithoutTypeArgs(), argument_names());
|
||||
}
|
||||
|
||||
private:
|
||||
intptr_t type_args_len_;
|
||||
const Array& argument_names_;
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments_;
|
||||
TokenPosition token_pos_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TemplateDartCall);
|
||||
};
|
||||
|
||||
|
||||
class ClosureCallInstr : public TemplateDartCall<1> {
|
||||
public:
|
||||
ClosureCallInstr(Value* function,
|
||||
ClosureCallNode* node,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
argument_names_(node->arguments()->names()),
|
||||
token_pos_(node->token_pos()),
|
||||
arguments_(arguments) {
|
||||
: TemplateDartCall(Thread::Current()->GetNextDeoptId(),
|
||||
node->arguments()->type_args_len(),
|
||||
node->arguments()->names(),
|
||||
arguments,
|
||||
node->token_pos()) {
|
||||
ASSERT(!arguments->is_empty());
|
||||
SetInputAt(0, function);
|
||||
}
|
||||
|
||||
ClosureCallInstr(Value* function,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments,
|
||||
intptr_t type_args_len,
|
||||
const Array& argument_names,
|
||||
TokenPosition token_pos)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
argument_names_(argument_names),
|
||||
token_pos_(token_pos),
|
||||
arguments_(arguments) {
|
||||
: TemplateDartCall(Thread::Current()->GetNextDeoptId(),
|
||||
type_args_len,
|
||||
argument_names,
|
||||
arguments,
|
||||
token_pos) {
|
||||
ASSERT(!arguments->is_empty());
|
||||
SetInputAt(0, function);
|
||||
}
|
||||
|
||||
DECLARE_INSTRUCTION(ClosureCall)
|
||||
|
||||
const Array& argument_names() const { return argument_names_; }
|
||||
virtual TokenPosition token_pos() const { return token_pos_; }
|
||||
|
||||
virtual intptr_t ArgumentCount() const { return arguments_->length(); }
|
||||
virtual PushArgumentInstr* PushArgumentAt(intptr_t index) const {
|
||||
return (*arguments_)[index];
|
||||
}
|
||||
|
||||
// TODO(kmillikin): implement exact call counts for closure calls.
|
||||
virtual intptr_t CallCount() const { return 1; }
|
||||
|
||||
|
@ -2796,36 +2856,33 @@ class ClosureCallInstr : public TemplateDefinition<1, Throws> {
|
|||
PRINT_OPERANDS_TO_SUPPORT
|
||||
|
||||
private:
|
||||
const Array& argument_names_;
|
||||
TokenPosition token_pos_;
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ClosureCallInstr);
|
||||
};
|
||||
|
||||
|
||||
class InstanceCallInstr : public TemplateDefinition<0, Throws> {
|
||||
class InstanceCallInstr : public TemplateDartCall<0> {
|
||||
public:
|
||||
InstanceCallInstr(TokenPosition token_pos,
|
||||
const String& function_name,
|
||||
Token::Kind token_kind,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments,
|
||||
intptr_t type_args_len,
|
||||
const Array& argument_names,
|
||||
intptr_t checked_argument_count,
|
||||
const ZoneGrowableArray<const ICData*>& ic_data_array)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
: TemplateDartCall(Thread::Current()->GetNextDeoptId(),
|
||||
type_args_len,
|
||||
argument_names,
|
||||
arguments,
|
||||
token_pos),
|
||||
ic_data_(NULL),
|
||||
token_pos_(token_pos),
|
||||
function_name_(function_name),
|
||||
token_kind_(token_kind),
|
||||
arguments_(arguments),
|
||||
argument_names_(argument_names),
|
||||
checked_argument_count_(checked_argument_count),
|
||||
has_unique_selector_(false) {
|
||||
ic_data_ = GetICData(ic_data_array);
|
||||
ASSERT(function_name.IsNotTemporaryScopedHandle());
|
||||
ASSERT(!arguments->is_empty());
|
||||
ASSERT(argument_names.IsZoneHandle() || argument_names.InVMHeap());
|
||||
ASSERT(Token::IsBinaryOperator(token_kind) ||
|
||||
Token::IsEqualityOperator(token_kind) ||
|
||||
Token::IsRelationalOperator(token_kind) ||
|
||||
|
@ -2844,14 +2901,8 @@ class InstanceCallInstr : public TemplateDefinition<0, Throws> {
|
|||
// ICData can be replaced by optimizer.
|
||||
void set_ic_data(const ICData* value) { ic_data_ = value; }
|
||||
|
||||
virtual TokenPosition token_pos() const { return token_pos_; }
|
||||
const String& function_name() const { return function_name_; }
|
||||
Token::Kind token_kind() const { return token_kind_; }
|
||||
virtual intptr_t ArgumentCount() const { return arguments_->length(); }
|
||||
virtual PushArgumentInstr* PushArgumentAt(intptr_t index) const {
|
||||
return (*arguments_)[index];
|
||||
}
|
||||
const Array& argument_names() const { return argument_names_; }
|
||||
intptr_t checked_argument_count() const { return checked_argument_count_; }
|
||||
|
||||
bool has_unique_selector() const { return has_unique_selector_; }
|
||||
|
@ -2873,17 +2924,16 @@ class InstanceCallInstr : public TemplateDefinition<0, Throws> {
|
|||
|
||||
bool MatchesCoreName(const String& name);
|
||||
|
||||
RawFunction* ResolveForReceiverClass(const Class& cls);
|
||||
|
||||
protected:
|
||||
friend class JitOptimizer;
|
||||
void set_ic_data(ICData* value) { ic_data_ = value; }
|
||||
|
||||
private:
|
||||
const ICData* ic_data_;
|
||||
const TokenPosition token_pos_;
|
||||
const String& function_name_;
|
||||
const Token::Kind token_kind_; // Binary op, unary op, kGET or kILLEGAL.
|
||||
ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
|
||||
const Array& argument_names_;
|
||||
const intptr_t checked_argument_count_;
|
||||
bool has_unique_selector_;
|
||||
|
||||
|
@ -2934,9 +2984,9 @@ class PolymorphicInstanceCallInstr : public TemplateDefinition<0, Throws> {
|
|||
virtual intptr_t CallCount() const;
|
||||
|
||||
// If this polymophic call site was created to cover the remaining cids after
|
||||
// inlinng then we need to keep track of the total number of calls including
|
||||
// the ones that wer inlined. This is different from the CallCount above: Eg
|
||||
// if there were 100 calls originally, distributed across three class-ids in
|
||||
// inlining then we need to keep track of the total number of calls including
|
||||
// the ones that we inlined. This is different from the CallCount above: Eg
|
||||
// if there were 100 calls originally, distributed across three class-ids in
|
||||
// the ratio 50, 40, 7, 3. The first two were inlined, so now we have only
|
||||
// 10 calls in the CallCount above, but the heuristics need to know that the
|
||||
// last two cids cover 7% and 3% of the calls, not 70% and 30%.
|
||||
|
@ -3263,45 +3313,47 @@ class IfThenElseInstr : public Definition {
|
|||
};
|
||||
|
||||
|
||||
class StaticCallInstr : public TemplateDefinition<0, Throws> {
|
||||
class StaticCallInstr : public TemplateDartCall<0> {
|
||||
public:
|
||||
StaticCallInstr(TokenPosition token_pos,
|
||||
const Function& function,
|
||||
intptr_t type_args_len,
|
||||
const Array& argument_names,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments,
|
||||
const ZoneGrowableArray<const ICData*>& ic_data_array)
|
||||
: TemplateDefinition(Thread::Current()->GetNextDeoptId()),
|
||||
: TemplateDartCall(Thread::Current()->GetNextDeoptId(),
|
||||
type_args_len,
|
||||
argument_names,
|
||||
arguments,
|
||||
token_pos),
|
||||
ic_data_(NULL),
|
||||
token_pos_(token_pos),
|
||||
function_(function),
|
||||
argument_names_(argument_names),
|
||||
arguments_(arguments),
|
||||
result_cid_(kDynamicCid),
|
||||
is_known_list_constructor_(false),
|
||||
identity_(AliasIdentity::Unknown()) {
|
||||
ic_data_ = GetICData(ic_data_array);
|
||||
ASSERT(function.IsZoneHandle());
|
||||
ASSERT(!function.IsNull());
|
||||
ASSERT(argument_names.IsZoneHandle() || argument_names.InVMHeap());
|
||||
}
|
||||
|
||||
StaticCallInstr(TokenPosition token_pos,
|
||||
const Function& function,
|
||||
intptr_t type_args_len,
|
||||
const Array& argument_names,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments,
|
||||
intptr_t deopt_id)
|
||||
: TemplateDefinition(deopt_id),
|
||||
: TemplateDartCall(deopt_id,
|
||||
type_args_len,
|
||||
argument_names,
|
||||
arguments,
|
||||
token_pos),
|
||||
ic_data_(NULL),
|
||||
token_pos_(token_pos),
|
||||
function_(function),
|
||||
argument_names_(argument_names),
|
||||
arguments_(arguments),
|
||||
result_cid_(kDynamicCid),
|
||||
is_known_list_constructor_(false),
|
||||
identity_(AliasIdentity::Unknown()) {
|
||||
ASSERT(function.IsZoneHandle());
|
||||
ASSERT(!function.IsNull());
|
||||
ASSERT(argument_names.IsZoneHandle() || argument_names.InVMHeap());
|
||||
}
|
||||
|
||||
// ICData for static calls carries call count.
|
||||
|
@ -3316,13 +3368,6 @@ class StaticCallInstr : public TemplateDefinition<0, Throws> {
|
|||
|
||||
// Accessors forwarded to the AST node.
|
||||
const Function& function() const { return function_; }
|
||||
const Array& argument_names() const { return argument_names_; }
|
||||
virtual TokenPosition token_pos() const { return token_pos_; }
|
||||
|
||||
virtual intptr_t ArgumentCount() const { return arguments_->length(); }
|
||||
virtual PushArgumentInstr* PushArgumentAt(intptr_t index) const {
|
||||
return (*arguments_)[index];
|
||||
}
|
||||
|
||||
virtual intptr_t CallCount() const {
|
||||
return ic_data() == NULL ? 0 : ic_data()->AggregateCount();
|
||||
|
@ -3354,10 +3399,7 @@ class StaticCallInstr : public TemplateDefinition<0, Throws> {
|
|||
|
||||
private:
|
||||
const ICData* ic_data_;
|
||||
const TokenPosition token_pos_;
|
||||
const Function& function_;
|
||||
const Array& argument_names_;
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments_;
|
||||
intptr_t result_cid_; // For some library functions we know the result.
|
||||
|
||||
// 'True' for recognized list constructors.
|
||||
|
@ -6780,6 +6822,7 @@ class CheckedSmiOpInstr : public TemplateDefinition<2, Throws> {
|
|||
Value* right,
|
||||
InstanceCallInstr* call)
|
||||
: TemplateDefinition(call->deopt_id()), call_(call), op_kind_(op_kind) {
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
SetInputAt(0, left);
|
||||
SetInputAt(1, right);
|
||||
}
|
||||
|
@ -6815,6 +6858,7 @@ class CheckedSmiComparisonInstr : public TemplateComparison<2, Throws> {
|
|||
: TemplateComparison(call->token_pos(), op_kind, call->deopt_id()),
|
||||
call_(call),
|
||||
is_negated_(false) {
|
||||
ASSERT(call->type_args_len() == 0);
|
||||
SetInputAt(0, left);
|
||||
SetInputAt(1, right);
|
||||
}
|
||||
|
|
|
@ -225,9 +225,9 @@ LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
|
|||
|
||||
void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Load arguments descriptor in R4.
|
||||
int argument_count = ArgumentCount();
|
||||
const Array& arguments_descriptor = Array::ZoneHandle(
|
||||
ArgumentsDescriptor::New(argument_count, argument_names()));
|
||||
const intptr_t argument_count = ArgumentCount(); // Includes type args.
|
||||
const Array& arguments_descriptor =
|
||||
Array::ZoneHandle(Z, GetArgumentsDescriptor());
|
||||
__ LoadObject(R4, arguments_descriptor);
|
||||
|
||||
// R4: Arguments descriptor.
|
||||
|
@ -1067,11 +1067,12 @@ LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
|
|||
void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const Register array = locs()->in(0).reg();
|
||||
__ Push(array);
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
|
||||
kNumberOfArguments, kNoArgumentNames, locs(),
|
||||
ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
ASSERT(locs()->out(0).reg() == R0);
|
||||
}
|
||||
|
||||
|
@ -5866,12 +5867,12 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
const ICData& ic_data = *instance_call()->ic_data();
|
||||
ASSERT(ic_data.NumberOfChecksIs(1));
|
||||
const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
|
||||
|
||||
const intptr_t kNumberOfArguments = 1;
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
|
||||
kNumberOfArguments,
|
||||
Object::null_array(), // No argument names.,
|
||||
locs(), ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
|
|
@ -220,9 +220,9 @@ LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
|
|||
|
||||
void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Load arguments descriptor in R4.
|
||||
int argument_count = ArgumentCount();
|
||||
const Array& arguments_descriptor = Array::ZoneHandle(
|
||||
ArgumentsDescriptor::New(argument_count, argument_names()));
|
||||
const intptr_t argument_count = ArgumentCount(); // Includes type args.
|
||||
const Array& arguments_descriptor =
|
||||
Array::ZoneHandle(Z, GetArgumentsDescriptor());
|
||||
__ LoadObject(R4, arguments_descriptor);
|
||||
|
||||
// R4: Arguments descriptor.
|
||||
|
@ -914,11 +914,12 @@ LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
|
|||
void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const Register array = locs()->in(0).reg();
|
||||
__ Push(array);
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
|
||||
kNumberOfArguments, kNoArgumentNames, locs(),
|
||||
ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
ASSERT(locs()->out(0).reg() == R0);
|
||||
}
|
||||
|
||||
|
@ -5101,12 +5102,12 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
const ICData& ic_data = *instance_call()->ic_data();
|
||||
ASSERT(ic_data.NumberOfChecksIs(1));
|
||||
const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
|
||||
|
||||
const intptr_t kNumberOfArguments = 1;
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
|
||||
kNumberOfArguments,
|
||||
Object::null_array(), // No argument names.,
|
||||
locs(), ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
|
|
@ -239,8 +239,8 @@ EMIT_NATIVE_CODE(PolymorphicInstanceCall,
|
|||
0,
|
||||
Location::RegisterLocation(0),
|
||||
LocationSummary::kCall) {
|
||||
const Array& arguments_descriptor = Array::Handle(ArgumentsDescriptor::New(
|
||||
instance_call()->ArgumentCount(), instance_call()->argument_names()));
|
||||
const Array& arguments_descriptor =
|
||||
Array::Handle(instance_call()->GetArgumentsDescriptor());
|
||||
const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
|
||||
|
||||
// Push the target onto the stack.
|
||||
|
@ -450,12 +450,11 @@ EMIT_NATIVE_CODE(ClosureCall,
|
|||
__ Push(locs()->in(0).reg());
|
||||
}
|
||||
|
||||
intptr_t argument_count = ArgumentCount();
|
||||
const Array& arguments_descriptor = Array::ZoneHandle(
|
||||
ArgumentsDescriptor::New(argument_count, argument_names()));
|
||||
const Array& arguments_descriptor =
|
||||
Array::ZoneHandle(GetArgumentsDescriptor());
|
||||
const intptr_t argdesc_kidx =
|
||||
compiler->assembler()->AddConstant(arguments_descriptor);
|
||||
__ StaticCall(argument_count, argdesc_kidx);
|
||||
__ StaticCall(ArgumentCount(), argdesc_kidx);
|
||||
compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
|
||||
if (compiler->is_optimizing()) {
|
||||
__ PopLocal(locs()->out(0).reg());
|
||||
|
@ -918,9 +917,10 @@ EMIT_NATIVE_CODE(StringInterpolate,
|
|||
if (compiler->is_optimizing()) {
|
||||
__ Push(locs()->in(0).reg());
|
||||
}
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kArgumentCount = 1;
|
||||
const Array& arguments_descriptor = Array::Handle(
|
||||
ArgumentsDescriptor::New(kArgumentCount, Object::null_array()));
|
||||
const Array& arguments_descriptor = Array::Handle(ArgumentsDescriptor::New(
|
||||
kTypeArgsLen, kArgumentCount, Object::null_array()));
|
||||
__ PushConstant(CallFunction());
|
||||
const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
|
||||
__ StaticCall(kArgumentCount, argdesc_kidx);
|
||||
|
|
|
@ -940,11 +940,12 @@ LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
|
|||
void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register array = locs()->in(0).reg();
|
||||
__ pushl(array);
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
|
||||
kNumberOfArguments, kNoArgumentNames, locs(),
|
||||
ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
ASSERT(locs()->out(0).reg() == EAX);
|
||||
}
|
||||
|
||||
|
@ -5381,12 +5382,12 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
const ICData& ic_data = *instance_call()->ic_data();
|
||||
ASSERT(ic_data.NumberOfChecksIs(1));
|
||||
const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
|
||||
|
||||
const intptr_t kNumberOfArguments = 1;
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
|
||||
kNumberOfArguments,
|
||||
Object::null_array(), // No argument names.
|
||||
locs(), ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
@ -6835,10 +6836,10 @@ LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
|
|||
|
||||
|
||||
void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Load arguments descriptors.
|
||||
intptr_t argument_count = ArgumentCount();
|
||||
const Array& arguments_descriptor = Array::ZoneHandle(
|
||||
ArgumentsDescriptor::New(argument_count, argument_names()));
|
||||
// Load arguments descriptor.
|
||||
const intptr_t argument_count = ArgumentCount(); // Includes type args.
|
||||
const Array& arguments_descriptor =
|
||||
Array::ZoneHandle(Z, GetArgumentsDescriptor());
|
||||
__ LoadObject(EDX, arguments_descriptor);
|
||||
|
||||
// EBX: Code (compiled code or lazy compile stub).
|
||||
|
|
|
@ -286,9 +286,9 @@ LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
|
|||
|
||||
void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Load arguments descriptor in S4.
|
||||
int argument_count = ArgumentCount();
|
||||
const Array& arguments_descriptor = Array::ZoneHandle(
|
||||
ArgumentsDescriptor::New(argument_count, argument_names()));
|
||||
const intptr_t argument_count = ArgumentCount(); // Includes type args.
|
||||
const Array& arguments_descriptor =
|
||||
Array::ZoneHandle(Z, GetArgumentsDescriptor());
|
||||
__ LoadObject(S4, arguments_descriptor);
|
||||
|
||||
// Load closure function code in T2.
|
||||
|
@ -1135,11 +1135,12 @@ LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
|
|||
void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register array = locs()->in(0).reg();
|
||||
__ Push(array);
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
|
||||
kNumberOfArguments, kNoArgumentNames, locs(),
|
||||
ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
ASSERT(locs()->out(0).reg() == V0);
|
||||
}
|
||||
|
||||
|
@ -4681,12 +4682,12 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
const ICData& ic_data = *instance_call()->ic_data();
|
||||
ASSERT(ic_data.NumberOfChecksIs(1));
|
||||
const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
|
||||
|
||||
const intptr_t kNumberOfArguments = 1;
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
|
||||
kNumberOfArguments,
|
||||
Object::null_array(), // No argument names.
|
||||
locs(), ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
|
|
@ -910,11 +910,12 @@ LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
|
|||
void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register array = locs()->in(0).reg();
|
||||
__ pushq(array);
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
|
||||
kNumberOfArguments, kNoArgumentNames, locs(),
|
||||
ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
ASSERT(locs()->out(0).reg() == RAX);
|
||||
}
|
||||
|
||||
|
@ -5325,17 +5326,17 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
__ SmiTag(result);
|
||||
__ jmp(&done);
|
||||
__ Bind(&do_call);
|
||||
__ pushq(value_obj);
|
||||
ASSERT(instance_call()->HasICData());
|
||||
const ICData& ic_data = *instance_call()->ic_data();
|
||||
ASSERT(ic_data.NumberOfChecksIs(1));
|
||||
const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
|
||||
|
||||
const intptr_t kNumberOfArguments = 1;
|
||||
__ pushq(value_obj);
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
|
||||
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
|
||||
kNumberOfArguments,
|
||||
Object::null_array(), // No argument names.
|
||||
locs(), ICData::Handle());
|
||||
args_info, locs(), ICData::Handle());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
@ -6691,9 +6692,9 @@ LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
|
|||
|
||||
void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Arguments descriptor is expected in R10.
|
||||
intptr_t argument_count = ArgumentCount();
|
||||
const Array& arguments_descriptor = Array::ZoneHandle(
|
||||
ArgumentsDescriptor::New(argument_count, argument_names()));
|
||||
const intptr_t argument_count = ArgumentCount(); // Includes type args.
|
||||
const Array& arguments_descriptor =
|
||||
Array::ZoneHandle(Z, GetArgumentsDescriptor());
|
||||
__ LoadObject(R10, arguments_descriptor);
|
||||
|
||||
// Function in RAX.
|
||||
|
|
|
@ -137,10 +137,8 @@ bool JitOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
|||
// finalized yet.
|
||||
return false;
|
||||
}
|
||||
const Array& args_desc_array =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(call->ArgumentCount(),
|
||||
call->argument_names()));
|
||||
ArgumentsDescriptor args_desc(args_desc_array);
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(Z, call->GetArgumentsDescriptor()));
|
||||
bool allow_add = false;
|
||||
const Function& function = Function::Handle(
|
||||
Z, Resolver::ResolveDynamicForReceiverClass(
|
||||
|
@ -171,9 +169,11 @@ bool JitOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
|||
const Class& owner_class = Class::Handle(Z, function().Owner());
|
||||
if (!owner_class.is_abstract() && !CHA::HasSubclasses(owner_class) &&
|
||||
!CHA::IsImplemented(owner_class)) {
|
||||
const Array& args_desc_array =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(call->ArgumentCount(),
|
||||
call->argument_names()));
|
||||
const int kTypeArgsLen = 0;
|
||||
ASSERT(call->type_args_len() == kTypeArgsLen);
|
||||
const Array& args_desc_array = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(kTypeArgsLen, call->ArgumentCount(),
|
||||
call->argument_names()));
|
||||
ArgumentsDescriptor args_desc(args_desc_array);
|
||||
bool allow_add = false;
|
||||
const Function& function = Function::Handle(
|
||||
|
|
|
@ -1309,6 +1309,7 @@ class Arguments : public TreeNode {
|
|||
virtual void AcceptTreeVisitor(TreeVisitor* visitor);
|
||||
virtual void VisitChildren(Visitor* visitor);
|
||||
|
||||
// TODO(regis): Support type arguments of generic functions.
|
||||
List<DartType>& types() { return types_; }
|
||||
List<Expression>& positional() { return positional_; }
|
||||
List<NamedExpression>& named() { return named_; }
|
||||
|
|
|
@ -995,8 +995,10 @@ const Object& StreamingConstantEvaluator::RunFunction(
|
|||
const Object& StreamingConstantEvaluator::RunFunction(const Function& function,
|
||||
const Array& arguments,
|
||||
const Array& names) {
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(arguments.Length(), names));
|
||||
// We do not support generic methods yet.
|
||||
const int kTypeArgsLen = 0;
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length(), names));
|
||||
const Object& result = Object::Handle(
|
||||
Z, DartEntry::InvokeFunction(function, arguments, args_descriptor));
|
||||
if (result.IsError()) {
|
||||
|
@ -1012,6 +1014,7 @@ RawObject* StreamingConstantEvaluator::EvaluateConstConstructorCall(
|
|||
const Object& argument) {
|
||||
// Factories have one extra argument: the type arguments.
|
||||
// Constructors have 1 extra arguments: receiver.
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArgs = 1;
|
||||
const int kNumExtraArgs = 1;
|
||||
const int num_arguments = kNumArgs + kNumExtraArgs;
|
||||
|
@ -1032,8 +1035,9 @@ RawObject* StreamingConstantEvaluator::EvaluateConstConstructorCall(
|
|||
arg_values.SetAt(0, type_arguments);
|
||||
}
|
||||
arg_values.SetAt((0 + kNumExtraArgs), argument);
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(num_arguments, Object::empty_array()));
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, num_arguments,
|
||||
Object::empty_array()));
|
||||
const Object& result = Object::Handle(
|
||||
Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
|
||||
ASSERT(!result.IsError());
|
||||
|
@ -2782,7 +2786,9 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
|
|||
Array& argument_names = Array::ZoneHandle(Z);
|
||||
instructions += BuildArguments(&argument_names, NULL,
|
||||
special_case_identical); // read arguments.
|
||||
ASSERT(target.AreValidArguments(argument_count, argument_names, NULL));
|
||||
const int kTypeArgsLen = 0;
|
||||
ASSERT(target.AreValidArguments(kTypeArgsLen, argument_count, argument_names,
|
||||
NULL));
|
||||
|
||||
// Special case identical(x, y) call.
|
||||
// TODO(27590) consider moving this into the inliner and force inline it
|
||||
|
|
|
@ -1561,6 +1561,7 @@ RawObject* ConstantEvaluator::EvaluateConstConstructorCall(
|
|||
const Object& argument) {
|
||||
// Factories have one extra argument: the type arguments.
|
||||
// Constructors have 1 extra arguments: receiver.
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArgs = 1;
|
||||
const int kNumExtraArgs = 1;
|
||||
const int num_arguments = kNumArgs + kNumExtraArgs;
|
||||
|
@ -1581,8 +1582,9 @@ RawObject* ConstantEvaluator::EvaluateConstConstructorCall(
|
|||
arg_values.SetAt(0, type_arguments);
|
||||
}
|
||||
arg_values.SetAt((0 + kNumExtraArgs), argument);
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(num_arguments, Object::empty_array()));
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, num_arguments,
|
||||
Object::empty_array()));
|
||||
const Object& result = Object::Handle(
|
||||
Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
|
||||
ASSERT(!result.IsError());
|
||||
|
@ -1995,8 +1997,9 @@ const Object& ConstantEvaluator::RunFunction(const Function& function,
|
|||
const Object& ConstantEvaluator::RunFunction(const Function& function,
|
||||
const Array& arguments,
|
||||
const Array& names) {
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(arguments.Length(), names));
|
||||
const int kTypeArgsLen = 0; // Generic functions not yet supported.
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length(), names));
|
||||
const Object& result = Object::Handle(
|
||||
Z, DartEntry::InvokeFunction(function, arguments, args_descriptor));
|
||||
if (result.IsError()) {
|
||||
|
@ -2532,9 +2535,10 @@ Fragment FlowGraphBuilder::InstanceCall(TokenPosition position,
|
|||
const Array& argument_names,
|
||||
intptr_t num_args_checked) {
|
||||
ArgumentArray arguments = GetArguments(argument_count);
|
||||
InstanceCallInstr* call =
|
||||
new (Z) InstanceCallInstr(position, name, kind, arguments, argument_names,
|
||||
num_args_checked, ic_data_array_);
|
||||
const intptr_t kTypeArgsLen = 0; // Generic instance calls not yet supported.
|
||||
InstanceCallInstr* call = new (Z)
|
||||
InstanceCallInstr(position, name, kind, arguments, kTypeArgsLen,
|
||||
argument_names, num_args_checked, ic_data_array_);
|
||||
Push(call);
|
||||
return Fragment(call);
|
||||
}
|
||||
|
@ -2544,8 +2548,10 @@ Fragment FlowGraphBuilder::ClosureCall(int argument_count,
|
|||
const Array& argument_names) {
|
||||
Value* function = Pop();
|
||||
ArgumentArray arguments = GetArguments(argument_count);
|
||||
ClosureCallInstr* call = new (Z) ClosureCallInstr(
|
||||
function, arguments, argument_names, TokenPosition::kNoSource);
|
||||
const intptr_t kTypeArgsLen = 0; // Generic closures not yet supported.
|
||||
ClosureCallInstr* call =
|
||||
new (Z) ClosureCallInstr(function, arguments, kTypeArgsLen,
|
||||
argument_names, TokenPosition::kNoSource);
|
||||
Push(call);
|
||||
return Fragment(call);
|
||||
}
|
||||
|
@ -2758,8 +2764,10 @@ Fragment FlowGraphBuilder::StaticCall(TokenPosition position,
|
|||
intptr_t argument_count,
|
||||
const Array& argument_names) {
|
||||
ArgumentArray arguments = GetArguments(argument_count);
|
||||
StaticCallInstr* call = new (Z) StaticCallInstr(
|
||||
position, target, argument_names, arguments, ic_data_array_);
|
||||
const intptr_t kTypeArgsLen = 0; // Generic static calls not yet supported.
|
||||
StaticCallInstr* call =
|
||||
new (Z) StaticCallInstr(position, target, kTypeArgsLen, argument_names,
|
||||
arguments, ic_data_array_);
|
||||
const intptr_t list_cid =
|
||||
GetResultCidOfListFactory(Z, target, argument_count);
|
||||
if (list_cid != kDynamicCid) {
|
||||
|
@ -2880,15 +2888,17 @@ Fragment FlowGraphBuilder::StringInterpolate(TokenPosition position) {
|
|||
|
||||
|
||||
Fragment FlowGraphBuilder::StringInterpolateSingle(TokenPosition position) {
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumberOfArguments = 1;
|
||||
const Array& kNoArgumentNames = Object::null_array();
|
||||
const dart::Class& cls = dart::Class::Handle(
|
||||
dart::Library::LookupCoreClass(Symbols::StringBase()));
|
||||
ASSERT(!cls.IsNull());
|
||||
const Function& function = Function::ZoneHandle(
|
||||
Z, Resolver::ResolveStatic(cls, dart::Library::PrivateCoreLibName(
|
||||
Symbols::InterpolateSingle()),
|
||||
kNumberOfArguments, kNoArgumentNames));
|
||||
Z,
|
||||
Resolver::ResolveStatic(
|
||||
cls, dart::Library::PrivateCoreLibName(Symbols::InterpolateSingle()),
|
||||
kTypeArgsLen, kNumberOfArguments, kNoArgumentNames));
|
||||
Fragment instructions;
|
||||
instructions += PushArgument();
|
||||
instructions += StaticCall(position, function, 1);
|
||||
|
@ -4054,6 +4064,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher(
|
|||
Fragment body(normal_entry);
|
||||
body += CheckStackOverflowInPrologue();
|
||||
|
||||
// TODO(regis): Check if a type argument vector is passed.
|
||||
|
||||
// The receiver is the first argument to noSuchMethod, and it is the first
|
||||
// argument passed to the dispatcher function.
|
||||
LocalScope* scope = parsed_function_->node_sequence()->scope();
|
||||
|
@ -4109,8 +4121,9 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher(
|
|||
body += StaticCall(TokenPosition::kMinSource, allocation_function, 4);
|
||||
body += PushArgument(); // For the call to noSuchMethod.
|
||||
|
||||
const int kTypeArgsLen = 0;
|
||||
ArgumentsDescriptor two_arguments(
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(2)));
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, 2)));
|
||||
Function& no_such_method =
|
||||
Function::ZoneHandle(Z, Resolver::ResolveDynamicForReceiverClass(
|
||||
dart::Class::Handle(Z, function.Owner()),
|
||||
|
@ -5017,7 +5030,9 @@ void FlowGraphBuilder::VisitStaticInvocation(StaticInvocation* node) {
|
|||
const Array& argument_names = H.ArgumentNames(&named);
|
||||
|
||||
// The frontend ensures we the [StaticInvocation] has matching arguments.
|
||||
ASSERT(target.AreValidArguments(argument_count, argument_names, NULL));
|
||||
const intptr_t kTypeArgsLen = 0; // Generic functions not yet supported.
|
||||
ASSERT(target.AreValidArguments(kTypeArgsLen, argument_count, argument_names,
|
||||
NULL));
|
||||
|
||||
Fragment instructions;
|
||||
LocalVariable* instance_variable = NULL;
|
||||
|
|
|
@ -4816,7 +4816,9 @@ void TypeArguments::set_instantiations(const Array& value) const {
|
|||
|
||||
|
||||
intptr_t TypeArguments::Length() const {
|
||||
ASSERT(!IsNull());
|
||||
if (IsNull()) {
|
||||
return 0;
|
||||
}
|
||||
return Smi::Value(raw_ptr()->length_);
|
||||
}
|
||||
|
||||
|
@ -6198,9 +6200,24 @@ intptr_t Function::NumImplicitParameters() const {
|
|||
}
|
||||
|
||||
|
||||
bool Function::AreValidArgumentCounts(intptr_t num_arguments,
|
||||
bool Function::AreValidArgumentCounts(intptr_t num_type_arguments,
|
||||
intptr_t num_arguments,
|
||||
intptr_t num_named_arguments,
|
||||
String* error_message) const {
|
||||
if ((num_type_arguments != 0) &&
|
||||
(num_type_arguments != NumTypeParameters())) {
|
||||
if (error_message != NULL) {
|
||||
const intptr_t kMessageBufferSize = 64;
|
||||
char message_buffer[kMessageBufferSize];
|
||||
OS::SNPrint(message_buffer, kMessageBufferSize,
|
||||
"%" Pd " type arguments passed, but %" Pd " expected",
|
||||
num_type_arguments, NumTypeParameters());
|
||||
// Allocate in old space because it can be invoked in background
|
||||
// optimizing compilation.
|
||||
*error_message = String::New(message_buffer, Heap::kOld);
|
||||
}
|
||||
return false; // Too many type arguments.
|
||||
}
|
||||
if (num_named_arguments > NumOptionalNamedParameters()) {
|
||||
if (error_message != NULL) {
|
||||
const intptr_t kMessageBufferSize = 64;
|
||||
|
@ -6257,13 +6274,14 @@ bool Function::AreValidArgumentCounts(intptr_t num_arguments,
|
|||
}
|
||||
|
||||
|
||||
bool Function::AreValidArguments(intptr_t num_arguments,
|
||||
bool Function::AreValidArguments(intptr_t num_type_arguments,
|
||||
intptr_t num_arguments,
|
||||
const Array& argument_names,
|
||||
String* error_message) const {
|
||||
const intptr_t num_named_arguments =
|
||||
argument_names.IsNull() ? 0 : argument_names.Length();
|
||||
if (!AreValidArgumentCounts(num_arguments, num_named_arguments,
|
||||
error_message)) {
|
||||
if (!AreValidArgumentCounts(num_type_arguments, num_arguments,
|
||||
num_named_arguments, error_message)) {
|
||||
return false;
|
||||
}
|
||||
// Verify that all argument names are valid parameter names.
|
||||
|
@ -6304,11 +6322,12 @@ bool Function::AreValidArguments(intptr_t num_arguments,
|
|||
|
||||
bool Function::AreValidArguments(const ArgumentsDescriptor& args_desc,
|
||||
String* error_message) const {
|
||||
const intptr_t num_type_arguments = args_desc.TypeArgsLen();
|
||||
const intptr_t num_arguments = args_desc.Count();
|
||||
const intptr_t num_named_arguments = args_desc.NamedCount();
|
||||
|
||||
if (!AreValidArgumentCounts(num_arguments, num_named_arguments,
|
||||
error_message)) {
|
||||
if (!AreValidArgumentCounts(num_type_arguments, num_arguments,
|
||||
num_named_arguments, error_message)) {
|
||||
return false;
|
||||
}
|
||||
// Verify that all argument names are valid parameter names.
|
||||
|
|
|
@ -2647,14 +2647,16 @@ class Function : public Object {
|
|||
|
||||
// Returns true if the argument counts are valid for calling this function.
|
||||
// Otherwise, it returns false and the reason (if error_message is not NULL).
|
||||
bool AreValidArgumentCounts(intptr_t num_arguments,
|
||||
bool AreValidArgumentCounts(intptr_t num_type_arguments,
|
||||
intptr_t num_arguments,
|
||||
intptr_t num_named_arguments,
|
||||
String* error_message) const;
|
||||
|
||||
// Returns true if the total argument count and the names of optional
|
||||
// arguments are valid for calling this function.
|
||||
// Returns true if the type argument count, total argument count and the names
|
||||
// of optional arguments are valid for calling this function.
|
||||
// Otherwise, it returns false and the reason (if error_message is not NULL).
|
||||
bool AreValidArguments(intptr_t num_arguments,
|
||||
bool AreValidArguments(intptr_t num_type_arguments,
|
||||
intptr_t num_arguments,
|
||||
const Array& argument_names,
|
||||
String* error_message) const;
|
||||
bool AreValidArguments(const ArgumentsDescriptor& args_desc,
|
||||
|
|
|
@ -247,30 +247,34 @@ void ObjectStore::InitKnownObjects() {
|
|||
Function& function = Function::Handle(zone);
|
||||
function_name ^= async_lib.PrivateName(Symbols::SetAsyncThreadStackTrace());
|
||||
ASSERT(!function_name.IsNull());
|
||||
function ^= Resolver::ResolveStatic(async_lib, Object::null_string(),
|
||||
function_name, 1, Object::null_array());
|
||||
function ^=
|
||||
Resolver::ResolveStatic(async_lib, Object::null_string(), function_name,
|
||||
0, 1, Object::null_array());
|
||||
ASSERT(!function.IsNull());
|
||||
set_async_set_thread_stack_trace(function);
|
||||
|
||||
function_name ^= async_lib.PrivateName(Symbols::ClearAsyncThreadStackTrace());
|
||||
ASSERT(!function_name.IsNull());
|
||||
function ^= Resolver::ResolveStatic(async_lib, Object::null_string(),
|
||||
function_name, 0, Object::null_array());
|
||||
function ^=
|
||||
Resolver::ResolveStatic(async_lib, Object::null_string(), function_name,
|
||||
0, 0, Object::null_array());
|
||||
ASSERT(!function.IsNull());
|
||||
set_async_clear_thread_stack_trace(function);
|
||||
|
||||
|
||||
function_name ^= async_lib.PrivateName(Symbols::AsyncStarMoveNextHelper());
|
||||
ASSERT(!function_name.IsNull());
|
||||
function ^= Resolver::ResolveStatic(async_lib, Object::null_string(),
|
||||
function_name, 1, Object::null_array());
|
||||
function ^=
|
||||
Resolver::ResolveStatic(async_lib, Object::null_string(), function_name,
|
||||
0, 1, Object::null_array());
|
||||
ASSERT(!function.IsNull());
|
||||
set_async_star_move_next_helper(function);
|
||||
|
||||
function_name ^= async_lib.PrivateName(Symbols::_CompleteOnAsyncReturn());
|
||||
ASSERT(!function_name.IsNull());
|
||||
function ^= Resolver::ResolveStatic(async_lib, Object::null_string(),
|
||||
function_name, 2, Object::null_array());
|
||||
function ^=
|
||||
Resolver::ResolveStatic(async_lib, Object::null_string(), function_name,
|
||||
0, 2, Object::null_array());
|
||||
ASSERT(!function.IsNull());
|
||||
set_complete_on_async_return(function);
|
||||
if (FLAG_async_debugger) {
|
||||
|
|
|
@ -3020,8 +3020,10 @@ ISOLATE_UNIT_TEST_CASE(ICData) {
|
|||
const intptr_t id = 12;
|
||||
const intptr_t num_args_tested = 1;
|
||||
const String& target_name = String::Handle(Symbols::New(thread, "Thun"));
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 1;
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs, Object::null_array()));
|
||||
ICData& o1 = ICData::Handle();
|
||||
o1 = ICData::New(function, target_name, args_descriptor, id, num_args_tested,
|
||||
false);
|
||||
|
@ -3842,7 +3844,7 @@ ISOLATE_UNIT_TEST_CASE(FindInvocationDispatcherFunctionIndex) {
|
|||
// Add invocation dispatcher.
|
||||
const String& invocation_dispatcher_name =
|
||||
String::Handle(Symbols::New(thread, "myMethod"));
|
||||
const Array& args_desc = Array::Handle(ArgumentsDescriptor::New(1));
|
||||
const Array& args_desc = Array::Handle(ArgumentsDescriptor::New(0, 1));
|
||||
Function& invocation_dispatcher = Function::Handle();
|
||||
invocation_dispatcher ^= cls.GetInvocationDispatcher(
|
||||
invocation_dispatcher_name, args_desc,
|
||||
|
|
|
@ -1557,29 +1557,31 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) {
|
|||
|
||||
OpenFunctionBlock(func);
|
||||
|
||||
const Function& parent = Function::Handle(func.parent_function());
|
||||
intptr_t type_args_len = 0; // Length of type args vector passed to parent.
|
||||
LocalVariable* type_args_var = NULL;
|
||||
if (FLAG_reify_generic_functions) {
|
||||
// The parent function of an implicit closure is the original function, i.e.
|
||||
// non-closurized. It is not an enclosing function in the usual sense of a
|
||||
// parent function. Do not set parent_type_arguments() in parsed_function_.
|
||||
ASSERT(func.IsGeneric() == func.HasGenericParent());
|
||||
ASSERT(func.IsGeneric() == parent.IsGeneric());
|
||||
|
||||
if (func.IsGeneric()) {
|
||||
type_args_len = func.NumTypeParameters();
|
||||
// Insert function type arguments variable to scope.
|
||||
LocalVariable* function_type_arguments = new (Z) LocalVariable(
|
||||
type_args_var = new (Z) LocalVariable(
|
||||
TokenPosition::kNoSource, TokenPosition::kNoSource,
|
||||
Symbols::FunctionTypeArgumentsVar(), Object::dynamic_type());
|
||||
current_block_->scope->AddVariable(function_type_arguments);
|
||||
current_block_->scope->AddVariable(type_args_var);
|
||||
ASSERT(FunctionLevel() == 0);
|
||||
parsed_function_->set_function_type_arguments(function_type_arguments);
|
||||
parsed_function_->set_function_type_arguments(type_args_var);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(regis): Pass the function type arguments if func is generic.
|
||||
ParamList params;
|
||||
params.AddFinalParameter(token_pos, &Symbols::ClosureParameter(),
|
||||
&Object::dynamic_type());
|
||||
|
||||
const Function& parent = Function::Handle(func.parent_function());
|
||||
if (parent.IsImplicitSetterFunction()) {
|
||||
const TokenPosition ident_pos = func.token_pos();
|
||||
ASSERT(IsIdentifier());
|
||||
|
@ -1605,7 +1607,8 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) {
|
|||
LocalScope* scope = current_block_->scope;
|
||||
AddFormalParamsToScope(¶ms, scope);
|
||||
|
||||
ArgumentListNode* func_args = new ArgumentListNode(token_pos);
|
||||
ArgumentListNode* func_args =
|
||||
new ArgumentListNode(token_pos, type_args_var, type_args_len);
|
||||
if (!func.is_static()) {
|
||||
func_args->Add(LoadReceiver(token_pos));
|
||||
}
|
||||
|
@ -1654,9 +1657,10 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) {
|
|||
|
||||
ArgumentListNode* arguments = BuildNoSuchMethodArguments(
|
||||
token_pos, func_name, *func_args, NULL, false);
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArguments = 2; // Receiver, InvocationMirror.
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kNumArguments)));
|
||||
ArgumentsDescriptor args_desc(Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
Function& no_such_method =
|
||||
Function::ZoneHandle(Z, Resolver::ResolveDynamicForReceiverClass(
|
||||
owner, Symbols::NoSuchMethod(), args_desc));
|
||||
|
@ -1797,9 +1801,10 @@ SequenceNode* Parser::ParseNoSuchMethodDispatcher(const Function& func) {
|
|||
const String& func_name = String::ZoneHandle(Z, func.name());
|
||||
ArgumentListNode* arguments =
|
||||
BuildNoSuchMethodArguments(token_pos, func_name, *func_args, NULL, false);
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArguments = 2; // Receiver, InvocationMirror.
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
Function& no_such_method = Function::ZoneHandle(
|
||||
Z,
|
||||
Resolver::ResolveDynamicForReceiverClass(
|
||||
|
@ -2378,7 +2383,8 @@ RawFunction* Parser::GetSuperFunction(TokenPosition token_pos,
|
|||
Function& super_func = Function::Handle(
|
||||
Z, Resolver::ResolveDynamicAnyArgs(Z, super_class, name));
|
||||
if (!super_func.IsNull() &&
|
||||
!super_func.AreValidArguments(arguments->length(), arguments->names(),
|
||||
!super_func.AreValidArguments(arguments->type_args_len(),
|
||||
arguments->length(), arguments->names(),
|
||||
NULL)) {
|
||||
super_func = Function::null();
|
||||
} else if (super_func.IsNull() && resolve_getter) {
|
||||
|
@ -2416,12 +2422,19 @@ StaticCallNode* Parser::BuildInvocationMirrorAllocation(
|
|||
arguments->Add(new LiteralNode(args_pos, function_name));
|
||||
// The second argument is the arguments descriptor of the original function.
|
||||
const Array& args_descriptor = Array::ZoneHandle(
|
||||
ArgumentsDescriptor::New(function_args.length(), function_args.names()));
|
||||
ArgumentsDescriptor::New(function_args.type_args_len(),
|
||||
function_args.length(), function_args.names()));
|
||||
arguments->Add(new LiteralNode(args_pos, args_descriptor));
|
||||
// The third argument is an array containing the original function arguments,
|
||||
// including the receiver.
|
||||
// including the function type arguments and the receiver.
|
||||
ArrayNode* args_array =
|
||||
new ArrayNode(args_pos, Type::ZoneHandle(Type::ArrayType()));
|
||||
// The type_args_var is only used in the generated body of an implicit closure
|
||||
// where noSuchMethod should never be called.
|
||||
ASSERT(function_args.type_args_var() == NULL);
|
||||
if (!function_args.type_arguments().IsNull()) {
|
||||
// TODO(regis): Pass the original type arguments to the invocation mirror.
|
||||
}
|
||||
for (intptr_t i = 0; i < function_args.length(); i++) {
|
||||
AstNode* arg = function_args.NodeAt(i);
|
||||
if ((temp_for_last_arg != NULL) && (i == function_args.length() - 1)) {
|
||||
|
@ -2467,16 +2480,18 @@ ArgumentListNode* Parser::BuildNoSuchMethodArguments(
|
|||
}
|
||||
|
||||
|
||||
AstNode* Parser::ParseSuperCall(const String& function_name) {
|
||||
AstNode* Parser::ParseSuperCall(const String& function_name,
|
||||
const TypeArguments& func_type_args) {
|
||||
TRACE_PARSER("ParseSuperCall");
|
||||
ASSERT(CurrentToken() == Token::kLPAREN);
|
||||
const TokenPosition supercall_pos = TokenPos();
|
||||
|
||||
// 'this' parameter is the first argument to super call.
|
||||
ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
|
||||
// 'this' parameter is the first argument to super call (after the type args).
|
||||
ArgumentListNode* arguments =
|
||||
new ArgumentListNode(supercall_pos, func_type_args);
|
||||
AstNode* receiver = LoadReceiver(supercall_pos);
|
||||
arguments->Add(receiver);
|
||||
ParseActualParameters(arguments, kAllowConst);
|
||||
ParseActualParameters(arguments, Object::null_type_arguments(), kAllowConst);
|
||||
|
||||
const bool kResolveGetter = true;
|
||||
bool is_no_such_method = false;
|
||||
|
@ -2490,7 +2505,8 @@ AstNode* Parser::ParseSuperCall(const String& function_name) {
|
|||
AstNode* closure = new StaticGetterNode(
|
||||
supercall_pos, LoadReceiver(supercall_pos), super_class, function_name);
|
||||
// 'this' is not passed as parameter to the closure.
|
||||
ArgumentListNode* closure_arguments = new ArgumentListNode(supercall_pos);
|
||||
ArgumentListNode* closure_arguments =
|
||||
new ArgumentListNode(supercall_pos, func_type_args);
|
||||
for (int i = 1; i < arguments->length(); i++) {
|
||||
closure_arguments->Add(arguments->NodeAt(i));
|
||||
}
|
||||
|
@ -2705,7 +2721,8 @@ StaticCallNode* Parser::GenerateSuperConstructorCall(
|
|||
}
|
||||
|
||||
String& error_message = String::Handle(Z);
|
||||
if (!super_ctor.AreValidArguments(arguments->length(), arguments->names(),
|
||||
if (!super_ctor.AreValidArguments(arguments->type_args_len(),
|
||||
arguments->length(), arguments->names(),
|
||||
&error_message)) {
|
||||
ReportError(supercall_pos,
|
||||
"invalid arguments passed to super constructor '%s()': %s",
|
||||
|
@ -2740,7 +2757,7 @@ StaticCallNode* Parser::ParseSuperInitializer(const Class& cls,
|
|||
|
||||
// 'this' parameter must not be accessible to the other super call arguments.
|
||||
receiver->set_invisible(true);
|
||||
ParseActualParameters(arguments, kAllowConst);
|
||||
ParseActualParameters(arguments, Object::null_type_arguments(), kAllowConst);
|
||||
receiver->set_invisible(false);
|
||||
|
||||
// Resolve the constructor.
|
||||
|
@ -2760,7 +2777,8 @@ StaticCallNode* Parser::ParseSuperInitializer(const Class& cls,
|
|||
ReportError(supercall_pos, "super constructor must be const");
|
||||
}
|
||||
String& error_message = String::Handle(Z);
|
||||
if (!super_ctor.AreValidArguments(arguments->length(), arguments->names(),
|
||||
if (!super_ctor.AreValidArguments(arguments->type_args_len(),
|
||||
arguments->length(), arguments->names(),
|
||||
&error_message)) {
|
||||
ReportError(supercall_pos,
|
||||
"invalid arguments passed to super class constructor '%s': %s",
|
||||
|
@ -3132,7 +3150,7 @@ void Parser::ParseConstructorRedirection(const Class& cls,
|
|||
arguments->Add(implicit_argument);
|
||||
|
||||
receiver->set_invisible(true);
|
||||
ParseActualParameters(arguments, kAllowConst);
|
||||
ParseActualParameters(arguments, Object::null_type_arguments(), kAllowConst);
|
||||
receiver->set_invisible(false);
|
||||
// Resolve the constructor.
|
||||
const Function& redirect_ctor =
|
||||
|
@ -3151,7 +3169,8 @@ void Parser::ParseConstructorRedirection(const Class& cls,
|
|||
String::Handle(Z, redirect_ctor.UserVisibleName()).ToCString());
|
||||
}
|
||||
String& error_message = String::Handle(Z);
|
||||
if (!redirect_ctor.AreValidArguments(arguments->length(), arguments->names(),
|
||||
if (!redirect_ctor.AreValidArguments(arguments->type_args_len(),
|
||||
arguments->length(), arguments->names(),
|
||||
&error_message)) {
|
||||
ReportError(call_pos, "invalid arguments passed to constructor '%s': %s",
|
||||
String::Handle(Z, redirect_ctor.UserVisibleName()).ToCString(),
|
||||
|
@ -9618,9 +9637,10 @@ AstNode* Parser::MakeStaticCall(const String& cls_name,
|
|||
ArgumentListNode* arguments) {
|
||||
const Class& cls = Class::Handle(Z, Library::LookupCoreClass(cls_name));
|
||||
ASSERT(!cls.IsNull());
|
||||
const intptr_t kTypeArgsLen = 0; // Not passing type args to generic func.
|
||||
const Function& func = Function::ZoneHandle(
|
||||
Z, Resolver::ResolveStatic(cls, func_name, arguments->length(),
|
||||
arguments->names()));
|
||||
Z, Resolver::ResolveStatic(cls, func_name, kTypeArgsLen,
|
||||
arguments->length(), arguments->names()));
|
||||
ASSERT(!func.IsNull());
|
||||
return new (Z) StaticCallNode(arguments->token_pos(), func, arguments);
|
||||
}
|
||||
|
@ -11626,14 +11646,19 @@ AstNode* Parser::ParseUnaryExpr() {
|
|||
|
||||
ArgumentListNode* Parser::ParseActualParameters(
|
||||
ArgumentListNode* implicit_arguments,
|
||||
const TypeArguments& func_type_args,
|
||||
bool require_const) {
|
||||
TRACE_PARSER("ParseActualParameters");
|
||||
ASSERT(CurrentToken() == Token::kLPAREN);
|
||||
const bool saved_mode = SetAllowFunctionLiterals(true);
|
||||
ArgumentListNode* arguments;
|
||||
if (implicit_arguments == NULL) {
|
||||
arguments = new (Z) ArgumentListNode(TokenPos());
|
||||
// TODO(regis): When require_const is true, do we need to check that
|
||||
// func_type_args are null or instantiated?
|
||||
arguments = new (Z) ArgumentListNode(TokenPos(), func_type_args);
|
||||
} else {
|
||||
// If implicit arguments are provided, they include type arguments (if any).
|
||||
ASSERT(func_type_args.IsNull());
|
||||
arguments = implicit_arguments;
|
||||
}
|
||||
const GrowableObjectArray& names =
|
||||
|
@ -11684,15 +11709,17 @@ ArgumentListNode* Parser::ParseActualParameters(
|
|||
AstNode* Parser::ParseStaticCall(const Class& cls,
|
||||
const String& func_name,
|
||||
TokenPosition ident_pos,
|
||||
const TypeArguments& func_type_args,
|
||||
const LibraryPrefix* prefix) {
|
||||
TRACE_PARSER("ParseStaticCall");
|
||||
const TokenPosition call_pos = TokenPos();
|
||||
ASSERT(CurrentToken() == Token::kLPAREN);
|
||||
ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
|
||||
ArgumentListNode* arguments =
|
||||
ParseActualParameters(NULL, func_type_args, kAllowConst);
|
||||
const int num_arguments = arguments->length();
|
||||
const Function& func = Function::ZoneHandle(
|
||||
Z, Resolver::ResolveStatic(cls, func_name, num_arguments,
|
||||
arguments->names()));
|
||||
Z, Resolver::ResolveStatic(cls, func_name, func_type_args.Length(),
|
||||
num_arguments, arguments->names()));
|
||||
if (func.IsNull()) {
|
||||
// Check if there is a static field of the same name, it could be a closure
|
||||
// and so we try and invoke the closure.
|
||||
|
@ -11704,9 +11731,10 @@ AstNode* Parser::ParseStaticCall(const Class& cls,
|
|||
const String& getter_name =
|
||||
String::ZoneHandle(Z, Field::LookupGetterSymbol(func_name));
|
||||
if (!getter_name.IsNull()) {
|
||||
const int kTypeArgsLen = 0; // no type arguments.
|
||||
const int kNumArguments = 0; // no arguments.
|
||||
func = Resolver::ResolveStatic(cls, getter_name, kNumArguments,
|
||||
Object::empty_array());
|
||||
func = Resolver::ResolveStatic(cls, getter_name, kTypeArgsLen,
|
||||
kNumArguments, Object::empty_array());
|
||||
if (!func.IsNull()) {
|
||||
ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter);
|
||||
closure = new (Z) StaticGetterNode(
|
||||
|
@ -11725,7 +11753,8 @@ AstNode* Parser::ParseStaticCall(const Class& cls,
|
|||
NULL, // No existing function.
|
||||
prefix);
|
||||
} else if (cls.IsTopLevel() && (cls.library() == Library::CoreLibrary()) &&
|
||||
(func.name() == Symbols::Identical().raw())) {
|
||||
(func.name() == Symbols::Identical().raw()) &&
|
||||
func_type_args.IsNull()) {
|
||||
// This is the predefined toplevel function identical(a,b).
|
||||
// Create a comparison node instead of a static call to the function.
|
||||
ASSERT(num_arguments == 2);
|
||||
|
@ -11759,20 +11788,24 @@ AstNode* Parser::ParseStaticCall(const Class& cls,
|
|||
AstNode* Parser::ParseInstanceCall(AstNode* receiver,
|
||||
const String& func_name,
|
||||
TokenPosition ident_pos,
|
||||
const TypeArguments& func_type_args,
|
||||
bool is_conditional) {
|
||||
TRACE_PARSER("ParseInstanceCall");
|
||||
CheckToken(Token::kLPAREN);
|
||||
ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
|
||||
ArgumentListNode* arguments =
|
||||
ParseActualParameters(NULL, func_type_args, kAllowConst);
|
||||
return new (Z) InstanceCallNode(ident_pos, receiver, func_name, arguments,
|
||||
is_conditional);
|
||||
}
|
||||
|
||||
|
||||
AstNode* Parser::ParseClosureCall(AstNode* closure) {
|
||||
AstNode* Parser::ParseClosureCall(AstNode* closure,
|
||||
const TypeArguments& func_type_args) {
|
||||
TRACE_PARSER("ParseClosureCall");
|
||||
const TokenPosition call_pos = TokenPos();
|
||||
ASSERT(CurrentToken() == Token::kLPAREN);
|
||||
ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
|
||||
ArgumentListNode* arguments =
|
||||
ParseActualParameters(NULL, func_type_args, kAllowConst);
|
||||
return BuildClosureCall(call_pos, closure, arguments);
|
||||
}
|
||||
|
||||
|
@ -11972,29 +12005,31 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
|
|||
if (IsArgumentPart()) {
|
||||
// Identifier followed by optional type arguments and opening paren:
|
||||
// method call.
|
||||
TypeArguments& func_type_args = TypeArguments::ZoneHandle(Z);
|
||||
if (CurrentToken() == Token::kLT) {
|
||||
// Type arguments.
|
||||
if (!FLAG_generic_method_syntax) {
|
||||
ReportError("generic type arguments not supported.");
|
||||
}
|
||||
// TODO(regis): Pass type arguments in generic call.
|
||||
// For now, resolve type arguments and ignore.
|
||||
ParseTypeArguments(ClassFinalizer::kCanonicalize);
|
||||
func_type_args = ParseTypeArguments(ClassFinalizer::kCanonicalize);
|
||||
if (!FLAG_reify_generic_functions) {
|
||||
func_type_args = TypeArguments::null();
|
||||
}
|
||||
}
|
||||
PrimaryNode* primary_node = left->AsPrimaryNode();
|
||||
if ((primary_node != NULL) && primary_node->primary().IsClass()) {
|
||||
// Static method call prefixed with class name.
|
||||
const Class& cls = Class::Cast(primary_node->primary());
|
||||
selector =
|
||||
ParseStaticCall(cls, *ident, ident_pos, primary_node->prefix());
|
||||
selector = ParseStaticCall(cls, *ident, ident_pos, func_type_args,
|
||||
primary_node->prefix());
|
||||
} else {
|
||||
if ((primary_node != NULL) && primary_node->is_deferred_reference()) {
|
||||
const Class& cls = Class::Handle(library_.toplevel_class());
|
||||
selector =
|
||||
ParseStaticCall(cls, *ident, ident_pos, primary_node->prefix());
|
||||
selector = ParseStaticCall(cls, *ident, ident_pos, func_type_args,
|
||||
primary_node->prefix());
|
||||
} else {
|
||||
selector =
|
||||
ParseInstanceCall(left, *ident, ident_pos, is_conditional);
|
||||
selector = ParseInstanceCall(left, *ident, ident_pos,
|
||||
func_type_args, is_conditional);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -12063,14 +12098,16 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
|
|||
selector = new (Z)
|
||||
LoadIndexedNode(bracket_pos, array, index, Class::ZoneHandle(Z));
|
||||
} else if (IsArgumentPart()) {
|
||||
TypeArguments& func_type_args = TypeArguments::ZoneHandle(Z);
|
||||
if (CurrentToken() == Token::kLT) {
|
||||
// Type arguments.
|
||||
if (!FLAG_generic_method_syntax) {
|
||||
ReportError("generic type arguments not supported.");
|
||||
}
|
||||
// TODO(regis): Pass type arguments in generic call.
|
||||
// For now, resolve type arguments and ignore.
|
||||
ParseTypeArguments(ClassFinalizer::kCanonicalize);
|
||||
func_type_args = ParseTypeArguments(ClassFinalizer::kCanonicalize);
|
||||
if (!FLAG_reify_generic_functions) {
|
||||
func_type_args = TypeArguments::null();
|
||||
}
|
||||
}
|
||||
if (left->IsPrimaryNode()) {
|
||||
PrimaryNode* primary_node = left->AsPrimaryNode();
|
||||
|
@ -12081,7 +12118,8 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
|
|||
if (func.is_static()) {
|
||||
// Parse static function call.
|
||||
Class& cls = Class::Handle(Z, func.Owner());
|
||||
selector = ParseStaticCall(cls, func_name, primary_pos);
|
||||
selector =
|
||||
ParseStaticCall(cls, func_name, primary_pos, func_type_args);
|
||||
} else {
|
||||
// Dynamic function call on implicit "this" parameter.
|
||||
if (current_function().is_static()) {
|
||||
|
@ -12090,9 +12128,9 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
|
|||
"from static function",
|
||||
func_name.ToCString());
|
||||
}
|
||||
selector =
|
||||
ParseInstanceCall(LoadReceiver(primary_pos), func_name,
|
||||
primary_pos, false /* is_conditional */);
|
||||
selector = ParseInstanceCall(LoadReceiver(primary_pos), func_name,
|
||||
primary_pos, func_type_args,
|
||||
false /* is_conditional */);
|
||||
}
|
||||
} else if (primary_node->primary().IsString()) {
|
||||
// Primary is an unresolved name.
|
||||
|
@ -12104,20 +12142,23 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
|
|||
if (primary_node->is_deferred_reference()) {
|
||||
// The static call will be converted to throwing a NSM error.
|
||||
const Class& cls = Class::Handle(library_.toplevel_class());
|
||||
selector =
|
||||
ParseStaticCall(cls, name, primary_pos, primary_node->prefix());
|
||||
selector = ParseStaticCall(cls, name, primary_pos, func_type_args,
|
||||
primary_node->prefix());
|
||||
} else if (current_function().is_static()) {
|
||||
// The static call will be converted to throwing a NSM error.
|
||||
selector = ParseStaticCall(current_class(), name, primary_pos);
|
||||
selector = ParseStaticCall(current_class(), name, primary_pos,
|
||||
func_type_args);
|
||||
} else {
|
||||
// Treat as call to unresolved (instance) method.
|
||||
selector =
|
||||
ParseInstanceCall(LoadReceiver(primary_pos), name, primary_pos,
|
||||
false /* is_conditional */);
|
||||
func_type_args, false /* is_conditional */);
|
||||
}
|
||||
} else if (primary_node->primary().IsTypeParameter()) {
|
||||
// TODO(regis): What about the parsed type arguments?
|
||||
selector = LoadTypeParameter(primary_node);
|
||||
} else if (primary_node->primary().IsClass()) {
|
||||
// TODO(regis): What about the parsed type arguments?
|
||||
const Class& type_class = Class::Cast(primary_node->primary());
|
||||
AbstractType& type = Type::ZoneHandle(
|
||||
Z, Type::New(type_class, Object::null_type_arguments(),
|
||||
|
@ -12133,7 +12174,7 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
|
|||
} else {
|
||||
// Left is not a primary node; this must be a closure call.
|
||||
AstNode* closure = left;
|
||||
selector = ParseClosureCall(closure);
|
||||
selector = ParseClosureCall(closure, func_type_args);
|
||||
}
|
||||
} else {
|
||||
// No (more) selectors to parse.
|
||||
|
@ -12683,10 +12724,11 @@ StaticGetterNode* Parser::RunStaticFieldInitializer(
|
|||
NoReloadScope no_reload_scope(isolate(), thread());
|
||||
NoOOBMessageScope no_msg_scope(thread());
|
||||
field.SetStaticValue(Object::transition_sentinel());
|
||||
const int kNumArguments = 0; // no arguments.
|
||||
const int kTypeArgsLen = 0; // No type argument vector.
|
||||
const int kNumArguments = 0; // No arguments.
|
||||
const Function& func = Function::Handle(
|
||||
Z, Resolver::ResolveStatic(field_owner, getter_name, kNumArguments,
|
||||
Object::empty_array()));
|
||||
Z, Resolver::ResolveStatic(field_owner, getter_name, kTypeArgsLen,
|
||||
kNumArguments, Object::empty_array()));
|
||||
ASSERT(!func.IsNull());
|
||||
ASSERT(func.kind() == RawFunction::kImplicitStaticFinalGetter);
|
||||
Object& const_value = Object::Handle(Z);
|
||||
|
@ -12737,8 +12779,10 @@ RawObject* Parser::EvaluateConstConstructorCall(
|
|||
ArgumentListNode* arguments) {
|
||||
NoReloadScope no_reload_scope(isolate(), thread());
|
||||
NoOOBMessageScope no_msg_scope(thread());
|
||||
// Factories and constructors are not generic functions.
|
||||
const int kTypeArgsLen = 0;
|
||||
// Factories have one extra argument: the type arguments.
|
||||
// Constructors have 1 extra arguments: receiver.
|
||||
// Constructors have one extra arguments: receiver.
|
||||
const int kNumExtraArgs = 1;
|
||||
const int num_arguments = arguments->length() + kNumExtraArgs;
|
||||
const Array& arg_values =
|
||||
|
@ -12765,8 +12809,9 @@ RawObject* Parser::EvaluateConstConstructorCall(
|
|||
ASSERT(arg->IsLiteralNode());
|
||||
arg_values.SetAt((i + kNumExtraArgs), arg->AsLiteralNode()->literal());
|
||||
}
|
||||
const Array& args_descriptor = Array::Handle(
|
||||
Z, ArgumentsDescriptor::New(num_arguments, arguments->names()));
|
||||
const Array& args_descriptor =
|
||||
Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, num_arguments,
|
||||
arguments->names()));
|
||||
const Object& result = Object::Handle(
|
||||
Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
|
||||
if (result.IsError()) {
|
||||
|
@ -14070,7 +14115,8 @@ AstNode* Parser::ParseNewOperator(Token::Kind op_kind) {
|
|||
if (!is_tearoff_expression) {
|
||||
CheckToken(Token::kLPAREN);
|
||||
call_pos = TokenPos();
|
||||
arguments = ParseActualParameters(NULL, is_const);
|
||||
arguments =
|
||||
ParseActualParameters(NULL, TypeArguments::ZoneHandle(Z), is_const);
|
||||
} else {
|
||||
// Allocate dummy node with no arguments so we don't have to deal
|
||||
// with the NULL corner case below.
|
||||
|
@ -14249,9 +14295,10 @@ AstNode* Parser::ParseNewOperator(Token::Kind op_kind) {
|
|||
}
|
||||
|
||||
ASSERT(!is_tearoff_expression);
|
||||
const int kTypeArgsLen = 0;
|
||||
String& error_message = String::Handle(Z);
|
||||
if (!constructor.AreValidArguments(arguments_length, arguments->names(),
|
||||
&error_message)) {
|
||||
if (!constructor.AreValidArguments(kTypeArgsLen, arguments_length,
|
||||
arguments->names(), &error_message)) {
|
||||
const String& external_constructor_name =
|
||||
(named_constructor ? constructor_name : type_class_name);
|
||||
if (is_const) {
|
||||
|
@ -14657,8 +14704,19 @@ AstNode* Parser::ParsePrimary() {
|
|||
ConsumeToken();
|
||||
const TokenPosition ident_pos = TokenPos();
|
||||
const String& ident = *ExpectIdentifier("identifier expected");
|
||||
if (CurrentToken() == Token::kLPAREN) {
|
||||
primary = ParseSuperCall(ident);
|
||||
if (IsArgumentPart()) {
|
||||
TypeArguments& func_type_args = TypeArguments::ZoneHandle(Z);
|
||||
if (CurrentToken() == Token::kLT) {
|
||||
// Type arguments.
|
||||
if (!FLAG_generic_method_syntax) {
|
||||
ReportError("generic type arguments not supported.");
|
||||
}
|
||||
func_type_args = ParseTypeArguments(ClassFinalizer::kCanonicalize);
|
||||
if (!FLAG_reify_generic_functions) {
|
||||
func_type_args = TypeArguments::null();
|
||||
}
|
||||
}
|
||||
primary = ParseSuperCall(ident, func_type_args);
|
||||
} else {
|
||||
primary = ParseSuperFieldAccess(ident, ident_pos);
|
||||
}
|
||||
|
|
|
@ -616,7 +616,8 @@ class Parser : public ValueObject {
|
|||
ArgumentListNode* arguments,
|
||||
bool resolve_getter,
|
||||
bool* is_no_such_method);
|
||||
AstNode* ParseSuperCall(const String& function_name);
|
||||
AstNode* ParseSuperCall(const String& function_name,
|
||||
const TypeArguments& func_type_args);
|
||||
AstNode* ParseSuperFieldAccess(const String& field_name,
|
||||
TokenPosition field_pos);
|
||||
AstNode* ParseSuperOperator();
|
||||
|
@ -833,16 +834,20 @@ class Parser : public ValueObject {
|
|||
|
||||
// An implicit argument, if non-null, is prepended to the returned list.
|
||||
ArgumentListNode* ParseActualParameters(ArgumentListNode* implicit_arguments,
|
||||
const TypeArguments& func_type_args,
|
||||
bool require_const);
|
||||
AstNode* ParseStaticCall(const Class& cls,
|
||||
const String& method_name,
|
||||
TokenPosition ident_pos,
|
||||
const TypeArguments& func_type_args,
|
||||
const LibraryPrefix* prefix = NULL);
|
||||
AstNode* ParseInstanceCall(AstNode* receiver,
|
||||
const String& method_name,
|
||||
TokenPosition ident_pos,
|
||||
const TypeArguments& func_type_args,
|
||||
bool is_conditional);
|
||||
AstNode* ParseClosureCall(AstNode* closure);
|
||||
AstNode* ParseClosureCall(AstNode* closure,
|
||||
const TypeArguments& func_type_args);
|
||||
AstNode* GenerateStaticFieldLookup(const Field& field,
|
||||
TokenPosition ident_pos);
|
||||
AstNode* GenerateStaticFieldAccess(const Class& cls,
|
||||
|
|
|
@ -823,11 +823,13 @@ void Precompiler::CollectCallbackFields() {
|
|||
// Create arguments descriptor with fixed parameters from
|
||||
// signature of field_type.
|
||||
function = Type::Cast(field_type).signature();
|
||||
if (function.IsGeneric()) continue;
|
||||
if (function.HasOptionalParameters()) continue;
|
||||
if (FLAG_trace_precompiler) {
|
||||
THR_Print("Found callback field %s\n", field_name.ToCString());
|
||||
}
|
||||
args_desc = ArgumentsDescriptor::New(function.num_fixed_parameters());
|
||||
args_desc = ArgumentsDescriptor::New(0, // No type argument vector.
|
||||
function.num_fixed_parameters());
|
||||
cids.Clear();
|
||||
if (T->cha()->ConcreteSubclasses(cls, &cids)) {
|
||||
for (intptr_t j = 0; j < cids.length(); ++j) {
|
||||
|
@ -2513,9 +2515,8 @@ void Precompiler::PopulateWithICData(const Function& function,
|
|||
if (instr->IsInstanceCall()) {
|
||||
InstanceCallInstr* call = instr->AsInstanceCall();
|
||||
if (!call->HasICData()) {
|
||||
const Array& arguments_descriptor = Array::Handle(
|
||||
zone, ArgumentsDescriptor::New(call->ArgumentCount(),
|
||||
call->argument_names()));
|
||||
const Array& arguments_descriptor =
|
||||
Array::Handle(zone, call->GetArgumentsDescriptor());
|
||||
const ICData& ic_data = ICData::ZoneHandle(
|
||||
zone, ICData::New(function, call->function_name(),
|
||||
arguments_descriptor, call->deopt_id(),
|
||||
|
@ -2525,9 +2526,8 @@ void Precompiler::PopulateWithICData(const Function& function,
|
|||
} else if (instr->IsStaticCall()) {
|
||||
StaticCallInstr* call = instr->AsStaticCall();
|
||||
if (!call->HasICData()) {
|
||||
const Array& arguments_descriptor = Array::Handle(
|
||||
zone, ArgumentsDescriptor::New(call->ArgumentCount(),
|
||||
call->argument_names()));
|
||||
const Array& arguments_descriptor =
|
||||
Array::Handle(zone, call->GetArgumentsDescriptor());
|
||||
const Function& target = call->function();
|
||||
MethodRecognizer::Kind recognized_kind =
|
||||
MethodRecognizer::RecognizeKind(target);
|
||||
|
|
|
@ -537,9 +537,10 @@ StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
|
|||
StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
|
||||
const Function& function,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
return new (Z)
|
||||
StaticCallInstr(TokenPosition::kNoSource, function, Object::null_array(),
|
||||
arguments, ic_data_array_);
|
||||
StaticCallInstr(TokenPosition::kNoSource, function, kTypeArgsLen,
|
||||
Object::null_array(), arguments, ic_data_array_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -585,9 +586,11 @@ InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
|
|||
InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
|
||||
const InstanceCallDescriptor& desc,
|
||||
ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
|
||||
return new (Z) InstanceCallInstr(
|
||||
TokenPosition::kNoSource, desc.name, desc.token_kind, arguments,
|
||||
Object::null_array(), desc.checked_argument_count, ic_data_array_);
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
return new (Z)
|
||||
InstanceCallInstr(TokenPosition::kNoSource, desc.name, desc.token_kind,
|
||||
arguments, kTypeArgsLen, Object::null_array(),
|
||||
desc.checked_argument_count, ic_data_array_);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -146,6 +146,7 @@ RawFunction* Resolver::ResolveDynamicAnyArgs(Zone* zone,
|
|||
RawFunction* Resolver::ResolveStatic(const Library& library,
|
||||
const String& class_name,
|
||||
const String& function_name,
|
||||
intptr_t type_args_len,
|
||||
intptr_t num_arguments,
|
||||
const Array& argument_names) {
|
||||
ASSERT(!library.IsNull());
|
||||
|
@ -155,12 +156,13 @@ RawFunction* Resolver::ResolveStatic(const Library& library,
|
|||
const Object& object = Object::Handle(library.ResolveName(function_name));
|
||||
if (!object.IsNull() && object.IsFunction()) {
|
||||
function ^= object.raw();
|
||||
if (!function.AreValidArguments(num_arguments, argument_names, NULL)) {
|
||||
if (!function.AreValidArguments(type_args_len, num_arguments,
|
||||
argument_names, NULL)) {
|
||||
if (FLAG_trace_resolving) {
|
||||
String& error_message = String::Handle();
|
||||
// Obtain more detailed error message.
|
||||
function.AreValidArguments(num_arguments, argument_names,
|
||||
&error_message);
|
||||
function.AreValidArguments(type_args_len, num_arguments,
|
||||
argument_names, &error_message);
|
||||
THR_Print("ResolveStatic error '%s': %s.\n",
|
||||
function_name.ToCString(), error_message.ToCString());
|
||||
}
|
||||
|
@ -178,8 +180,8 @@ RawFunction* Resolver::ResolveStatic(const Library& library,
|
|||
// ResolveStatic will return a NULL function object.
|
||||
const Class& cls = Class::Handle(library.LookupClass(class_name));
|
||||
if (!cls.IsNull()) {
|
||||
function =
|
||||
ResolveStatic(cls, function_name, num_arguments, argument_names);
|
||||
function = ResolveStatic(cls, function_name, type_args_len, num_arguments,
|
||||
argument_names);
|
||||
}
|
||||
if (FLAG_trace_resolving && function.IsNull()) {
|
||||
THR_Print("ResolveStatic error: function '%s.%s' not found.\n",
|
||||
|
@ -192,6 +194,7 @@ RawFunction* Resolver::ResolveStatic(const Library& library,
|
|||
|
||||
RawFunction* Resolver::ResolveStatic(const Class& cls,
|
||||
const String& function_name,
|
||||
intptr_t type_args_len,
|
||||
intptr_t num_arguments,
|
||||
const Array& argument_names) {
|
||||
ASSERT(!cls.IsNull());
|
||||
|
@ -201,14 +204,15 @@ RawFunction* Resolver::ResolveStatic(const Class& cls,
|
|||
const Function& function =
|
||||
Function::Handle(cls.LookupStaticFunction(function_name));
|
||||
if (function.IsNull() ||
|
||||
!function.AreValidArguments(num_arguments, argument_names, NULL)) {
|
||||
!function.AreValidArguments(type_args_len, num_arguments, argument_names,
|
||||
NULL)) {
|
||||
// Return a null function to signal to the upper levels to throw a
|
||||
// resolution error or maybe throw the error right here.
|
||||
if (FLAG_trace_resolving) {
|
||||
String& error_message = String::Handle(String::New("function not found"));
|
||||
if (!function.IsNull()) {
|
||||
// Obtain more detailed error message.
|
||||
function.AreValidArguments(num_arguments, argument_names,
|
||||
function.AreValidArguments(type_args_len, num_arguments, argument_names,
|
||||
&error_message);
|
||||
}
|
||||
THR_Print("ResolveStatic error '%s': %s.\n", function_name.ToCString(),
|
||||
|
@ -222,6 +226,7 @@ RawFunction* Resolver::ResolveStatic(const Class& cls,
|
|||
|
||||
RawFunction* Resolver::ResolveStaticAllowPrivate(const Class& cls,
|
||||
const String& function_name,
|
||||
intptr_t type_args_len,
|
||||
intptr_t num_arguments,
|
||||
const Array& argument_names) {
|
||||
ASSERT(!cls.IsNull());
|
||||
|
@ -231,14 +236,15 @@ RawFunction* Resolver::ResolveStaticAllowPrivate(const Class& cls,
|
|||
const Function& function =
|
||||
Function::Handle(cls.LookupStaticFunctionAllowPrivate(function_name));
|
||||
if (function.IsNull() ||
|
||||
!function.AreValidArguments(num_arguments, argument_names, NULL)) {
|
||||
!function.AreValidArguments(type_args_len, num_arguments, argument_names,
|
||||
NULL)) {
|
||||
// Return a null function to signal to the upper levels to throw a
|
||||
// resolution error or maybe throw the error right here.
|
||||
if (FLAG_trace_resolving) {
|
||||
String& error_message = String::Handle(String::New("function not found"));
|
||||
if (!function.IsNull()) {
|
||||
// Obtain more detailed error message.
|
||||
function.AreValidArguments(num_arguments, argument_names,
|
||||
function.AreValidArguments(type_args_len, num_arguments, argument_names,
|
||||
&error_message);
|
||||
}
|
||||
THR_Print("ResolveStaticAllowPrivate error '%s': %s.\n",
|
||||
|
|
|
@ -50,6 +50,7 @@ class Resolver : public AllStatic {
|
|||
static RawFunction* ResolveStatic(const Library& library,
|
||||
const String& cls_name,
|
||||
const String& function_name,
|
||||
intptr_t type_args_len,
|
||||
intptr_t num_arguments,
|
||||
const Array& argument_names);
|
||||
|
||||
|
@ -57,6 +58,7 @@ class Resolver : public AllStatic {
|
|||
// public functions.
|
||||
static RawFunction* ResolveStatic(const Class& cls,
|
||||
const String& function_name,
|
||||
intptr_t type_args_len,
|
||||
intptr_t num_arguments,
|
||||
const Array& argument_names);
|
||||
|
||||
|
@ -64,6 +66,7 @@ class Resolver : public AllStatic {
|
|||
// public and private functions.
|
||||
static RawFunction* ResolveStaticAllowPrivate(const Class& cls,
|
||||
const String& function_name,
|
||||
intptr_t type_args_len,
|
||||
intptr_t num_arguments,
|
||||
const Array& argument_names);
|
||||
};
|
||||
|
|
|
@ -88,10 +88,11 @@ TEST_CASE(DartStaticResolve) {
|
|||
|
||||
// Now try to resolve and invoke the static function in this class.
|
||||
{
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 2;
|
||||
const Function& function = Function::Handle(
|
||||
Resolver::ResolveStatic(library, class_name, static_function_name,
|
||||
kNumArguments, Object::empty_array()));
|
||||
const Function& function = Function::Handle(Resolver::ResolveStatic(
|
||||
library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
|
||||
Object::empty_array()));
|
||||
EXPECT(!function.IsNull()); // No ambiguity error expected.
|
||||
const Array& args = Array::Handle(Array::New(kNumArguments));
|
||||
const String& arg0 = String::Handle(String::New("junk"));
|
||||
|
@ -105,10 +106,11 @@ TEST_CASE(DartStaticResolve) {
|
|||
|
||||
// Now try to resolve a static function with invalid argument count.
|
||||
{
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 1;
|
||||
const Function& bad_function = Function::Handle(
|
||||
Resolver::ResolveStatic(library, class_name, static_function_name,
|
||||
kNumArguments, Object::empty_array()));
|
||||
const Function& bad_function = Function::Handle(Resolver::ResolveStatic(
|
||||
library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
|
||||
Object::empty_array()));
|
||||
EXPECT(bad_function.IsNull()); // No ambiguity error expected.
|
||||
}
|
||||
|
||||
|
@ -117,10 +119,11 @@ TEST_CASE(DartStaticResolve) {
|
|||
const String& super_static_function_name =
|
||||
String::Handle(String::New("statCall"));
|
||||
const String& super_class_name = String::Handle(String::New("Base"));
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 0;
|
||||
const Function& super_function = Function::Handle(Resolver::ResolveStatic(
|
||||
library, super_class_name, super_static_function_name, kNumArguments,
|
||||
Object::empty_array()));
|
||||
library, super_class_name, super_static_function_name, kTypeArgsLen,
|
||||
kNumArguments, Object::empty_array()));
|
||||
EXPECT(!super_function.IsNull()); // No ambiguity error expected.
|
||||
}
|
||||
}
|
||||
|
@ -150,9 +153,10 @@ TEST_CASE(DartDynamicResolve) {
|
|||
|
||||
// Now try to resolve and invoke the instance function in this class.
|
||||
{
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 3;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
const Function& function = Function::Handle(
|
||||
Resolver::ResolveDynamic(receiver, function_name, args_desc));
|
||||
EXPECT(!function.IsNull());
|
||||
|
@ -169,9 +173,10 @@ TEST_CASE(DartDynamicResolve) {
|
|||
|
||||
// Now try to resolve an instance function with invalid argument count.
|
||||
{
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 1;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
const Function& bad_function = Function::Handle(
|
||||
Resolver::ResolveDynamic(receiver, function_name, args_desc));
|
||||
EXPECT(bad_function.IsNull());
|
||||
|
@ -179,9 +184,10 @@ TEST_CASE(DartDynamicResolve) {
|
|||
|
||||
// Hierarchy walking.
|
||||
{
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 1;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
const String& super_function_name = String::Handle(String::New("dynCall"));
|
||||
const Function& super_function = Function::Handle(
|
||||
Resolver::ResolveDynamic(receiver, super_function_name, args_desc));
|
||||
|
|
|
@ -858,9 +858,10 @@ static bool ResolveCallThroughGetter(const Instance& receiver,
|
|||
Function* result) {
|
||||
// 1. Check if there is a getter with the same name.
|
||||
const String& getter_name = String::Handle(Field::GetterName(target_name));
|
||||
const int kTypeArgsLen = 0;
|
||||
const int kNumArguments = 1;
|
||||
ArgumentsDescriptor args_desc(
|
||||
Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
|
||||
const Function& getter =
|
||||
Function::Handle(Resolver::ResolveDynamicForReceiverClass(
|
||||
receiver_class, getter_name, args_desc));
|
||||
|
@ -930,7 +931,7 @@ static RawFunction* ComputeTypeCheckTarget(const Instance& receiver,
|
|||
|
||||
|
||||
static RawFunction* InlineCacheMissHandler(
|
||||
const GrowableArray<const Instance*>& args,
|
||||
const GrowableArray<const Instance*>& args, // Checked arguments only.
|
||||
const ICData& ic_data) {
|
||||
const Instance& receiver = *args[0];
|
||||
ArgumentsDescriptor arguments_descriptor(
|
||||
|
@ -1144,8 +1145,11 @@ DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 1) {
|
|||
// We lost the original ICData when we patched to the monomorphic case.
|
||||
const String& name = String::Handle(zone, old_target.name());
|
||||
ASSERT(!old_target.HasOptionalParameters());
|
||||
const Array& descriptor = Array::Handle(
|
||||
zone, ArgumentsDescriptor::New(old_target.num_fixed_parameters()));
|
||||
ASSERT(!old_target.IsGeneric());
|
||||
const int kTypeArgsLen = 0;
|
||||
const Array& descriptor =
|
||||
Array::Handle(zone, ArgumentsDescriptor::New(
|
||||
kTypeArgsLen, old_target.num_fixed_parameters()));
|
||||
const ICData& ic_data =
|
||||
ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
|
||||
Thread::kNoDeoptId, 1, /* args_tested */
|
||||
|
@ -1241,7 +1245,8 @@ DEFINE_RUNTIME_ENTRY(UnlinkedCall, 2) {
|
|||
ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
|
||||
}
|
||||
|
||||
if (!target_function.IsNull() && !target_function.HasOptionalParameters()) {
|
||||
if (!target_function.IsNull() && !target_function.HasOptionalParameters() &&
|
||||
!target_function.IsGeneric()) {
|
||||
// Patch to monomorphic call.
|
||||
ASSERT(target_function.HasCode());
|
||||
const Code& target_code = Code::Handle(zone, target_function.CurrentCode());
|
||||
|
@ -1299,8 +1304,11 @@ DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) {
|
|||
// We lost the original ICData when we patched to the monomorphic case.
|
||||
const String& name = String::Handle(zone, old_target.name());
|
||||
ASSERT(!old_target.HasOptionalParameters());
|
||||
const Array& descriptor = Array::Handle(
|
||||
zone, ArgumentsDescriptor::New(old_target.num_fixed_parameters()));
|
||||
ASSERT(!old_target.IsGeneric());
|
||||
const int kTypeArgsLen = 0;
|
||||
const Array& descriptor =
|
||||
Array::Handle(zone, ArgumentsDescriptor::New(
|
||||
kTypeArgsLen, old_target.num_fixed_parameters()));
|
||||
const ICData& ic_data =
|
||||
ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
|
||||
Thread::kNoDeoptId, 1, /* args_tested */
|
||||
|
@ -1409,7 +1417,8 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
|
|||
const ICData& ic_data = ICData::Cast(ic_data_or_cache);
|
||||
const intptr_t number_of_checks = ic_data.NumberOfChecks();
|
||||
|
||||
if (number_of_checks == 0 && !target_function.HasOptionalParameters() &&
|
||||
if ((number_of_checks == 0) && !target_function.HasOptionalParameters() &&
|
||||
!target_function.IsGeneric() &&
|
||||
!Isolate::Current()->compilation_allowed()) {
|
||||
// This call site is unlinked: transition to a monomorphic direct call.
|
||||
// Note we cannot do this if the target has optional parameters because
|
||||
|
|
|
@ -606,6 +606,12 @@ static void GenerateDispatcherCode(Assembler* assembler,
|
|||
__ Push(R8); // Receiver.
|
||||
__ Push(R9); // ICData/MegamorphicCache.
|
||||
__ Push(R4); // Arguments descriptor.
|
||||
|
||||
// Adjust arguments count.
|
||||
__ ldr(R3, FieldAddress(R4, ArgumentsDescriptor::type_args_len_offset()));
|
||||
__ cmp(R3, Operand(0));
|
||||
__ AddImmediate(R2, R2, Smi::RawValue(1), NE); // Include the type arguments.
|
||||
|
||||
// R2: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
const intptr_t kNumArgs = 4;
|
||||
|
@ -1251,6 +1257,11 @@ void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
|
|||
__ LoadImmediate(IP, 0);
|
||||
__ PushList((1 << R4) | (1 << R8) | (1 << IP));
|
||||
|
||||
// Adjust arguments count.
|
||||
__ ldr(R3, FieldAddress(R4, ArgumentsDescriptor::type_args_len_offset()));
|
||||
__ cmp(R3, Operand(0));
|
||||
__ AddImmediate(R2, R2, Smi::RawValue(1), NE); // Include the type arguments.
|
||||
|
||||
// R2: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
|
||||
|
|
|
@ -627,6 +627,13 @@ static void GenerateDispatcherCode(Assembler* assembler,
|
|||
__ Push(R6); // Receiver.
|
||||
__ Push(R5); // ICData/MegamorphicCache.
|
||||
__ Push(R4); // Arguments descriptor.
|
||||
|
||||
// Adjust arguments count.
|
||||
__ LoadFieldFromOffset(R3, R4, ArgumentsDescriptor::type_args_len_offset());
|
||||
__ AddImmediate(TMP, R2, Smi::RawValue(1)); // Include the type arguments.
|
||||
__ cmp(R3, Operand(0));
|
||||
__ csinc(R2, R2, TMP, EQ); // R2 <- (R3 == 0) ? R2 : TMP.
|
||||
|
||||
// R2: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
const intptr_t kNumArgs = 4;
|
||||
|
@ -1285,6 +1292,12 @@ void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
|
|||
__ Push(R6);
|
||||
__ Push(R4);
|
||||
|
||||
// Adjust arguments count.
|
||||
__ LoadFieldFromOffset(R3, R4, ArgumentsDescriptor::type_args_len_offset());
|
||||
__ AddImmediate(TMP, R2, Smi::RawValue(1)); // Include the type arguments.
|
||||
__ cmp(R3, Operand(0));
|
||||
__ csinc(R2, R2, TMP, EQ); // R2 <- (R3 == 0) ? R2 : TMP.
|
||||
|
||||
// R2: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
|
||||
|
|
|
@ -519,7 +519,16 @@ static void GenerateDispatcherCode(Assembler* assembler,
|
|||
__ pushl(EAX); // Receiver.
|
||||
__ pushl(ECX); // ICData/MegamorphicCache.
|
||||
__ pushl(EDX); // Arguments descriptor array.
|
||||
|
||||
// Adjust arguments count.
|
||||
__ cmpl(FieldAddress(EDX, ArgumentsDescriptor::type_args_len_offset()),
|
||||
Immediate(0));
|
||||
__ movl(EDX, EDI);
|
||||
Label args_count_ok;
|
||||
__ j(EQUAL, &args_count_ok, Assembler::kNearJump);
|
||||
__ addl(EDX, Immediate(Smi::RawValue(1))); // Include the type arguments.
|
||||
__ Bind(&args_count_ok);
|
||||
|
||||
// EDX: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
const intptr_t kNumArgs = 4;
|
||||
|
@ -1158,7 +1167,15 @@ void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
|
|||
__ pushl(EAX); // Receiver.
|
||||
__ pushl(EDX); // Arguments descriptor array.
|
||||
|
||||
// Adjust arguments count.
|
||||
__ cmpl(FieldAddress(EDX, ArgumentsDescriptor::type_args_len_offset()),
|
||||
Immediate(0));
|
||||
__ movl(EDX, EDI);
|
||||
Label args_count_ok;
|
||||
__ j(EQUAL, &args_count_ok, Assembler::kNearJump);
|
||||
__ addl(EDX, Immediate(Smi::RawValue(1))); // Include the type arguments.
|
||||
__ Bind(&args_count_ok);
|
||||
|
||||
// EDX: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
|
||||
|
|
|
@ -623,6 +623,14 @@ static void GenerateDispatcherCode(Assembler* assembler,
|
|||
__ sw(T6, Address(SP, 2 * kWordSize));
|
||||
__ sw(S5, Address(SP, 1 * kWordSize));
|
||||
__ sw(S4, Address(SP, 0 * kWordSize));
|
||||
|
||||
// Adjust arguments count.
|
||||
__ lw(TMP, FieldAddress(S4, ArgumentsDescriptor::type_args_len_offset()));
|
||||
Label args_count_ok;
|
||||
__ BranchEqual(TMP, Immediate(0), &args_count_ok);
|
||||
__ AddImmediate(A1, A1, Smi::RawValue(1)); // Include the type arguments.
|
||||
__ Bind(&args_count_ok);
|
||||
|
||||
// A1: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
const intptr_t kNumArgs = 4;
|
||||
|
@ -1308,6 +1316,13 @@ void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
|
|||
__ sw(T6, Address(SP, 1 * kWordSize));
|
||||
__ sw(S4, Address(SP, 0 * kWordSize));
|
||||
|
||||
// Adjust arguments count.
|
||||
__ lw(TMP, FieldAddress(S4, ArgumentsDescriptor::type_args_len_offset()));
|
||||
Label args_count_ok;
|
||||
__ BranchEqual(TMP, Immediate(0), &args_count_ok);
|
||||
__ AddImmediate(A1, A1, Smi::RawValue(1)); // Include the type arguments.
|
||||
__ Bind(&args_count_ok);
|
||||
|
||||
// A1: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
|
||||
|
|
|
@ -564,8 +564,17 @@ static void GenerateDispatcherCode(Assembler* assembler,
|
|||
__ pushq(RAX); // Receiver.
|
||||
__ pushq(RBX); // ICData/MegamorphicCache.
|
||||
__ pushq(R10); // Arguments descriptor array.
|
||||
|
||||
// Adjust arguments count.
|
||||
__ cmpq(FieldAddress(R10, ArgumentsDescriptor::type_args_len_offset()),
|
||||
Immediate(0));
|
||||
__ movq(R10, RDI);
|
||||
// EDX: Smi-tagged arguments array length.
|
||||
Label args_count_ok;
|
||||
__ j(EQUAL, &args_count_ok, Assembler::kNearJump);
|
||||
__ addq(R10, Immediate(Smi::RawValue(1))); // Include the type arguments.
|
||||
__ Bind(&args_count_ok);
|
||||
|
||||
// R10: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
const intptr_t kNumArgs = 4;
|
||||
__ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
|
||||
|
@ -1214,7 +1223,16 @@ void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
|
|||
__ pushq(RAX); // Receiver.
|
||||
__ pushq(R10); // Arguments descriptor array.
|
||||
|
||||
__ movq(R10, R13); // Smi-tagged arguments array length.
|
||||
// Adjust arguments count.
|
||||
__ cmpq(FieldAddress(R10, ArgumentsDescriptor::type_args_len_offset()),
|
||||
Immediate(0));
|
||||
__ movq(R10, R13);
|
||||
Label args_count_ok;
|
||||
__ j(EQUAL, &args_count_ok, Assembler::kNearJump);
|
||||
__ addq(R10, Immediate(Smi::RawValue(1))); // Include the type arguments.
|
||||
__ Bind(&args_count_ok);
|
||||
|
||||
// R10: Smi-tagged arguments array length.
|
||||
PushArgumentsArray(assembler);
|
||||
|
||||
const intptr_t kNumArgs = 3;
|
||||
|
|
|
@ -478,7 +478,10 @@ class AssemblerTest {
|
|||
COMPILE_ASSERT(!is_double<Arg3Type>::value);
|
||||
const Object& arg1obj = Object::Handle(reinterpret_cast<RawObject*>(arg1));
|
||||
const Object& arg2obj = Object::Handle(reinterpret_cast<RawObject*>(arg2));
|
||||
const Array& argdesc = Array::Handle(ArgumentsDescriptor::New(2));
|
||||
const intptr_t kTypeArgsLen = 0;
|
||||
const intptr_t kNumArgs = 2;
|
||||
const Array& argdesc =
|
||||
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs));
|
||||
const Array& arguments = Array::Handle(Array::New(2));
|
||||
arguments.SetAt(0, arg1obj);
|
||||
arguments.SetAt(1, arg2obj);
|
||||
|
|
Loading…
Reference in a new issue