| // Copyright (c) 2013, 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 "vm/object_store.h" | |
| #include "vm/dart_entry.h" | |
| #include "vm/exceptions.h" | |
| #include "vm/isolate.h" | |
| #include "vm/object.h" | |
| #include "vm/raw_object.h" | |
| #include "vm/resolver.h" | |
| #include "vm/stub_code.h" | |
| #include "vm/symbols.h" | |
| #include "vm/visitor.h" | |
| namespace dart { | |
| void IsolateObjectStore::VisitObjectPointers(ObjectPointerVisitor* visitor) { | |
| ASSERT(visitor != nullptr); | |
| visitor->set_gc_root_type("isolate_object store"); | |
| visitor->VisitPointers(from(), to()); | |
| visitor->clear_gc_root_type(); | |
| } | |
| void IsolateObjectStore::Init() { | |
| for (ObjectPtr* current = from(); current <= to(); current++) { | |
| *current = Object::null(); | |
| } | |
| } | |
| #ifndef PRODUCT | |
| void IsolateObjectStore::PrintToJSONObject(JSONObject* jsobj) { | |
| jsobj->AddProperty("type", "_IsolateObjectStore"); | |
| { | |
| JSONObject fields(jsobj, "fields"); | |
| Object& value = Object::Handle(); | |
| // A strtab is smaller than an array of strings. | |
| static const char* const names = "" | |
| #define EMIT_FIELD_NAME(type, name) #name "_\0" | |
| ISOLATE_OBJECT_STORE_FIELD_LIST(EMIT_FIELD_NAME, EMIT_FIELD_NAME) | |
| #undef EMIT_FIELD_NAME | |
| ; // NOLINT | |
| const char* name = names; | |
| for (ObjectPtr* current = from(); current <= to(); current++) { | |
| value = *current; | |
| fields.AddProperty(name, value); | |
| name += strlen(name) + 1; | |
| } | |
| } | |
| } | |
| #endif // !PRODUCT | |
| ErrorPtr IsolateObjectStore::PreallocateObjects() { | |
| Thread* thread = Thread::Current(); | |
| Isolate* isolate = thread->isolate(); | |
| ASSERT(isolate != nullptr && isolate->isolate_object_store() == this); | |
| resume_capabilities_ = GrowableObjectArray::New(); | |
| exit_listeners_ = GrowableObjectArray::New(); | |
| error_listeners_ = GrowableObjectArray::New(); | |
| dart_args_1_ = Array::New(1); | |
| dart_args_2_ = Array::New(2); | |
| return Error::null(); | |
| } | |
| ObjectStore::ObjectStore() | |
| : | |
| #define EMIT_FIELD_INIT(type, name) name##_(nullptr), | |
| OBJECT_STORE_FIELD_LIST(EMIT_FIELD_INIT, | |
| EMIT_FIELD_INIT, | |
| EMIT_FIELD_INIT, | |
| EMIT_FIELD_INIT, | |
| EMIT_FIELD_INIT, | |
| EMIT_FIELD_INIT, | |
| EMIT_FIELD_INIT, | |
| EMIT_FIELD_INIT, | |
| EMIT_FIELD_INIT) | |
| #undef EMIT_FIELD_INIT | |
| // Just to prevent a trailing comma. | |
| unused_field_(0) { | |
| for (ObjectPtr* current = from(); current <= to(); current++) { | |
| *current = Object::null(); | |
| } | |
| } | |
| ObjectStore::~ObjectStore() {} | |
| void ObjectStore::VisitObjectPointers(ObjectPointerVisitor* visitor) { | |
| ASSERT(visitor != nullptr); | |
| visitor->set_gc_root_type("object store"); | |
| visitor->VisitPointers(from(), to()); | |
| visitor->clear_gc_root_type(); | |
| } | |
| #ifndef PRODUCT | |
| void ObjectStore::PrintToJSONObject(JSONObject* jsobj) { | |
| jsobj->AddProperty("type", "_ObjectStore"); | |
| { | |
| JSONObject fields(jsobj, "fields"); | |
| Object& value = Object::Handle(); | |
| // A strtab is smaller than an array of strings. | |
| static const char* const names = "" | |
| #define EMIT_FIELD_NAME(type, name) #name "_\0" | |
| OBJECT_STORE_FIELD_LIST( | |
| EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME, | |
| EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME, | |
| EMIT_FIELD_NAME) | |
| #undef EMIT_FIELD_NAME | |
| ; // NOLINT | |
| const char* name = names; | |
| for (ObjectPtr* current = from(); current <= to(); current++) { | |
| value = *current; | |
| fields.AddProperty(name, value); | |
| name += strlen(name) + 1; | |
| } | |
| } | |
| } | |
| #endif // !PRODUCT | |
| static InstancePtr AllocateObjectByClassName(const Library& library, | |
| const String& class_name) { | |
| const Class& cls = Class::Handle(library.LookupClassAllowPrivate(class_name)); | |
| ASSERT(!cls.IsNull()); | |
| return Instance::New(cls); | |
| } | |
| ErrorPtr ObjectStore::PreallocateObjects() { | |
| Thread* thread = Thread::Current(); | |
| IsolateGroup* isolate_group = thread->isolate_group(); | |
| // Either we are the object store on isolate group, or isolate group has no | |
| // object store and we are the object store on the isolate. | |
| ASSERT(isolate_group != nullptr && isolate_group->object_store() == this); | |
| if (this->stack_overflow() != Instance::null()) { | |
| ASSERT(this->out_of_memory() != Instance::null()); | |
| return Error::null(); | |
| } | |
| ASSERT(this->stack_overflow() == Instance::null()); | |
| ASSERT(this->out_of_memory() == Instance::null()); | |
| Object& result = Object::Handle(); | |
| const Library& library = Library::Handle(Library::CoreLibrary()); | |
| result = AllocateObjectByClassName(library, Symbols::StackOverflowError()); | |
| if (result.IsError()) { | |
| return Error::Cast(result).ptr(); | |
| } | |
| set_stack_overflow(Instance::Cast(result)); | |
| result = AllocateObjectByClassName(library, Symbols::OutOfMemoryError()); | |
| if (result.IsError()) { | |
| return Error::Cast(result).ptr(); | |
| } | |
| set_out_of_memory(Instance::Cast(result)); | |
| return Error::null(); | |
| } | |
| FunctionPtr ObjectStore::PrivateObjectLookup(const String& name) { | |
| const Library& core_lib = Library::Handle(core_library()); | |
| const String& mangled = String::ZoneHandle(core_lib.PrivateName(name)); | |
| const Class& cls = Class::Handle(object_class()); | |
| Thread* thread = Thread::Current(); | |
| const auto& error = cls.EnsureIsFinalized(thread); | |
| ASSERT(error == Error::null()); | |
| const Function& result = Function::Handle( | |
| Resolver::ResolveDynamicFunction(thread->zone(), cls, mangled)); | |
| ASSERT(!result.IsNull()); | |
| return result.ptr(); | |
| } | |
| void ObjectStore::InitKnownObjects() { | |
| Thread* thread = Thread::Current(); | |
| Zone* zone = thread->zone(); | |
| Class& cls = Class::Handle(zone); | |
| const Library& compact_hash_lib = | |
| Library::Handle(zone, _compact_hash_library()); | |
| cls = compact_hash_lib.LookupClassAllowPrivate(Symbols::_Set()); | |
| ASSERT(!cls.IsNull()); | |
| set_set_impl_class(cls); | |
| #if defined(DART_PRECOMPILED_RUNTIME) | |
| // The rest of these objects are only needed for code generation. | |
| return; | |
| #else | |
| auto isolate_group = thread->isolate_group(); | |
| ASSERT(isolate_group != nullptr && isolate_group->object_store() == this); | |
| const Library& async_lib = Library::Handle(zone, async_library()); | |
| ASSERT(!async_lib.IsNull()); | |
| cls = async_lib.LookupClass(Symbols::Future()); | |
| ASSERT(!cls.IsNull()); | |
| set_future_class(cls); | |
| String& function_name = String::Handle(zone); | |
| Function& function = Function::Handle(zone); | |
| Field& field = Field::Handle(zone); | |
| cls = | |
| async_lib.LookupClassAllowPrivate(Symbols::_AsyncStarStreamController()); | |
| ASSERT(!cls.IsNull()); | |
| RELEASE_ASSERT(cls.EnsureIsFinalized(thread) == Error::null()); | |
| set_async_star_stream_controller(cls); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::add()); | |
| ASSERT(!function.IsNull()); | |
| set_async_star_stream_controller_add(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::addStream()); | |
| ASSERT(!function.IsNull()); | |
| set_async_star_stream_controller_add_stream(function); | |
| field = cls.LookupFieldAllowPrivate(Symbols::asyncStarBody()); | |
| ASSERT(!field.IsNull()); | |
| // Force the state of guarded cid to be nullable closure so that | |
| // AllocateSuspendState could write to the field directly without | |
| // updating the guard state. | |
| field.set_guarded_cid(kClosureCid); | |
| field.set_is_nullable(true); | |
| set_async_star_stream_controller_async_star_body(field); | |
| #if !defined(PRODUCT) | |
| // Disable debugging and inlining of all functions on the | |
| // _AsyncStarStreamController class. | |
| const Array& functions = Array::Handle(zone, cls.current_functions()); | |
| for (intptr_t i = 0; i < functions.Length(); i++) { | |
| function ^= functions.At(i); | |
| if (function.IsNull()) { | |
| break; | |
| } | |
| function.set_is_debuggable(false); | |
| function.set_is_inlinable(false); | |
| } | |
| #endif | |
| cls = async_lib.LookupClassAllowPrivate(Symbols::Stream()); | |
| ASSERT(!cls.IsNull()); | |
| set_stream_class(cls); | |
| cls = async_lib.LookupClassAllowPrivate(Symbols::_SuspendState()); | |
| ASSERT(!cls.IsNull()); | |
| const auto& error = cls.EnsureIsFinalized(thread); | |
| ASSERT(error == Error::null()); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_initAsync()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_init_async(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_await()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_await(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_awaitWithTypeCheck()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_await_with_type_check(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_returnAsync()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_return_async(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_returnAsyncNotFuture()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_return_async_not_future(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_initAsyncStar()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_init_async_star(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_yieldAsyncStar()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_yield_async_star(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_returnAsyncStar()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_return_async_star(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_initSyncStar()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_init_sync_star(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_suspendSyncStarAtStart()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_suspend_sync_star_at_start(function); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_handleException()); | |
| ASSERT(!function.IsNull()); | |
| set_suspend_state_handle_exception(function); | |
| cls = async_lib.LookupClassAllowPrivate(Symbols::_SyncStarIterator()); | |
| ASSERT(!cls.IsNull()); | |
| RELEASE_ASSERT(cls.EnsureIsFinalized(thread) == Error::null()); | |
| set_sync_star_iterator_class(cls); | |
| field = cls.LookupFieldAllowPrivate(Symbols::_current()); | |
| ASSERT(!field.IsNull()); | |
| set_sync_star_iterator_current(field); | |
| field = cls.LookupFieldAllowPrivate(Symbols::_state()); | |
| ASSERT(!field.IsNull()); | |
| // Force the state of guarded cid to be nullable SuspendState so that | |
| // AllocateSuspendState could write to the field directly without | |
| // updating the guard state. | |
| field.set_guarded_cid(kSuspendStateCid); | |
| field.set_is_nullable(true); | |
| set_sync_star_iterator_state(field); | |
| field = cls.LookupFieldAllowPrivate(Symbols::_yieldStarIterable()); | |
| ASSERT(!field.IsNull()); | |
| set_sync_star_iterator_yield_star_iterable(field); | |
| const Library& core_lib = Library::Handle(zone, core_library()); | |
| cls = core_lib.LookupClassAllowPrivate(Symbols::_CompileTimeError()); | |
| ASSERT(!cls.IsNull()); | |
| set_compiletime_error_class(cls); | |
| cls = core_lib.LookupClassAllowPrivate(Symbols::Pragma()); | |
| ASSERT(!cls.IsNull()); | |
| set_pragma_class(cls); | |
| RELEASE_ASSERT(cls.EnsureIsFinalized(thread) == Error::null()); | |
| set_pragma_name(Field::Handle(zone, cls.LookupField(Symbols::name()))); | |
| set_pragma_options(Field::Handle(zone, cls.LookupField(Symbols::options()))); | |
| cls = core_lib.LookupClassAllowPrivate(Symbols::_GrowableList()); | |
| ASSERT(!cls.IsNull()); | |
| RELEASE_ASSERT(cls.EnsureIsFinalized(thread) == Error::null()); | |
| growable_list_factory_ = | |
| cls.LookupFactoryAllowPrivate(Symbols::_GrowableListFactory()); | |
| ASSERT(growable_list_factory_ != Function::null()); | |
| cls = core_lib.LookupClassAllowPrivate(Symbols::Error()); | |
| ASSERT(!cls.IsNull()); | |
| set_error_class(cls); | |
| cls = core_lib.LookupClassAllowPrivate(Symbols::Expando()); | |
| ASSERT(!cls.IsNull()); | |
| set_expando_class(cls); | |
| cls = core_lib.LookupClassAllowPrivate(Symbols::Iterable()); | |
| ASSERT(!cls.IsNull()); | |
| set_iterable_class(cls); | |
| // Cache the core private functions used for fast instance of checks. | |
| simple_instance_of_function_ = | |
| PrivateObjectLookup(Symbols::_simpleInstanceOf()); | |
| simple_instance_of_true_function_ = | |
| PrivateObjectLookup(Symbols::_simpleInstanceOfTrue()); | |
| simple_instance_of_false_function_ = | |
| PrivateObjectLookup(Symbols::_simpleInstanceOfFalse()); | |
| // Ensure AddSmiSmiCheckForFastSmiStubs run by the background compiler | |
| // will not create new functions. | |
| const Class& smi_class = Class::Handle(zone, this->smi_class()); | |
| RELEASE_ASSERT(smi_class.EnsureIsFinalized(thread) == Error::null()); | |
| function_name = | |
| Function::CreateDynamicInvocationForwarderName(Symbols::Plus()); | |
| Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name, | |
| /*allow_add=*/true); | |
| function_name = | |
| Function::CreateDynamicInvocationForwarderName(Symbols::Minus()); | |
| Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name, | |
| /*allow_add=*/true); | |
| function_name = | |
| Function::CreateDynamicInvocationForwarderName(Symbols::Equals()); | |
| Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name, | |
| /*allow_add=*/true); | |
| function_name = | |
| Function::CreateDynamicInvocationForwarderName(Symbols::LAngleBracket()); | |
| Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name, | |
| /*allow_add=*/true); | |
| function_name = | |
| Function::CreateDynamicInvocationForwarderName(Symbols::RAngleBracket()); | |
| Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name, | |
| /*allow_add=*/true); | |
| function_name = | |
| Function::CreateDynamicInvocationForwarderName(Symbols::BitAnd()); | |
| Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name, | |
| /*allow_add=*/true); | |
| function_name = | |
| Function::CreateDynamicInvocationForwarderName(Symbols::BitOr()); | |
| Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name, | |
| /*allow_add=*/true); | |
| function_name = | |
| Function::CreateDynamicInvocationForwarderName(Symbols::Star()); | |
| Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name, | |
| /*allow_add=*/true); | |
| #endif // defined(DART_PRECOMPILED_RUNTIME) | |
| } | |
| void ObjectStore::LazyInitCoreMembers() { | |
| auto* const thread = Thread::Current(); | |
| SafepointWriteRwLocker locker(thread, | |
| thread->isolate_group()->program_lock()); | |
| if (list_class_.load() == Type::null()) { | |
| ASSERT(non_nullable_list_rare_type_.load() == Type::null()); | |
| ASSERT(non_nullable_map_rare_type_.load() == Type::null()); | |
| ASSERT(enum_index_field_.load() == Field::null()); | |
| ASSERT(enum_name_field_.load() == Field::null()); | |
| ASSERT(_object_equals_function_.load() == Function::null()); | |
| ASSERT(_object_hash_code_function_.load() == Function::null()); | |
| ASSERT(_object_to_string_function_.load() == Function::null()); | |
| auto* const zone = thread->zone(); | |
| const auto& core_lib = Library::Handle(zone, Library::CoreLibrary()); | |
| auto& cls = Class::Handle(zone); | |
| cls = core_lib.LookupClass(Symbols::List()); | |
| ASSERT(!cls.IsNull()); | |
| list_class_.store(cls.ptr()); | |
| auto& type = Type::Handle(zone); | |
| type = cls.RareType(); | |
| non_nullable_list_rare_type_.store(type.ptr()); | |
| cls = core_lib.LookupClass(Symbols::Map()); | |
| ASSERT(!cls.IsNull()); | |
| map_class_.store(cls.ptr()); | |
| type = cls.RareType(); | |
| non_nullable_map_rare_type_.store(type.ptr()); | |
| cls = core_lib.LookupClass(Symbols::Set()); | |
| ASSERT(!cls.IsNull()); | |
| set_class_.store(cls.ptr()); | |
| auto& field = Field::Handle(zone); | |
| cls = core_lib.LookupClassAllowPrivate(Symbols::_Enum()); | |
| ASSERT(!cls.IsNull()); | |
| const auto& error = cls.EnsureIsFinalized(thread); | |
| ASSERT(error == Error::null()); | |
| field = cls.LookupInstanceField(Symbols::Index()); | |
| ASSERT(!field.IsNull()); | |
| enum_index_field_.store(field.ptr()); | |
| field = cls.LookupInstanceFieldAllowPrivate(Symbols::_name()); | |
| ASSERT(!field.IsNull()); | |
| enum_name_field_.store(field.ptr()); | |
| cls = core_lib.LookupClassAllowPrivate(Symbols::_BigIntImpl()); | |
| ASSERT(!cls.IsNull()); | |
| bigint_impl_class_.store(cls.ptr()); | |
| auto& function = Function::Handle(zone); | |
| function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectHashCode()); | |
| ASSERT(!function.IsNull()); | |
| _object_hash_code_function_.store(function.ptr()); | |
| function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectEquals()); | |
| ASSERT(!function.IsNull()); | |
| _object_equals_function_.store(function.ptr()); | |
| function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectToString()); | |
| ASSERT(!function.IsNull()); | |
| _object_to_string_function_.store(function.ptr()); | |
| } | |
| } | |
| void ObjectStore::LazyInitAsyncMembers() { | |
| auto* const thread = Thread::Current(); | |
| SafepointWriteRwLocker locker(thread, | |
| thread->isolate_group()->program_lock()); | |
| if (nullable_future_null_type_.load() == Type::null()) { | |
| ASSERT(non_nullable_future_never_type_.load() == Type::null()); | |
| auto* const zone = thread->zone(); | |
| const auto& cls = Class::Handle(zone, future_class()); | |
| ASSERT(!cls.IsNull()); | |
| auto& type_args = TypeArguments::Handle(zone); | |
| auto& type = Type::Handle(zone); | |
| type = never_type(); | |
| ASSERT(!type.IsNull()); | |
| type_args = TypeArguments::New(1); | |
| type_args.SetTypeAt(0, type); | |
| type = Type::New(cls, type_args, Nullability::kNonNullable); | |
| type.SetIsFinalized(); | |
| type ^= type.Canonicalize(thread); | |
| non_nullable_future_never_type_.store(type.ptr()); | |
| type = null_type(); | |
| ASSERT(!type.IsNull()); | |
| type_args = TypeArguments::New(1); | |
| type_args.SetTypeAt(0, type); | |
| type = Type::New(cls, type_args, Nullability::kNullable); | |
| type.SetIsFinalized(); | |
| type ^= type.Canonicalize(thread); | |
| nullable_future_null_type_.store(type.ptr()); | |
| } | |
| } | |
| void ObjectStore::LazyInitFfiMembers() { | |
| auto* const thread = Thread::Current(); | |
| SafepointWriteRwLocker locker(thread, | |
| thread->isolate_group()->program_lock()); | |
| if (handle_finalizer_message_function_.load() == Function::null()) { | |
| auto* const zone = thread->zone(); | |
| auto& cls = Class::Handle(zone); | |
| auto& field = Field::Handle(zone); | |
| auto& function = Function::Handle(zone); | |
| auto& error = Error::Handle(zone); | |
| const auto& ffi_lib = Library::Handle(zone, Library::FfiLibrary()); | |
| ASSERT(!ffi_lib.IsNull()); | |
| cls = finalizer_class(); | |
| ASSERT(!cls.IsNull()); | |
| error = cls.EnsureIsFinalized(thread); | |
| ASSERT(error.IsNull()); | |
| function = | |
| cls.LookupFunctionAllowPrivate(Symbols::_handleFinalizerMessage()); | |
| ASSERT(!function.IsNull()); | |
| handle_finalizer_message_function_.store(function.ptr()); | |
| cls = native_finalizer_class(); | |
| ASSERT(!cls.IsNull()); | |
| error = cls.EnsureIsFinalized(thread); | |
| ASSERT(error.IsNull()); | |
| function = cls.LookupFunctionAllowPrivate( | |
| Symbols::_handleNativeFinalizerMessage()); | |
| ASSERT(!function.IsNull()); | |
| handle_native_finalizer_message_function_.store(function.ptr()); | |
| cls = ffi_lib.LookupClass(Symbols::FfiNative()); | |
| ASSERT(!cls.IsNull()); | |
| error = cls.EnsureIsFinalized(thread); | |
| ASSERT(error.IsNull()); | |
| function = | |
| cls.LookupStaticFunctionAllowPrivate(Symbols::_ffi_resolver_function()); | |
| ASSERT(!function.IsNull()); | |
| ffi_resolver_function_.store(function.ptr()); | |
| cls = ffi_lib.LookupClass(Symbols::Array()); | |
| ASSERT(!cls.IsNull()); | |
| ffi_array_class_.store(cls.ptr()); | |
| cls = ffi_lib.LookupClassAllowPrivate(Symbols::_Compound()); | |
| ASSERT(!cls.IsNull()); | |
| error = cls.EnsureIsFinalized(thread); | |
| ASSERT(error.IsNull()); | |
| ffi_compound_class_.store(cls.ptr()); | |
| field = cls.LookupInstanceFieldAllowPrivate(Symbols::_offsetInBytes()); | |
| ASSERT(!field.IsNull()); | |
| compound_offset_in_bytes_field_.store(field.ptr()); | |
| field = cls.LookupInstanceFieldAllowPrivate(Symbols::_typedDataBase()); | |
| ASSERT(!field.IsNull()); | |
| compound_typed_data_base_field_.store(field.ptr()); | |
| cls = ffi_lib.LookupClass(Symbols::Struct()); | |
| ASSERT(!cls.IsNull()); | |
| ffi_struct_class_.store(cls.ptr()); | |
| cls = ffi_lib.LookupClass(Symbols::Union()); | |
| ASSERT(!cls.IsNull()); | |
| ffi_union_class_.store(cls.ptr()); | |
| cls = ffi_lib.LookupClass(Symbols::VarArgs()); | |
| ASSERT(!cls.IsNull()); | |
| ffi_varargs_class_.store(cls.ptr()); | |
| } | |
| } | |
| void ObjectStore::LazyInitIsolateMembers() { | |
| auto* const thread = Thread::Current(); | |
| SafepointWriteRwLocker locker(thread, | |
| thread->isolate_group()->program_lock()); | |
| if (lookup_port_handler_.load() == Type::null()) { | |
| ASSERT(lookup_open_ports_.load() == Type::null()); | |
| ASSERT(handle_message_function_.load() == Type::null()); | |
| auto* const zone = thread->zone(); | |
| const auto& isolate_lib = Library::Handle(zone, Library::IsolateLibrary()); | |
| auto& cls = Class::Handle(zone); | |
| auto& function = Function::Handle(zone); | |
| cls = isolate_lib.LookupClass(Symbols::Capability()); | |
| ASSERT(!cls.IsNull()); | |
| capability_class_.store(cls.ptr()); | |
| cls = isolate_lib.LookupClass(Symbols::SendPort()); | |
| ASSERT(!cls.IsNull()); | |
| send_port_class_.store(cls.ptr()); | |
| cls = isolate_lib.LookupClass(Symbols::TransferableTypedData()); | |
| ASSERT(!cls.IsNull()); | |
| transferable_class_.store(cls.ptr()); | |
| cls = isolate_lib.LookupClassAllowPrivate(Symbols::_RawReceivePort()); | |
| ASSERT(!cls.IsNull()); | |
| const auto& error = cls.EnsureIsFinalized(thread); | |
| ASSERT(error == Error::null()); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_lookupHandler()); | |
| ASSERT(!function.IsNull()); | |
| lookup_port_handler_.store(function.ptr()); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_lookupOpenPorts()); | |
| ASSERT(!function.IsNull()); | |
| lookup_open_ports_.store(function.ptr()); | |
| function = cls.LookupFunctionAllowPrivate(Symbols::_handleMessage()); | |
| ASSERT(!function.IsNull()); | |
| handle_message_function_.store(function.ptr()); | |
| } | |
| } | |
| void ObjectStore::LazyInitInternalMembers() { | |
| auto* const thread = Thread::Current(); | |
| SafepointWriteRwLocker locker(thread, | |
| thread->isolate_group()->program_lock()); | |
| if (symbol_class_.load() == Type::null()) { | |
| ASSERT(symbol_name_field_.load() == Field::null()); | |
| auto* const zone = thread->zone(); | |
| auto& cls = Class::Handle(zone); | |
| auto& field = Field::Handle(zone); | |
| auto& error = Error::Handle(zone); | |
| const auto& internal_lib = | |
| Library::Handle(zone, Library::InternalLibrary()); | |
| cls = internal_lib.LookupClass(Symbols::Symbol()); | |
| ASSERT(!cls.IsNull()); | |
| error = cls.EnsureIsFinalized(thread); | |
| ASSERT(error.IsNull()); | |
| symbol_class_.store(cls.ptr()); | |
| field = cls.LookupInstanceFieldAllowPrivate(Symbols::_name()); | |
| ASSERT(!field.IsNull()); | |
| symbol_name_field_.store(field.ptr()); | |
| } | |
| } | |
| } // namespace dart |