// Copyright 2022 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/wasm/assembler-buffer-cache.h" #include <algorithm> #include "src/codegen/assembler.h" #include "src/wasm/wasm-engine.h" namespace v8::internal::wasm { class CachedAssemblerBuffer final : public AssemblerBuffer { public: CachedAssemblerBuffer(AssemblerBufferCache* cache, base::AddressRegion region) : cache_(cache), region_(region) {} ~CachedAssemblerBuffer() override { cache_->Return(region_); } uint8_t* start() const override { return reinterpret_cast<uint8_t*>(region_.begin()); } int size() const override { return static_cast<int>(region_.size()); } std::unique_ptr<AssemblerBuffer> Grow(int new_size) override { return cache_->GetAssemblerBuffer(new_size); } private: AssemblerBufferCache* const cache_; const base::AddressRegion region_; }; AssemblerBufferCache::~AssemblerBufferCache() { for (base::AddressRegion region : available_memory_.regions()) { GetWasmCodeManager()->FreeAssemblerBufferSpace(region); } } std::unique_ptr<AssemblerBuffer> AssemblerBufferCache::GetAssemblerBuffer( int size) { DCHECK_LT(0, size); base::AddressRegion region = available_memory_.Allocate(size); if (region.is_empty()) { static constexpr int kMinimumReservation = 64 * KB; int minimum_allocation = std::max(kMinimumReservation, std::max(total_allocated_ / 4, size)); base::AddressRegion new_space = GetWasmCodeManager()->AllocateAssemblerBufferSpace(minimum_allocation); available_memory_.Merge(new_space); CHECK_GE(kMaxInt - total_allocated_, new_space.size()); total_allocated_ += new_space.size(); region = available_memory_.Allocate(size); DCHECK(!region.is_empty()); } return std::make_unique<CachedAssemblerBuffer>(this, region); } void AssemblerBufferCache::Return(base::AddressRegion region) { available_memory_.Merge(region); } } // namespace v8::internal::wasm