V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
wasm-memory.h
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.
26  public:
27  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  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  // Decreases the amount of reserved address space.
70  void ReleaseReservation(size_t num_bytes);
71 
72  // Removes an allocation from the tracker.
73  AllocationData ReleaseAllocation(Isolate* isolate, const void* buffer_start);
74 
75  bool IsWasmMemory(const void* buffer_start);
76 
77  // Returns whether the given buffer is a Wasm memory with guard regions large
78  // enough to safely use trap handlers.
79  bool HasFullGuardRegions(const void* buffer_start);
80 
81  // Returns a pointer to a Wasm buffer's allocation data, or nullptr if the
82  // buffer is not tracked.
83  const AllocationData* FindAllocationData(const void* buffer_start);
84 
85  // Checks if a buffer points to a Wasm memory and if so does any necessary
86  // work to reclaim the buffer. If this function returns false, the caller must
87  // free the buffer manually.
88  bool FreeMemoryIfIsWasmMemory(Isolate* isolate, const void* buffer_start);
89 
90  // Allocation results are reported to UMA
91  //
92  // See wasm_memory_allocation_result in counters.h
93  enum class AllocationStatus {
94  kSuccess, // Succeeded on the first try
95 
96  kSuccessAfterRetry, // Succeeded after garbage collection
97 
98  kAddressSpaceLimitReachedFailure, // Failed because Wasm is at its address
99  // space limit
100 
101  kOtherFailure // Failed for an unknown reason
102  };
103 
104  private:
105  void AddAddressSpaceSample(Isolate* isolate);
106 
107  // Clients use a two-part process. First they "reserve" the address space,
108  // which signifies an intent to actually allocate it. This determines whether
109  // doing the allocation would put us over our limit. Once there is a
110  // reservation, clients can do the allocation and register the result.
111  //
112  // We should always have:
113  // allocated_address_space_ <= reserved_address_space_ <= kAddressSpaceLimit
114  std::atomic<size_t> reserved_address_space_{0};
115 
116  // Used to protect access to the allocated address space counter and
117  // allocation map. This is needed because Wasm memories can be freed on
118  // another thread by the ArrayBufferTracker.
119  base::Mutex mutex_;
120 
121  size_t allocated_address_space_ = 0;
122 
123  // Track Wasm memory allocation information. This is keyed by the start of the
124  // buffer, rather than by the start of the allocation.
125  std::unordered_map<const void*, AllocationData> allocations_;
126 
127  DISALLOW_COPY_AND_ASSIGN(WasmMemoryTracker);
128 };
129 
130 // Attempts to allocate an array buffer with guard regions suitable for trap
131 // handling. If address space is not available, it will return a buffer with
132 // mini-guards that will require bounds checks.
133 MaybeHandle<JSArrayBuffer> NewArrayBuffer(
134  Isolate*, size_t size, SharedFlag shared = SharedFlag::kNotShared);
135 
136 Handle<JSArrayBuffer> SetupArrayBuffer(
137  Isolate*, void* backing_store, size_t size, bool is_external,
138  SharedFlag shared = SharedFlag::kNotShared);
139 
140 void DetachMemoryBuffer(Isolate* isolate, Handle<JSArrayBuffer> buffer,
141  bool free_memory);
142 
143 } // namespace wasm
144 } // namespace internal
145 } // namespace v8
146 
147 #endif // V8_WASM_WASM_MEMORY_H_
Definition: v8.h:85
Definition: libplatform.h:13