diff options
Diffstat (limited to 'chromium/v8/src/wasm/wasm-engine.cc')
-rw-r--r-- | chromium/v8/src/wasm/wasm-engine.cc | 190 |
1 files changed, 129 insertions, 61 deletions
diff --git a/chromium/v8/src/wasm/wasm-engine.cc b/chromium/v8/src/wasm/wasm-engine.cc index 717c5defd79..4f772d9bdd3 100644 --- a/chromium/v8/src/wasm/wasm-engine.cc +++ b/chromium/v8/src/wasm/wasm-engine.cc @@ -8,10 +8,11 @@ #include "src/compilation-statistics.h" #include "src/objects-inl.h" #include "src/objects/js-promise.h" +#include "src/wasm/function-compiler.h" #include "src/wasm/module-compiler.h" #include "src/wasm/module-decoder.h" #include "src/wasm/streaming-decoder.h" -#include "src/wasm/wasm-objects.h" +#include "src/wasm/wasm-objects-inl.h" namespace v8 { namespace internal { @@ -20,13 +21,18 @@ namespace wasm { WasmEngine::WasmEngine() : code_manager_(&memory_tracker_, kMaxWasmCodeMemory) {} -WasmEngine::~WasmEngine() = default; +WasmEngine::~WasmEngine() { + // All AsyncCompileJobs have been canceled. + DCHECK(jobs_.empty()); +} -bool WasmEngine::SyncValidate(Isolate* isolate, const ModuleWireBytes& bytes) { +bool WasmEngine::SyncValidate(Isolate* isolate, const WasmFeatures& enabled, + const ModuleWireBytes& bytes) { // TODO(titzer): remove dependency on the isolate. if (bytes.start() == nullptr || bytes.length() == 0) return false; - ModuleResult result = SyncDecodeWasmModule(isolate, bytes.start(), - bytes.end(), true, kWasmOrigin); + ModuleResult result = + DecodeWasmModule(enabled, bytes.start(), bytes.end(), true, kWasmOrigin, + isolate->counters(), allocator()); return result.ok(); } @@ -34,20 +40,24 @@ MaybeHandle<WasmModuleObject> WasmEngine::SyncCompileTranslatedAsmJs( Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes, Handle<Script> asm_js_script, Vector<const byte> asm_js_offset_table_bytes) { - ModuleResult result = SyncDecodeWasmModule(isolate, bytes.start(), - bytes.end(), false, kAsmJsOrigin); + ModuleResult result = + DecodeWasmModule(kAsmjsWasmFeatures, bytes.start(), bytes.end(), false, + kAsmJsOrigin, isolate->counters(), allocator()); CHECK(!result.failed()); // Transfer ownership of the WasmModule to the {Managed<WasmModule>} generated // in {CompileToModuleObject}. - return CompileToModuleObject(isolate, thrower, std::move(result.val), bytes, - asm_js_script, asm_js_offset_table_bytes); + return CompileToModuleObject(isolate, kAsmjsWasmFeatures, thrower, + std::move(result.val), bytes, asm_js_script, + asm_js_offset_table_bytes); } MaybeHandle<WasmModuleObject> WasmEngine::SyncCompile( - Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes) { - ModuleResult result = SyncDecodeWasmModule(isolate, bytes.start(), - bytes.end(), false, kWasmOrigin); + Isolate* isolate, const WasmFeatures& enabled, ErrorThrower* thrower, + const ModuleWireBytes& bytes) { + ModuleResult result = + DecodeWasmModule(enabled, bytes.start(), bytes.end(), false, kWasmOrigin, + isolate->counters(), allocator()); if (result.failed()) { thrower->CompileFailed("Wasm decoding failed", result); return {}; @@ -55,8 +65,8 @@ MaybeHandle<WasmModuleObject> WasmEngine::SyncCompile( // Transfer ownership of the WasmModule to the {Managed<WasmModule>} generated // in {CompileToModuleObject}. - return CompileToModuleObject(isolate, thrower, std::move(result.val), bytes, - Handle<Script>(), Vector<const byte>()); + return CompileToModuleObject(isolate, enabled, thrower, std::move(result.val), + bytes, Handle<Script>(), Vector<const byte>()); } MaybeHandle<WasmInstanceObject> WasmEngine::SyncInstantiate( @@ -70,7 +80,7 @@ MaybeHandle<WasmInstanceObject> WasmEngine::SyncInstantiate( void WasmEngine::AsyncInstantiate( Isolate* isolate, std::unique_ptr<InstantiationResultResolver> resolver, Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports) { - ErrorThrower thrower(isolate, nullptr); + ErrorThrower thrower(isolate, "WebAssembly Instantiation"); // Instantiate a TryCatch so that caught exceptions won't progagate out. // They will still be set as pending exceptions on the isolate. // TODO(clemensh): Avoid TryCatch, use Execution::TryCall internally to invoke @@ -87,24 +97,24 @@ void WasmEngine::AsyncInstantiate( return; } - // We either have a pending exception (if the start function threw), or an - // exception in the ErrorThrower. - DCHECK_EQ(1, isolate->has_pending_exception() + thrower.error()); - if (thrower.error()) { - resolver->OnInstantiationFailed(thrower.Reify()); - } else { - // The start function has thrown an exception. We have to move the - // exception to the promise chain. + if (isolate->has_pending_exception()) { + // The JS code executed during instantiation has thrown an exception. + // We have to move the exception to the promise chain. Handle<Object> exception(isolate->pending_exception(), isolate); isolate->clear_pending_exception(); DCHECK(*isolate->external_caught_exception_address()); *isolate->external_caught_exception_address() = false; resolver->OnInstantiationFailed(exception); + thrower.Reset(); + } else { + DCHECK(thrower.error()); + resolver->OnInstantiationFailed(thrower.Reify()); } } void WasmEngine::AsyncCompile( - Isolate* isolate, std::unique_ptr<CompilationResultResolver> resolver, + Isolate* isolate, const WasmFeatures& enabled, + std::shared_ptr<CompilationResultResolver> resolver, const ModuleWireBytes& bytes, bool is_shared) { if (!FLAG_wasm_async_compilation) { // Asynchronous compilation disabled; fall back on synchronous compilation. @@ -114,12 +124,11 @@ void WasmEngine::AsyncCompile( // Make a copy of the wire bytes to avoid concurrent modification. std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]); memcpy(copy.get(), bytes.start(), bytes.length()); - i::wasm::ModuleWireBytes bytes_copy(copy.get(), - copy.get() + bytes.length()); - module_object = SyncCompile(isolate, &thrower, bytes_copy); + ModuleWireBytes bytes_copy(copy.get(), copy.get() + bytes.length()); + module_object = SyncCompile(isolate, enabled, &thrower, bytes_copy); } else { // The wire bytes are not shared, OK to use them directly. - module_object = SyncCompile(isolate, &thrower, bytes); + module_object = SyncCompile(isolate, enabled, &thrower, bytes); } if (thrower.error()) { resolver->OnCompilationFailed(thrower.Reify()); @@ -132,8 +141,9 @@ void WasmEngine::AsyncCompile( if (FLAG_wasm_test_streaming) { std::shared_ptr<StreamingDecoder> streaming_decoder = - isolate->wasm_engine()->StartStreamingCompilation( - isolate, handle(isolate->context(), isolate), std::move(resolver)); + StartStreamingCompilation(isolate, enabled, + handle(isolate->context(), isolate), + std::move(resolver)); streaming_decoder->OnBytesReceived(bytes.module_bytes()); streaming_decoder->Finish(); return; @@ -144,20 +154,53 @@ void WasmEngine::AsyncCompile( memcpy(copy.get(), bytes.start(), bytes.length()); AsyncCompileJob* job = CreateAsyncCompileJob( - isolate, std::move(copy), bytes.length(), + isolate, enabled, std::move(copy), bytes.length(), handle(isolate->context(), isolate), std::move(resolver)); job->Start(); } std::shared_ptr<StreamingDecoder> WasmEngine::StartStreamingCompilation( - Isolate* isolate, Handle<Context> context, - std::unique_ptr<CompilationResultResolver> resolver) { + Isolate* isolate, const WasmFeatures& enabled, Handle<Context> context, + std::shared_ptr<CompilationResultResolver> resolver) { AsyncCompileJob* job = - CreateAsyncCompileJob(isolate, std::unique_ptr<byte[]>(nullptr), 0, - context, std::move(resolver)); + CreateAsyncCompileJob(isolate, enabled, std::unique_ptr<byte[]>(nullptr), + 0, context, std::move(resolver)); return job->CreateStreamingDecoder(); } +bool WasmEngine::CompileFunction(Isolate* isolate, NativeModule* native_module, + uint32_t function_index, ExecutionTier tier) { + ErrorThrower thrower(isolate, "Manually requested tier up"); + // Note we assume that "one-off" compilations can discard detected features. + WasmFeatures detected = kNoWasmFeatures; + WasmCode* ret = WasmCompilationUnit::CompileWasmFunction( + isolate, native_module, &detected, &thrower, + GetModuleEnv(native_module->compilation_state()), + &native_module->module()->functions[function_index], tier); + return ret != nullptr; +} + +std::shared_ptr<NativeModule> WasmEngine::ExportNativeModule( + Handle<WasmModuleObject> module_object) { + return module_object->managed_native_module()->get(); +} + +Handle<WasmModuleObject> WasmEngine::ImportNativeModule( + Isolate* isolate, std::shared_ptr<NativeModule> shared_module) { + CHECK_EQ(code_manager(), shared_module->code_manager()); + Vector<const byte> wire_bytes = shared_module->wire_bytes(); + Handle<Script> script = CreateWasmScript(isolate, wire_bytes); + Handle<WasmModuleObject> module_object = + WasmModuleObject::New(isolate, shared_module, script); + + // TODO(6792): Wrappers below might be cloned using {Factory::CopyCode}. + // This requires unlocking the code space here. This should eventually be + // moved into the allocator. + CodeSpaceMemoryModificationScope modification_scope(isolate->heap()); + CompileJsToWasmWrappers(isolate, module_object); + return module_object; +} + CompilationStatistics* WasmEngine::GetOrCreateTurboStatistics() { base::LockGuard<base::Mutex> guard(&mutex_); if (compilation_stats_ == nullptr) { @@ -181,27 +224,22 @@ CodeTracer* WasmEngine::GetCodeTracer() { return code_tracer_.get(); } -void WasmEngine::Register(CancelableTaskManager* task_manager) { - task_managers_.emplace_back(task_manager); -} - -void WasmEngine::Unregister(CancelableTaskManager* task_manager) { - task_managers_.remove(task_manager); -} - AsyncCompileJob* WasmEngine::CreateAsyncCompileJob( - Isolate* isolate, std::unique_ptr<byte[]> bytes_copy, size_t length, - Handle<Context> context, - std::unique_ptr<CompilationResultResolver> resolver) { - AsyncCompileJob* job = new AsyncCompileJob( - isolate, std::move(bytes_copy), length, context, std::move(resolver)); + Isolate* isolate, const WasmFeatures& enabled, + std::unique_ptr<byte[]> bytes_copy, size_t length, Handle<Context> context, + std::shared_ptr<CompilationResultResolver> resolver) { + AsyncCompileJob* job = + new AsyncCompileJob(isolate, enabled, std::move(bytes_copy), length, + context, std::move(resolver)); // Pass ownership to the unique_ptr in {jobs_}. + base::LockGuard<base::Mutex> guard(&mutex_); jobs_[job] = std::unique_ptr<AsyncCompileJob>(job); return job; } std::unique_ptr<AsyncCompileJob> WasmEngine::RemoveCompileJob( AsyncCompileJob* job) { + base::LockGuard<base::Mutex> guard(&mutex_); auto item = jobs_.find(job); DCHECK(item != jobs_.end()); std::unique_ptr<AsyncCompileJob> result = std::move(item->second); @@ -209,26 +247,56 @@ std::unique_ptr<AsyncCompileJob> WasmEngine::RemoveCompileJob( return result; } -void WasmEngine::AbortCompileJobsOnIsolate(Isolate* isolate) { - // Iterate over a copy of {jobs_}, because {job->Abort} modifies {jobs_}. - std::vector<AsyncCompileJob*> isolate_jobs; - +bool WasmEngine::HasRunningCompileJob(Isolate* isolate) { + base::LockGuard<base::Mutex> guard(&mutex_); for (auto& entry : jobs_) { - if (entry.first->isolate() != isolate) continue; - isolate_jobs.push_back(entry.first); + if (entry.first->isolate() == isolate) return true; } + return false; +} - for (auto* job : isolate_jobs) job->Abort(); +void WasmEngine::DeleteCompileJobsOnIsolate(Isolate* isolate) { + base::LockGuard<base::Mutex> guard(&mutex_); + for (auto it = jobs_.begin(); it != jobs_.end();) { + if (it->first->isolate() == isolate) { + it = jobs_.erase(it); + } else { + ++it; + } + } } -void WasmEngine::TearDown() { - // Cancel all registered task managers. - for (auto task_manager : task_managers_) { - task_manager->CancelAndWait(); +namespace { + +struct WasmEnginePointerConstructTrait final { + static void Construct(void* raw_ptr) { + auto engine_ptr = reinterpret_cast<std::shared_ptr<WasmEngine>*>(raw_ptr); + *engine_ptr = std::shared_ptr<WasmEngine>(); } +}; + +// Holds the global shared pointer to the single {WasmEngine} that is intended +// to be shared among Isolates within the same process. The {LazyStaticInstance} +// here is required because {std::shared_ptr} has a non-trivial initializer. +base::LazyStaticInstance<std::shared_ptr<WasmEngine>, + WasmEnginePointerConstructTrait>::type + global_wasm_engine; + +} // namespace + +void WasmEngine::InitializeOncePerProcess() { + if (!FLAG_wasm_shared_engine) return; + global_wasm_engine.Pointer()->reset(new WasmEngine()); +} + +void WasmEngine::GlobalTearDown() { + if (!FLAG_wasm_shared_engine) return; + global_wasm_engine.Pointer()->reset(); +} - // Cancel all AsyncCompileJobs. - jobs_.clear(); +std::shared_ptr<WasmEngine> WasmEngine::GetWasmEngine() { + if (FLAG_wasm_shared_engine) return global_wasm_engine.Get(); + return std::shared_ptr<WasmEngine>(new WasmEngine()); } } // namespace wasm |