blob: af17f5e4c7eb388a74a11eb6a2c5145cd8e356cd [file] [log] [blame]
// 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/object_id_ring.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_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_FileReadCallback file_read,
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_read, 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);
}
// There is a planned and known asymmetry here: We enter one scope for the VM
// isolate so that we can allocate the "persistent" scoped handles for the
// predefined API values (such as Dart_True, Dart_False and Dart_Null).
Dart_EnterScope();
Api::InitHandles();
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;
}
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);
ObjectIdRing::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_heap_profile_initialize) {
isolate->heap()->ProfileToFile("initialize");
}
Object::VerifyBuiltinVtables();
StubCode::Init(isolate);
if (snapshot_buffer == NULL) {
if (!isolate->object_store()->PreallocateObjects()) {
return isolate->object_store()->sticky_error();
}
}
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::RunShutdownCallback() {
Isolate* isolate = Isolate::Current();
void* callback_data = isolate->init_callback_data();
Dart_IsolateShutdownCallback callback = Isolate::ShutdownCallback();
if (callback != NULL) {
(callback)(callback_data);
}
}
void Dart::ShutdownIsolate() {
Isolate* isolate = Isolate::Current();
isolate->Shutdown();
delete isolate;
}
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