LCOV - code coverage report
Current view: top level - src/wasm - wasm-memory.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 30 30 100.0 %
Date: 2017-10-20 Functions: 4 4 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             : #include "src/wasm/wasm-memory.h"
       6             : #include "src/objects-inl.h"
       7             : #include "src/wasm/wasm-limits.h"
       8             : #include "src/wasm/wasm-module.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : namespace wasm {
      13             : 
      14       28219 : void* TryAllocateBackingStore(Isolate* isolate, size_t size,
      15             :                               bool enable_guard_regions, void*& allocation_base,
      16             :                               size_t& allocation_length) {
      17             :   // TODO(eholk): Right now enable_guard_regions has no effect on 32-bit
      18             :   // systems. It may be safer to fail instead, given that other code might do
      19             :   // things that would be unsafe if they expected guard pages where there
      20             :   // weren't any.
      21       13764 :   if (enable_guard_regions) {
      22             :     // TODO(eholk): On Windows we want to make sure we don't commit the guard
      23             :     // pages yet.
      24             : 
      25             :     // We always allocate the largest possible offset into the heap, so the
      26             :     // addressable memory after the guard page can be made inaccessible.
      27        1382 :     allocation_length = RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize());
      28             :     DCHECK_EQ(0, size % base::OS::CommitPageSize());
      29             : 
      30             :     // AllocateGuarded makes the whole region inaccessible by default.
      31             :     allocation_base =
      32         691 :         isolate->array_buffer_allocator()->Reserve(allocation_length);
      33         691 :     if (allocation_base == nullptr) {
      34             :       return nullptr;
      35             :     }
      36             : 
      37             :     void* memory = allocation_base;
      38             : 
      39             :     // Make the part we care about accessible.
      40             :     isolate->array_buffer_allocator()->SetProtection(
      41         691 :         memory, size, v8::ArrayBuffer::Allocator::Protection::kReadWrite);
      42             : 
      43             :     reinterpret_cast<v8::Isolate*>(isolate)
      44         691 :         ->AdjustAmountOfExternalAllocatedMemory(size);
      45             : 
      46         691 :     return memory;
      47             :   } else {
      48             :     void* memory =
      49       26146 :         size == 0 ? nullptr : isolate->array_buffer_allocator()->Allocate(size);
      50       13073 :     allocation_base = memory;
      51       13073 :     allocation_length = size;
      52       13073 :     return memory;
      53             :   }
      54             : }
      55             : 
      56       19190 : Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* allocation_base,
      57             :                                        size_t allocation_length,
      58             :                                        void* backing_store, size_t size,
      59             :                                        bool is_external,
      60             :                                        bool enable_guard_regions,
      61             :                                        SharedFlag shared) {
      62             :   Handle<JSArrayBuffer> buffer =
      63       19190 :       isolate->factory()->NewJSArrayBuffer(shared, TENURED);
      64             :   DCHECK_GE(kMaxInt, size);
      65             :   if (shared == SharedFlag::kShared) DCHECK(FLAG_experimental_wasm_threads);
      66             :   JSArrayBuffer::Setup(buffer, isolate, is_external, allocation_base,
      67             :                        allocation_length, backing_store, static_cast<int>(size),
      68       19190 :                        shared);
      69             :   buffer->set_is_neuterable(false);
      70             :   buffer->set_is_wasm_buffer(true);
      71             :   buffer->set_has_guard_region(enable_guard_regions);
      72       19190 :   return buffer;
      73             : }
      74             : 
      75       13972 : Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size,
      76             :                                      bool enable_guard_regions,
      77             :                                      SharedFlag shared) {
      78             :   // Check against kMaxInt, since the byte length is stored as int in the
      79             :   // JSArrayBuffer. Note that wasm_max_mem_pages can be raised from the command
      80             :   // line, and we don't want to fail a CHECK then.
      81       13972 :   if (size > FLAG_wasm_max_mem_pages * WasmModule::kPageSize ||
      82             :       size > kMaxInt) {
      83             :     // TODO(titzer): lift restriction on maximum memory allocated here.
      84             :     return Handle<JSArrayBuffer>::null();
      85             :   }
      86             : 
      87       13962 :   void* allocation_base = nullptr;  // Set by TryAllocateBackingStore
      88       13962 :   size_t allocation_length = 0;     // Set by TryAllocateBackingStore
      89             :   // Do not reserve memory till non zero memory is encountered.
      90             :   void* memory =
      91             :       (size == 0) ? nullptr
      92             :                   : TryAllocateBackingStore(isolate, size, enable_guard_regions,
      93       13962 :                                             allocation_base, allocation_length);
      94             : 
      95       13962 :   if (size > 0 && memory == nullptr) {
      96             :     return Handle<JSArrayBuffer>::null();
      97             :   }
      98             : 
      99             : #if DEBUG
     100             :   // Double check the API allocator actually zero-initialized the memory.
     101             :   const byte* bytes = reinterpret_cast<const byte*>(memory);
     102             :   for (size_t i = 0; i < size; ++i) {
     103             :     DCHECK_EQ(0, bytes[i]);
     104             :   }
     105             : #endif
     106             : 
     107             :   constexpr bool is_external = false;
     108             :   return SetupArrayBuffer(isolate, allocation_base, allocation_length, memory,
     109       13962 :                           size, is_external, enable_guard_regions, shared);
     110             : }
     111             : 
     112         348 : void DetachMemoryBuffer(Isolate* isolate, Handle<JSArrayBuffer> buffer,
     113             :                         bool free_memory) {
     114             :   const bool is_external = buffer->is_external();
     115             :   DCHECK(!buffer->is_neuterable());
     116         348 :   if (!is_external) {
     117             :     buffer->set_is_external(true);
     118         330 :     isolate->heap()->UnregisterArrayBuffer(*buffer);
     119         330 :     if (free_memory) {
     120             :       // We need to free the memory before neutering the buffer because
     121             :       // FreeBackingStore reads buffer->allocation_base(), which is nulled out
     122             :       // by Neuter. This means there is a dangling pointer until we neuter the
     123             :       // buffer. Since there is no way for the user to directly call
     124             :       // FreeBackingStore, we can ensure this is safe.
     125         234 :       buffer->FreeBackingStore();
     126             :     }
     127             :   }
     128             :   buffer->set_is_neuterable(true);
     129         348 :   buffer->Neuter();
     130         348 : }
     131             : 
     132             : }  // namespace wasm
     133             : }  // namespace internal
     134             : }  // namespace v8

Generated by: LCOV version 1.10