5 #include "src/wasm/wasm-engine.h" 7 #include "src/code-tracer.h" 8 #include "src/compilation-statistics.h" 9 #include "src/objects-inl.h" 10 #include "src/objects/js-promise.h" 11 #include "src/wasm/function-compiler.h" 12 #include "src/wasm/module-compiler.h" 13 #include "src/wasm/module-decoder.h" 14 #include "src/wasm/streaming-decoder.h" 15 #include "src/wasm/wasm-objects-inl.h" 21 WasmEngine::WasmEngine()
22 : code_manager_(&memory_tracker_, kMaxWasmCodeMemory) {}
24 WasmEngine::~WasmEngine() {
26 DCHECK(jobs_.empty());
28 DCHECK(isolates_.empty());
31 bool WasmEngine::SyncValidate(Isolate* isolate,
const WasmFeatures& enabled,
32 const ModuleWireBytes& bytes) {
34 if (bytes.start() ==
nullptr || bytes.length() == 0)
return false;
36 DecodeWasmModule(enabled, bytes.start(), bytes.end(),
true, kWasmOrigin,
37 isolate->counters(), allocator());
41 MaybeHandle<AsmWasmData> WasmEngine::SyncCompileTranslatedAsmJs(
42 Isolate* isolate, ErrorThrower* thrower,
const ModuleWireBytes& bytes,
43 Vector<const byte> asm_js_offset_table_bytes,
44 Handle<HeapNumber> uses_bitset) {
46 DecodeWasmModule(kAsmjsWasmFeatures, bytes.start(), bytes.end(),
false,
47 kAsmJsOrigin, isolate->counters(), allocator());
48 CHECK(!result.failed());
52 Handle<FixedArray> export_wrappers;
53 std::unique_ptr<NativeModule> native_module =
54 CompileToNativeModule(isolate, kAsmjsWasmFeatures, thrower,
55 std::move(result).value(), bytes, &export_wrappers);
56 if (!native_module)
return {};
60 Handle<ByteArray> asm_js_offset_table =
61 isolate->factory()->NewByteArray(asm_js_offset_table_bytes.length());
62 asm_js_offset_table->copy_in(0, asm_js_offset_table_bytes.start(),
63 asm_js_offset_table_bytes.length());
65 return AsmWasmData::New(isolate, std::move(native_module), export_wrappers,
66 asm_js_offset_table, uses_bitset);
69 Handle<WasmModuleObject> WasmEngine::FinalizeTranslatedAsmJs(
70 Isolate* isolate, Handle<AsmWasmData> asm_wasm_data,
71 Handle<Script> script) {
72 std::shared_ptr<NativeModule> native_module =
73 asm_wasm_data->managed_native_module()->get();
74 Handle<FixedArray> export_wrappers =
75 handle(asm_wasm_data->export_wrappers(), isolate);
76 size_t code_size_estimate =
77 wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
78 native_module->module());
80 Handle<WasmModuleObject> module_object =
81 WasmModuleObject::New(isolate, std::move(native_module), script,
82 export_wrappers, code_size_estimate);
83 module_object->set_asm_js_offset_table(asm_wasm_data->asm_js_offset_table());
87 MaybeHandle<WasmModuleObject> WasmEngine::SyncCompile(
88 Isolate* isolate,
const WasmFeatures& enabled, ErrorThrower* thrower,
89 const ModuleWireBytes& bytes) {
91 DecodeWasmModule(enabled, bytes.start(), bytes.end(),
false, kWasmOrigin,
92 isolate->counters(), allocator());
93 if (result.failed()) {
94 thrower->CompileFailed(
"Wasm decoding failed", result);
100 Handle<FixedArray> export_wrappers;
101 std::unique_ptr<NativeModule> native_module =
102 CompileToNativeModule(isolate, enabled, thrower,
103 std::move(result).value(), bytes, &export_wrappers);
104 if (!native_module)
return {};
106 Handle<Script> script =
107 CreateWasmScript(isolate, bytes, native_module->module()->source_map_url);
108 size_t code_size_estimate =
109 wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
110 native_module->module());
121 Handle<WasmModuleObject> module_object =
122 WasmModuleObject::New(isolate, std::move(native_module), script,
123 export_wrappers, code_size_estimate);
126 isolate->debug()->OnAfterCompile(script);
127 return module_object;
130 MaybeHandle<WasmInstanceObject> WasmEngine::SyncInstantiate(
131 Isolate* isolate, ErrorThrower* thrower,
132 Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
133 MaybeHandle<JSArrayBuffer> memory) {
134 return InstantiateToInstanceObject(isolate, thrower, module_object, imports,
138 void WasmEngine::AsyncInstantiate(
139 Isolate* isolate, std::unique_ptr<InstantiationResultResolver> resolver,
140 Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports) {
141 ErrorThrower thrower(isolate,
"WebAssembly Instantiation");
146 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
147 catcher.SetVerbose(
false);
148 catcher.SetCaptureMessage(
false);
150 MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate(
151 isolate, &thrower, module_object, imports, Handle<JSArrayBuffer>::null());
153 if (!instance_object.is_null()) {
154 resolver->OnInstantiationSucceeded(instance_object.ToHandleChecked());
158 if (isolate->has_pending_exception()) {
161 Handle<Object> exception(isolate->pending_exception(), isolate);
162 isolate->clear_pending_exception();
163 DCHECK(*isolate->external_caught_exception_address());
164 *isolate->external_caught_exception_address() =
false;
165 resolver->OnInstantiationFailed(exception);
168 DCHECK(thrower.error());
169 resolver->OnInstantiationFailed(thrower.Reify());
173 void WasmEngine::AsyncCompile(
174 Isolate* isolate,
const WasmFeatures& enabled,
175 std::shared_ptr<CompilationResultResolver> resolver,
176 const ModuleWireBytes& bytes,
bool is_shared) {
177 if (!FLAG_wasm_async_compilation) {
179 ErrorThrower thrower(isolate,
"WasmCompile");
180 MaybeHandle<WasmModuleObject> module_object;
183 std::unique_ptr<uint8_t[]> copy(
new uint8_t[bytes.length()]);
184 memcpy(copy.get(), bytes.start(), bytes.length());
185 ModuleWireBytes bytes_copy(copy.get(), copy.get() + bytes.length());
186 module_object = SyncCompile(isolate, enabled, &thrower, bytes_copy);
189 module_object = SyncCompile(isolate, enabled, &thrower, bytes);
191 if (thrower.error()) {
192 resolver->OnCompilationFailed(thrower.Reify());
195 Handle<WasmModuleObject> module = module_object.ToHandleChecked();
196 resolver->OnCompilationSucceeded(module);
200 if (FLAG_wasm_test_streaming) {
201 std::shared_ptr<StreamingDecoder> streaming_decoder =
202 StartStreamingCompilation(isolate, enabled,
203 handle(isolate->context(), isolate),
204 std::move(resolver));
205 streaming_decoder->OnBytesReceived(bytes.module_bytes());
206 streaming_decoder->Finish();
211 std::unique_ptr<byte[]> copy(
new byte[bytes.length()]);
212 memcpy(copy.get(), bytes.start(), bytes.length());
214 AsyncCompileJob* job = CreateAsyncCompileJob(
215 isolate, enabled, std::move(copy), bytes.length(),
216 handle(isolate->context(), isolate), std::move(resolver));
220 std::shared_ptr<StreamingDecoder> WasmEngine::StartStreamingCompilation(
221 Isolate* isolate,
const WasmFeatures& enabled, Handle<Context> context,
222 std::shared_ptr<CompilationResultResolver> resolver) {
223 AsyncCompileJob* job =
224 CreateAsyncCompileJob(isolate, enabled, std::unique_ptr<byte[]>(
nullptr),
225 0, context, std::move(resolver));
226 return job->CreateStreamingDecoder();
229 bool WasmEngine::CompileFunction(Isolate* isolate, NativeModule* native_module,
230 uint32_t function_index, ExecutionTier tier) {
232 WasmFeatures detected = kNoWasmFeatures;
233 return WasmCompilationUnit::CompileWasmFunction(
234 isolate, native_module, &detected,
235 &native_module->module()->functions[function_index], tier);
238 std::shared_ptr<NativeModule> WasmEngine::ExportNativeModule(
239 Handle<WasmModuleObject> module_object) {
240 return module_object->managed_native_module()->get();
243 Handle<WasmModuleObject> WasmEngine::ImportNativeModule(
244 Isolate* isolate, std::shared_ptr<NativeModule> shared_module) {
245 Vector<const byte> wire_bytes = shared_module->wire_bytes();
246 const WasmModule* module = shared_module->module();
247 Handle<Script> script =
248 CreateWasmScript(isolate, wire_bytes, module->source_map_url);
249 size_t code_size = shared_module->committed_code_space();
250 Handle<WasmModuleObject> module_object = WasmModuleObject::New(
251 isolate, std::move(shared_module), script, code_size);
252 CompileJsToWasmWrappers(isolate, module_object->native_module(),
253 handle(module_object->export_wrappers(), isolate));
254 return module_object;
257 CompilationStatistics* WasmEngine::GetOrCreateTurboStatistics() {
258 base::MutexGuard guard(&mutex_);
259 if (compilation_stats_ ==
nullptr) {
260 compilation_stats_.reset(
new CompilationStatistics());
262 return compilation_stats_.get();
265 void WasmEngine::DumpAndResetTurboStatistics() {
266 base::MutexGuard guard(&mutex_);
267 if (compilation_stats_ !=
nullptr) {
269 os << AsPrintableStatistics{*compilation_stats_.get(),
false} << std::endl;
271 compilation_stats_.reset();
274 CodeTracer* WasmEngine::GetCodeTracer() {
275 base::MutexGuard guard(&mutex_);
276 if (code_tracer_ ==
nullptr) code_tracer_.reset(
new CodeTracer(-1));
277 return code_tracer_.get();
280 AsyncCompileJob* WasmEngine::CreateAsyncCompileJob(
281 Isolate* isolate,
const WasmFeatures& enabled,
282 std::unique_ptr<byte[]> bytes_copy,
size_t length, Handle<Context> context,
283 std::shared_ptr<CompilationResultResolver> resolver) {
284 AsyncCompileJob* job =
285 new AsyncCompileJob(isolate, enabled, std::move(bytes_copy), length,
286 context, std::move(resolver));
288 base::MutexGuard guard(&mutex_);
289 jobs_[job] = std::unique_ptr<AsyncCompileJob>(job);
293 std::unique_ptr<AsyncCompileJob> WasmEngine::RemoveCompileJob(
294 AsyncCompileJob* job) {
295 base::MutexGuard guard(&mutex_);
296 auto item = jobs_.find(job);
297 DCHECK(item != jobs_.end());
298 std::unique_ptr<AsyncCompileJob> result = std::move(item->second);
303 bool WasmEngine::HasRunningCompileJob(Isolate* isolate) {
304 base::MutexGuard guard(&mutex_);
305 DCHECK_EQ(1, isolates_.count(isolate));
306 for (
auto& entry : jobs_) {
307 if (entry.first->isolate() == isolate)
return true;
312 void WasmEngine::DeleteCompileJobsOnIsolate(Isolate* isolate) {
313 base::MutexGuard guard(&mutex_);
314 DCHECK_EQ(1, isolates_.count(isolate));
315 for (
auto it = jobs_.begin(); it != jobs_.end();) {
316 if (it->first->isolate() == isolate) {
317 it = jobs_.erase(it);
324 void WasmEngine::AddIsolate(Isolate* isolate) {
325 base::MutexGuard guard(&mutex_);
326 DCHECK_EQ(0, isolates_.count(isolate));
327 isolates_.insert(isolate);
330 void WasmEngine::RemoveIsolate(Isolate* isolate) {
331 base::MutexGuard guard(&mutex_);
332 DCHECK_EQ(1, isolates_.count(isolate));
333 isolates_.erase(isolate);
338 struct WasmEnginePointerConstructTrait final {
339 static void Construct(
void* raw_ptr) {
340 auto engine_ptr =
reinterpret_cast<std::shared_ptr<WasmEngine>*
>(raw_ptr);
341 *engine_ptr = std::shared_ptr<WasmEngine>();
348 base::LazyStaticInstance<std::shared_ptr<WasmEngine>,
349 WasmEnginePointerConstructTrait>::type
355 void WasmEngine::InitializeOncePerProcess() {
356 if (!FLAG_wasm_shared_engine)
return;
357 global_wasm_engine.Pointer()->reset(
new WasmEngine());
361 void WasmEngine::GlobalTearDown() {
362 if (!FLAG_wasm_shared_engine)
return;
363 global_wasm_engine.Pointer()->reset();
367 std::shared_ptr<WasmEngine> WasmEngine::GetWasmEngine() {
368 if (FLAG_wasm_shared_engine)
return global_wasm_engine.Get();
369 return std::shared_ptr<WasmEngine>(
new WasmEngine());
374 STATIC_ASSERT(kV8MaxWasmMemoryPages <= kMaxUInt32);
375 return std::min(
uint32_t{kV8MaxWasmMemoryPages}, FLAG_wasm_max_mem_pages);