| // 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/dart.h" |
| |
| #include "vm/code_observers.h" |
| #include "vm/dart_api_state.h" |
| #include "vm/dart_entry.h" |
| #include "vm/flags.h" |
| #include "vm/freelist.h" |
| #include "vm/handles.h" |
| #include "vm/heap.h" |
| #include "vm/isolate.h" |
| #include "vm/object.h" |
| #include "vm/object_store.h" |
| #include "vm/port.h" |
| #include "vm/simulator.h" |
| #include "vm/snapshot.h" |
| #include "vm/stub_code.h" |
| #include "vm/symbols.h" |
| #include "vm/thread_pool.h" |
| #include "vm/virtual_memory.h" |
| #include "vm/zone.h" |
| |
| namespace dart { |
| |
| DEFINE_FLAG(bool, heap_profile_initialize, false, |
| "Writes a heap profile on isolate initialization."); |
| DECLARE_FLAG(bool, print_bootstrap); |
| DECLARE_FLAG(bool, print_class_table); |
| DECLARE_FLAG(bool, trace_isolates); |
| |
| Isolate* Dart::vm_isolate_ = NULL; |
| ThreadPool* Dart::thread_pool_ = NULL; |
| DebugInfo* Dart::pprof_symbol_generator_ = NULL; |
| ReadOnlyHandles* Dart::predefined_handles_ = NULL; |
| |
| // An object visitor which will mark all visited objects. This is used to |
| // premark all objects in the vm_isolate_ heap. |
| class PremarkingVisitor : public ObjectVisitor { |
| public: |
| explicit PremarkingVisitor(Isolate* isolate) : ObjectVisitor(isolate) {} |
| |
| void VisitObject(RawObject* obj) { |
| // RawInstruction objects are premarked on allocation. |
| if (!obj->IsMarked()) { |
| obj->SetMarkBit(); |
| } |
| } |
| }; |
| |
| |
| // Structure for managing read-only global handles allocation used for |
| // creating global read-only handles that are pre created and initialized |
| // for use across all isolates. Having these global pre created handles |
| // stored in the vm isolate ensures that we don't constantly create and |
| // destroy handles for read-only objects referred in the VM code |
| // (e.g: symbols, null object, empty array etc.) |
| // The ReadOnlyHandles C++ Wrapper around VMHandles which is a ValueObject is |
| // to ensure that the handles area is not trashed by automatic running of C++ |
| // static destructors when 'exit()" is called by any isolate. There might be |
| // other isolates running at the same time and trashing the handles area will |
| // have unintended consequences. |
| class ReadOnlyHandles { |
| public: |
| ReadOnlyHandles() { } |
| |
| private: |
| VMHandles handles_; |
| |
| friend class Dart; |
| DISALLOW_COPY_AND_ASSIGN(ReadOnlyHandles); |
| }; |
| |
| |
| // TODO(turnidge): We should add a corresponding Dart::Cleanup. |
| const char* Dart::InitOnce(Dart_IsolateCreateCallback create, |
| Dart_IsolateInterruptCallback interrupt, |
| Dart_IsolateUnhandledExceptionCallback unhandled, |
| Dart_IsolateShutdownCallback shutdown, |
| Dart_FileOpenCallback file_open, |
| Dart_FileWriteCallback file_write, |
| Dart_FileCloseCallback file_close) { |
| // TODO(iposva): Fix race condition here. |
| if (vm_isolate_ != NULL || !Flags::Initialized()) { |
| return "VM already initialized."; |
| } |
| Isolate::SetFileCallbacks(file_open, file_write, file_close); |
| OS::InitOnce(); |
| VirtualMemory::InitOnce(); |
| Isolate::InitOnce(); |
| PortMap::InitOnce(); |
| FreeListElement::InitOnce(); |
| Api::InitOnce(); |
| CodeObservers::InitOnce(); |
| #if defined(USING_SIMULATOR) |
| Simulator::InitOnce(); |
| #endif |
| // Create the read-only handles area. |
| ASSERT(predefined_handles_ == NULL); |
| predefined_handles_ = new ReadOnlyHandles(); |
| // Create the VM isolate and finish the VM initialization. |
| ASSERT(thread_pool_ == NULL); |
| thread_pool_ = new ThreadPool(); |
| { |
| ASSERT(vm_isolate_ == NULL); |
| ASSERT(Flags::Initialized()); |
| vm_isolate_ = Isolate::Init("vm-isolate"); |
| StackZone zone(vm_isolate_); |
| HandleScope handle_scope(vm_isolate_); |
| Heap::Init(vm_isolate_); |
| ObjectStore::Init(vm_isolate_); |
| Object::InitOnce(); |
| ArgumentsDescriptor::InitOnce(); |
| StubCode::InitOnce(); |
| Scanner::InitOnce(); |
| Symbols::InitOnce(vm_isolate_); |
| Object::CreateInternalMetaData(); |
| CPUFeatures::InitOnce(); |
| #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) |
| // Dart VM requires at least SSE2. |
| if (!CPUFeatures::sse2_supported()) { |
| return "SSE2 is required."; |
| } |
| #endif |
| PremarkingVisitor premarker(vm_isolate_); |
| vm_isolate_->heap()->IterateOldObjects(&premarker); |
| vm_isolate_->heap()->WriteProtect(true); |
| } |
| Isolate::SetCurrent(NULL); // Unregister the VM isolate from this thread. |
| Isolate::SetCreateCallback(create); |
| Isolate::SetInterruptCallback(interrupt); |
| Isolate::SetUnhandledExceptionCallback(unhandled); |
| Isolate::SetShutdownCallback(shutdown); |
| return NULL; |
| } |
| |
| |
| Isolate* Dart::CreateIsolate(const char* name_prefix) { |
| // Create a new isolate. |
| Isolate* isolate = Isolate::Init(name_prefix); |
| ASSERT(isolate != NULL); |
| return isolate; |
| } |
| |
| |
| static void PrintLibrarySources(Isolate* isolate) { |
| const GrowableObjectArray& libs = GrowableObjectArray::Handle( |
| isolate->object_store()->libraries()); |
| intptr_t lib_count = libs.Length(); |
| Library& lib = Library::Handle(); |
| Array& scripts = Array::Handle(); |
| Script& script = Script::Handle(); |
| String& url = String::Handle(); |
| String& source = String::Handle(); |
| for (int i = 0; i < lib_count; i++) { |
| lib ^= libs.At(i); |
| url = lib.url(); |
| OS::Print("Library %s:\n", url.ToCString()); |
| scripts = lib.LoadedScripts(); |
| intptr_t script_count = scripts.Length(); |
| for (intptr_t i = 0; i < script_count; i++) { |
| script ^= scripts.At(i); |
| url = script.url(); |
| source = script.Source(); |
| OS::Print("Source for %s:\n", url.ToCString()); |
| OS::Print("%s\n", source.ToCString()); |
| } |
| } |
| } |
| |
| |
| RawError* Dart::InitializeIsolate(const uint8_t* snapshot_buffer, void* data) { |
| // Initialize the new isolate. |
| TIMERSCOPE(time_isolate_initialization); |
| Isolate* isolate = Isolate::Current(); |
| ASSERT(isolate != NULL); |
| StackZone zone(isolate); |
| HandleScope handle_scope(isolate); |
| Heap::Init(isolate); |
| ObjectStore::Init(isolate); |
| |
| if (snapshot_buffer == NULL) { |
| const Error& error = Error::Handle(Object::Init(isolate)); |
| if (!error.IsNull()) { |
| return error.raw(); |
| } |
| } else { |
| // Initialize from snapshot (this should replicate the functionality |
| // of Object::Init(..) in a regular isolate creation path. |
| Object::InitFromSnapshot(isolate); |
| |
| // TODO(turnidge): Remove once length is not part of the snapshot. |
| const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_buffer); |
| ASSERT(snapshot->kind() == Snapshot::kFull); |
| if (FLAG_trace_isolates) { |
| OS::Print("Size of isolate snapshot = %d\n", snapshot->length()); |
| } |
| SnapshotReader reader(snapshot->content(), snapshot->length(), |
| Snapshot::kFull, isolate); |
| reader.ReadFullSnapshot(); |
| if (FLAG_trace_isolates) { |
| isolate->heap()->PrintSizes(); |
| isolate->megamorphic_cache_table()->PrintSizes(); |
| } |
| if (FLAG_print_bootstrap) { |
| PrintLibrarySources(isolate); |
| } |
| } |
| |
| if (FLAG_heap_profile_initialize) { |
| isolate->heap()->ProfileToFile("initialize"); |
| } |
| |
| Object::VerifyBuiltinVtables(); |
| |
| StubCode::Init(isolate); |
| isolate->megamorphic_cache_table()->InitMissHandler(); |
| |
| isolate->heap()->EnableGrowthControl(); |
| isolate->set_init_callback_data(data); |
| Api::SetupAcquiredError(isolate); |
| if (FLAG_print_class_table) { |
| isolate->class_table()->Print(); |
| } |
| return Error::null(); |
| } |
| |
| |
| void Dart::ShutdownIsolate() { |
| Isolate* isolate = Isolate::Current(); |
| void* callback_data = isolate->init_callback_data(); |
| isolate->Shutdown(); |
| delete isolate; |
| |
| Dart_IsolateShutdownCallback callback = Isolate::ShutdownCallback(); |
| if (callback != NULL) { |
| (callback)(callback_data); |
| } |
| } |
| |
| |
| uword Dart::AllocateReadOnlyHandle() { |
| ASSERT(Isolate::Current() == Dart::vm_isolate()); |
| ASSERT(predefined_handles_ != NULL); |
| return predefined_handles_->handles_.AllocateScopedHandle(); |
| } |
| |
| |
| bool Dart::IsReadOnlyHandle(uword address) { |
| ASSERT(predefined_handles_ != NULL); |
| return predefined_handles_->handles_.IsValidScopedHandle(address); |
| } |
| |
| } // namespace dart |