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:
Régis Crelier 2017-05-18 14:03:43 -07:00
parent 59e6c332ea
commit 9aafded095
50 changed files with 1037 additions and 569 deletions

View file

@ -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)
];

View file

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

View file

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

View file

@ -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) ||

View file

@ -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);
}

View file

@ -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,

View file

@ -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_;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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.

View file

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

View file

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

View file

@ -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 __

View file

@ -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,

View file

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

View file

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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

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

View file

@ -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).

View file

@ -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);
}

View file

@ -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.

View file

@ -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(

View file

@ -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_; }

View file

@ -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

View file

@ -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;

View file

@ -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.

View file

@ -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,

View file

@ -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) {

View file

@ -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,

View file

@ -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(&params, 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);
}

View file

@ -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,

View file

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

View file

@ -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_);
}

View file

@ -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",

View file

@ -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);
};

View file

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

View file

@ -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

View file

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

View file

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

View file

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

View file

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

View file

@ -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;

View file

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