LCOV - code coverage report
Current view: top level - src/wasm - wasm-engine.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 152 202 75.2 %
Date: 2019-02-19 Functions: 33 41 80.5 %

          Line data    Source code
       1             : // Copyright 2018 the V8 project 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.
       4             : 
       5             : #include "src/wasm/wasm-engine.h"
       6             : 
       7             : #include "src/code-tracer.h"
       8             : #include "src/compilation-statistics.h"
       9             : #include "src/counters.h"
      10             : #include "src/objects-inl.h"
      11             : #include "src/objects/heap-number.h"
      12             : #include "src/objects/js-promise.h"
      13             : #include "src/ostreams.h"
      14             : #include "src/wasm/function-compiler.h"
      15             : #include "src/wasm/module-compiler.h"
      16             : #include "src/wasm/module-decoder.h"
      17             : #include "src/wasm/module-instantiate.h"
      18             : #include "src/wasm/streaming-decoder.h"
      19             : #include "src/wasm/wasm-objects-inl.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : namespace wasm {
      24             : 
      25             : namespace {
      26             : class LogCodesTask : public Task {
      27             :  public:
      28             :   LogCodesTask(base::Mutex* mutex, LogCodesTask** task_slot, Isolate* isolate)
      29           0 :       : mutex_(mutex), task_slot_(task_slot), isolate_(isolate) {
      30             :     DCHECK_NOT_NULL(task_slot);
      31             :     DCHECK_NOT_NULL(isolate);
      32             :   }
      33             : 
      34           0 :   ~LogCodesTask() {
      35             :     // If the platform deletes this task before executing it, we also deregister
      36             :     // it to avoid use-after-free from still-running background threads.
      37           0 :     if (!cancelled()) DeregisterTask();
      38           0 :   }
      39             : 
      40             :   // Hold the {mutex_} when calling this method.
      41           0 :   void AddCode(WasmCode* code) { code_to_log_.push_back(code); }
      42             : 
      43           0 :   void Run() override {
      44           0 :     if (cancelled()) return;
      45           0 :     DeregisterTask();
      46             :     // If by now we should not log code any more, do not log it.
      47           0 :     if (!WasmCode::ShouldBeLogged(isolate_)) return;
      48           0 :     for (WasmCode* code : code_to_log_) {
      49           0 :       code->LogCode(isolate_);
      50             :     }
      51             :   }
      52             : 
      53             :   void Cancel() {
      54             :     // Cancel will only be called on Isolate shutdown, which happens on the
      55             :     // Isolate's foreground thread. Thus no synchronization needed.
      56           0 :     isolate_ = nullptr;
      57             :   }
      58             : 
      59             :   bool cancelled() const { return isolate_ == nullptr; }
      60             : 
      61           0 :   void DeregisterTask() {
      62             :     // The task will only be deregistered from the foreground thread (executing
      63             :     // this task or calling its destructor), thus we do not need synchronization
      64             :     // on this field access.
      65           0 :     if (task_slot_ == nullptr) return;  // already deregistered.
      66             :     // Remove this task from the {IsolateInfo} in the engine. The next
      67             :     // logging request will allocate and schedule a new task.
      68           0 :     base::MutexGuard guard(mutex_);
      69             :     DCHECK_EQ(this, *task_slot_);
      70           0 :     *task_slot_ = nullptr;
      71           0 :     task_slot_ = nullptr;
      72             :   }
      73             : 
      74             :  private:
      75             :   // The mutex of the WasmEngine.
      76             :   base::Mutex* const mutex_;
      77             :   // The slot in the WasmEngine where this LogCodesTask is stored. This is
      78             :   // cleared by this task before execution or on task destruction.
      79             :   LogCodesTask** task_slot_;
      80             :   Isolate* isolate_;
      81             :   std::vector<WasmCode*> code_to_log_;
      82             : };
      83             : }  // namespace
      84             : 
      85      122068 : struct WasmEngine::IsolateInfo {
      86       61049 :   explicit IsolateInfo(Isolate* isolate)
      87       61049 :       : log_codes(WasmCode::ShouldBeLogged(isolate)) {
      88             :     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
      89       61049 :     v8::Platform* platform = V8::GetCurrentPlatform();
      90      122098 :     foreground_task_runner = platform->GetForegroundTaskRunner(v8_isolate);
      91       61049 :   }
      92             : 
      93             :   // All native modules that are being used by this Isolate (currently only
      94             :   // grows, never shrinks).
      95             :   std::set<NativeModule*> native_modules;
      96             : 
      97             :   // Caches whether code needs to be logged on this isolate.
      98             :   bool log_codes;
      99             : 
     100             :   // The currently scheduled LogCodesTask.
     101             :   LogCodesTask* log_codes_task = nullptr;
     102             : 
     103             :   // The foreground task runner of the isolate (can be called from background).
     104             :   std::shared_ptr<v8::TaskRunner> foreground_task_runner;
     105             : };
     106             : 
     107       59619 : WasmEngine::WasmEngine()
     108      238476 :     : code_manager_(&memory_tracker_, FLAG_wasm_max_code_space * MB) {}
     109             : 
     110      117004 : WasmEngine::~WasmEngine() {
     111             :   // Synchronize on all background compile tasks.
     112       58502 :   background_compile_task_manager_.CancelAndWait();
     113             :   // All AsyncCompileJobs have been canceled.
     114             :   DCHECK(async_compile_jobs_.empty());
     115             :   // All Isolates have been deregistered.
     116             :   DCHECK(isolates_.empty());
     117             :   // All NativeModules did die.
     118             :   DCHECK(isolates_per_native_module_.empty());
     119       58502 : }
     120             : 
     121      127090 : bool WasmEngine::SyncValidate(Isolate* isolate, const WasmFeatures& enabled,
     122             :                               const ModuleWireBytes& bytes) {
     123             :   // TODO(titzer): remove dependency on the isolate.
     124      254180 :   if (bytes.start() == nullptr || bytes.length() == 0) return false;
     125             :   ModuleResult result =
     126             :       DecodeWasmModule(enabled, bytes.start(), bytes.end(), true, kWasmOrigin,
     127      381270 :                        isolate->counters(), allocator());
     128      127090 :   return result.ok();
     129             : }
     130             : 
     131        2439 : MaybeHandle<AsmWasmData> WasmEngine::SyncCompileTranslatedAsmJs(
     132             :     Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes,
     133             :     Vector<const byte> asm_js_offset_table_bytes,
     134             :     Handle<HeapNumber> uses_bitset) {
     135             :   ModuleResult result =
     136             :       DecodeWasmModule(kAsmjsWasmFeatures, bytes.start(), bytes.end(), false,
     137        7317 :                        kAsmJsOrigin, isolate->counters(), allocator());
     138        2439 :   CHECK(!result.failed());
     139             : 
     140             :   // Transfer ownership of the WasmModule to the {Managed<WasmModule>} generated
     141             :   // in {CompileToNativeModule}.
     142             :   Handle<FixedArray> export_wrappers;
     143             :   std::unique_ptr<NativeModule> native_module =
     144             :       CompileToNativeModule(isolate, kAsmjsWasmFeatures, thrower,
     145        4878 :                             std::move(result).value(), bytes, &export_wrappers);
     146        2439 :   if (!native_module) return {};
     147             : 
     148             :   // Create heap objects for asm.js offset table to be stored in the module
     149             :   // object.
     150             :   Handle<ByteArray> asm_js_offset_table =
     151        2439 :       isolate->factory()->NewByteArray(asm_js_offset_table_bytes.length());
     152             :   asm_js_offset_table->copy_in(0, asm_js_offset_table_bytes.start(),
     153        2439 :                                asm_js_offset_table_bytes.length());
     154             : 
     155             :   return AsmWasmData::New(isolate, std::move(native_module), export_wrappers,
     156        7317 :                           asm_js_offset_table, uses_bitset);
     157             : }
     158             : 
     159        4962 : Handle<WasmModuleObject> WasmEngine::FinalizeTranslatedAsmJs(
     160             :     Isolate* isolate, Handle<AsmWasmData> asm_wasm_data,
     161             :     Handle<Script> script) {
     162             :   std::shared_ptr<NativeModule> native_module =
     163        9924 :       asm_wasm_data->managed_native_module()->get();
     164             :   Handle<FixedArray> export_wrappers =
     165        9924 :       handle(asm_wasm_data->export_wrappers(), isolate);
     166             :   size_t code_size_estimate =
     167             :       wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
     168        9924 :           native_module->module());
     169             : 
     170             :   Handle<WasmModuleObject> module_object =
     171             :       WasmModuleObject::New(isolate, std::move(native_module), script,
     172        9924 :                             export_wrappers, code_size_estimate);
     173        9924 :   module_object->set_asm_js_offset_table(asm_wasm_data->asm_js_offset_table());
     174        9924 :   return module_object;
     175             : }
     176             : 
     177      149705 : MaybeHandle<WasmModuleObject> WasmEngine::SyncCompile(
     178      134089 :     Isolate* isolate, const WasmFeatures& enabled, ErrorThrower* thrower,
     179             :     const ModuleWireBytes& bytes) {
     180             :   ModuleResult result =
     181             :       DecodeWasmModule(enabled, bytes.start(), bytes.end(), false, kWasmOrigin,
     182      449120 :                        isolate->counters(), allocator());
     183      149710 :   if (result.failed()) {
     184             :     thrower->CompileFailed(result.error());
     185        9037 :     return {};
     186             :   }
     187             : 
     188             :   // Transfer ownership of the WasmModule to the {Managed<WasmModule>} generated
     189             :   // in {CompileToModuleObject}.
     190             :   Handle<FixedArray> export_wrappers;
     191             :   std::unique_ptr<NativeModule> native_module =
     192             :       CompileToNativeModule(isolate, enabled, thrower,
     193      281347 :                             std::move(result).value(), bytes, &export_wrappers);
     194      140674 :   if (!native_module) return {};
     195             : 
     196             :   Handle<Script> script =
     197      134089 :       CreateWasmScript(isolate, bytes, native_module->module()->source_map_url);
     198             :   size_t code_size_estimate =
     199             :       wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
     200      134089 :           native_module->module());
     201             : 
     202             :   // Create the module object.
     203             :   // TODO(clemensh): For the same module (same bytes / same hash), we should
     204             :   // only have one WasmModuleObject. Otherwise, we might only set
     205             :   // breakpoints on a (potentially empty) subset of the instances.
     206             : 
     207             :   // Create the compiled module object and populate with compiled functions
     208             :   // and information needed at instantiation time. This object needs to be
     209             :   // serializable. Instantiation may occur off a deserialized version of this
     210             :   // object.
     211             :   Handle<WasmModuleObject> module_object =
     212             :       WasmModuleObject::New(isolate, std::move(native_module), script,
     213      268178 :                             export_wrappers, code_size_estimate);
     214             : 
     215             :   // Finish the Wasm script now and make it public to the debugger.
     216      134089 :   isolate->debug()->OnAfterCompile(script);
     217      283799 :   return module_object;
     218             : }
     219             : 
     220      133571 : MaybeHandle<WasmInstanceObject> WasmEngine::SyncInstantiate(
     221             :     Isolate* isolate, ErrorThrower* thrower,
     222             :     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
     223             :     MaybeHandle<JSArrayBuffer> memory) {
     224             :   return InstantiateToInstanceObject(isolate, thrower, module_object, imports,
     225      135943 :                                      memory);
     226             : }
     227             : 
     228        2372 : void WasmEngine::AsyncInstantiate(
     229             :     Isolate* isolate, std::unique_ptr<InstantiationResultResolver> resolver,
     230             :     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports) {
     231             :   ErrorThrower thrower(isolate, "WebAssembly.instantiate()");
     232             :   // Instantiate a TryCatch so that caught exceptions won't progagate out.
     233             :   // They will still be set as pending exceptions on the isolate.
     234             :   // TODO(clemensh): Avoid TryCatch, use Execution::TryCall internally to invoke
     235             :   // start function and report thrown exception explicitly via out argument.
     236        3484 :   v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
     237        2372 :   catcher.SetVerbose(false);
     238        2372 :   catcher.SetCaptureMessage(false);
     239             : 
     240             :   MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate(
     241             :       isolate, &thrower, module_object, imports, Handle<JSArrayBuffer>::null());
     242             : 
     243        2372 :   if (!instance_object.is_null()) {
     244        2520 :     resolver->OnInstantiationSucceeded(instance_object.ToHandleChecked());
     245        3632 :     return;
     246             :   }
     247             : 
     248        1112 :   if (isolate->has_pending_exception()) {
     249             :     // The JS code executed during instantiation has thrown an exception.
     250             :     // We have to move the exception to the promise chain.
     251             :     Handle<Object> exception(isolate->pending_exception(), isolate);
     252          40 :     isolate->clear_pending_exception();
     253             :     DCHECK(*isolate->external_caught_exception_address());
     254          40 :     *isolate->external_caught_exception_address() = false;
     255          40 :     resolver->OnInstantiationFailed(exception);
     256          40 :     thrower.Reset();
     257             :   } else {
     258             :     DCHECK(thrower.error());
     259        1072 :     resolver->OnInstantiationFailed(thrower.Reify());
     260        1112 :   }
     261             : }
     262             : 
     263        2331 : void WasmEngine::AsyncCompile(
     264             :     Isolate* isolate, const WasmFeatures& enabled,
     265             :     std::shared_ptr<CompilationResultResolver> resolver,
     266             :     const ModuleWireBytes& bytes, bool is_shared) {
     267        2331 :   if (!FLAG_wasm_async_compilation) {
     268             :     // Asynchronous compilation disabled; fall back on synchronous compilation.
     269             :     ErrorThrower thrower(isolate, "WasmCompile");
     270             :     MaybeHandle<WasmModuleObject> module_object;
     271           0 :     if (is_shared) {
     272             :       // Make a copy of the wire bytes to avoid concurrent modification.
     273           0 :       std::unique_ptr<uint8_t[]> copy(new uint8_t[bytes.length()]);
     274             :       memcpy(copy.get(), bytes.start(), bytes.length());
     275           0 :       ModuleWireBytes bytes_copy(copy.get(), copy.get() + bytes.length());
     276           0 :       module_object = SyncCompile(isolate, enabled, &thrower, bytes_copy);
     277             :     } else {
     278             :       // The wire bytes are not shared, OK to use them directly.
     279           0 :       module_object = SyncCompile(isolate, enabled, &thrower, bytes);
     280             :     }
     281           0 :     if (thrower.error()) {
     282           0 :       resolver->OnCompilationFailed(thrower.Reify());
     283           0 :       return;
     284             :     }
     285           0 :     Handle<WasmModuleObject> module = module_object.ToHandleChecked();
     286           0 :     resolver->OnCompilationSucceeded(module);
     287           0 :     return;
     288             :   }
     289             : 
     290        2331 :   if (FLAG_wasm_test_streaming) {
     291             :     std::shared_ptr<StreamingDecoder> streaming_decoder =
     292             :         StartStreamingCompilation(isolate, enabled,
     293             :                                   handle(isolate->context(), isolate),
     294         368 :                                   std::move(resolver));
     295         184 :     streaming_decoder->OnBytesReceived(bytes.module_bytes());
     296         184 :     streaming_decoder->Finish();
     297             :     return;
     298             :   }
     299             :   // Make a copy of the wire bytes in case the user program changes them
     300             :   // during asynchronous compilation.
     301        2147 :   std::unique_ptr<byte[]> copy(new byte[bytes.length()]);
     302             :   memcpy(copy.get(), bytes.start(), bytes.length());
     303             : 
     304             :   AsyncCompileJob* job = CreateAsyncCompileJob(
     305             :       isolate, enabled, std::move(copy), bytes.length(),
     306        6441 :       handle(isolate->context(), isolate), std::move(resolver));
     307        2147 :   job->Start();
     308             : }
     309             : 
     310         356 : std::shared_ptr<StreamingDecoder> WasmEngine::StartStreamingCompilation(
     311             :     Isolate* isolate, const WasmFeatures& enabled, Handle<Context> context,
     312             :     std::shared_ptr<CompilationResultResolver> resolver) {
     313             :   AsyncCompileJob* job =
     314             :       CreateAsyncCompileJob(isolate, enabled, std::unique_ptr<byte[]>(nullptr),
     315        1068 :                             0, context, std::move(resolver));
     316         356 :   return job->CreateStreamingDecoder();
     317             : }
     318             : 
     319          16 : void WasmEngine::CompileFunction(Isolate* isolate, NativeModule* native_module,
     320             :                                  uint32_t function_index, ExecutionTier tier) {
     321             :   // Note we assume that "one-off" compilations can discard detected features.
     322          16 :   WasmFeatures detected = kNoWasmFeatures;
     323             :   WasmCompilationUnit::CompileWasmFunction(
     324             :       isolate, native_module, &detected,
     325          48 :       &native_module->module()->functions[function_index], tier);
     326          16 : }
     327             : 
     328           0 : std::shared_ptr<NativeModule> WasmEngine::ExportNativeModule(
     329             :     Handle<WasmModuleObject> module_object) {
     330           0 :   return module_object->shared_native_module();
     331             : }
     332             : 
     333         136 : Handle<WasmModuleObject> WasmEngine::ImportNativeModule(
     334             :     Isolate* isolate, std::shared_ptr<NativeModule> shared_native_module) {
     335         136 :   NativeModule* native_module = shared_native_module.get();
     336             :   ModuleWireBytes wire_bytes(native_module->wire_bytes());
     337             :   const WasmModule* module = native_module->module();
     338             :   Handle<Script> script =
     339         136 :       CreateWasmScript(isolate, wire_bytes, module->source_map_url);
     340         136 :   size_t code_size = native_module->committed_code_space();
     341             :   Handle<WasmModuleObject> module_object = WasmModuleObject::New(
     342         272 :       isolate, std::move(shared_native_module), script, code_size);
     343             :   CompileJsToWasmWrappers(isolate, native_module->module(),
     344         544 :                           handle(module_object->export_wrappers(), isolate));
     345             :   {
     346         136 :     base::MutexGuard lock(&mutex_);
     347             :     DCHECK_EQ(1, isolates_.count(isolate));
     348             :     isolates_[isolate]->native_modules.insert(native_module);
     349             :     DCHECK_EQ(1, isolates_per_native_module_.count(native_module));
     350             :     isolates_per_native_module_[native_module].insert(isolate);
     351             :   }
     352         136 :   return module_object;
     353             : }
     354             : 
     355           0 : CompilationStatistics* WasmEngine::GetOrCreateTurboStatistics() {
     356           0 :   base::MutexGuard guard(&mutex_);
     357           0 :   if (compilation_stats_ == nullptr) {
     358           0 :     compilation_stats_.reset(new CompilationStatistics());
     359             :   }
     360           0 :   return compilation_stats_.get();
     361             : }
     362             : 
     363           0 : void WasmEngine::DumpAndResetTurboStatistics() {
     364           0 :   base::MutexGuard guard(&mutex_);
     365           0 :   if (compilation_stats_ != nullptr) {
     366           0 :     StdoutStream os;
     367           0 :     os << AsPrintableStatistics{*compilation_stats_.get(), false} << std::endl;
     368             :   }
     369             :   compilation_stats_.reset();
     370           0 : }
     371             : 
     372           0 : CodeTracer* WasmEngine::GetCodeTracer() {
     373           0 :   base::MutexGuard guard(&mutex_);
     374           0 :   if (code_tracer_ == nullptr) code_tracer_.reset(new CodeTracer(-1));
     375           0 :   return code_tracer_.get();
     376             : }
     377             : 
     378        2503 : AsyncCompileJob* WasmEngine::CreateAsyncCompileJob(
     379             :     Isolate* isolate, const WasmFeatures& enabled,
     380             :     std::unique_ptr<byte[]> bytes_copy, size_t length, Handle<Context> context,
     381             :     std::shared_ptr<CompilationResultResolver> resolver) {
     382             :   AsyncCompileJob* job =
     383             :       new AsyncCompileJob(isolate, enabled, std::move(bytes_copy), length,
     384       10012 :                           context, std::move(resolver));
     385             :   // Pass ownership to the unique_ptr in {async_compile_jobs_}.
     386        2503 :   base::MutexGuard guard(&mutex_);
     387        2503 :   async_compile_jobs_[job] = std::unique_ptr<AsyncCompileJob>(job);
     388        5006 :   return job;
     389             : }
     390             : 
     391        2493 : std::unique_ptr<AsyncCompileJob> WasmEngine::RemoveCompileJob(
     392             :     AsyncCompileJob* job) {
     393        2493 :   base::MutexGuard guard(&mutex_);
     394             :   auto item = async_compile_jobs_.find(job);
     395             :   DCHECK(item != async_compile_jobs_.end());
     396             :   std::unique_ptr<AsyncCompileJob> result = std::move(item->second);
     397             :   async_compile_jobs_.erase(item);
     398        2493 :   return result;
     399             : }
     400             : 
     401       54345 : bool WasmEngine::HasRunningCompileJob(Isolate* isolate) {
     402       54345 :   base::MutexGuard guard(&mutex_);
     403             :   DCHECK_EQ(1, isolates_.count(isolate));
     404      108690 :   for (auto& entry : async_compile_jobs_) {
     405        2107 :     if (entry.first->isolate() == isolate) return true;
     406             :   }
     407             :   return false;
     408             : }
     409             : 
     410       61043 : void WasmEngine::DeleteCompileJobsOnIsolate(Isolate* isolate) {
     411             :   // Under the mutex get all jobs to delete. Then delete them without holding
     412             :   // the mutex, such that deletion can reenter the WasmEngine.
     413             :   std::vector<std::unique_ptr<AsyncCompileJob>> jobs_to_delete;
     414             :   {
     415       61043 :     base::MutexGuard guard(&mutex_);
     416             :     DCHECK_EQ(1, isolates_.count(isolate));
     417      122101 :     for (auto it = async_compile_jobs_.begin();
     418             :          it != async_compile_jobs_.end();) {
     419          13 :       if (it->first->isolate() != isolate) {
     420             :         ++it;
     421             :         continue;
     422             :       }
     423          10 :       jobs_to_delete.push_back(std::move(it->second));
     424             :       it = async_compile_jobs_.erase(it);
     425             :     }
     426       61044 :   }
     427       61044 : }
     428             : 
     429       61047 : void WasmEngine::AddIsolate(Isolate* isolate) {
     430       61047 :   base::MutexGuard guard(&mutex_);
     431             :   DCHECK_EQ(0, isolates_.count(isolate));
     432      122098 :   isolates_.emplace(isolate, base::make_unique<IsolateInfo>(isolate));
     433             : 
     434             :   // Install sampling GC callback.
     435             :   // TODO(v8:7424): For now we sample module sizes in a GC callback. This will
     436             :   // bias samples towards apps with high memory pressure. We should switch to
     437             :   // using sampling based on regular intervals independent of the GC.
     438             :   auto callback = [](v8::Isolate* v8_isolate, v8::GCType type,
     439      148996 :                      v8::GCCallbackFlags flags, void* data) {
     440       74498 :     Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     441             :     WasmEngine* engine = isolate->wasm_engine();
     442       74498 :     base::MutexGuard lock(&engine->mutex_);
     443             :     DCHECK_EQ(1, engine->isolates_.count(isolate));
     444      768337 :     for (NativeModule* native_module :
     445      693839 :          engine->isolates_[isolate]->native_modules) {
     446             :       int code_size =
     447      693839 :           static_cast<int>(native_module->committed_code_space() / MB);
     448     1387678 :       isolate->counters()->wasm_module_code_size_mb()->AddSample(code_size);
     449             :     }
     450      148996 :   };
     451             :   isolate->heap()->AddGCEpilogueCallback(callback, v8::kGCTypeMarkSweepCompact,
     452       61049 :                                          nullptr);
     453       61049 : }
     454             : 
     455       61034 : void WasmEngine::RemoveIsolate(Isolate* isolate) {
     456       61034 :   base::MutexGuard guard(&mutex_);
     457             :   auto it = isolates_.find(isolate);
     458             :   DCHECK_NE(isolates_.end(), it);
     459      122216 :   for (NativeModule* native_module : it->second->native_modules) {
     460             :     DCHECK_EQ(1, isolates_per_native_module_[native_module].count(isolate));
     461             :     isolates_per_native_module_[native_module].erase(isolate);
     462             :   }
     463       61034 :   if (auto* task = it->second->log_codes_task) task->Cancel();
     464             :   isolates_.erase(it);
     465       61034 : }
     466             : 
     467      407128 : void WasmEngine::LogCode(WasmCode* code) {
     468      203564 :   base::MutexGuard guard(&mutex_);
     469      203564 :   NativeModule* native_module = code->native_module();
     470             :   DCHECK_EQ(1, isolates_per_native_module_.count(native_module));
     471      610692 :   for (Isolate* isolate : isolates_per_native_module_[native_module]) {
     472             :     DCHECK_EQ(1, isolates_.count(isolate));
     473             :     IsolateInfo* info = isolates_[isolate].get();
     474      203564 :     if (info->log_codes == false) continue;
     475           0 :     if (info->log_codes_task == nullptr) {
     476             :       auto new_task = base::make_unique<LogCodesTask>(
     477           0 :           &mutex_, &info->log_codes_task, isolate);
     478           0 :       info->log_codes_task = new_task.get();
     479           0 :       info->foreground_task_runner->PostTask(std::move(new_task));
     480             :     }
     481           0 :     info->log_codes_task->AddCode(code);
     482             :   }
     483      203564 : }
     484             : 
     485         763 : void WasmEngine::EnableCodeLogging(Isolate* isolate) {
     486         763 :   base::MutexGuard guard(&mutex_);
     487             :   auto it = isolates_.find(isolate);
     488             :   DCHECK_NE(isolates_.end(), it);
     489         763 :   it->second->log_codes = true;
     490         763 : }
     491             : 
     492     1240019 : std::unique_ptr<NativeModule> WasmEngine::NewNativeModule(
     493             :     Isolate* isolate, const WasmFeatures& enabled, size_t code_size_estimate,
     494             :     bool can_request_more, std::shared_ptr<const WasmModule> module) {
     495             :   std::unique_ptr<NativeModule> native_module =
     496             :       code_manager_.NewNativeModule(this, isolate, enabled, code_size_estimate,
     497     2480042 :                                     can_request_more, std::move(module));
     498     1240023 :   base::MutexGuard lock(&mutex_);
     499     2480046 :   isolates_per_native_module_[native_module.get()].insert(isolate);
     500             :   DCHECK_EQ(1, isolates_.count(isolate));
     501     2480046 :   isolates_[isolate]->native_modules.insert(native_module.get());
     502     1240023 :   return native_module;
     503             : }
     504             : 
     505     1240022 : void WasmEngine::FreeNativeModule(NativeModule* native_module) {
     506             :   {
     507     1240022 :     base::MutexGuard guard(&mutex_);
     508             :     auto it = isolates_per_native_module_.find(native_module);
     509             :     DCHECK_NE(isolates_per_native_module_.end(), it);
     510     3720053 :     for (Isolate* isolate : it->second) {
     511             :       DCHECK_EQ(1, isolates_.count(isolate));
     512             :       DCHECK_EQ(1, isolates_[isolate]->native_modules.count(native_module));
     513             :       isolates_[isolate]->native_modules.erase(native_module);
     514             :     }
     515             :     isolates_per_native_module_.erase(it);
     516             :   }
     517     1240023 :   code_manager_.FreeNativeModule(native_module);
     518     1240023 : }
     519             : 
     520             : namespace {
     521             : 
     522      179071 : DEFINE_LAZY_LEAKY_OBJECT_GETTER(std::shared_ptr<WasmEngine>,
     523             :                                 GetSharedWasmEngine)
     524             : 
     525             : }  // namespace
     526             : 
     527             : // static
     528       59591 : void WasmEngine::InitializeOncePerProcess() {
     529      119182 :   if (!FLAG_wasm_shared_engine) return;
     530      119182 :   *GetSharedWasmEngine() = std::make_shared<WasmEngine>();
     531             : }
     532             : 
     533             : // static
     534       58516 : void WasmEngine::GlobalTearDown() {
     535      117032 :   if (!FLAG_wasm_shared_engine) return;
     536       58516 :   GetSharedWasmEngine()->reset();
     537             : }
     538             : 
     539             : // static
     540       60964 : std::shared_ptr<WasmEngine> WasmEngine::GetWasmEngine() {
     541       60964 :   if (FLAG_wasm_shared_engine) return *GetSharedWasmEngine();
     542             :   return std::make_shared<WasmEngine>();
     543             : }
     544             : 
     545             : // {max_mem_pages} is declared in wasm-limits.h.
     546     1651264 : uint32_t max_mem_pages() {
     547             :   STATIC_ASSERT(kV8MaxWasmMemoryPages <= kMaxUInt32);
     548     3302528 :   return std::min(uint32_t{kV8MaxWasmMemoryPages}, FLAG_wasm_max_mem_pages);
     549             : }
     550             : 
     551             : }  // namespace wasm
     552             : }  // namespace internal
     553      178779 : }  // namespace v8

Generated by: LCOV version 1.10