1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gin/public/isolate_holder.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/rand_util.h"
13 #include "base/sys_info.h"
14 #include "gin/array_buffer.h"
15 #include "gin/debug_impl.h"
16 #include "gin/function_template.h"
17 #include "gin/per_isolate_data.h"
18 #include "gin/public/v8_platform.h"
19 #include "gin/run_microtasks_observer.h"
21 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
22 #include "base/files/memory_mapped_file.h"
23 #include "base/path_service.h"
24 #endif // V8_USE_EXTERNAL_STARTUP_DATA
30 v8::ArrayBuffer::Allocator
* g_array_buffer_allocator
= NULL
;
32 bool GenerateEntropy(unsigned char* buffer
, size_t amount
) {
33 base::RandBytes(buffer
, amount
);
37 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
38 base::MemoryMappedFile
* g_mapped_natives
= NULL
;
39 base::MemoryMappedFile
* g_mapped_snapshot
= NULL
;
41 bool MapV8Files(base::FilePath
* natives_path
, base::FilePath
* snapshot_path
,
42 int natives_fd
= -1, int snapshot_fd
= -1) {
43 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
;
45 g_mapped_natives
= new base::MemoryMappedFile
;
46 if (!g_mapped_natives
->IsValid()) {
48 ? !g_mapped_natives
->Initialize(base::File(*natives_path
, flags
))
49 : !g_mapped_natives
->Initialize(base::File(natives_fd
))) {
50 delete g_mapped_natives
;
51 g_mapped_natives
= NULL
;
52 LOG(FATAL
) << "Couldn't mmap v8 natives data file";
57 g_mapped_snapshot
= new base::MemoryMappedFile
;
58 if (!g_mapped_snapshot
->IsValid()) {
60 ? !g_mapped_snapshot
->Initialize(base::File(*snapshot_path
, flags
))
61 : !g_mapped_snapshot
->Initialize(base::File(snapshot_fd
))) {
62 delete g_mapped_snapshot
;
63 g_mapped_snapshot
= NULL
;
64 LOG(ERROR
) << "Couldn't mmap v8 snapshot data file";
71 #endif // V8_USE_EXTERNAL_STARTUP_DATA
76 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
78 bool IsolateHolder::LoadV8Snapshot() {
79 if (g_mapped_natives
&& g_mapped_snapshot
)
82 base::FilePath data_path
;
83 PathService::Get(base::DIR_ANDROID_APP_DATA
, &data_path
);
84 DCHECK(!data_path
.empty());
86 base::FilePath natives_path
= data_path
.AppendASCII("natives_blob.bin");
87 base::FilePath snapshot_path
= data_path
.AppendASCII("snapshot_blob.bin");
89 return MapV8Files(&natives_path
, &snapshot_path
);
93 bool IsolateHolder::LoadV8SnapshotFD(int natives_fd
, int snapshot_fd
) {
94 if (g_mapped_natives
&& g_mapped_snapshot
)
97 return MapV8Files(NULL
, NULL
, natives_fd
, snapshot_fd
);
99 #endif // V8_USE_EXTERNAL_STARTUP_DATA
101 IsolateHolder::IsolateHolder() {
102 CHECK(g_array_buffer_allocator
)
103 << "You need to invoke gin::IsolateHolder::Initialize first";
104 v8::Isolate::CreateParams params
;
105 params
.entry_hook
= DebugImpl::GetFunctionEntryHook();
106 params
.code_event_handler
= DebugImpl::GetJitCodeEventHandler();
107 params
.constraints
.ConfigureDefaults(base::SysInfo::AmountOfPhysicalMemory(),
108 base::SysInfo::AmountOfVirtualMemory(),
109 base::SysInfo::NumberOfProcessors());
110 isolate_
= v8::Isolate::New(params
);
111 isolate_data_
.reset(new PerIsolateData(isolate_
, g_array_buffer_allocator
));
116 isolate_
->GetCodeRange(&code_range
, &size
);
117 Debug::CodeRangeCreatedCallback callback
=
118 DebugImpl::GetCodeRangeCreatedCallback();
119 if (code_range
&& size
&& callback
)
120 callback(code_range
, size
);
125 IsolateHolder::~IsolateHolder() {
126 if (task_observer_
.get())
127 base::MessageLoop::current()->RemoveTaskObserver(task_observer_
.get());
132 isolate_
->GetCodeRange(&code_range
, &size
);
133 Debug::CodeRangeDeletedCallback callback
=
134 DebugImpl::GetCodeRangeDeletedCallback();
135 if (code_range
&& callback
)
136 callback(code_range
);
139 isolate_data_
.reset();
144 void IsolateHolder::Initialize(ScriptMode mode
,
145 v8::ArrayBuffer::Allocator
* allocator
) {
147 static bool v8_is_initialized
= false;
148 if (v8_is_initialized
)
150 v8::V8::InitializePlatform(V8Platform::Get());
151 v8::V8::SetArrayBufferAllocator(allocator
);
152 g_array_buffer_allocator
= allocator
;
153 if (mode
== gin::IsolateHolder::kStrictMode
) {
154 static const char v8_flags
[] = "--use_strict";
155 v8::V8::SetFlagsFromString(v8_flags
, sizeof(v8_flags
) - 1);
157 v8::V8::SetEntropySource(&GenerateEntropy
);
158 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
159 v8::StartupData natives
;
160 natives
.data
= reinterpret_cast<const char*>(g_mapped_natives
->data());
161 natives
.raw_size
= g_mapped_natives
->length();
162 natives
.compressed_size
= g_mapped_natives
->length();
163 v8::V8::SetNativesDataBlob(&natives
);
165 v8::StartupData snapshot
;
166 snapshot
.data
= reinterpret_cast<const char*>(g_mapped_snapshot
->data());
167 snapshot
.raw_size
= g_mapped_snapshot
->length();
168 snapshot
.compressed_size
= g_mapped_snapshot
->length();
169 v8::V8::SetSnapshotDataBlob(&snapshot
);
170 #endif // V8_USE_EXTERNAL_STARTUP_DATA
171 v8::V8::Initialize();
172 v8_is_initialized
= true;
175 void IsolateHolder::AddRunMicrotasksObserver() {
176 DCHECK(!task_observer_
.get());
177 task_observer_
.reset(new RunMicrotasksObserver(isolate_
));;
178 base::MessageLoop::current()->AddTaskObserver(task_observer_
.get());
181 void IsolateHolder::RemoveRunMicrotasksObserver() {
182 DCHECK(task_observer_
.get());
183 base::MessageLoop::current()->RemoveTaskObserver(task_observer_
.get());
184 task_observer_
.reset();