| Index: runtime/lib/mirrors.cc
|
| diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
|
| index dbead74ecea3e7fc86a6879a72b926a2eb10876c..c39f4539c33e6fe2762b6a77ab2578b9657fcfe6 100644
|
| --- a/runtime/lib/mirrors.cc
|
| +++ b/runtime/lib/mirrors.cc
|
| @@ -774,22 +774,26 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_identityHash, 1) {
|
|
|
| // Invoke the function, or noSuchMethod if it is null. Propagate any unhandled
|
| // exceptions. Wrap and propagate any compilation errors.
|
| -static RawObject* ReflectivelyInvokeDynamicFunction(const Instance& receiver,
|
| - const Function& function,
|
| - const String& target_name,
|
| - const Array& arguments) {
|
| - // Note "arguments" is already the internal arguments with the receiver as
|
| - // the first element.
|
| +static RawObject* ReflectivelyInvokeDynamicFunction(
|
| + const Instance& receiver,
|
| + const Function& function,
|
| + const String& target_name,
|
| + const Array& args,
|
| + const Array& args_descriptor) {
|
| + // Note "args" is already the internal arguments with the receiver as the
|
| + // first element.
|
| Object& result = Object::Handle();
|
| - if (function.IsNull() || !function.is_visible()) {
|
| - const Array& arguments_descriptor =
|
| - Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
|
| + if (function.IsNull() ||
|
| + !function.is_visible() ||
|
| + !function.AreValidArguments(ArgumentsDescriptor(args_descriptor), NULL)) {
|
| result = DartEntry::InvokeNoSuchMethod(receiver,
|
| target_name,
|
| - arguments,
|
| - arguments_descriptor);
|
| + args,
|
| + args_descriptor);
|
| } else {
|
| - result = DartEntry::InvokeFunction(function, arguments);
|
| + result = DartEntry::InvokeFunction(function,
|
| + args,
|
| + args_descriptor);
|
| }
|
|
|
| if (result.IsError()) {
|
| @@ -799,30 +803,18 @@ static RawObject* ReflectivelyInvokeDynamicFunction(const Instance& receiver,
|
| return result.raw();
|
| }
|
|
|
| -
|
| -DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 4) {
|
| +DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 5) {
|
| // Argument 0 is the mirror, which is unused by the native. It exists
|
| // because this native is an instance method in order to be polymorphic
|
| // with its cousins.
|
| GET_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(1));
|
| GET_NON_NULL_NATIVE_ARGUMENT(
|
| String, function_name, arguments->NativeArgAt(2));
|
| - GET_NON_NULL_NATIVE_ARGUMENT(
|
| - Array, positional_args, arguments->NativeArgAt(3));
|
| -
|
| - intptr_t number_of_arguments = positional_args.Length();
|
| -
|
| - const Array& args =
|
| - Array::Handle(Array::New(number_of_arguments + 1)); // Plus receiver.
|
| - Object& arg = Object::Handle();
|
| - args.SetAt(0, reflectee);
|
| - for (int i = 0; i < number_of_arguments; i++) {
|
| - arg = positional_args.At(i);
|
| - args.SetAt(i + 1, arg); // Plus receiver.
|
| - }
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
|
|
|
| - ArgumentsDescriptor args_desc(
|
| - Array::Handle(ArgumentsDescriptor::New(args.Length())));
|
| + const Array& args_descriptor =
|
| + Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
|
|
|
| Class& klass = Class::Handle(reflectee.clazz());
|
| Function& function = Function::Handle();
|
| @@ -834,15 +826,11 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 4) {
|
| klass = klass.SuperClass();
|
| }
|
|
|
| - if (!function.IsNull() &&
|
| - !function.AreValidArguments(args_desc, NULL)) {
|
| - function = Function::null();
|
| - }
|
| -
|
| return ReflectivelyInvokeDynamicFunction(reflectee,
|
| function,
|
| function_name,
|
| - args);
|
| + args,
|
| + args_descriptor);
|
| }
|
|
|
|
|
| @@ -872,11 +860,14 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invokeGetter, 3) {
|
| const int kNumArgs = 1;
|
| const Array& args = Array::Handle(Array::New(kNumArgs));
|
| args.SetAt(0, reflectee);
|
| + const Array& args_descriptor =
|
| + Array::Handle(ArgumentsDescriptor::New(args.Length()));
|
|
|
| return ReflectivelyInvokeDynamicFunction(reflectee,
|
| getter,
|
| internal_getter_name,
|
| - args);
|
| + args,
|
| + args_descriptor);
|
| }
|
|
|
|
|
| @@ -917,37 +908,33 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invokeSetter, 4) {
|
| const Array& args = Array::Handle(Array::New(kNumArgs));
|
| args.SetAt(0, reflectee);
|
| args.SetAt(1, value);
|
| + const Array& args_descriptor =
|
| + Array::Handle(ArgumentsDescriptor::New(args.Length()));
|
|
|
| return ReflectivelyInvokeDynamicFunction(reflectee,
|
| setter,
|
| internal_setter_name,
|
| - args);
|
| + args,
|
| + args_descriptor);
|
| }
|
|
|
|
|
| -DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 2) {
|
| +DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 3) {
|
| GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
|
| ASSERT(!closure.IsNull() && closure.IsCallable(NULL, NULL));
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(1));
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(2));
|
|
|
| - const Array& positional_args =
|
| - Array::CheckedHandle(arguments->NativeArgAt(1));
|
| - intptr_t number_of_arguments = positional_args.Length();
|
| -
|
| - // Set up arguments to include the closure as the first argument.
|
| - const Array& args = Array::Handle(Array::New(number_of_arguments + 1));
|
| - Object& obj = Object::Handle();
|
| - args.SetAt(0, closure);
|
| - for (int i = 0; i < number_of_arguments; i++) {
|
| - obj = positional_args.At(i);
|
| - args.SetAt(i + 1, obj);
|
| - }
|
| + const Array& args_descriptor =
|
| + Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
|
|
|
| - obj = DartEntry::InvokeClosure(args);
|
| - if (obj.IsError()) {
|
| - ThrowInvokeError(Error::Cast(obj));
|
| + const Object& result =
|
| + Object::Handle(DartEntry::InvokeClosure(args, args_descriptor));
|
| + if (result.IsError()) {
|
| + ThrowInvokeError(Error::Cast(result));
|
| UNREACHABLE();
|
| }
|
| - return obj.raw();
|
| + return result.raw();
|
| }
|
|
|
|
|
| @@ -963,7 +950,7 @@ DEFINE_NATIVE_ENTRY(ClosureMirror_function, 1) {
|
| }
|
|
|
|
|
| -DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 4) {
|
| +DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 5) {
|
| // Argument 0 is the mirror, which is unused by the native. It exists
|
| // because this native is an instance method in order to be polymorphic
|
| // with its cousins.
|
| @@ -971,18 +958,17 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 4) {
|
| const Class& klass = Class::Handle(ref.GetClassReferent());
|
| GET_NON_NULL_NATIVE_ARGUMENT(
|
| String, function_name, arguments->NativeArgAt(2));
|
| - GET_NON_NULL_NATIVE_ARGUMENT(
|
| - Array, positional_args, arguments->NativeArgAt(3));
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
|
|
|
| - intptr_t number_of_arguments = positional_args.Length();
|
| + const Array& args_descriptor =
|
| + Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
|
|
|
| const Function& function = Function::Handle(
|
| klass.LookupStaticFunctionAllowPrivate(function_name));
|
|
|
| if (function.IsNull() ||
|
| - !function.AreValidArgumentCounts(number_of_arguments,
|
| - /* named_args */ 0,
|
| - NULL) ||
|
| + !function.AreValidArguments(ArgumentsDescriptor(args_descriptor), NULL) ||
|
| !function.is_visible()) {
|
| ThrowNoSuchMethod(AbstractType::Handle(RawTypeOfClass(klass)),
|
| function_name,
|
| @@ -992,8 +978,8 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 4) {
|
| UNREACHABLE();
|
| }
|
|
|
| - Object& result = Object::Handle(DartEntry::InvokeFunction(function,
|
| - positional_args));
|
| + Object& result = Object::Handle(
|
| + DartEntry::InvokeFunction(function, args, args_descriptor));
|
| if (result.IsError()) {
|
| ThrowInvokeError(Error::Cast(result));
|
| UNREACHABLE();
|
| @@ -1094,15 +1080,13 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 4) {
|
| }
|
|
|
|
|
| -DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 3) {
|
| +DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 4) {
|
| GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
| const Class& klass = Class::Handle(ref.GetClassReferent());
|
| GET_NON_NULL_NATIVE_ARGUMENT(
|
| String, constructor_name, arguments->NativeArgAt(1));
|
| - GET_NON_NULL_NATIVE_ARGUMENT(
|
| - Array, positional_args, arguments->NativeArgAt(2));
|
| -
|
| - intptr_t number_of_arguments = positional_args.Length();
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, explicit_args, arguments->NativeArgAt(2));
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(3));
|
|
|
| // By convention, the static function implementing a named constructor 'C'
|
| // for class 'A' is labeled 'A.C', and the static function implementing the
|
| @@ -1116,42 +1100,100 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 3) {
|
| String::Concat(internal_constructor_name, constructor_name);
|
| }
|
|
|
| - Function& constructor = Function::Handle(
|
| + Function& lookup_constructor = Function::Handle(
|
| klass.LookupFunctionAllowPrivate(internal_constructor_name));
|
|
|
| - if (constructor.IsNull() ||
|
| - (!constructor.IsConstructor() && !constructor.IsFactory()) ||
|
| - !constructor.AreValidArgumentCounts(number_of_arguments +
|
| - constructor.NumImplicitParameters(),
|
| - /* named args */ 0,
|
| - NULL) ||
|
| - !constructor.is_visible()) {
|
| + if (lookup_constructor.IsNull() ||
|
| + !(lookup_constructor.IsConstructor() || lookup_constructor.IsFactory()) ||
|
| + !lookup_constructor.is_visible()) {
|
| + // Pretend we didn't find the constructor at all when the arity is wrong
|
| + // so as to produce the same NoSuchMethodError as the non-reflective case.
|
| + lookup_constructor = Function::null();
|
| + ThrowNoSuchMethod(AbstractType::Handle(RawTypeOfClass(klass)),
|
| + internal_constructor_name,
|
| + lookup_constructor,
|
| + InvocationMirror::kConstructor,
|
| + InvocationMirror::kMethod);
|
| + UNREACHABLE();
|
| + }
|
| +
|
| + Class& redirected_klass = Class::Handle(klass.raw());
|
| + Function& redirected_constructor = Function::Handle(lookup_constructor.raw());
|
| + if (lookup_constructor.IsRedirectingFactory()) {
|
| + ClassFinalizer::ResolveRedirectingFactory(klass, lookup_constructor);
|
| + Type& type = Type::Handle(lookup_constructor.RedirectionType());
|
| + redirected_constructor = lookup_constructor.RedirectionTarget();
|
| + ASSERT(!redirected_constructor.IsNull());
|
| + redirected_klass = type.type_class();
|
| + }
|
| +
|
| + const intptr_t num_explicit_args = explicit_args.Length();
|
| + const intptr_t num_implicit_args =
|
| + redirected_constructor.IsConstructor() ? 2 : 1;
|
| + const Array& args =
|
| + Array::Handle(Array::New(num_implicit_args + num_explicit_args));
|
| +
|
| + // Copy over the explicit arguments.
|
| + Object& explicit_argument = Object::Handle();
|
| + for (int i = 0; i < num_explicit_args; i++) {
|
| + explicit_argument = explicit_args.At(i);
|
| + args.SetAt(i + num_implicit_args, explicit_argument);
|
| + }
|
| +
|
| + const Array& args_descriptor =
|
| + Array::Handle(ArgumentsDescriptor::New(args.Length(),
|
| + arg_names));
|
| +
|
| + if (!redirected_constructor.AreValidArguments(
|
| + ArgumentsDescriptor(args_descriptor), NULL) ||
|
| + !redirected_constructor.is_visible()) {
|
| // Pretend we didn't find the constructor at all when the arity is wrong
|
| // so as to produce the same NoSuchMethodError as the non-reflective case.
|
| - constructor = Function::null();
|
| + redirected_constructor = Function::null();
|
| ThrowNoSuchMethod(AbstractType::Handle(RawTypeOfClass(klass)),
|
| internal_constructor_name,
|
| - constructor,
|
| + redirected_constructor,
|
| InvocationMirror::kConstructor,
|
| InvocationMirror::kMethod);
|
| UNREACHABLE();
|
| }
|
|
|
| + Instance& new_object = Instance::Handle();
|
| + if (redirected_constructor.IsConstructor()) {
|
| + // Constructors get the uninitialized object and a constructor phase. Note
|
| + // we have delayed allocation until after the function type and argument
|
| + // matching checks.
|
| + new_object = Instance::New(redirected_klass);
|
| + args.SetAt(0, new_object);
|
| + args.SetAt(1, Smi::Handle(Smi::New(Function::kCtorPhaseAll)));
|
| + } else {
|
| + // Factories get type arguments.
|
| + // TODO(12921): Should we allow the user to specify type arguments? Use type
|
| + // arguments from the mirror?
|
| + args.SetAt(0, Object::null_abstract_type_arguments());
|
| + }
|
| +
|
| + // Invoke the constructor and return the new object.
|
| const Object& result =
|
| - Object::Handle(DartEntry::InvokeConstructor(klass,
|
| - constructor,
|
| - positional_args));
|
| + Object::Handle(DartEntry::InvokeFunction(redirected_constructor,
|
| + args,
|
| + args_descriptor));
|
| if (result.IsError()) {
|
| - ThrowInvokeError(Error::Cast(result));
|
| - UNREACHABLE();
|
| + return result.raw();
|
| }
|
| +
|
| // Factories may return null.
|
| ASSERT(result.IsInstance() || result.IsNull());
|
| - return result.raw();
|
| +
|
| + if (redirected_constructor.IsConstructor()) {
|
| + return new_object.raw();
|
| + } else {
|
| + return result.raw();
|
| + }
|
| }
|
|
|
|
|
| -DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 4) {
|
| +DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 5) {
|
| // Argument 0 is the mirror, which is unused by the native. It exists
|
| // because this native is an instance method in order to be polymorphic
|
| // with its cousins.
|
| @@ -1159,10 +1201,11 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 4) {
|
| const Library& library = Library::Handle(ref.GetLibraryReferent());
|
| GET_NON_NULL_NATIVE_ARGUMENT(
|
| String, function_name, arguments->NativeArgAt(2));
|
| - GET_NON_NULL_NATIVE_ARGUMENT(
|
| - Array, positional_args, arguments->NativeArgAt(3));
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
|
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
|
|
|
| - intptr_t number_of_arguments = positional_args.Length();
|
| + const Array& args_descriptor =
|
| + Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
|
|
|
| String& ambiguity_error_msg = String::Handle(isolate);
|
| const Function& function = Function::Handle(
|
| @@ -1174,10 +1217,8 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 4) {
|
| }
|
|
|
| if (function.IsNull() ||
|
| - !function.AreValidArgumentCounts(number_of_arguments,
|
| - 0,
|
| - NULL) ||
|
| - !function.is_visible()) {
|
| + !function.AreValidArguments(ArgumentsDescriptor(args_descriptor), NULL) ||
|
| + !function.is_visible()) {
|
| ThrowNoSuchMethod(Instance::null_instance(),
|
| function_name,
|
| function,
|
| @@ -1187,7 +1228,7 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 4) {
|
| }
|
|
|
| const Object& result = Object::Handle(
|
| - DartEntry::InvokeFunction(function, positional_args));
|
| + DartEntry::InvokeFunction(function, args, args_descriptor));
|
| if (result.IsError()) {
|
| ThrowInvokeError(Error::Cast(result));
|
| UNREACHABLE();
|
|
|