Chromium Code Reviews| Index: runtime/lib/mirrors.cc |
| diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc |
| index cc278b2ebd795c39e106810d01c78d14e57d9182..67c3fa9ae9a33c5d5aac1cf3dbe99beb4bb39b86 100644 |
| --- a/runtime/lib/mirrors.cc |
| +++ b/runtime/lib/mirrors.cc |
| @@ -54,7 +54,7 @@ static void ThrowInvokeError(const Error& error) { |
| // Conventions: |
| // * For throwing a NSM in a class klass we use its runtime type as receiver, |
| -// i.e., RawTypeOfClass(klass). |
| +// i.e., klass.RareType(). |
| // * For throwing a NSM in a library, we just pass the null instance as |
| // receiver. |
| static void ThrowNoSuchMethod(const Instance& receiver, |
| @@ -399,6 +399,337 @@ static RawInstance* CreateMirrorSystem() { |
| } |
| +static bool FieldIsUninitialized(const Field& field) { |
| + ASSERT(!field.IsNull()); |
| + |
| + // Return getter method for uninitialized fields, rather than the |
| + // field object, since the value in the field object will not be |
| + // initialized until the first time the getter is invoked. |
| + const Instance& value = Instance::Handle(field.value()); |
| + ASSERT(value.raw() != Object::transition_sentinel().raw()); |
| + return value.raw() == Object::sentinel().raw(); |
| +} |
|
siva
2013/09/26 17:05:07
This function should probably be an instance metho
rmacnak
2013/09/26 17:49:39
Please also update the equivalent use in Dart_SetF
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.(including Dart_GetField/_SetField)
|
| + |
| + |
| +// Invoke the function, or noSuchMethod if it is null. Propagate any unhandled |
| +// exceptions. Wrap and propagate any compilation errors. |
| +static RawInstance* ReflectivelyInvokeDynamicFunction( |
|
rmacnak
2013/09/26 17:49:39
Let's drop the "Reflectively" for parallelism with
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + const Instance& receiver, |
| + const Function& function, |
| + const String& target_name, |
| + const Array& args, |
| + const Array& args_descriptor_array) { |
| + // Note "args" is already the internal arguments with the receiver as the |
| + // first element. |
| + Object& result = Object::Handle(); |
| + |
| + ArgumentsDescriptor args_descriptor(args_descriptor_array); |
| + if (function.IsNull() || |
| + !function.is_visible() || |
| + !function.AreValidArguments(args_descriptor, NULL)) { |
| + result = DartEntry::InvokeNoSuchMethod(receiver, |
| + target_name, |
| + args, |
| + args_descriptor_array); |
| + } else { |
| + result = DartEntry::InvokeFunction(function, |
| + args, |
| + args_descriptor_array); |
| + } |
| + |
| + if (result.IsError()) { |
| + ThrowInvokeError(Error::Cast(result)); |
| + UNREACHABLE(); |
| + } else if (result.IsInstance()) { |
| + return Instance::Cast(result).raw(); |
| + } |
| + ASSERT(result.IsNull()); |
| + return Instance::null(); |
| +} |
| + |
| + |
| +RawInstance* InvokeLibraryGetter(const Library& library, |
| + const String& getter_name, |
| + const bool throw_nsm_if_absent) { |
| + // To access a top-level we may need to use the Field or the |
| + // getter Function. The getter function may either be in the |
| + // library or in the field's owner class, depending. |
|
siva
2013/09/26 17:05:07
This comment seems to be incomplete....
rmacnak
2013/09/26 17:49:39
To perform a reflective getter invocation, we need
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + const Field& field = Field::Handle( |
| + library.LookupFieldAllowPrivate(getter_name)); |
| + Function& getter = Function::Handle(); |
| + if (field.IsNull()) { |
| + // No field found and no ambiguity error. Check for a getter in the lib. |
| + const String& internal_getter_name = |
| + String::Handle(Field::GetterName(getter_name)); |
| + getter = library.LookupFunctionAllowPrivate(internal_getter_name); |
| + if (getter.IsNull()) { |
| + getter = library.LookupFunctionAllowPrivate(getter_name); |
| + if (!getter.IsNull()) { |
| + // Looking for a getter but found a regular method: closurize. |
| + const Function& closure_function = |
| + Function::Handle(getter.ImplicitClosureFunction()); |
| + return closure_function.ImplicitStaticClosure(); |
| + } |
|
siva
2013/09/26 17:05:07
I saw some similar code in Ryan's CL maybe it need
rmacnak
2013/09/26 17:49:39
That code was moved here, not duplicated.
Michael Lippautz (Google)
2013/09/26 21:16:01
This is Ryan's code. It just moved here.
|
| + } |
| + } else if (!field.IsNull() && FieldIsUninitialized(field)) { |
|
siva
2013/09/26 17:05:07
At this point we know field.IsNull() is not true w
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + // A field was found. Check for a getter in the field's owner classs. |
| + const Class& klass = Class::Handle(field.owner()); |
| + const String& internal_getter_name = |
| + String::Handle(Field::GetterName(getter_name)); |
| + getter = klass.LookupStaticFunctionAllowPrivate(internal_getter_name); |
| + } |
| + |
| + if (!getter.IsNull() && getter.is_visible()) { |
| + // Invoke the getter and return the result. |
| + const Object& result = Object::Handle( |
| + DartEntry::InvokeFunction(getter, Object::empty_array())); |
| + if (result.IsError()) { |
| + ThrowInvokeError(Error::Cast(result)); |
| + UNREACHABLE(); |
| + } else if (result.IsInstance()) { |
| + return Instance::Cast(result).raw(); |
| + } |
| + ASSERT(result.IsNull()); |
| + return Instance::null(); |
|
siva
2013/09/26 17:05:07
Maybe you should have a static helper method
stati
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + } |
| + if (!field.IsNull()) { |
| + return field.value(); |
| + } |
|
siva
2013/09/26 17:05:07
I think the code needs to be restructured as
if (f
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + if (throw_nsm_if_absent) { |
| + ThrowNoSuchMethod(Instance::null_instance(), |
| + getter_name, |
| + getter, |
| + InvocationMirror::kTopLevel, |
| + InvocationMirror::kGetter); |
| + UNREACHABLE(); |
| + } |
| + return Instance::null(); |
| +} |
| + |
| + |
| +RawInstance* InvokeClassGetter(const Class& klass, |
| + const String& getter_name, |
| + const bool throw_nsm_if_absent) { |
| + // Note static fields do not have implicit getters. |
| + const Field& field = Field::Handle(klass.LookupStaticField(getter_name)); |
| + if (field.IsNull() || FieldIsUninitialized(field)) { |
| + const String& internal_getter_name = String::Handle( |
| + Field::GetterName(getter_name)); |
| + Function& getter = Function::Handle( |
| + klass.LookupStaticFunctionAllowPrivate(internal_getter_name)); |
| + |
| + if (getter.IsNull() || !getter.is_visible()) { |
| + if (getter.IsNull()) { |
| + getter = klass.LookupStaticFunctionAllowPrivate(getter_name); |
| + if (!getter.IsNull()) { |
| + // Looking for a getter but found a regular method: closurize. |
| + const Function& closure_function = |
| + Function::Handle(getter.ImplicitClosureFunction()); |
| + return closure_function.ImplicitStaticClosure(); |
| + } |
| + } |
| + if (throw_nsm_if_absent) { |
| + ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()), |
| + getter_name, |
| + getter, |
| + InvocationMirror::kStatic, |
| + InvocationMirror::kGetter); |
| + UNREACHABLE(); |
| + } |
| + return Instance::null(); |
| + } |
| + |
| + // Invoke the getter and return the result. |
| + Object& result = Object::Handle( |
|
rmacnak
2013/09/26 17:49:39
const
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + DartEntry::InvokeFunction(getter, Object::empty_array())); |
| + if (result.IsError()) { |
| + ThrowInvokeError(Error::Cast(result)); |
| + UNREACHABLE(); |
| + } else if (result.IsInstance()) { |
| + return Instance::Cast(result).raw(); |
| + } |
| + ASSERT(result.IsNull()); |
| + return Instance::null(); |
|
siva
2013/09/26 17:05:07
ditto comment about returnResult
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + } |
| + return field.value(); |
| +} |
| + |
| + |
| + |
| + |
| +RawInstance* InvokeInstanceGetter(const Class& klass, |
| + const Instance& reflectee, |
| + const String& getter_name, |
| + const bool throw_nsm_if_absent) { |
| + String& internal_getter_name = String::Handle(Field::GetterName(getter_name)); |
| + Function& function = Function::Handle( |
| + Resolver::ResolveDynamicAnyArgsAllowPrivate(klass, internal_getter_name)); |
| + |
| + if (!function.IsNull() || (function.IsNull() && throw_nsm_if_absent)) { |
|
siva
2013/09/26 17:05:07
shouldn't this just be
if (!function.IsNull() || t
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + 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, |
| + function, |
| + internal_getter_name, |
| + args, |
| + args_descriptor); |
| + } |
| + return Instance::null(); |
| +} |
| + |
| + |
| +RawInstance* LookupFunctionOrFieldInLibraryPrefix( |
| + const LibraryPrefix& prefix, |
| + const String& lookup_name) { |
| + Instance& result = Instance::Handle(); |
| + const Object& entry = Object::Handle(prefix.LookupObject(lookup_name)); |
| + if (!entry.IsNull() && entry.IsField()) { |
| + const Field& field = Field::Cast(entry); |
| + const Class& field_owner = Class::Handle(field.owner()); |
| + const Library& field_library = Library::Handle(field_owner.library()); |
| + result ^= InvokeLibraryGetter(field_library, lookup_name, false); |
| + if (!result.IsNull()) { |
| + return result.raw(); |
| + } |
|
siva
2013/09/26 17:05:07
why not just
return result.raw();
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + } else if (!entry.IsNull() && entry.IsFunction()) { |
|
siva
2013/09/26 17:05:07
why test of !entry.IsNull() twice?
Structure as
if
rmacnak
2013/09/26 17:49:39
Could it be a Class?
Michael Lippautz (Google)
2013/09/26 21:16:01
Can be a class. Restructured nonetheless.
|
| + const Function& func = Function::Cast(entry); |
| + const Function& closure_function = Function::Handle( |
| + func.ImplicitClosureFunction()); |
| + return closure_function.ImplicitStaticClosure(); |
| + } |
| + return Instance::null(); |
| +} |
| + |
| + |
| +RawInstance* LookupStaticFunctionOrFieldInClass(const Class& klass, |
| + const String& lookup_name) { |
| + Instance& result = Instance::Handle( |
| + InvokeClassGetter(klass, lookup_name, false)); |
| + if (!result.IsNull()) { |
| + return result.raw(); |
| + } |
| + |
| + Function& func = Function::Handle(); |
| + Class& kls = Class::Handle(klass.raw()); |
|
rmacnak
2013/09/26 17:49:39
Consider 'lookup_class'
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + for (; func.IsNull() && !kls.IsNull(); kls = kls.SuperClass()) { |
| + func ^= kls.LookupStaticFunctionAllowPrivate(lookup_name); |
| + } |
| + if (!func.IsNull()) { |
| + const Function& closure_function = Function::Handle( |
| + func.ImplicitClosureFunction()); |
|
siva
2013/09/26 17:05:07
ASSERT(!closure_function.IsNull());
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + return closure_function.ImplicitStaticClosure(); |
| + } |
| + |
| + return Instance::null(); |
| +} |
| + |
| + |
| +static RawInstance* LookupFunctionOrFieldInFunctionContext( |
| + const Function& func, |
| + const Context& ctx, |
| + const String& lookup_name) { |
| + const ContextScope& ctx_scope = ContextScope::Handle(func.context_scope()); |
| + intptr_t this_index = -1; |
| + |
| + // Search local context. |
| + String& name = String::Handle(); |
| + for (intptr_t i = 0; i < ctx_scope.num_variables(); i++) { |
| + name ^= ctx_scope.NameAt(i); |
| + if (name.Equals(lookup_name)) { |
| + return ctx.At(i); |
| + } else if (name.Equals(Symbols::This())) { |
| + // Record instance index to search for the field in the instance |
| + // afterwards. |
| + this_index = i; |
| + } |
| + } |
| + |
| + // Search the instance this function is attached to. |
| + if (this_index >= 0) { |
| + // Since we want the closurized version of a function, we can access, both, |
| + // functions and fields through their internal getter name. If the internal |
|
rmacnak
2013/09/26 17:49:39
implicit getter, not internal
Michael Lippautz (Google)
2013/09/26 21:16:01
Done.
|
| + // getter does not exist for the function, a method extractor will be |
| + // created. |
| + const String& internal_getter_name = String::Handle( |
| + Field::GetterName(lookup_name)); |
| + const Class& owner = Class::Handle(func.Owner()); |
| + const Instance& receiver = Instance::Handle(ctx.At(this_index)); |
| + const Function& getter = Function::Handle( |
| + Resolver::ResolveDynamicAnyArgsAllowPrivate( |
| + owner, internal_getter_name)); |
| + if (!getter.IsNull()) { |
| + const int kNumArgs = 1; |
| + const Array& args = Array::Handle(Array::New(kNumArgs)); |
| + args.SetAt(0, receiver); |
| + const Array& args_descriptor = Array::Handle( |
| + ArgumentsDescriptor::New(args.Length())); |
| + |
| + return ReflectivelyInvokeDynamicFunction(receiver, |
| + getter, |
| + internal_getter_name, |
| + args, |
| + args_descriptor); |
| + } |
| + } |
| + return Instance::null(); |
| +} |
| + |
| + |
| +RawInstance* LookupFunctionOrFieldInLibraryHelper(const Library& library, |
| + const String& class_name, |
| + const String& lookup_name) { |
| + if (class_name.IsNull()) { |
| + Instance& result = Instance::Handle( |
| + InvokeLibraryGetter(library, lookup_name, false)); |
| + if (!result.IsNull()) { |
| + return result.raw(); |
| + } |
| + Function& func = Function::Handle( |
| + library.LookupFunctionAllowPrivate(lookup_name)); |
| + if (!func.IsNull()) { |
| + const Function& closure_function = Function::Handle( |
| + func.ImplicitClosureFunction()); |
| + return closure_function.ImplicitStaticClosure(); |
| + } |
| + } else { |
| + Class& cls = Class::Handle( |
| + library.LookupClassAllowPrivate(class_name)); |
| + if (!cls.IsNull()) { |
| + return LookupStaticFunctionOrFieldInClass(cls, lookup_name); |
| + } |
| + } |
| + return Instance::null(); |
| +} |
| + |
| + |
| +RawInstance* LookupFunctionOrFieldInLibrary(const Library& library, |
| + const String& class_name, |
| + const String& lookup_name) { |
| + Instance& result = Instance::Handle(); |
| + // Check current library. |
| + result ^= LookupFunctionOrFieldInLibraryHelper( |
| + library, class_name, lookup_name); |
| + if (!result.IsNull()) { |
| + return result.raw(); |
| + } |
| + // Check all imports. |
| + Library& lib_it = Library::Handle(); |
| + for (intptr_t i = 0; i < library.num_imports(); i++) { |
| + lib_it ^= library.ImportLibraryAt(i); |
| + result ^= LookupFunctionOrFieldInLibraryHelper( |
| + lib_it, class_name, lookup_name); |
| + if (!result.IsNull()) { |
| + return result.raw(); |
| + } |
| + } |
| + return Instance::null(); |
| +} |
| + |
| + |
| DEFINE_NATIVE_ENTRY(Mirrors_makeLocalMirrorSystem, 0) { |
| return CreateMirrorSystem(); |
| } |
| @@ -506,18 +837,6 @@ DEFINE_NATIVE_ENTRY(FunctionTypeMirror_return_type, 1) { |
| } |
| -static bool FieldIsUninitialized(const Field& field) { |
| - ASSERT(!field.IsNull()); |
| - |
| - // Return getter method for uninitialized fields, rather than the |
| - // field object, since the value in the field object will not be |
| - // initialized until the first time the getter is invoked. |
| - const Instance& value = Instance::Handle(field.value()); |
| - ASSERT(value.raw() != Object::transition_sentinel().raw()); |
| - return value.raw() == Object::sentinel().raw(); |
| -} |
| - |
| - |
| DEFINE_NATIVE_ENTRY(ClassMirror_library, 1) { |
| GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0)); |
| const Class& klass = Class::Handle(ref.GetClassReferent()); |
| @@ -757,40 +1076,6 @@ 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& args, |
| - const Array& args_descriptor_array) { |
| - // Note "args" is already the internal arguments with the receiver as the |
| - // first element. |
| - Object& result = Object::Handle(); |
| - |
| - ArgumentsDescriptor args_descriptor(args_descriptor_array); |
| - if (function.IsNull() || |
| - !function.is_visible() || |
| - !function.AreValidArguments(args_descriptor, NULL)) { |
| - result = DartEntry::InvokeNoSuchMethod(receiver, |
| - target_name, |
| - args, |
| - args_descriptor_array); |
| - } else { |
| - result = DartEntry::InvokeFunction(function, |
| - args, |
| - args_descriptor_array); |
| - } |
| - |
| - if (result.IsError()) { |
| - ThrowInvokeError(Error::Cast(result)); |
| - UNREACHABLE(); |
| - } |
| - return result.raw(); |
| -} |
| - |
| - |
| 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 |
| @@ -822,23 +1107,8 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invokeGetter, 3) { |
| // with its cousins. |
| GET_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(1)); |
| GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2)); |
| - |
| Class& klass = Class::Handle(reflectee.clazz()); |
| - String& internal_getter_name = String::Handle(Field::GetterName(getter_name)); |
| - Function& function = Function::Handle( |
| - Resolver::ResolveDynamicAnyArgsAllowPrivate(klass, internal_getter_name)); |
| - |
| - 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, |
| - function, |
| - internal_getter_name, |
| - args, |
| - args_descriptor); |
| + return InvokeInstanceGetter(klass, reflectee, getter_name, true); |
| } |
| @@ -909,6 +1179,84 @@ DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 3) { |
| } |
| +DEFINE_NATIVE_ENTRY(ClosureMirror_find_in_context, 2) { |
| + enum { |
| + kNoLookups = 0, |
| + kContext = 1, |
| + kStatic = 2, |
| + kLibraryPrefix = 4, |
| + kGlobal = 8 |
| + }; |
| + |
| + GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0)); |
| + GET_NON_NULL_NATIVE_ARGUMENT(Array, lookup_parts, arguments->NativeArgAt(1)); |
| + ASSERT(lookup_parts.Length() >= 1 && lookup_parts.Length() <= 3); |
| + |
| + Function& function = Function::Handle(); |
| + const bool callable = closure.IsCallable(&function, NULL); |
| + ASSERT(callable); |
| + |
| + const int parts_len = lookup_parts.Length(); |
| + // Lookup name is always the last part. |
| + const String& lookup_name = String::Handle(String::RawCast( |
| + lookup_parts.At(parts_len - 1))); |
| + |
| + unsigned lookups = kNoLookups; |
|
siva
2013/09/26 17:05:07
we don't normally used unsigned like this,
why not
Michael Lippautz (Google)
2013/09/26 21:16:01
Not used anymore.
|
| + String& part_name = String::Handle(); |
| + Class& owner = Class::Handle(function.Owner()); |
| + LibraryPrefix& prefix = LibraryPrefix::Handle(); |
| + Library& this_library = Library::Handle(owner.library()); |
| + |
| + if (parts_len == 1) { |
| + // Could be either a field in context, an instance or static field of the |
| + // enclosing class, or a field in the current library or any imported |
| + // library. |
| + lookups = (kContext | kStatic | kGlobal); |
| + } else if (parts_len == 2) { |
| + // Could be either library.field or class.staticfield. |
| + part_name ^= lookup_parts.At(0); |
| + prefix ^= this_library.LookupLocalLibraryPrefix(part_name); |
| + lookups = prefix.IsNull() ? kGlobal : kLibraryPrefix; |
| + } else if (parts_len == 3) { |
| + // Can only be library.class.staticfield. |
| + part_name ^= lookup_parts.At(0); |
| + prefix ^= this_library.LookupLocalLibraryPrefix(part_name); |
| + if (prefix.IsNull()) { |
| + return Instance::null(); |
| + } |
| + part_name ^= lookup_parts.At(1); |
| + owner ^= prefix.LookupClass(part_name); |
| + if (owner.IsNull()) { |
| + return Instance::null(); |
| + } |
| + lookups = kStatic; |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + |
| + Instance& result = Instance::Handle(); |
| + if ((lookups & kContext) && result.IsNull()) { |
|
rmacnak
2013/09/26 17:49:39
I'm suspicious of using null to indicate no-result
Michael Lippautz (Google)
2013/09/26 21:16:01
Done (see above).
|
| + result ^= LookupFunctionOrFieldInFunctionContext( |
| + function, Context::Handle(Closure::context(closure)), lookup_name); |
| + } |
| + if ((lookups & kStatic) && result.IsNull() && !owner.IsTopLevel()) { |
| + result ^= LookupStaticFunctionOrFieldInClass(owner, lookup_name); |
| + } |
| + if ((lookups & kLibraryPrefix) && result.IsNull()) { |
| + result ^= LookupFunctionOrFieldInLibraryPrefix(prefix, lookup_name); |
| + } |
| + if ((lookups & kGlobal) && result.IsNull()) { |
| + result ^= LookupFunctionOrFieldInLibrary(this_library, |
| + part_name, |
| + lookup_name); |
| + } |
|
siva
2013/09/26 17:05:07
I am not sure if this 'lookups' stuff is a good id
Michael Lippautz (Google)
2013/09/26 21:16:01
Inlined the lookup calls.
|
| + if (!result.IsNull()) { |
| + return result.raw(); |
| + } |
| + return Instance::null(); |
|
siva
2013/09/26 17:05:07
return result.raw();
is sufficient
Michael Lippautz (Google)
2013/09/26 21:16:01
Different now.
|
| +} |
| + |
| + |
| DEFINE_NATIVE_ENTRY(ClosureMirror_function, 1) { |
| GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0)); |
| ASSERT(!closure.IsNull()); |
| @@ -968,43 +1316,7 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeGetter, 3) { |
| GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1)); |
| const Class& klass = Class::Handle(ref.GetClassReferent()); |
| GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2)); |
| - |
| - // Note static fields do not have implicit getters. |
| - const Field& field = Field::Handle(klass.LookupStaticField(getter_name)); |
| - if (field.IsNull() || FieldIsUninitialized(field)) { |
| - const String& internal_getter_name = String::Handle( |
| - Field::GetterName(getter_name)); |
| - Function& getter = Function::Handle( |
| - klass.LookupStaticFunctionAllowPrivate(internal_getter_name)); |
| - |
| - if (getter.IsNull() || !getter.is_visible()) { |
| - if (getter.IsNull()) { |
| - getter = klass.LookupStaticFunctionAllowPrivate(getter_name); |
| - if (!getter.IsNull()) { |
| - // Looking for a getter but found a regular method: closurize. |
| - const Function& closure_function = |
| - Function::Handle(getter.ImplicitClosureFunction()); |
| - return closure_function.ImplicitStaticClosure(); |
| - } |
| - } |
| - ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()), |
| - getter_name, |
| - getter, |
| - InvocationMirror::kStatic, |
| - InvocationMirror::kGetter); |
| - UNREACHABLE(); |
| - } |
| - |
| - // Invoke the getter and return the result. |
| - Object& result = Object::Handle( |
| - DartEntry::InvokeFunction(getter, Object::empty_array())); |
| - if (result.IsError()) { |
| - ThrowInvokeError(Error::Cast(result)); |
| - UNREACHABLE(); |
| - } |
| - return result.raw(); |
| - } |
| - return field.value(); |
| + return InvokeClassGetter(klass, getter_name, true); |
| } |
| @@ -1231,55 +1543,7 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invokeGetter, 3) { |
| GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1)); |
| const Library& library = Library::Handle(ref.GetLibraryReferent()); |
| GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2)); |
| - |
| - // To access a top-level we may need to use the Field or the |
| - // getter Function. The getter function may either be in the |
| - // library or in the field's owner class, depending. |
| - const Field& field = Field::Handle( |
| - library.LookupFieldAllowPrivate(getter_name)); |
| - Function& getter = Function::Handle(); |
| - if (field.IsNull()) { |
| - // No field found and no ambiguity error. Check for a getter in the lib. |
| - const String& internal_getter_name = |
| - String::Handle(Field::GetterName(getter_name)); |
| - getter = library.LookupFunctionAllowPrivate(internal_getter_name); |
| - if (getter.IsNull()) { |
| - getter = library.LookupFunctionAllowPrivate(getter_name); |
| - if (!getter.IsNull()) { |
| - // Looking for a getter but found a regular method: closurize. |
| - const Function& closure_function = |
| - Function::Handle(getter.ImplicitClosureFunction()); |
| - return closure_function.ImplicitStaticClosure(); |
| - } |
| - } |
| - } else if (!field.IsNull() && FieldIsUninitialized(field)) { |
| - // A field was found. Check for a getter in the field's owner classs. |
| - const Class& klass = Class::Handle(field.owner()); |
| - const String& internal_getter_name = |
| - String::Handle(Field::GetterName(getter_name)); |
| - getter = klass.LookupStaticFunctionAllowPrivate(internal_getter_name); |
| - } |
| - |
| - if (!getter.IsNull() && getter.is_visible()) { |
| - // Invoke the getter and return the result. |
| - const Object& result = Object::Handle( |
| - DartEntry::InvokeFunction(getter, Object::empty_array())); |
| - if (result.IsError()) { |
| - ThrowInvokeError(Error::Cast(result)); |
| - UNREACHABLE(); |
| - } |
| - return result.raw(); |
| - } |
| - if (!field.IsNull()) { |
| - return field.value(); |
| - } |
| - ThrowNoSuchMethod(Instance::null_instance(), |
| - getter_name, |
| - getter, |
| - InvocationMirror::kTopLevel, |
| - InvocationMirror::kGetter); |
| - UNREACHABLE(); |
| - return Instance::null(); |
| + return InvokeLibraryGetter(library, getter_name, true); |
| } |