|  | // 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(); | 
|  |  | 
|  | static const char* const names[] = { | 
|  | #define EMIT_FIELD_NAME(type, name) #name "_", | 
|  | ISOLATE_OBJECT_STORE_FIELD_LIST(EMIT_FIELD_NAME, EMIT_FIELD_NAME) | 
|  | #undef EMIT_FIELD_NAME | 
|  | }; | 
|  | ObjectPtr* current = from(); | 
|  | intptr_t i = 0; | 
|  | while (current <= to()) { | 
|  | value = *current; | 
|  | fields.AddProperty(names[i], value); | 
|  | current++; | 
|  | i++; | 
|  | } | 
|  | ASSERT(i == ARRAY_SIZE(names)); | 
|  | } | 
|  | } | 
|  | #endif  // !PRODUCT | 
|  |  | 
|  | static StackTracePtr CreatePreallocatedStackTrace(Zone* zone) { | 
|  | const Array& code_array = Array::Handle( | 
|  | zone, Array::New(StackTrace::kPreallocatedStackdepth, Heap::kOld)); | 
|  | const TypedData& pc_offset_array = TypedData::Handle( | 
|  | zone, TypedData::New(kUintPtrCid, StackTrace::kPreallocatedStackdepth, | 
|  | Heap::kOld)); | 
|  | const StackTrace& stack_trace = | 
|  | StackTrace::Handle(zone, StackTrace::New(code_array, pc_offset_array)); | 
|  | // Expansion of inlined functions requires additional memory at run time, | 
|  | // avoid it. | 
|  | stack_trace.set_expand_inlined(false); | 
|  | return stack_trace.ptr(); | 
|  | } | 
|  |  | 
|  | ErrorPtr IsolateObjectStore::PreallocateObjects(const Object& out_of_memory) { | 
|  | Thread* thread = Thread::Current(); | 
|  | Isolate* isolate = thread->isolate(); | 
|  | Zone* zone = thread->zone(); | 
|  | ASSERT(isolate != nullptr && isolate->isolate_object_store() == this); | 
|  | ASSERT(preallocated_stack_trace() == StackTrace::null()); | 
|  | resume_capabilities_ = GrowableObjectArray::New(); | 
|  | exit_listeners_ = GrowableObjectArray::New(); | 
|  | error_listeners_ = GrowableObjectArray::New(); | 
|  | dart_args_1_ = Array::New(1); | 
|  | dart_args_2_ = Array::New(2); | 
|  |  | 
|  | // Allocate pre-allocated unhandled exception object initialized with the | 
|  | // pre-allocated OutOfMemoryError. | 
|  | const StackTrace& preallocated_stack_trace = | 
|  | StackTrace::Handle(zone, CreatePreallocatedStackTrace(zone)); | 
|  | set_preallocated_stack_trace(preallocated_stack_trace); | 
|  | set_preallocated_unhandled_exception(UnhandledException::Handle( | 
|  | zone, UnhandledException::New(Instance::Cast(out_of_memory), | 
|  | preallocated_stack_trace))); | 
|  | const UnwindError& preallocated_unwind_error = | 
|  | UnwindError::Handle(zone, UnwindError::New(String::Handle( | 
|  | zone, String::New("isolate is exiting")))); | 
|  | set_preallocated_unwind_error(preallocated_unwind_error); | 
|  |  | 
|  | 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(); | 
|  | } | 
|  |  | 
|  | void ObjectStore::InitStubs() { | 
|  | #define DO(member, name) set_##member(StubCode::name()); | 
|  | OBJECT_STORE_STUB_CODE_LIST(DO) | 
|  | #undef DO | 
|  | } | 
|  |  | 
|  | #ifndef PRODUCT | 
|  | void ObjectStore::PrintToJSONObject(JSONObject* jsobj) { | 
|  | jsobj->AddProperty("type", "_ObjectStore"); | 
|  |  | 
|  | { | 
|  | JSONObject fields(jsobj, "fields"); | 
|  | Object& value = Object::Handle(); | 
|  | static const char* const names[] = { | 
|  | #define EMIT_FIELD_NAME(type, name) #name "_", | 
|  | 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 | 
|  | }; | 
|  | ObjectPtr* current = from(); | 
|  | intptr_t i = 0; | 
|  | while (current <= to()) { | 
|  | value = *current; | 
|  | fields.AddProperty(names[i], value); | 
|  | current++; | 
|  | i++; | 
|  | } | 
|  | ASSERT(i == ARRAY_SIZE(names)); | 
|  | } | 
|  | } | 
|  | #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& collection_lib = Library::Handle(zone, collection_library()); | 
|  | cls = collection_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()); | 
|  | 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()); | 
|  | 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()); | 
|  |  | 
|  | 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& 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::VarArgs()); | 
|  | ASSERT(!cls.IsNull()); | 
|  | 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 |