dart-sdk/runtime/lib/mirrors.cc
koda@google.com 9c181ec6d5 Thread/Isolate refactoring: new(Isolate*) -> new(Zone*)
Refactor all remaning cases where the current zone is used through new(Isolate*) and remove this interface.

Removing this interface is needed to move towards multiple threads per isolate, and also makes the caller more aware of the scope of the zone used, reducing the risk of use-after-free.

Make the current thread and the stack zone created around native/runtime entries directly available in their body, saving an indirection (and optimized away if unused).

R=iposva@google.com

Review URL: https://codereview.chromium.org//982873004

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@44541 260f80e4-7a28-3924-810f-c04153c831b5
2015-03-17 19:24:26 +00:00

2039 lines
75 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "lib/mirrors.h"
#include "lib/invocation_mirror.h"
#include "vm/bootstrap_natives.h"
#include "vm/class_finalizer.h"
#include "vm/compiler.h"
#include "vm/dart_entry.h"
#include "vm/exceptions.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/port.h"
#include "vm/resolver.h"
#include "vm/symbols.h"
namespace dart {
static RawInstance* CreateMirror(const String& mirror_class_name,
const Array& constructor_arguments) {
const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary());
const String& constructor_name = Symbols::Dot();
const Object& result = Object::Handle(
DartLibraryCalls::InstanceCreate(mirrors_lib,
mirror_class_name,
constructor_name,
constructor_arguments));
ASSERT(!result.IsError());
return Instance::Cast(result).raw();
}
// Conventions:
// * For throwing a NSM in a class klass we use its runtime type as receiver,
// 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,
const String& function_name,
const Function& function,
const Array& arguments,
const InvocationMirror::Call call,
const InvocationMirror::Type type) {
const Smi& invocation_type = Smi::Handle(Smi::New(
InvocationMirror::EncodeType(call, type)));
const Array& args = Array::Handle(Array::New(6));
args.SetAt(0, receiver);
args.SetAt(1, function_name);
args.SetAt(2, invocation_type);
args.SetAt(3, arguments);
// TODO(rmacnak): Argument 4 (attempted argument names).
if (!function.IsNull()) {
const intptr_t total_num_parameters = function.NumParameters();
const Array& array = Array::Handle(Array::New(total_num_parameters));
String& param_name = String::Handle();
for (int i = 0; i < total_num_parameters; i++) {
param_name = function.ParameterNameAt(i);
array.SetAt(i, param_name);
}
args.SetAt(5, array);
}
Exceptions::ThrowByType(Exceptions::kNoSuchMethod, args);
UNREACHABLE();
}
static void EnsureConstructorsAreCompiled(const Function& func) {
// Only generative constructors can have initializing formals.
if (!func.IsGenerativeConstructor()) return;
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
const Class& cls = Class::Handle(zone, func.Owner());
const Error& error = Error::Handle(
zone, cls.EnsureIsFinalized(thread->isolate()));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
UNREACHABLE();
}
if (!func.HasCode()) {
const Error& error = Error::Handle(
zone, Compiler::CompileFunction(thread, func));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
UNREACHABLE();
}
}
}
static RawInstance* CreateParameterMirrorList(const Function& func,
const Instance& owner_mirror) {
HANDLESCOPE(Isolate::Current());
const intptr_t implicit_param_count = func.NumImplicitParameters();
const intptr_t non_implicit_param_count = func.NumParameters() -
implicit_param_count;
const intptr_t index_of_first_optional_param =
non_implicit_param_count - func.NumOptionalParameters();
const intptr_t index_of_first_named_param =
non_implicit_param_count - func.NumOptionalNamedParameters();
const Array& results = Array::Handle(Array::New(non_implicit_param_count));
const Array& args = Array::Handle(Array::New(9));
Smi& pos = Smi::Handle();
String& name = String::Handle();
Instance& param = Instance::Handle();
Bool& is_final = Bool::Handle();
Object& default_value = Object::Handle();
Object& metadata = Object::Handle();
// We force compilation of constructors to ensure the types of initializing
// formals have been corrected. We do not force the compilation of all types
// of functions because some have no body, e.g. signature functions.
EnsureConstructorsAreCompiled(func);
bool has_extra_parameter_info = true;
if (non_implicit_param_count == 0) {
has_extra_parameter_info = false;
}
if (func.IsImplicitConstructor()) {
// This covers the default constructor and forwarding constructors.
has_extra_parameter_info = false;
}
Array& param_descriptor = Array::Handle();
if (has_extra_parameter_info) {
// Reparse the function for the following information:
// * The default value of a parameter.
// * Whether a parameters has been deflared as final.
// * Any metadata associated with the parameter.
const Object& result =
Object::Handle(Parser::ParseFunctionParameters(func));
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
UNREACHABLE();
}
param_descriptor ^= result.raw();
ASSERT(param_descriptor.Length() ==
(Parser::kParameterEntrySize * non_implicit_param_count));
}
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func)));
args.SetAt(2, owner_mirror);
if (!has_extra_parameter_info) {
is_final ^= Bool::True().raw();
default_value = Object::null();
metadata = Object::null();
}
for (intptr_t i = 0; i < non_implicit_param_count; i++) {
pos ^= Smi::New(i);
name ^= func.ParameterNameAt(implicit_param_count + i);
if (has_extra_parameter_info) {
is_final ^= param_descriptor.At(i * Parser::kParameterEntrySize +
Parser::kParameterIsFinalOffset);
default_value = param_descriptor.At(i * Parser::kParameterEntrySize +
Parser::kParameterDefaultValueOffset);
metadata = param_descriptor.At(i * Parser::kParameterEntrySize +
Parser::kParameterMetadataOffset);
}
ASSERT(default_value.IsNull() || default_value.IsInstance());
// Arguments 0 (referent) and 2 (owner) are the same for all parameters. See
// above.
args.SetAt(1, name);
args.SetAt(3, pos);
args.SetAt(4, Bool::Get(i >= index_of_first_optional_param));
args.SetAt(5, Bool::Get(i >= index_of_first_named_param));
args.SetAt(6, is_final);
args.SetAt(7, default_value);
args.SetAt(8, metadata);
param ^= CreateMirror(Symbols::_LocalParameterMirror(), args);
results.SetAt(i, param);
}
results.MakeImmutable();
return results.raw();
}
static RawInstance* CreateTypeVariableMirror(const TypeParameter& param,
const Instance& owner_mirror) {
const Array& args = Array::Handle(Array::New(3));
args.SetAt(0, param);
args.SetAt(1, String::Handle(param.name()));
args.SetAt(2, owner_mirror);
return CreateMirror(Symbols::_LocalTypeVariableMirror(), args);
}
// We create a list in native code and let Dart code create the type mirror
// object and the ordered map.
static RawInstance* CreateTypeVariableList(const Class& cls) {
const TypeArguments& args = TypeArguments::Handle(cls.type_parameters());
if (args.IsNull()) {
return Object::empty_array().raw();
}
const Array& result = Array::Handle(Array::New(args.Length() * 2));
TypeParameter& type = TypeParameter::Handle();
String& name = String::Handle();
for (intptr_t i = 0; i < args.Length(); i++) {
type ^= args.TypeAt(i);
ASSERT(type.IsTypeParameter());
ASSERT(!type.IsMalformed());
ASSERT(type.IsFinalized());
name ^= type.name();
result.SetAt(2 * i, name);
result.SetAt(2 * i + 1, type);
}
return result.raw();
}
static RawInstance* CreateTypedefMirror(const Class& cls,
const AbstractType& type,
const Bool& is_declaration,
const Instance& owner_mirror) {
const Array& args = Array::Handle(Array::New(6));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, type);
args.SetAt(2, String::Handle(cls.Name()));
args.SetAt(3, Bool::Get(cls.NumTypeParameters() != 0));
args.SetAt(4, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
args.SetAt(5, owner_mirror);
return CreateMirror(Symbols::_LocalTypedefMirror(), args);
}
static RawInstance* CreateFunctionTypeMirror(const Class& cls,
const AbstractType& type) {
const Array& args = Array::Handle(Array::New(2));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, type);
return CreateMirror(Symbols::_LocalFunctionTypeMirror(), args);
}
static RawInstance* CreateMethodMirror(const Function& func,
const Instance& owner_mirror) {
const Array& args = Array::Handle(Array::New(12));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func)));
String& name = String::Handle(func.name());
name = String::IdentifierPrettyNameRetainPrivate(name);
args.SetAt(1, name);
args.SetAt(2, owner_mirror);
args.SetAt(3, Bool::Get(func.is_static()));
args.SetAt(4, Bool::Get(func.is_abstract()));
args.SetAt(5, Bool::Get(func.IsGetterFunction()));
args.SetAt(6, Bool::Get(func.IsSetterFunction()));
bool isConstructor = (func.kind() == RawFunction::kConstructor);
args.SetAt(7, Bool::Get(isConstructor));
args.SetAt(8, Bool::Get(isConstructor && func.is_const()));
args.SetAt(9, Bool::Get(isConstructor && func.IsGenerativeConstructor()));
args.SetAt(10, Bool::Get(isConstructor && func.is_redirecting()));
args.SetAt(11, Bool::Get(isConstructor && func.IsFactory()));
return CreateMirror(Symbols::_LocalMethodMirror(), args);
}
static RawInstance* CreateVariableMirror(const Field& field,
const Instance& owner_mirror) {
const MirrorReference& field_ref =
MirrorReference::Handle(MirrorReference::New(field));
const String& name = String::Handle(field.name());
const Array& args = Array::Handle(Array::New(7));
args.SetAt(0, field_ref);
args.SetAt(1, name);
args.SetAt(2, owner_mirror);
args.SetAt(3, Object::null_instance()); // Null for type.
args.SetAt(4, Bool::Get(field.is_static()));
args.SetAt(5, Bool::Get(field.is_final()));
args.SetAt(6, Bool::Get(field.is_const()));
return CreateMirror(Symbols::_LocalVariableMirror(), args);
}
static RawFunction* CallMethod(const Class& cls) {
if (cls.IsSignatureClass()) {
return cls.signature_function();
}
Class& lookup_cls = Class::Handle(cls.raw());
Function& call_function = Function::Handle();
do {
call_function = lookup_cls.LookupDynamicFunction(Symbols::Call());
if (!call_function.IsNull()) {
return call_function.raw();
}
lookup_cls = lookup_cls.SuperClass();
} while (!lookup_cls.IsNull());
return Function::null();
}
static RawInstance* CreateClassMirror(const Class& cls,
const AbstractType& type,
const Bool& is_declaration,
const Instance& owner_mirror) {
if (type.IsTypeRef()) {
AbstractType& ref_type = AbstractType::Handle(TypeRef::Cast(type).type());
ASSERT(!ref_type.IsTypeRef());
ASSERT(ref_type.IsCanonical());
return CreateClassMirror(cls, ref_type, is_declaration, owner_mirror);
}
ASSERT(!cls.IsDynamicClass() && !cls.IsVoidClass());
ASSERT(!type.IsNull());
ASSERT(type.IsFinalized());
if (cls.IsSignatureClass()) {
if (cls.IsCanonicalSignatureClass()) {
// We represent function types as canonical signature classes.
return CreateFunctionTypeMirror(cls, type);
} else {
// We represent typedefs as non-canonical signature classes.
return CreateTypedefMirror(cls, type, is_declaration, owner_mirror);
}
}
const Error& error = Error::Handle(cls.EnsureIsFinalized(Isolate::Current()));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
UNREACHABLE();
}
const Array& args = Array::Handle(Array::New(9));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, type);
// Note that the VM does not consider mixin application aliases to be mixin
// applications, so this only covers anonymous mixin applications. We do not
// set the names of anonymous mixin applications here because the mirrors
// use a different naming convention than the VM (lib.S with lib.M and S&M
// respectively).
if (!cls.IsMixinApplication()) {
args.SetAt(2, String::Handle(cls.Name()));
}
args.SetAt(3, owner_mirror);
args.SetAt(4, Bool::Get(cls.is_abstract()));
args.SetAt(5, Bool::Get(cls.IsGeneric()));
args.SetAt(6, Bool::Get(cls.is_mixin_app_alias()));
args.SetAt(7, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
args.SetAt(8, Bool::Get(cls.is_enum_class()));
return CreateMirror(Symbols::_LocalClassMirror(), args);
}
static RawInstance* CreateLibraryMirror(const Library& lib) {
const Array& args = Array::Handle(Array::New(3));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(lib)));
String& str = String::Handle();
str = lib.name();
args.SetAt(1, str);
str = lib.url();
if (str.Equals("dart:_builtin") || str.Equals("dart:_blink")) {
// Censored library (grumble).
return Instance::null();
}
args.SetAt(2, str);
return CreateMirror(Symbols::_LocalLibraryMirror(), args);
}
static RawInstance* CreateCombinatorMirror(const Object& identifiers,
bool is_show) {
const Array& args = Array::Handle(Array::New(2));
args.SetAt(0, identifiers);
args.SetAt(1, Bool::Get(is_show));
return CreateMirror(Symbols::_LocalCombinatorMirror(), args);
}
static RawInstance* CreateLibraryDependencyMirror(const Instance& importer,
const Namespace& ns,
const String& prefix,
const bool is_import,
const bool is_deferred) {
const Library& importee = Library::Handle(ns.library());
const Instance& importee_mirror =
Instance::Handle(CreateLibraryMirror(importee));
if (importee_mirror.IsNull()) {
// Imported library is censored: censor the import.
return Instance::null();
}
const Array& show_names = Array::Handle(ns.show_names());
const Array& hide_names = Array::Handle(ns.hide_names());
intptr_t n = show_names.IsNull() ? 0 : show_names.Length();
intptr_t m = hide_names.IsNull() ? 0 : hide_names.Length();
const Array& combinators = Array::Handle(Array::New(n + m));
Object& t = Object::Handle();
intptr_t i = 0;
for (intptr_t j = 0; j < n; j++) {
t = show_names.At(j);
t = CreateCombinatorMirror(t, true);
combinators.SetAt(i++, t);
}
for (intptr_t j = 0; j < m; j++) {
t = hide_names.At(j);
t = CreateCombinatorMirror(t, false);
combinators.SetAt(i++, t);
}
Object& metadata = Object::Handle(ns.GetMetadata());
if (metadata.IsError()) {
Exceptions::PropagateError(Error::Cast(metadata));
UNREACHABLE();
}
const Array& args = Array::Handle(Array::New(7));
args.SetAt(0, importer);
args.SetAt(1, importee_mirror);
args.SetAt(2, combinators);
args.SetAt(3, prefix);
args.SetAt(4, Bool::Get(is_import));
args.SetAt(5, Bool::Get(is_deferred));
args.SetAt(6, metadata);
return CreateMirror(Symbols::_LocalLibraryDependencyMirror(), args);
}
DEFINE_NATIVE_ENTRY(LibraryMirror_libraryDependencies, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, lib_mirror, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Library& lib = Library::Handle(ref.GetLibraryReferent());
Array& ports = Array::Handle();
Namespace& ns = Namespace::Handle();
Instance& dep = Instance::Handle();
String& prefix = String::Handle();
GrowableObjectArray& deps =
GrowableObjectArray::Handle(GrowableObjectArray::New());
// Unprefixed imports.
ports = lib.imports();
for (intptr_t i = 0; i < ports.Length(); i++) {
ns ^= ports.At(i);
if (!ns.IsNull()) {
dep = CreateLibraryDependencyMirror(lib_mirror, ns, prefix, true, false);
if (!dep.IsNull()) {
deps.Add(dep);
}
}
}
// Exports.
ports = lib.exports();
for (intptr_t i = 0; i < ports.Length(); i++) {
ns ^= ports.At(i);
dep = CreateLibraryDependencyMirror(lib_mirror, ns, prefix, false, false);
if (!dep.IsNull()) {
deps.Add(dep);
}
}
// Prefixed imports.
DictionaryIterator entries(lib);
Object& entry = Object::Handle();
while (entries.HasNext()) {
entry = entries.GetNext();
if (entry.IsLibraryPrefix()) {
const LibraryPrefix& lib_prefix = LibraryPrefix::Cast(entry);
prefix = lib_prefix.name();
ports = lib_prefix.imports();
for (intptr_t i = 0; i < ports.Length(); i++) {
ns ^= ports.At(i);
if (!ns.IsNull()) {
dep = CreateLibraryDependencyMirror(lib_mirror, ns, prefix, true,
lib_prefix.is_deferred_load());
if (!dep.IsNull()) {
deps.Add(dep);
}
}
}
}
}
return deps.raw();
}
static RawInstance* CreateTypeMirror(const AbstractType& type) {
if (type.IsTypeRef()) {
AbstractType& ref_type = AbstractType::Handle(TypeRef::Cast(type).type());
ASSERT(!ref_type.IsTypeRef());
ASSERT(ref_type.IsCanonical());
return CreateTypeMirror(ref_type);
}
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed());
if (type.HasResolvedTypeClass()) {
const Class& cls = Class::Handle(type.type_class());
// Handle void and dynamic types.
if (cls.IsVoidClass()) {
Array& args = Array::Handle(Array::New(1));
args.SetAt(0, Symbols::Void());
// TODO(mlippautz): Create once in the VM isolate and retrieve from there.
return CreateMirror(Symbols::_SpecialTypeMirror(), args);
} else if (cls.IsDynamicClass()) {
Array& args = Array::Handle(Array::New(1));
args.SetAt(0, Symbols::Dynamic());
// TODO(mlippautz): Create once in the VM isolate and retrieve from there.
return CreateMirror(Symbols::_SpecialTypeMirror(), args);
}
return CreateClassMirror(cls, type, Bool::False(), Object::null_instance());
} else if (type.IsTypeParameter()) {
return CreateTypeVariableMirror(TypeParameter::Cast(type),
Object::null_instance());
} else if (type.IsBoundedType()) {
AbstractType& actual_type =
AbstractType::Handle(BoundedType::Cast(type).type());
return CreateTypeMirror(actual_type);
}
UNREACHABLE();
return Instance::null();
}
static RawInstance* CreateIsolateMirror() {
Isolate* isolate = Isolate::Current();
const String& debug_name = String::Handle(String::New(isolate->name()));
const Library& root_library =
Library::Handle(isolate, isolate->object_store()->root_library());
const Instance& root_library_mirror =
Instance::Handle(CreateLibraryMirror(root_library));
const Array& args = Array::Handle(Array::New(2));
args.SetAt(0, debug_name);
args.SetAt(1, root_library_mirror);
return CreateMirror(Symbols::_LocalIsolateMirror(), args);
}
static RawInstance* CreateMirrorSystem() {
Isolate* isolate = Isolate::Current();
const GrowableObjectArray& libraries = GrowableObjectArray::Handle(
isolate, isolate->object_store()->libraries());
const intptr_t num_libraries = libraries.Length();
const GrowableObjectArray& library_mirrors = GrowableObjectArray::Handle(
isolate, GrowableObjectArray::New(num_libraries));
Library& library = Library::Handle(isolate);
Instance& library_mirror = Instance::Handle(isolate);
for (int i = 0; i < num_libraries; i++) {
library ^= libraries.At(i);
library_mirror = CreateLibraryMirror(library);
if (!library_mirror.IsNull()) {
library_mirrors.Add(library_mirror);
}
}
const Instance& isolate_mirror = Instance::Handle(CreateIsolateMirror());
const Array& args = Array::Handle(Array::New(2));
args.SetAt(0, library_mirrors);
args.SetAt(1, isolate_mirror);
return CreateMirror(Symbols::_LocalMirrorSystem(), args);
}
static RawInstance* ReturnResult(const Object& result) {
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
UNREACHABLE();
}
if (result.IsInstance()) {
return Instance::Cast(result).raw();
}
ASSERT(result.IsNull());
return Instance::null();
}
// Invoke the function, or noSuchMethod if it is null. Propagate any unhandled
// exceptions. Wrap and propagate any compilation errors.
static RawInstance* InvokeDynamicFunction(
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_reflectable() ||
!function.AreValidArguments(args_descriptor, NULL)) {
result = DartEntry::InvokeNoSuchMethod(receiver,
target_name,
args,
args_descriptor_array);
} else {
result = DartEntry::InvokeFunction(function,
args,
args_descriptor_array);
}
return ReturnResult(result);
}
static 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 on whether it was an actual getter, or an uninitialized
// field.
const Field& field = Field::Handle(
library.LookupLocalField(getter_name));
Function& getter = Function::Handle();
if (field.IsNull()) {
// No field found. Check for a getter in the lib.
const String& internal_getter_name =
String::Handle(Field::GetterName(getter_name));
getter = library.LookupLocalFunction(internal_getter_name);
if (getter.IsNull()) {
getter = library.LookupLocalFunction(getter_name);
if (!getter.IsNull()) {
// Looking for a getter but found a regular method: closurize it.
const Function& closure_function =
Function::Handle(getter.ImplicitClosureFunction());
return closure_function.ImplicitStaticClosure();
}
}
} else {
if (!field.IsUninitialized()) {
return field.value();
}
// An uninitialized 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.LookupStaticFunction(internal_getter_name);
}
if (!getter.IsNull() && getter.is_reflectable()) {
// Invoke the getter and return the result.
const Object& result = Object::Handle(
DartEntry::InvokeFunction(getter, Object::empty_array()));
return ReturnResult(result);
}
if (throw_nsm_if_absent) {
ThrowNoSuchMethod(Instance::null_instance(),
getter_name,
getter,
Object::null_array(),
InvocationMirror::kTopLevel,
InvocationMirror::kGetter);
UNREACHABLE();
}
// Fall through case: Indicate that we didn't find any function or field using
// a special null instance. This is different from a field being null. Callers
// make sure that this null does not leak into Dartland.
return Object::sentinel().raw();
}
static 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() || field.IsUninitialized()) {
const String& internal_getter_name = String::Handle(
Field::GetterName(getter_name));
Function& getter = Function::Handle(
klass.LookupStaticFunction(internal_getter_name));
if (getter.IsNull() || !getter.is_reflectable()) {
if (getter.IsNull()) {
getter = klass.LookupStaticFunction(getter_name);
if (!getter.IsNull()) {
// Looking for a getter but found a regular method: closurize it.
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,
Object::null_array(),
InvocationMirror::kStatic,
InvocationMirror::kGetter);
UNREACHABLE();
}
// Fall through case: Indicate that we didn't find any function or field
// using a special null instance. This is different from a field being
// null. Callers make sure that this null does not leak into Dartland.
return Object::sentinel().raw();
}
// Invoke the getter and return the result.
const Object& result = Object::Handle(
DartEntry::InvokeFunction(getter, Object::empty_array()));
return ReturnResult(result);
}
return field.value();
}
static RawInstance* InvokeInstanceGetter(const Class& klass,
const Instance& reflectee,
const String& getter_name,
const bool throw_nsm_if_absent) {
const String& internal_getter_name = String::Handle(
Field::GetterName(getter_name));
Function& function = Function::Handle(
Resolver::ResolveDynamicAnyArgs(klass, internal_getter_name));
if (!function.IsNull() || throw_nsm_if_absent) {
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()));
// InvokeDynamic invokes NoSuchMethod if the provided function is null.
return InvokeDynamicFunction(reflectee,
function,
internal_getter_name,
args,
args_descriptor);
}
// Fall through case: Indicate that we didn't find any function or field using
// a special null instance. This is different from a field being null. Callers
// make sure that this null does not leak into Dartland.
return Object::sentinel().raw();
}
static RawAbstractType* InstantiateType(const AbstractType& type,
const AbstractType& instantiator) {
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed());
if (type.IsInstantiated()) {
return type.Canonicalize();
}
ASSERT(!instantiator.IsNull());
ASSERT(instantiator.IsFinalized());
ASSERT(!instantiator.IsMalformed());
const TypeArguments& type_args =
TypeArguments::Handle(instantiator.arguments());
Error& bound_error = Error::Handle();
AbstractType& result =
AbstractType::Handle(type.InstantiateFrom(type_args, &bound_error));
if (!bound_error.IsNull()) {
Exceptions::PropagateError(bound_error);
UNREACHABLE();
}
ASSERT(result.IsFinalized());
return result.Canonicalize();
}
DEFINE_NATIVE_ENTRY(Mirrors_makeLocalMirrorSystem, 0) {
return CreateMirrorSystem();
}
DEFINE_NATIVE_ENTRY(Mirrors_makeLocalClassMirror, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(!type.IsMalformed());
ASSERT(type.IsFinalized());
ASSERT(type.HasResolvedTypeClass());
const Class& cls = Class::Handle(type.type_class());
ASSERT(!cls.IsNull());
if (cls.IsDynamicClass() ||
cls.IsVoidClass() ||
(cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass())) {
Exceptions::ThrowArgumentError(type);
UNREACHABLE();
}
return CreateClassMirror(cls,
AbstractType::Handle(cls.DeclarationType()),
Bool::True(), // is_declaration
Object::null_instance());
}
DEFINE_NATIVE_ENTRY(Mirrors_makeLocalTypeMirror, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
return CreateTypeMirror(type);
}
DEFINE_NATIVE_ENTRY(Mirrors_mangleName, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Library& lib = Library::Handle(ref.GetLibraryReferent());
return lib.IsPrivate(name) ? lib.PrivateName(name) : name.raw();
}
DEFINE_NATIVE_ENTRY(MirrorReference_equals, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, a, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, b, arguments->NativeArgAt(1));
return Bool::Get(a.referent() == b.referent()).raw();
}
DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(0));
Object& decl = Object::Handle();
if (reflectee.IsMirrorReference()) {
const MirrorReference& decl_ref = MirrorReference::Cast(reflectee);
decl = decl_ref.referent();
} else if (reflectee.IsTypeParameter()) {
decl = reflectee.raw();
} else {
UNREACHABLE();
}
Class& klass = Class::Handle();
Library& library = Library::Handle();
if (decl.IsClass()) {
klass ^= decl.raw();
library = klass.library();
} else if (decl.IsFunction()) {
klass = Function::Cast(decl).origin();
library = klass.library();
} else if (decl.IsField()) {
klass = Field::Cast(decl).origin();
library = klass.library();
} else if (decl.IsLibrary()) {
library ^= decl.raw();
} else if (decl.IsTypeParameter()) {
klass ^= TypeParameter::Cast(decl).parameterized_class();
library = klass.library();
} else {
return Object::empty_array().raw();
}
const Object& metadata = Object::Handle(library.GetMetadata(decl));
if (metadata.IsError()) {
Exceptions::PropagateError(Error::Cast(metadata));
}
return metadata.raw();
}
DEFINE_NATIVE_ENTRY(FunctionTypeMirror_call_method, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance,
owner_mirror,
arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Class& cls = Class::Handle(ref.GetClassReferent());
const Function& func = Function::Handle(CallMethod(cls));
ASSERT(!func.IsNull());
return CreateMethodMirror(func, owner_mirror);
}
DEFINE_NATIVE_ENTRY(FunctionTypeMirror_parameters, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, owner, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Class& cls = Class::Handle(ref.GetClassReferent());
const Function& func = Function::Handle(cls.signature_function());
return CreateParameterMirrorList(func, owner);
}
DEFINE_NATIVE_ENTRY(FunctionTypeMirror_return_type, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType,
instantiator,
arguments->NativeArgAt(1));
const Class& cls = Class::Handle(ref.GetClassReferent());
const Function& func = Function::Handle(CallMethod(cls));
ASSERT(!func.IsNull());
AbstractType& type = AbstractType::Handle(func.result_type());
return InstantiateType(type, instantiator);
}
DEFINE_NATIVE_ENTRY(ClassMirror_library, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
const Class& klass = Class::Handle(ref.GetClassReferent());
const Library& library = Library::Handle(klass.library());
ASSERT(!library.IsNull());
return CreateLibraryMirror(library);
}
DEFINE_NATIVE_ENTRY(ClassMirror_supertype, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(!type.IsMalformed());
ASSERT(type.IsFinalized());
if (!type.HasResolvedTypeClass()) {
Exceptions::ThrowArgumentError(type);
UNREACHABLE();
}
const Class& cls = Class::Handle(type.type_class());
const AbstractType& super_type = AbstractType::Handle(cls.super_type());
ASSERT(super_type.IsNull() || super_type.IsFinalized());
return super_type.raw();
}
DEFINE_NATIVE_ENTRY(ClassMirror_supertype_instantiated, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(!type.IsMalformed());
ASSERT(type.IsFinalized());
if (!type.HasResolvedTypeClass()) {
Exceptions::ThrowArgumentError(type);
UNREACHABLE();
}
const Class& cls = Class::Handle(type.type_class());
const AbstractType& super_type = AbstractType::Handle(cls.super_type());
return InstantiateType(super_type, type);
}
DEFINE_NATIVE_ENTRY(ClassMirror_interfaces, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(!type.IsMalformed());
ASSERT(type.IsFinalized());
if (!type.HasResolvedTypeClass()) {
Exceptions::ThrowArgumentError(type);
UNREACHABLE();
}
const Class& cls = Class::Handle(type.type_class());
const Error& error = Error::Handle(cls.EnsureIsFinalized(isolate));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
}
return cls.interfaces();
}
DEFINE_NATIVE_ENTRY(ClassMirror_interfaces_instantiated, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(!type.IsMalformed());
ASSERT(type.IsFinalized());
if (!type.HasResolvedTypeClass()) {
Exceptions::ThrowArgumentError(type);
UNREACHABLE();
}
const Class& cls = Class::Handle(type.type_class());
const Error& error = Error::Handle(cls.EnsureIsFinalized(isolate));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
}
Array& interfaces = Array::Handle(cls.interfaces());
Array& interfaces_inst = Array::Handle(Array::New(interfaces.Length()));
AbstractType& interface = AbstractType::Handle();
for (int i = 0; i < interfaces.Length(); i++) {
interface ^= interfaces.At(i);
interface = InstantiateType(interface, type);
interfaces_inst.SetAt(i, interface);
}
return interfaces_inst.raw();
}
DEFINE_NATIVE_ENTRY(ClassMirror_mixin, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
ASSERT(!type.IsMalformed());
ASSERT(type.IsFinalized());
if (!type.HasResolvedTypeClass()) {
Exceptions::ThrowArgumentError(type);
UNREACHABLE();
}
const Class& cls = Class::Handle(type.type_class());
const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
ASSERT(mixin_type.IsNull() || mixin_type.IsFinalized());
return mixin_type.raw();
}
DEFINE_NATIVE_ENTRY(ClassMirror_mixin_instantiated, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType,
instantiator,
arguments->NativeArgAt(1));
ASSERT(!type.IsMalformed());
ASSERT(type.IsFinalized());
if (!type.HasResolvedTypeClass()) {
Exceptions::ThrowArgumentError(type);
UNREACHABLE();
}
const Class& cls = Class::Handle(type.type_class());
const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
if (mixin_type.IsNull()) {
return mixin_type.raw();
}
return InstantiateType(mixin_type, instantiator);
}
DEFINE_NATIVE_ENTRY(ClassMirror_members, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance,
owner_mirror,
arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Class& klass = Class::Handle(ref.GetClassReferent());
const Error& error = Error::Handle(klass.EnsureIsFinalized(isolate));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
}
const Array& fields = Array::Handle(klass.fields());
const intptr_t num_fields = fields.Length();
const Array& functions = Array::Handle(klass.functions());
const intptr_t num_functions = functions.Length();
Instance& member_mirror = Instance::Handle();
const GrowableObjectArray& member_mirrors = GrowableObjectArray::Handle(
GrowableObjectArray::New(num_fields + num_functions));
Field& field = Field::Handle();
for (intptr_t i = 0; i < num_fields; i++) {
field ^= fields.At(i);
if (!field.is_synthetic()) {
member_mirror = CreateVariableMirror(field, owner_mirror);
member_mirrors.Add(member_mirror);
}
}
Function& func = Function::Handle();
for (intptr_t i = 0; i < num_functions; i++) {
func ^= functions.At(i);
if (func.is_reflectable() &&
(func.kind() == RawFunction::kRegularFunction ||
func.kind() == RawFunction::kGetterFunction ||
func.kind() == RawFunction::kSetterFunction)) {
member_mirror = CreateMethodMirror(func, owner_mirror);
member_mirrors.Add(member_mirror);
}
}
return member_mirrors.raw();
}
DEFINE_NATIVE_ENTRY(ClassMirror_constructors, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance,
owner_mirror,
arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Class& klass = Class::Handle(ref.GetClassReferent());
const Error& error = Error::Handle(klass.EnsureIsFinalized(isolate));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
}
const Array& functions = Array::Handle(klass.functions());
const intptr_t num_functions = functions.Length();
Instance& constructor_mirror = Instance::Handle();
const GrowableObjectArray& constructor_mirrors = GrowableObjectArray::Handle(
GrowableObjectArray::New(num_functions));
Function& func = Function::Handle();
for (intptr_t i = 0; i < num_functions; i++) {
func ^= functions.At(i);
if (func.is_reflectable() && func.kind() == RawFunction::kConstructor) {
constructor_mirror = CreateMethodMirror(func, owner_mirror);
constructor_mirrors.Add(constructor_mirror);
}
}
return constructor_mirrors.raw();
}
DEFINE_NATIVE_ENTRY(LibraryMirror_members, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance,
owner_mirror,
arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Library& library = Library::Handle(ref.GetLibraryReferent());
Instance& member_mirror = Instance::Handle();
const GrowableObjectArray& member_mirrors =
GrowableObjectArray::Handle(GrowableObjectArray::New());
Object& entry = Object::Handle();
DictionaryIterator entries(library);
AbstractType& type = AbstractType::Handle();
while (entries.HasNext()) {
entry = entries.GetNext();
if (entry.IsClass()) {
const Class& klass = Class::Cast(entry);
// We filter out function signature classes and dynamic.
// TODO(12478): Should not need to filter out dynamic.
// Note that the VM does not consider mixin application aliases to be
// mixin applications.
if (!klass.IsCanonicalSignatureClass() &&
!klass.IsDynamicClass() &&
!klass.IsMixinApplication()) {
type = klass.DeclarationType();
member_mirror = CreateClassMirror(klass,
type,
Bool::True(), // is_declaration
owner_mirror);
member_mirrors.Add(member_mirror);
}
} else if (entry.IsField()) {
const Field& field = Field::Cast(entry);
if (!field.is_synthetic()) {
member_mirror = CreateVariableMirror(field, owner_mirror);
member_mirrors.Add(member_mirror);
}
} else if (entry.IsFunction()) {
const Function& func = Function::Cast(entry);
if (func.is_reflectable() &&
(func.kind() == RawFunction::kRegularFunction ||
func.kind() == RawFunction::kGetterFunction ||
func.kind() == RawFunction::kSetterFunction)) {
member_mirror = CreateMethodMirror(func, owner_mirror);
member_mirrors.Add(member_mirror);
}
}
}
return member_mirrors.raw();
}
DEFINE_NATIVE_ENTRY(ClassMirror_type_variables, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
const Class& klass = Class::Handle(ref.GetClassReferent());
return CreateTypeVariableList(klass);
}
DEFINE_NATIVE_ENTRY(ClassMirror_type_arguments, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
const Class& cls = Class::Handle(type.type_class());
const intptr_t num_params = cls.NumTypeParameters();
if (num_params == 0) {
return Object::empty_array().raw();
}
const Array& result = Array::Handle(Array::New(num_params));
AbstractType& arg_type = AbstractType::Handle();
Instance& type_mirror = Instance::Handle();
const TypeArguments& args = TypeArguments::Handle(type.arguments());
// Handle argument lists that have been optimized away, because either no
// arguments have been provided, or all arguments are dynamic. Return a list
// of typemirrors on dynamic in this case.
if (args.IsNull()) {
arg_type ^= Object::dynamic_type();
type_mirror ^= CreateTypeMirror(arg_type);
for (intptr_t i = 0; i < num_params; i++) {
result.SetAt(i, type_mirror);
}
return result.raw();
}
ASSERT(args.Length() >= num_params);
const intptr_t num_inherited_args = args.Length() - num_params;
for (intptr_t i = 0; i < num_params; i++) {
arg_type ^= args.TypeAt(i + num_inherited_args);
type_mirror = CreateTypeMirror(arg_type);
result.SetAt(i, type_mirror);
}
return result.raw();
}
DEFINE_NATIVE_ENTRY(TypeVariableMirror_owner, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
const Class& owner = Class::Handle(param.parameterized_class());
const AbstractType& type = AbstractType::Handle(owner.DeclarationType());
return CreateClassMirror(owner,
type,
Bool::True(), // is_declaration
Instance::null_instance());
}
DEFINE_NATIVE_ENTRY(TypeVariableMirror_upper_bound, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
return param.bound();
}
DEFINE_NATIVE_ENTRY(Mirrors_evalInLibraryWithPrivateKey, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(String, expression, arguments->NativeArgAt(0));
GET_NATIVE_ARGUMENT(String, private_key, arguments->NativeArgAt(1));
const GrowableObjectArray& libraries =
GrowableObjectArray::Handle(isolate->object_store()->libraries());
const int num_libraries = libraries.Length();
Library& each_library = Library::Handle();
Library& ctxt_library = Library::Handle();
String& library_key = String::Handle();
if (private_key.IsNull()) {
ctxt_library = Library::CoreLibrary();
} else {
for (int i = 0; i < num_libraries; i++) {
each_library ^= libraries.At(i);
library_key = each_library.private_key();
if (library_key.Equals(private_key)) {
ctxt_library = each_library.raw();
break;
}
}
}
ASSERT(!ctxt_library.IsNull());
const Object& result =
Object::Handle(ctxt_library.Evaluate(expression,
Array::empty_array(),
Array::empty_array()));
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
UNREACHABLE();
}
return result.raw();
}
DEFINE_NATIVE_ENTRY(TypedefMirror_declaration, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
const Class& cls = Class::Handle(type.type_class());
// We represent typedefs as non-canonical signature classes.
ASSERT(cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass());
return CreateTypedefMirror(cls,
AbstractType::Handle(cls.DeclarationType()),
Bool::True(), // is_declaration
Object::null_instance());
}
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, args, arguments->NativeArgAt(3));
GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
Class& klass = Class::Handle(reflectee.clazz());
Function& function = Function::Handle(
Resolver::ResolveDynamicAnyArgs(klass, function_name));
const Array& args_descriptor =
Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
if (function.IsNull()) {
// Didn't find a method: try to find a getter and invoke call on its result.
const String& getter_name =
String::Handle(Field::GetterName(function_name));
function = Resolver::ResolveDynamicAnyArgs(klass, getter_name);
if (!function.IsNull()) {
ASSERT(function.kind() != RawFunction::kMethodExtractor);
// Invoke the getter.
const int kNumArgs = 1;
const Array& getter_args = Array::Handle(Array::New(kNumArgs));
getter_args.SetAt(0, reflectee);
const Array& getter_args_descriptor =
Array::Handle(ArgumentsDescriptor::New(getter_args.Length()));
const Instance& getter_result = Instance::Handle(
InvokeDynamicFunction(reflectee,
function,
getter_name,
getter_args,
getter_args_descriptor));
// Replace the closure as the receiver in the arguments list.
args.SetAt(0, getter_result);
// Call the closure.
const Object& call_result =
Object::Handle(DartEntry::InvokeClosure(args, args_descriptor));
if (call_result.IsError()) {
Exceptions::PropagateError(Error::Cast(call_result));
UNREACHABLE();
}
return call_result.raw();
}
}
// Found an ordinary method.
return InvokeDynamicFunction(reflectee,
function,
function_name,
args,
args_descriptor);
}
DEFINE_NATIVE_ENTRY(InstanceMirror_invokeGetter, 3) {
// 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, getter_name, arguments->NativeArgAt(2));
Class& klass = Class::Handle(reflectee.clazz());
return InvokeInstanceGetter(klass, reflectee, getter_name, true);
}
DEFINE_NATIVE_ENTRY(InstanceMirror_invokeSetter, 4) {
// 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, setter_name, arguments->NativeArgAt(2));
GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(3));
const Class& klass = Class::Handle(reflectee.clazz());
const String& internal_setter_name =
String::Handle(Field::SetterName(setter_name));
const Function& setter = Function::Handle(
Resolver::ResolveDynamicAnyArgs(klass, internal_setter_name));
const int kNumArgs = 2;
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 InvokeDynamicFunction(reflectee,
setter,
internal_setter_name,
args,
args_descriptor);
}
DEFINE_NATIVE_ENTRY(InstanceMirror_computeType, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
const Type& type = Type::Handle(instance.GetType());
// The static type of null is specified to be the bottom type, however, the
// runtime type of null is the Null type, which we correctly return here.
return type.Canonicalize();
}
DEFINE_NATIVE_ENTRY(ClosureMirror_function, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
ASSERT(!closure.IsNull());
Function& function = Function::Handle();
bool callable = closure.IsCallable(&function);
if (callable) {
return CreateMethodMirror(function, Instance::null_instance());
}
return Instance::null();
}
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.
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Class& klass = Class::Handle(ref.GetClassReferent());
GET_NON_NULL_NATIVE_ARGUMENT(
String, function_name, arguments->NativeArgAt(2));
GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
Function& function = Function::Handle(
klass.LookupStaticFunction(function_name));
if (function.IsNull()) {
// Didn't find a method: try to find a getter and invoke call on its result.
const String& getter_name =
String::Handle(Field::GetterName(function_name));
function = klass.LookupStaticFunction(getter_name);
if (!function.IsNull()) {
// Invoke the getter.
const Object& getter_result = Object::Handle(
DartEntry::InvokeFunction(function, Object::empty_array()));
if (getter_result.IsError()) {
Exceptions::PropagateError(Error::Cast(getter_result));
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));
Object& temp = Object::Handle();
for (int i = 0; i < numArgs; 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));
// Call the closure.
const Object& call_result = Object::Handle(
DartEntry::InvokeClosure(call_args, call_args_descriptor_array));
if (call_result.IsError()) {
Exceptions::PropagateError(Error::Cast(call_result));
UNREACHABLE();
}
return call_result.raw();
}
}
const Array& args_descriptor_array =
Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
if (function.IsNull() ||
!function.AreValidArguments(args_descriptor, NULL) ||
!function.is_reflectable()) {
ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
function_name,
function,
Object::null_array(),
InvocationMirror::kStatic,
InvocationMirror::kMethod);
UNREACHABLE();
}
Object& result = Object::Handle(
DartEntry::InvokeFunction(function, args, args_descriptor_array));
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
UNREACHABLE();
}
return result.raw();
}
DEFINE_NATIVE_ENTRY(ClassMirror_invokeGetter, 3) {
// 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_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));
return InvokeClassGetter(klass, getter_name, true);
}
DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 4) {
// 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_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Class& klass = Class::Handle(ref.GetClassReferent());
GET_NON_NULL_NATIVE_ARGUMENT(String, setter_name, arguments->NativeArgAt(2));
GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(3));
// Check for real fields and user-defined setters.
const Field& field = Field::Handle(klass.LookupStaticField(setter_name));
Function& setter = Function::Handle();
const String& internal_setter_name = String::Handle(
Field::SetterName(setter_name));
if (field.IsNull()) {
setter = klass.LookupStaticFunction(internal_setter_name);
const int kNumArgs = 1;
const Array& args = Array::Handle(Array::New(kNumArgs));
args.SetAt(0, value);
if (setter.IsNull() || !setter.is_reflectable()) {
ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
internal_setter_name,
setter,
args,
InvocationMirror::kStatic,
InvocationMirror::kSetter);
UNREACHABLE();
}
// Invoke the setter and return the result.
Object& result = Object::Handle(
DartEntry::InvokeFunction(setter, args));
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
UNREACHABLE();
}
return result.raw();
}
if (field.is_final()) {
ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
internal_setter_name,
setter,
Object::null_array(),
InvocationMirror::kStatic,
InvocationMirror::kSetter);
UNREACHABLE();
}
field.set_value(value);
return value.raw();
}
DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 5) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
const Class& klass = Class::Handle(ref.GetClassReferent());
GET_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(
String, constructor_name, arguments->NativeArgAt(2));
GET_NON_NULL_NATIVE_ARGUMENT(Array, explicit_args, arguments->NativeArgAt(3));
GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
// By convention, the static function implementing a named constructor 'C'
// for class 'A' is labeled 'A.C', and the static function implementing the
// unnamed constructor for class 'A' is labeled 'A.'.
// This convention prevents users from explicitly calling constructors.
const String& klass_name = String::Handle(klass.Name());
String& internal_constructor_name =
String::Handle(String::Concat(klass_name, Symbols::Dot()));
if (!constructor_name.IsNull()) {
internal_constructor_name =
String::Concat(internal_constructor_name, constructor_name);
}
Function& lookup_constructor = Function::Handle(
klass.LookupFunction(internal_constructor_name));
if (lookup_constructor.IsNull() ||
(lookup_constructor.kind() != RawFunction::kConstructor) ||
!lookup_constructor.is_reflectable()) {
// 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(klass.RareType()),
internal_constructor_name,
lookup_constructor,
Object::null_array(),
InvocationMirror::kConstructor,
InvocationMirror::kMethod);
UNREACHABLE();
}
if (klass.is_abstract() && !lookup_constructor.IsFactory()) {
const Array& error_args = Array::Handle(Array::New(3));
error_args.SetAt(0, klass_name);
// 1 = script url
// 2 = token position
Exceptions::ThrowByType(Exceptions::kAbstractClassInstantiation,
error_args);
UNREACHABLE();
}
ASSERT(!type.IsNull());
TypeArguments& type_arguments = TypeArguments::Handle(type.arguments());
if (!type.IsInstantiated()) {
// Must have been a declaration type.
AbstractType& rare_type = AbstractType::Handle(klass.RareType());
ASSERT(rare_type.IsInstantiated());
type_arguments = rare_type.arguments();
}
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& redirect_type = Type::Handle(lookup_constructor.RedirectionType());
if (!redirect_type.IsInstantiated()) {
// The type arguments of the redirection type are instantiated from the
// type arguments of the type reflected by the class mirror.
Error& bound_error = Error::Handle();
redirect_type ^= redirect_type.InstantiateFrom(type_arguments,
&bound_error);
if (!bound_error.IsNull()) {
Exceptions::PropagateError(bound_error);
UNREACHABLE();
}
redirect_type ^= redirect_type.Canonicalize();
}
type = redirect_type.raw();
type_arguments = redirect_type.arguments();
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.IsGenerativeConstructor() ? 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 =
Array::Handle(ArgumentsDescriptor::New(args.Length(),
arg_names));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
if (!redirected_constructor.AreValidArguments(args_descriptor, NULL) ||
!redirected_constructor.is_reflectable()) {
// 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.
redirected_constructor = Function::null();
ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
internal_constructor_name,
redirected_constructor,
Object::null_array(),
InvocationMirror::kConstructor,
InvocationMirror::kMethod);
UNREACHABLE();
}
Instance& new_object = Instance::Handle();
if (redirected_constructor.IsGenerativeConstructor()) {
// 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);
if (!type_arguments.IsNull()) {
// The type arguments will be null if the class has no type parameters, in
// which case the following call would fail because there is no slot
// reserved in the object for the type vector.
new_object.SetTypeArguments(type_arguments);
}
args.SetAt(0, new_object);
args.SetAt(1, Smi::Handle(Smi::New(Function::kCtorPhaseAll)));
} else {
// Factories get type arguments.
args.SetAt(0, type_arguments);
}
// Invoke the constructor and return the new object.
const Object& result =
Object::Handle(DartEntry::InvokeFunction(redirected_constructor,
args,
args_descriptor_array));
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
UNREACHABLE();
}
// Factories may return null.
ASSERT(result.IsInstance() || result.IsNull());
if (redirected_constructor.IsGenerativeConstructor()) {
return new_object.raw();
} else {
return result.raw();
}
}
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.
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Library& library = Library::Handle(ref.GetLibraryReferent());
GET_NON_NULL_NATIVE_ARGUMENT(
String, function_name, arguments->NativeArgAt(2));
GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(3));
GET_NON_NULL_NATIVE_ARGUMENT(Array, arg_names, arguments->NativeArgAt(4));
Function& function = Function::Handle(
library.LookupLocalFunction(function_name));
if (function.IsNull()) {
// Didn't find a method: try to find a getter and invoke call on its result.
const Instance& getter_result =
Instance::Handle(InvokeLibraryGetter(library, function_name, false));
if (getter_result.raw() != Object::sentinel().raw()) {
// Make room for the closure (receiver) in arguments.
intptr_t numArgs = args.Length();
const Array& call_args = Array::Handle(Array::New(numArgs + 1));
Object& temp = Object::Handle();
for (int i = 0; i < numArgs; 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));
// Call closure.
const Object& call_result = Object::Handle(
DartEntry::InvokeClosure(call_args, call_args_descriptor_array));
if (call_result.IsError()) {
Exceptions::PropagateError(Error::Cast(call_result));
UNREACHABLE();
}
return call_result.raw();
}
}
const Array& args_descriptor_array =
Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
if (function.IsNull() ||
!function.AreValidArguments(args_descriptor, NULL) ||
!function.is_reflectable()) {
ThrowNoSuchMethod(Instance::null_instance(),
function_name,
function,
Object::null_array(),
InvocationMirror::kTopLevel,
InvocationMirror::kMethod);
UNREACHABLE();
}
const Object& result = Object::Handle(
DartEntry::InvokeFunction(function, args, args_descriptor_array));
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
UNREACHABLE();
}
return result.raw();
}
DEFINE_NATIVE_ENTRY(LibraryMirror_invokeGetter, 3) {
// 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_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));
return InvokeLibraryGetter(library, getter_name, true);
}
DEFINE_NATIVE_ENTRY(LibraryMirror_invokeSetter, 4) {
// 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_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Library& library = Library::Handle(ref.GetLibraryReferent());
GET_NON_NULL_NATIVE_ARGUMENT(String, setter_name, arguments->NativeArgAt(2));
GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(3));
// To access a top-level we may need to use the Field or the
// setter Function. The setter function may either be in the
// library or in the field's owner class, depending.
const Field& field = Field::Handle(
library.LookupLocalField(setter_name));
Function& setter = Function::Handle();
const String& internal_setter_name =
String::Handle(Field::SetterName(setter_name));
if (field.IsNull()) {
setter = library.LookupLocalFunction(internal_setter_name);
const int kNumArgs = 1;
const Array& args = Array::Handle(Array::New(kNumArgs));
args.SetAt(0, value);
if (setter.IsNull() || !setter.is_reflectable()) {
ThrowNoSuchMethod(Instance::null_instance(),
internal_setter_name,
setter,
args,
InvocationMirror::kTopLevel,
InvocationMirror::kSetter);
UNREACHABLE();
}
// Invoke the setter and return the result.
const Object& result = Object::Handle(
DartEntry::InvokeFunction(setter, args));
if (result.IsError()) {
Exceptions::PropagateError(Error::Cast(result));
UNREACHABLE();
}
return result.raw();
}
if (field.is_final()) {
ThrowNoSuchMethod(Instance::null_instance(),
internal_setter_name,
setter,
Object::null_array(),
InvocationMirror::kTopLevel,
InvocationMirror::kSetter);
UNREACHABLE();
}
field.set_value(value);
return value.raw();
}
DEFINE_NATIVE_ENTRY(MethodMirror_owner, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
const Function& func = Function::Handle(ref.GetFunctionReferent());
if (func.IsNonImplicitClosureFunction()) {
return CreateMethodMirror(Function::Handle(
func.parent_function()), Object::null_instance());
}
const Class& owner = Class::Handle(func.Owner());
if (owner.IsTopLevel()) {
return CreateLibraryMirror(Library::Handle(owner.library()));
}
AbstractType& type = AbstractType::Handle(owner.DeclarationType());
return CreateClassMirror(owner, type, Bool::True(), Object::null_instance());
}
DEFINE_NATIVE_ENTRY(MethodMirror_parameters, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, owner, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Function& func = Function::Handle(ref.GetFunctionReferent());
return CreateParameterMirrorList(func, owner);
}
DEFINE_NATIVE_ENTRY(MethodMirror_return_type, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
const Function& func = Function::Handle(ref.GetFunctionReferent());
GET_NATIVE_ARGUMENT(AbstractType, instantiator, arguments->NativeArgAt(1));
// We handle constructors in Dart code.
ASSERT(!func.IsGenerativeConstructor());
const AbstractType& type = AbstractType::Handle(func.result_type());
return InstantiateType(type, instantiator);
}
DEFINE_NATIVE_ENTRY(MethodMirror_source, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
const Function& func = Function::Handle(ref.GetFunctionReferent());
if (func.IsImplicitConstructor() || func.IsSignatureFunction()) {
// We may need to handle more cases when the restrictions on mixins are
// relaxed. In particular we might start associating some source with the
// forwarding constructors when it becomes possible to specify a particular
// constructor from the mixin to use.
return Instance::null();
}
const Script& script = Script::Handle(func.script());
const TokenStream& stream = TokenStream::Handle(script.tokens());
if (!script.HasSource()) {
// When source is not available, avoid printing the whole token stream and
// doing expensive position calculations.
return stream.GenerateSource(func.token_pos(), func.end_token_pos() + 1);
}
const TokenStream::Iterator tkit(stream, func.end_token_pos());
intptr_t from_line;
intptr_t from_col;
intptr_t to_line;
intptr_t to_col;
script.GetTokenLocation(func.token_pos(), &from_line, &from_col);
script.GetTokenLocation(func.end_token_pos(), &to_line, &to_col);
intptr_t last_tok_len = String::Handle(tkit.CurrentLiteral()).Length();
// Handle special cases for end tokens of closures (where we exclude the last
// token):
// (1) "foo(() => null, bar);": End token is `,', but we don't print it.
// (2) "foo(() => null);": End token is ')`, but we don't print it.
// (3) "var foo = () => null;": End token is `;', but in this case the token
// semicolon belongs to the assignment so we skip it.
if ((tkit.CurrentTokenKind() == Token::kCOMMA) || // Case 1.
(tkit.CurrentTokenKind() == Token::kRPAREN) || // Case 2.
(tkit.CurrentTokenKind() == Token::kSEMICOLON &&
String::Handle(func.name()).Equals("<anonymous closure>"))) { // Case 3.
last_tok_len = 0;
}
const Instance& result = Instance::Handle(
script.GetSnippet(from_line, from_col, to_line, to_col + last_tok_len));
ASSERT(!result.IsNull());
return result.raw();
}
static RawInstance* CreateSourceLocation(const String& uri,
intptr_t line,
intptr_t column) {
const Array& args = Array::Handle(Array::New(3));
args.SetAt(0, uri);
args.SetAt(1, Smi::Handle(Smi::New(line)));
args.SetAt(2, Smi::Handle(Smi::New(column)));
return CreateMirror(Symbols::_SourceLocation(), args);
}
DEFINE_NATIVE_ENTRY(DeclarationMirror_location, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(0));
Object& decl = Object::Handle();
if (reflectee.IsMirrorReference()) {
const MirrorReference& decl_ref = MirrorReference::Cast(reflectee);
decl = decl_ref.referent();
} else if (reflectee.IsTypeParameter()) {
decl = reflectee.raw();
} else {
UNREACHABLE();
}
Script& script = Script::Handle();
intptr_t token_pos = Scanner::kNoSourcePos;
if (decl.IsFunction()) {
const Function& func = Function::Cast(decl);
if (func.IsImplicitConstructor() || func.IsSignatureFunction()) {
// These are synthetic methods; they have no source.
return Instance::null();
}
script = func.script();
token_pos = func.token_pos();
} else if (decl.IsClass()) {
const Class& cls = Class::Cast(decl);
const bool is_typedef = cls.IsSignatureClass() &&
!cls.IsCanonicalSignatureClass();
if (cls.is_synthesized_class() &&
!is_typedef &&
!cls.is_mixin_app_alias() &&
!cls.is_enum_class()) {
return Instance::null(); // Synthetic.
}
script = cls.script();
token_pos = cls.token_pos();
} else if (decl.IsField()) {
const Field& field = Field::Cast(decl);
const Class& owner = Class::Handle(field.owner());
script = owner.script();
token_pos = field.token_pos();
} else if (decl.IsTypeParameter()) {
const TypeParameter& type_var = TypeParameter::Cast(decl);
const Class& owner = Class::Handle(type_var.parameterized_class());
script = owner.script();
token_pos = type_var.token_pos();
} else if (decl.IsLibrary()) {
const Library& lib = Library::Cast(decl);
if (lib.raw() == Library::NativeWrappersLibrary()) {
return Instance::null(); // No source.
}
const Array& scripts = Array::Handle(lib.LoadedScripts());
for (intptr_t i = 0; i < scripts.Length(); i++) {
script ^= scripts.At(i);
if (script.kind() == RawScript::kLibraryTag) break;
}
ASSERT(!script.IsNull());
const String& libname = String::Handle(lib.name());
if (libname.Length() == 0) {
// No library declaration.
const String& uri = String::Handle(script.url());
return CreateSourceLocation(uri, 1, 1);
}
const TokenStream& stream = TokenStream::Handle(script.tokens());
TokenStream::Iterator tkit(stream, 0);
if (tkit.CurrentTokenKind() == Token::kSCRIPTTAG) tkit.Advance();
token_pos = tkit.CurrentPosition();
}
ASSERT(!script.IsNull());
ASSERT(token_pos != Scanner::kNoSourcePos);
const String& uri = String::Handle(script.url());
intptr_t from_line = 0;
intptr_t from_col = 0;
if (script.HasSource()) {
script.GetTokenLocation(token_pos, &from_line, &from_col);
} else {
// Avoid the slow path of printing the token stream when precise source
// information is not available.
script.GetTokenLocation(token_pos, &from_line, NULL);
}
// We should always have at least the line number.
ASSERT(from_line != 0);
return CreateSourceLocation(uri, from_line, from_col);
}
DEFINE_NATIVE_ENTRY(TypedefMirror_referent, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
const Class& cls = Class::Handle(type.type_class());
const Function& sig_func = Function::Handle(cls.signature_function());
const Class& sig_cls = Class::Handle(sig_func.signature_class());
AbstractType& referent_type = AbstractType::Handle(sig_cls.DeclarationType());
referent_type = InstantiateType(referent_type, type);
return CreateFunctionTypeMirror(sig_cls, referent_type);
}
DEFINE_NATIVE_ENTRY(ParameterMirror_type, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, pos, arguments->NativeArgAt(1));
GET_NATIVE_ARGUMENT(AbstractType, instantiator, arguments->NativeArgAt(2));
const Function& func = Function::Handle(ref.GetFunctionReferent());
const AbstractType& type = AbstractType::Handle(
func.ParameterTypeAt(func.NumImplicitParameters() + pos.Value()));
return InstantiateType(type, instantiator);
}
DEFINE_NATIVE_ENTRY(VariableMirror_type, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
const Field& field = Field::Handle(ref.GetFieldReferent());
GET_NATIVE_ARGUMENT(AbstractType, instantiator, arguments->NativeArgAt(1));
const AbstractType& type = AbstractType::Handle(field.type());
return InstantiateType(type, instantiator);
}
DEFINE_NATIVE_ENTRY(TypeMirror_subtypeTest, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
return Bool::Get(a.IsSubtypeOf(b, NULL)).raw();
}
DEFINE_NATIVE_ENTRY(TypeMirror_moreSpecificTest, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
return Bool::Get(a.IsMoreSpecificThan(b, NULL)).raw();
}
} // namespace dart