LCOV - code coverage report
Current view: top level - src/wasm - wasm-memory.h (source / functions) Hit Total Coverage
Test: app.info Lines: 2 2 100.0 %
Date: 2019-02-19 Functions: 1 1 100.0 %

          Line data    Source code
       1             : // Copyright 2017 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             : #ifndef V8_WASM_WASM_MEMORY_H_
       6             : #define V8_WASM_WASM_MEMORY_H_
       7             : 
       8             : #include <atomic>
       9             : #include <unordered_map>
      10             : 
      11             : #include "src/base/platform/mutex.h"
      12             : #include "src/flags.h"
      13             : #include "src/handles.h"
      14             : #include "src/objects/js-array-buffer.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : namespace wasm {
      19             : 
      20             : // The {WasmMemoryTracker} tracks reservations and allocations for wasm memory
      21             : // and wasm code. There is an upper limit on the total reserved memory which is
      22             : // checked by this class. Allocations are stored so we can look them up when an
      23             : // array buffer dies and figure out the reservation and allocation bounds for
      24             : // that buffer.
      25             : class WasmMemoryTracker {
      26             :  public:
      27      178857 :   WasmMemoryTracker() = default;
      28             :   V8_EXPORT_PRIVATE ~WasmMemoryTracker();
      29             : 
      30             :   // ReserveAddressSpace attempts to increase the reserved address space counter
      31             :   // by {num_bytes}. Returns true if successful (meaning it is okay to go ahead
      32             :   // and reserve {num_bytes} bytes), false otherwise.
      33             :   // Use {kSoftLimit} if you can implement a fallback which needs less reserved
      34             :   // memory.
      35             :   enum ReservationLimit { kSoftLimit, kHardLimit };
      36             :   bool ReserveAddressSpace(size_t num_bytes, ReservationLimit limit);
      37             : 
      38             :   void RegisterAllocation(Isolate* isolate, void* allocation_base,
      39             :                           size_t allocation_length, void* buffer_start,
      40             :                           size_t buffer_length);
      41             : 
      42             :   struct AllocationData {
      43             :     void* allocation_base = nullptr;
      44             :     size_t allocation_length = 0;
      45             :     void* buffer_start = nullptr;
      46             :     size_t buffer_length = 0;
      47             : 
      48             :    private:
      49             :     AllocationData() = default;
      50             :     AllocationData(void* allocation_base, size_t allocation_length,
      51             :                    void* buffer_start, size_t buffer_length)
      52             :         : allocation_base(allocation_base),
      53             :           allocation_length(allocation_length),
      54             :           buffer_start(buffer_start),
      55      176529 :           buffer_length(buffer_length) {
      56             :       DCHECK_LE(reinterpret_cast<uintptr_t>(allocation_base),
      57             :                 reinterpret_cast<uintptr_t>(buffer_start));
      58             :       DCHECK_GE(
      59             :           reinterpret_cast<uintptr_t>(allocation_base) + allocation_length,
      60             :           reinterpret_cast<uintptr_t>(buffer_start));
      61             :       DCHECK_GE(
      62             :           reinterpret_cast<uintptr_t>(allocation_base) + allocation_length,
      63             :           reinterpret_cast<uintptr_t>(buffer_start) + buffer_length);
      64             :     }
      65             : 
      66             :     friend WasmMemoryTracker;
      67             :   };
      68             : 
      69             :   // Allow tests to allocate a backing store the same way as we do it for
      70             :   // WebAssembly memory. This is used in unit tests for trap handler to
      71             :   // generate the same signals/exceptions for invalid memory accesses as
      72             :   // we would get with WebAssembly memory.
      73             :   V8_EXPORT_PRIVATE void* TryAllocateBackingStoreForTesting(
      74             :       Heap* heap, size_t size, void** allocation_base,
      75             :       size_t* allocation_length);
      76             : 
      77             :   // Free memory allocated with TryAllocateBackingStoreForTesting.
      78             :   V8_EXPORT_PRIVATE void FreeBackingStoreForTesting(base::AddressRegion memory,
      79             :                                                     void* buffer_start);
      80             : 
      81             :   // Decreases the amount of reserved address space.
      82             :   void ReleaseReservation(size_t num_bytes);
      83             : 
      84             :   // Removes an allocation from the tracker.
      85             :   AllocationData ReleaseAllocation(Isolate* isolate, const void* buffer_start);
      86             : 
      87             :   bool IsWasmMemory(const void* buffer_start);
      88             : 
      89             :   // Returns whether the given buffer is a Wasm memory with guard regions large
      90             :   // enough to safely use trap handlers.
      91             :   bool HasFullGuardRegions(const void* buffer_start);
      92             : 
      93             :   // Returns a pointer to a Wasm buffer's allocation data, or nullptr if the
      94             :   // buffer is not tracked.
      95             :   const AllocationData* FindAllocationData(const void* buffer_start);
      96             : 
      97             :   // Checks if a buffer points to a Wasm memory and if so does any necessary
      98             :   // work to reclaim the buffer. If this function returns false, the caller must
      99             :   // free the buffer manually.
     100             :   bool FreeMemoryIfIsWasmMemory(Isolate* isolate, const void* buffer_start);
     101             : 
     102             :   // Allocation results are reported to UMA
     103             :   //
     104             :   // See wasm_memory_allocation_result in counters.h
     105             :   enum class AllocationStatus {
     106             :     kSuccess,  // Succeeded on the first try
     107             : 
     108             :     kSuccessAfterRetry,  // Succeeded after garbage collection
     109             : 
     110             :     kAddressSpaceLimitReachedFailure,  // Failed because Wasm is at its address
     111             :                                        // space limit
     112             : 
     113             :     kOtherFailure  // Failed for an unknown reason
     114             :   };
     115             : 
     116             :  private:
     117             :   void AddAddressSpaceSample(Isolate* isolate);
     118             : 
     119             :   // Clients use a two-part process. First they "reserve" the address space,
     120             :   // which signifies an intent to actually allocate it. This determines whether
     121             :   // doing the allocation would put us over our limit. Once there is a
     122             :   // reservation, clients can do the allocation and register the result.
     123             :   //
     124             :   // We should always have:
     125             :   // allocated_address_space_ <= reserved_address_space_ <= kAddressSpaceLimit
     126             :   std::atomic<size_t> reserved_address_space_{0};
     127             : 
     128             :   // Used to protect access to the allocated address space counter and
     129             :   // allocation map. This is needed because Wasm memories can be freed on
     130             :   // another thread by the ArrayBufferTracker.
     131             :   base::Mutex mutex_;
     132             : 
     133             :   size_t allocated_address_space_ = 0;
     134             : 
     135             :   // Track Wasm memory allocation information. This is keyed by the start of the
     136             :   // buffer, rather than by the start of the allocation.
     137             :   std::unordered_map<const void*, AllocationData> allocations_;
     138             : 
     139             :   DISALLOW_COPY_AND_ASSIGN(WasmMemoryTracker);
     140             : };
     141             : 
     142             : // Attempts to allocate an array buffer with guard regions suitable for trap
     143             : // handling. If address space is not available, it will return a buffer with
     144             : // mini-guards that will require bounds checks.
     145             : MaybeHandle<JSArrayBuffer> NewArrayBuffer(
     146             :     Isolate*, size_t size, SharedFlag shared = SharedFlag::kNotShared);
     147             : 
     148             : Handle<JSArrayBuffer> SetupArrayBuffer(
     149             :     Isolate*, void* backing_store, size_t size, bool is_external,
     150             :     SharedFlag shared = SharedFlag::kNotShared);
     151             : 
     152             : void DetachMemoryBuffer(Isolate* isolate, Handle<JSArrayBuffer> buffer,
     153             :                         bool free_memory);
     154             : 
     155             : }  // namespace wasm
     156             : }  // namespace internal
     157             : }  // namespace v8
     158             : 
     159             : #endif  // V8_WASM_WASM_MEMORY_H_

Generated by: LCOV version 1.10