LCOV - code coverage report
Current view: top level - src/wasm - wasm-engine.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 167 219 76.3 %
Date: 2019-03-21 Functions: 37 45 82.2 %

          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      123038 : struct WasmEngine::IsolateInfo {
      86       61534 :   explicit IsolateInfo(Isolate* isolate)
      87       61534 :       : log_codes(WasmCode::ShouldBeLogged(isolate)) {
      88             :     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
      89       61534 :     v8::Platform* platform = V8::GetCurrentPlatform();
      90      123068 :     foreground_task_runner = platform->GetForegroundTaskRunner(v8_isolate);
      91       61534 :   }
      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       60134 : WasmEngine::WasmEngine()
     108      180402 :     : code_manager_(&memory_tracker_, FLAG_wasm_max_code_space * MB) {}
     109             : 
     110      235932 : WasmEngine::~WasmEngine() {
     111             :   // Synchronize on all background compile tasks.
     112       58983 :   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       58983 : }
     120             : 
     121      128010 : bool WasmEngine::SyncValidate(Isolate* isolate, const WasmFeatures& enabled,
     122             :                               const ModuleWireBytes& bytes) {
     123             :   // TODO(titzer): remove dependency on the isolate.
     124      256020 :   if (bytes.start() == nullptr || bytes.length() == 0) return false;
     125             :   ModuleResult result =
     126      256020 :       DecodeWasmModule(enabled, bytes.start(), bytes.end(), true, kWasmOrigin,
     127      256020 :                        isolate->counters(), allocator());
     128             :   return result.ok();
     129             : }
     130             : 
     131        2457 : 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        4914 :       DecodeWasmModule(kAsmjsWasmFeatures, bytes.start(), bytes.end(), false,
     137        4914 :                        kAsmJsOrigin, isolate->counters(), allocator());
     138        2457 :   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::shared_ptr<NativeModule> native_module =
     144             :       CompileToNativeModule(isolate, kAsmjsWasmFeatures, thrower,
     145        4914 :                             std::move(result).value(), bytes, &export_wrappers);
     146        2457 :   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        2457 :       isolate->factory()->NewByteArray(asm_js_offset_table_bytes.length());
     152             :   asm_js_offset_table->copy_in(0, asm_js_offset_table_bytes.start(),
     153             :                                asm_js_offset_table_bytes.length());
     154             : 
     155             :   return AsmWasmData::New(isolate, std::move(native_module), export_wrappers,
     156        4914 :                           asm_js_offset_table, uses_bitset);
     157             : }
     158             : 
     159        5010 : Handle<WasmModuleObject> WasmEngine::FinalizeTranslatedAsmJs(
     160             :     Isolate* isolate, Handle<AsmWasmData> asm_wasm_data,
     161             :     Handle<Script> script) {
     162             :   std::shared_ptr<NativeModule> native_module =
     163             :       asm_wasm_data->managed_native_module()->get();
     164             :   Handle<FixedArray> export_wrappers =
     165        5010 :       handle(asm_wasm_data->export_wrappers(), isolate);
     166             :   size_t code_size_estimate =
     167             :       wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
     168        5010 :           native_module->module());
     169             : 
     170             :   Handle<WasmModuleObject> module_object =
     171             :       WasmModuleObject::New(isolate, std::move(native_module), script,
     172       10020 :                             export_wrappers, code_size_estimate);
     173        5010 :   module_object->set_asm_js_offset_table(asm_wasm_data->asm_js_offset_table());
     174       10020 :   return module_object;
     175             : }
     176             : 
     177      151215 : MaybeHandle<WasmModuleObject> WasmEngine::SyncCompile(
     178             :     Isolate* isolate, const WasmFeatures& enabled, ErrorThrower* thrower,
     179             :     const ModuleWireBytes& bytes) {
     180             :   ModuleResult result =
     181      302442 :       DecodeWasmModule(enabled, bytes.start(), bytes.end(), false, kWasmOrigin,
     182      302451 :                        isolate->counters(), allocator());
     183      151227 :   if (result.failed()) {
     184             :     thrower->CompileFailed(result.error());
     185        9074 :     return {};
     186             :   }
     187             : 
     188             :   // Transfer ownership of the WasmModule to the {Managed<WasmModule>} generated
     189             :   // in {CompileToModuleObject}.
     190             :   Handle<FixedArray> export_wrappers;
     191             :   std::shared_ptr<NativeModule> native_module =
     192             :       CompileToNativeModule(isolate, enabled, thrower,
     193      284306 :                             std::move(result).value(), bytes, &export_wrappers);
     194      142153 :   if (!native_module) return {};
     195             : 
     196             :   Handle<Script> script =
     197      134640 :       CreateWasmScript(isolate, bytes, native_module->module()->source_map_url);
     198             :   size_t code_size_estimate =
     199             :       wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
     200      134640 :           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      269280 :                             export_wrappers, code_size_estimate);
     214             : 
     215             :   // Finish the Wasm script now and make it public to the debugger.
     216      134640 :   isolate->debug()->OnAfterCompile(script);
     217      134637 :   return module_object;
     218             : }
     219             : 
     220      134198 : 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      136594 :                                      memory);
     226             : }
     227             : 
     228        2396 : void WasmEngine::AsyncInstantiate(
     229             :     Isolate* isolate, std::unique_ptr<InstantiationResultResolver> resolver,
     230             :     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports) {
     231        1112 :   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        3508 :   v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
     237        2396 :   catcher.SetVerbose(false);
     238        2396 :   catcher.SetCaptureMessage(false);
     239             : 
     240             :   MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate(
     241             :       isolate, &thrower, module_object, imports, Handle<JSArrayBuffer>::null());
     242             : 
     243        2396 :   if (!instance_object.is_null()) {
     244        2568 :     resolver->OnInstantiationSucceeded(instance_object.ToHandleChecked());
     245        1284 :     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             :     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             :   }
     261             : }
     262             : 
     263        2363 : void WasmEngine::AsyncCompile(
     264             :     Isolate* isolate, const WasmFeatures& enabled,
     265             :     std::shared_ptr<CompilationResultResolver> resolver,
     266             :     const ModuleWireBytes& bytes, bool is_shared) {
     267        2363 :   if (!FLAG_wasm_async_compilation) {
     268             :     // Asynchronous compilation disabled; fall back on synchronous compilation.
     269           0 :     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        2363 :   if (FLAG_wasm_test_streaming) {
     291             :     std::shared_ptr<StreamingDecoder> streaming_decoder =
     292             :         StartStreamingCompilation(isolate, enabled,
     293             :                                   handle(isolate->context(), isolate),
     294         400 :                                   std::move(resolver));
     295         200 :     streaming_decoder->OnBytesReceived(bytes.module_bytes());
     296         200 :     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        2163 :   std::unique_ptr<byte[]> copy(new byte[bytes.length()]);
     302             :   memcpy(copy.get(), bytes.start(), bytes.length());
     303             : 
     304        4326 :   AsyncCompileJob* job = CreateAsyncCompileJob(
     305             :       isolate, enabled, std::move(copy), bytes.length(),
     306        2163 :       handle(isolate->context(), isolate), std::move(resolver));
     307        2163 :   job->Start();
     308             : }
     309             : 
     310         380 : 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         760 :       CreateAsyncCompileJob(isolate, enabled, std::unique_ptr<byte[]>(nullptr),
     315         380 :                             0, context, std::move(resolver));
     316         380 :   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          32 :       &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         155 : Handle<WasmModuleObject> WasmEngine::ImportNativeModule(
     334             :     Isolate* isolate, std::shared_ptr<NativeModule> shared_native_module) {
     335         155 :   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         155 :       CreateWasmScript(isolate, wire_bytes, module->source_map_url);
     340         155 :   size_t code_size = native_module->committed_code_space();
     341             :   Handle<WasmModuleObject> module_object = WasmModuleObject::New(
     342         310 :       isolate, std::move(shared_native_module), script, code_size);
     343         310 :   CompileJsToWasmWrappers(isolate, native_module->module(),
     344         155 :                           handle(module_object->export_wrappers(), isolate));
     345             :   {
     346         156 :     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         156 :   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           0 :   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        2543 : 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       10172 :                           context, std::move(resolver));
     385             :   // Pass ownership to the unique_ptr in {async_compile_jobs_}.
     386        2543 :   base::MutexGuard guard(&mutex_);
     387        5086 :   async_compile_jobs_[job] = std::unique_ptr<AsyncCompileJob>(job);
     388        5086 :   return job;
     389             : }
     390             : 
     391        2531 : std::unique_ptr<AsyncCompileJob> WasmEngine::RemoveCompileJob(
     392             :     AsyncCompileJob* job) {
     393        2531 :   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        2531 :   return result;
     399             : }
     400             : 
     401       54896 : bool WasmEngine::HasRunningCompileJob(Isolate* isolate) {
     402       54896 :   base::MutexGuard guard(&mutex_);
     403             :   DCHECK_EQ(1, isolates_.count(isolate));
     404       54896 :   for (auto& entry : async_compile_jobs_) {
     405        2804 :     if (entry.first->isolate() == isolate) return true;
     406             :   }
     407             :   return false;
     408             : }
     409             : 
     410       61528 : 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       61529 :   std::vector<std::unique_ptr<AsyncCompileJob>> jobs_to_delete;
     414             :   {
     415       61528 :     base::MutexGuard guard(&mutex_);
     416             :     DCHECK_EQ(1, isolates_.count(isolate));
     417       61543 :     for (auto it = async_compile_jobs_.begin();
     418             :          it != async_compile_jobs_.end();) {
     419          14 :       if (it->first->isolate() != isolate) {
     420             :         ++it;
     421             :         continue;
     422             :       }
     423          12 :       jobs_to_delete.push_back(std::move(it->second));
     424             :       it = async_compile_jobs_.erase(it);
     425             :     }
     426             :   }
     427       61529 : }
     428             : 
     429       61534 : void WasmEngine::AddIsolate(Isolate* isolate) {
     430       61534 :   base::MutexGuard guard(&mutex_);
     431             :   DCHECK_EQ(0, isolates_.count(isolate));
     432       61534 :   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      147886 :                      v8::GCCallbackFlags flags, void* data) {
     440       73943 :     Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     441             :     Counters* counters = isolate->counters();
     442             :     WasmEngine* engine = isolate->wasm_engine();
     443       73943 :     base::MutexGuard lock(&engine->mutex_);
     444             :     DCHECK_EQ(1, engine->isolates_.count(isolate));
     445      804569 :     for (auto* native_module : engine->isolates_[isolate]->native_modules) {
     446      730626 :       native_module->SampleCodeSize(counters, NativeModule::kSampling);
     447             :     }
     448      147886 :   };
     449       61534 :   isolate->heap()->AddGCEpilogueCallback(callback, v8::kGCTypeMarkSweepCompact,
     450       61534 :                                          nullptr);
     451       61534 : }
     452             : 
     453       61517 : void WasmEngine::RemoveIsolate(Isolate* isolate) {
     454       61517 :   base::MutexGuard guard(&mutex_);
     455             :   auto it = isolates_.find(isolate);
     456             :   DCHECK_NE(isolates_.end(), it);
     457       61691 :   for (NativeModule* native_module : it->second->native_modules) {
     458             :     DCHECK_EQ(1, isolates_per_native_module_[native_module].count(isolate));
     459             :     isolates_per_native_module_[native_module].erase(isolate);
     460             :   }
     461       61519 :   if (auto* task = it->second->log_codes_task) task->Cancel();
     462             :   isolates_.erase(it);
     463       61519 : }
     464             : 
     465      203708 : void WasmEngine::LogCode(WasmCode* code) {
     466      203708 :   base::MutexGuard guard(&mutex_);
     467      203708 :   NativeModule* native_module = code->native_module();
     468             :   DCHECK_EQ(1, isolates_per_native_module_.count(native_module));
     469      406659 :   for (Isolate* isolate : isolates_per_native_module_[native_module]) {
     470             :     DCHECK_EQ(1, isolates_.count(isolate));
     471             :     IsolateInfo* info = isolates_[isolate].get();
     472      202951 :     if (info->log_codes == false) continue;
     473           0 :     if (info->log_codes_task == nullptr) {
     474             :       auto new_task = base::make_unique<LogCodesTask>(
     475           0 :           &mutex_, &info->log_codes_task, isolate);
     476           0 :       info->log_codes_task = new_task.get();
     477           0 :       info->foreground_task_runner->PostTask(std::move(new_task));
     478             :     }
     479           0 :     info->log_codes_task->AddCode(code);
     480             :   }
     481      203708 : }
     482             : 
     483         811 : void WasmEngine::EnableCodeLogging(Isolate* isolate) {
     484         811 :   base::MutexGuard guard(&mutex_);
     485             :   auto it = isolates_.find(isolate);
     486             :   DCHECK_NE(isolates_.end(), it);
     487         811 :   it->second->log_codes = true;
     488         811 : }
     489             : 
     490     1241892 : std::shared_ptr<NativeModule> WasmEngine::NewNativeModule(
     491             :     Isolate* isolate, const WasmFeatures& enabled, size_t code_size_estimate,
     492             :     bool can_request_more, std::shared_ptr<const WasmModule> module) {
     493             :   std::shared_ptr<NativeModule> native_module =
     494             :       code_manager_.NewNativeModule(this, isolate, enabled, code_size_estimate,
     495     2483794 :                                     can_request_more, std::move(module));
     496     1241902 :   base::MutexGuard lock(&mutex_);
     497     2483804 :   isolates_per_native_module_[native_module.get()].insert(isolate);
     498             :   DCHECK_EQ(1, isolates_.count(isolate));
     499     2483804 :   isolates_[isolate]->native_modules.insert(native_module.get());
     500     1241902 :   return native_module;
     501             : }
     502             : 
     503     1241901 : void WasmEngine::FreeNativeModule(NativeModule* native_module) {
     504             :   {
     505     1241901 :     base::MutexGuard guard(&mutex_);
     506             :     auto it = isolates_per_native_module_.find(native_module);
     507             :     DCHECK_NE(isolates_per_native_module_.end(), it);
     508     2483784 :     for (Isolate* isolate : it->second) {
     509             :       DCHECK_EQ(1, isolates_.count(isolate));
     510             :       DCHECK_EQ(1, isolates_[isolate]->native_modules.count(native_module));
     511             :       isolates_[isolate]->native_modules.erase(native_module);
     512             :     }
     513             :     isolates_per_native_module_.erase(it);
     514             :   }
     515     1241902 :   code_manager_.FreeNativeModule(native_module);
     516     1241902 : }
     517             : 
     518             : namespace {
     519        1050 : class SampleTopTierCodeSizeTask : public CancelableTask {
     520             :  public:
     521             :   SampleTopTierCodeSizeTask(Isolate* isolate,
     522             :                             std::weak_ptr<NativeModule> native_module)
     523             :       : CancelableTask(isolate),
     524             :         isolate_(isolate),
     525         350 :         native_module_(std::move(native_module)) {}
     526             : 
     527         347 :   void RunInternal() override {
     528         347 :     if (std::shared_ptr<NativeModule> native_module = native_module_.lock()) {
     529         346 :       native_module->SampleCodeSize(isolate_->counters(),
     530         346 :                                     NativeModule::kAfterTopTier);
     531             :     }
     532         347 :   }
     533             : 
     534             :  private:
     535             :   Isolate* const isolate_;
     536             :   const std::weak_ptr<NativeModule> native_module_;
     537             : };
     538             : }  // namespace
     539             : 
     540         351 : void WasmEngine::SampleTopTierCodeSizeInAllIsolates(
     541             :     const std::shared_ptr<NativeModule>& native_module) {
     542         351 :   base::MutexGuard lock(&mutex_);
     543             :   DCHECK_EQ(1, isolates_per_native_module_.count(native_module.get()));
     544         702 :   for (Isolate* isolate : isolates_per_native_module_[native_module.get()]) {
     545             :     DCHECK_EQ(1, isolates_.count(isolate));
     546             :     IsolateInfo* info = isolates_[isolate].get();
     547         350 :     info->foreground_task_runner->PostTask(
     548        1050 :         base::make_unique<SampleTopTierCodeSizeTask>(isolate, native_module));
     549             :   }
     550         351 : }
     551             : 
     552             : namespace {
     553             : 
     554      240651 : DEFINE_LAZY_LEAKY_OBJECT_GETTER(std::shared_ptr<WasmEngine>,
     555             :                                 GetSharedWasmEngine)
     556             : 
     557             : }  // namespace
     558             : 
     559             : // static
     560       60106 : void WasmEngine::InitializeOncePerProcess() {
     561       60106 :   if (!FLAG_wasm_shared_engine) return;
     562      120212 :   *GetSharedWasmEngine() = std::make_shared<WasmEngine>();
     563             : }
     564             : 
     565             : // static
     566       58997 : void WasmEngine::GlobalTearDown() {
     567       58997 :   if (!FLAG_wasm_shared_engine) return;
     568       58997 :   GetSharedWasmEngine()->reset();
     569             : }
     570             : 
     571             : // static
     572       61450 : std::shared_ptr<WasmEngine> WasmEngine::GetWasmEngine() {
     573       61450 :   if (FLAG_wasm_shared_engine) return *GetSharedWasmEngine();
     574             :   return std::make_shared<WasmEngine>();
     575             : }
     576             : 
     577             : // {max_mem_pages} is declared in wasm-limits.h.
     578     1654620 : uint32_t max_mem_pages() {
     579             :   STATIC_ASSERT(kV8MaxWasmMemoryPages <= kMaxUInt32);
     580     3309240 :   return std::min(uint32_t{kV8MaxWasmMemoryPages}, FLAG_wasm_max_mem_pages);
     581             : }
     582             : 
     583             : // {max_table_init_entries} is declared in wasm-limits.h.
     584        6503 : uint32_t max_table_init_entries() {
     585             :   return std::min(uint32_t{kV8MaxWasmTableInitEntries},
     586       13006 :                   FLAG_wasm_max_table_size);
     587             : }
     588             : 
     589             : }  // namespace wasm
     590             : }  // namespace internal
     591      120216 : }  // namespace v8

Generated by: LCOV version 1.10