LCOV - code coverage report
Current view: top level - src - isolate-allocator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 51 52 98.1 %
Date: 2019-04-18 Functions: 5 5 100.0 %

          Line data    Source code
       1             : // Copyright 2018 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/isolate-allocator.h"
       6             : #include "src/base/bounded-page-allocator.h"
       7             : #include "src/isolate.h"
       8             : #include "src/ptr-compr.h"
       9             : #include "src/utils.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14       62442 : IsolateAllocator::IsolateAllocator(IsolateAllocationMode mode) {
      15             : #if V8_TARGET_ARCH_64_BIT
      16       62442 :   if (mode == IsolateAllocationMode::kInV8Heap) {
      17           1 :     Address heap_reservation_address = InitReservation();
      18           1 :     CommitPagesForIsolate(heap_reservation_address);
      19           1 :     return;
      20             :   }
      21             : #endif  // V8_TARGET_ARCH_64_BIT
      22             : 
      23             :   // Allocate Isolate in C++ heap.
      24       62441 :   CHECK_EQ(mode, IsolateAllocationMode::kInCppHeap);
      25       62441 :   page_allocator_ = GetPlatformPageAllocator();
      26       62441 :   isolate_memory_ = ::operator new(sizeof(Isolate));
      27             :   DCHECK(!reservation_.IsReserved());
      28             : }
      29             : 
      30      187279 : IsolateAllocator::~IsolateAllocator() {
      31       62427 :   if (reservation_.IsReserved()) {
      32             :     // The actual memory will be freed when the |reservation_| will die.
      33             :     return;
      34             :   }
      35             : 
      36             :   // The memory was allocated in C++ heap.
      37       62426 :   ::operator delete(isolate_memory_);
      38       62427 : }
      39             : 
      40             : #if V8_TARGET_ARCH_64_BIT
      41           1 : Address IsolateAllocator::InitReservation() {
      42           1 :   v8::PageAllocator* platform_page_allocator = GetPlatformPageAllocator();
      43             : 
      44             :   // Reserve a 4Gb region so that the middle is 4Gb aligned.
      45             :   // The VirtualMemory API does not support such an constraint so we have to
      46             :   // implement it manually here.
      47             :   size_t reservation_size = kPtrComprHeapReservationSize;
      48             :   size_t base_alignment = kPtrComprIsolateRootAlignment;
      49             : 
      50             :   const int kMaxAttempts = 3;
      51           1 :   for (int attempt = 0; attempt < kMaxAttempts; ++attempt) {
      52           1 :     Address hint = RoundDown(reinterpret_cast<Address>(
      53           1 :                                  platform_page_allocator->GetRandomMmapAddr()),
      54             :                              base_alignment) +
      55           1 :                    kPtrComprIsolateRootBias;
      56             : 
      57             :     // Within this reservation there will be a sub-region with proper alignment.
      58             :     VirtualMemory padded_reservation(platform_page_allocator,
      59             :                                      reservation_size * 2,
      60           1 :                                      reinterpret_cast<void*>(hint));
      61           1 :     if (!padded_reservation.IsReserved()) break;
      62             : 
      63             :     // Find such a sub-region inside the reservation that it's middle is
      64             :     // |base_alignment|-aligned.
      65             :     Address address =
      66             :         RoundUp(padded_reservation.address() + kPtrComprIsolateRootBias,
      67             :                 base_alignment) -
      68           1 :         kPtrComprIsolateRootBias;
      69           1 :     CHECK(padded_reservation.InVM(address, reservation_size));
      70             : 
      71             : #if defined(V8_OS_FUCHSIA)
      72             :     // Fuchsia does not respect given hints so as a workaround we will use
      73             :     // overreserved address space region instead of trying to re-reserve
      74             :     // a subregion.
      75             :     if (padded_reservation.InVM(address, reservation_size)) {
      76             :       reservation_ = std::move(padded_reservation);
      77             :       return address;
      78             :     }
      79             : #else
      80             :     // Now free the padded reservation and immediately try to reserve an exact
      81             :     // region at aligned address. We have to do this dancing because the
      82             :     // reservation address requirement is more complex than just a certain
      83             :     // alignment and not all operating systems support freeing parts of reserved
      84             :     // address space regions.
      85           1 :     padded_reservation.Free();
      86             : 
      87             :     VirtualMemory reservation(platform_page_allocator, reservation_size,
      88           1 :                               reinterpret_cast<void*>(address));
      89           1 :     if (!reservation.IsReserved()) break;
      90             : 
      91             :     // The reservation could still be somewhere else but we can accept it
      92             :     // if the reservation has the required alignment.
      93             :     Address aligned_address =
      94             :         RoundUp(reservation.address() + kPtrComprIsolateRootBias,
      95             :                 base_alignment) -
      96           1 :         kPtrComprIsolateRootBias;
      97             : 
      98           1 :     if (reservation.address() == aligned_address) {
      99           1 :       reservation_ = std::move(reservation);
     100           1 :       CHECK_EQ(reservation_.size(), reservation_size);
     101           1 :       return aligned_address;
     102             :     }
     103             : #endif
     104             :   }
     105             :   V8::FatalProcessOutOfMemory(nullptr,
     106           0 :                               "Failed to reserve memory for new V8 Isolate");
     107             :   return kNullAddress;
     108             : }
     109             : 
     110           1 : void IsolateAllocator::CommitPagesForIsolate(Address heap_address) {
     111           2 :   CHECK(reservation_.InVM(heap_address, kPtrComprHeapReservationSize));
     112             : 
     113           1 :   Address isolate_root = heap_address + kPtrComprIsolateRootBias;
     114           1 :   CHECK(IsAligned(isolate_root, kPtrComprIsolateRootAlignment));
     115             : 
     116           1 :   v8::PageAllocator* platform_page_allocator = GetPlatformPageAllocator();
     117             : 
     118             :   // Simplify BoundedPageAllocator's life by configuring it to use same page
     119             :   // size as the Heap will use (MemoryChunk::kPageSize).
     120           1 :   size_t page_size = RoundUp(size_t{1} << kPageSizeBits,
     121           2 :                              platform_page_allocator->AllocatePageSize());
     122             : 
     123           2 :   page_allocator_instance_ = base::make_unique<base::BoundedPageAllocator>(
     124             :       platform_page_allocator, heap_address, kPtrComprHeapReservationSize,
     125             :       page_size);
     126           1 :   page_allocator_ = page_allocator_instance_.get();
     127             : 
     128           1 :   Address isolate_address = isolate_root - Isolate::isolate_root_bias();
     129           1 :   Address isolate_end = isolate_address + sizeof(Isolate);
     130             : 
     131             :   // Inform the bounded page allocator about reserved pages.
     132             :   {
     133           1 :     Address reserved_region_address = RoundDown(isolate_address, page_size);
     134             :     size_t reserved_region_size =
     135           1 :         RoundUp(isolate_end, page_size) - reserved_region_address;
     136             : 
     137           1 :     CHECK(page_allocator_instance_->AllocatePagesAt(
     138             :         reserved_region_address, reserved_region_size,
     139             :         PageAllocator::Permission::kNoAccess));
     140             :   }
     141             : 
     142             :   // Commit pages where the Isolate will be stored.
     143             :   {
     144           1 :     size_t commit_page_size = platform_page_allocator->CommitPageSize();
     145             :     Address committed_region_address =
     146           1 :         RoundDown(isolate_address, commit_page_size);
     147             :     size_t committed_region_size =
     148           1 :         RoundUp(isolate_end, commit_page_size) - committed_region_address;
     149             : 
     150             :     // We are using |reservation_| directly here because |page_allocator_| has
     151             :     // bigger commit page size than we actually need.
     152           1 :     CHECK(reservation_.SetPermissions(committed_region_address,
     153             :                                       committed_region_size,
     154             :                                       PageAllocator::kReadWrite));
     155             : 
     156             :     if (Heap::ShouldZapGarbage()) {
     157             :       for (Address address = committed_region_address;
     158             :            address < committed_region_size; address += kSystemPointerSize) {
     159             :         Memory<Address>(address) = static_cast<Address>(kZapValue);
     160             :       }
     161             :     }
     162             :   }
     163           1 :   isolate_memory_ = reinterpret_cast<void*>(isolate_address);
     164           1 : }
     165             : #endif  // V8_TARGET_ARCH_64_BIT
     166             : 
     167             : }  // namespace internal
     168      122036 : }  // namespace v8

Generated by: LCOV version 1.10