diff --git a/src/vector.h b/src/vector.h index 60d58c3811..29e0b65f89 100644 --- a/src/vector.h +++ b/src/vector.h @@ -180,6 +180,12 @@ class OwnedVector { constexpr T* begin() const { return start(); } constexpr T* end() const { return start() + size(); } + // Access individual vector elements - checks bounds in debug mode. + T& operator[](size_t index) const { + DCHECK_LT(index, length_); + return data_[index]; + } + // Returns a {Vector} view of the data in this vector. Vector as_vector() const { return Vector(start(), size()); } diff --git a/src/wasm/wasm-code-manager.cc b/src/wasm/wasm-code-manager.cc index 45ac56d909..090d0afb47 100644 --- a/src/wasm/wasm-code-manager.cc +++ b/src/wasm/wasm-code-manager.cc @@ -420,7 +420,6 @@ NativeModule::NativeModule(WasmEngine* engine, const WasmFeatures& enabled, CompilationState::New(*shared_this, std::move(async_counters)); DCHECK_NOT_NULL(module_); owned_code_space_.emplace_back(std::move(code_space)); - owned_code_.reserve(num_functions()); #if defined(V8_OS_WIN_X64) // On some platforms, specifically Win64, we need to reserve some pages at @@ -786,7 +785,7 @@ WasmCode* NativeModule::PublishCodeLocked(std::unique_ptr code) { } WasmCodeRefScope::AddRef(code.get()); WasmCode* result = code.get(); - owned_code_.emplace_back(std::move(code)); + owned_code_.emplace(result->instruction_start(), std::move(code)); return result; } @@ -980,42 +979,14 @@ void NativeModule::SetWireBytes(OwnedVector wire_bytes) { WasmCode* NativeModule::Lookup(Address pc) const { base::MutexGuard lock(&allocation_mutex_); - if (owned_code_.empty()) return nullptr; - // First update the sorted portion counter. - if (owned_code_sorted_portion_ == 0) ++owned_code_sorted_portion_; - while (owned_code_sorted_portion_ < owned_code_.size() && - owned_code_[owned_code_sorted_portion_ - 1]->instruction_start() <= - owned_code_[owned_code_sorted_portion_]->instruction_start()) { - ++owned_code_sorted_portion_; - } - // Execute at most two rounds: First check whether the {pc} is within the - // sorted portion of {owned_code_}. If it's not, then sort the whole vector - // and retry. - while (true) { - auto iter = - std::upper_bound(owned_code_.begin(), owned_code_.end(), pc, - [](Address pc, const std::unique_ptr& code) { - DCHECK_NE(kNullAddress, pc); - DCHECK_NOT_NULL(code); - return pc < code->instruction_start(); - }); - if (iter != owned_code_.begin()) { - --iter; - WasmCode* candidate = iter->get(); - DCHECK_NOT_NULL(candidate); - if (candidate->contains(pc)) { - WasmCodeRefScope::AddRef(candidate); - return candidate; - } - } - if (owned_code_sorted_portion_ == owned_code_.size()) return nullptr; - std::sort(owned_code_.begin(), owned_code_.end(), - [](const std::unique_ptr& code1, - const std::unique_ptr& code2) { - return code1->instruction_start() < code2->instruction_start(); - }); - owned_code_sorted_portion_ = owned_code_.size(); - } + auto iter = owned_code_.upper_bound(pc); + if (iter == owned_code_.begin()) return nullptr; + --iter; + WasmCode* candidate = iter->second.get(); + DCHECK_EQ(candidate->instruction_start(), iter->first); + if (!candidate->contains(pc)) return nullptr; + WasmCodeRefScope::AddRef(candidate); + return candidate; } Address NativeModule::GetCallTargetForFunction(uint32_t func_index) const { @@ -1376,9 +1347,11 @@ bool NativeModule::IsRedirectedToInterpreter(uint32_t func_index) { } void NativeModule::FreeCode(Vector codes) { - // For now, we neither free the {WasmCode} objects, nor do we free any code. - // We just zap the code to ensure it's not executed any more. - // TODO(clemensh): Actually free the {WasmCode} objects and the code pages. + // For now, we only free the {WasmCode} objects and zap the code they referred + // to. We do not actually free the code pages yet. + // TODO(clemensh): Actually free the underlying code pages. + + // Zap code area. size_t code_size = 0; for (WasmCode* code : codes) { ZapCode(code->instruction_start(), code->instructions().size()); @@ -1387,6 +1360,13 @@ void NativeModule::FreeCode(Vector codes) { code_size += code->instructions().size(); } freed_code_size_.fetch_add(code_size); + + // Free the {WasmCode} objects. This will also unregister trap handler data. + base::MutexGuard guard(&allocation_mutex_); + for (WasmCode* code : codes) { + DCHECK_EQ(1, owned_code_.count(code->instruction_start())); + owned_code_.erase(code->instruction_start()); + } } void WasmCodeManager::FreeNativeModule(NativeModule* native_module) { diff --git a/src/wasm/wasm-code-manager.h b/src/wasm/wasm-code-manager.h index d62552b824..5fc8617bf2 100644 --- a/src/wasm/wasm-code-manager.h +++ b/src/wasm/wasm-code-manager.h @@ -513,14 +513,9 @@ class V8_EXPORT_PRIVATE NativeModule final { ////////////////////////////////////////////////////////////////////////////// // Protected by {allocation_mutex_}: - // Holds all allocated code objects. Mutable because it might get sorted in - // {Lookup()}. - mutable std::vector> owned_code_; - - // Keep track of the portion of {owned_code_} that is sorted. - // Entries [0, owned_code_sorted_portion_) are known to be sorted. - // Mutable because it might get modified in {Lookup()}. - mutable size_t owned_code_sorted_portion_ = 0; + // Holds all allocated code objects. For lookup based on pc, the key is the + // instruction start address of the value. + std::map> owned_code_; std::unique_ptr code_table_;