���� JFIF �� � ( %"1"%)+...383,7(-.-
![]() Server : Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.20 System : Linux st2.domain.com 3.10.0-1127.10.1.el7.x86_64 #1 SMP Wed Jun 3 14:28:03 UTC 2020 x86_64 User : apache ( 48) PHP Version : 7.4.20 Disable Function : NONE Directory : /home/real/node-v13.0.1/deps/v8/src/init/ |
// Copyright 2018 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/init/isolate-allocator.h" #include "src/base/bounded-page-allocator.h" #include "src/common/ptr-compr.h" #include "src/execution/isolate.h" #include "src/utils/utils.h" namespace v8 { namespace internal { IsolateAllocator::IsolateAllocator(IsolateAllocationMode mode) { #if V8_TARGET_ARCH_64_BIT if (mode == IsolateAllocationMode::kInV8Heap) { Address heap_reservation_address = InitReservation(); CommitPagesForIsolate(heap_reservation_address); return; } #endif // V8_TARGET_ARCH_64_BIT // Allocate Isolate in C++ heap. CHECK_EQ(mode, IsolateAllocationMode::kInCppHeap); page_allocator_ = GetPlatformPageAllocator(); isolate_memory_ = ::operator new(sizeof(Isolate)); DCHECK(!reservation_.IsReserved()); } IsolateAllocator::~IsolateAllocator() { if (reservation_.IsReserved()) { // The actual memory will be freed when the |reservation_| will die. return; } // The memory was allocated in C++ heap. ::operator delete(isolate_memory_); } #if V8_TARGET_ARCH_64_BIT Address IsolateAllocator::InitReservation() { v8::PageAllocator* platform_page_allocator = GetPlatformPageAllocator(); // Reserve a 4Gb region so that the middle is 4Gb aligned. // The VirtualMemory API does not support such an constraint so we have to // implement it manually here. size_t reservation_size = kPtrComprHeapReservationSize; size_t base_alignment = kPtrComprIsolateRootAlignment; const int kMaxAttempts = 4; for (int attempt = 0; attempt < kMaxAttempts; ++attempt) { Address hint = RoundDown(reinterpret_cast<Address>( platform_page_allocator->GetRandomMmapAddr()), base_alignment) + kPtrComprIsolateRootBias; // Within this reservation there will be a sub-region with proper alignment. VirtualMemory padded_reservation(platform_page_allocator, reservation_size * 2, reinterpret_cast<void*>(hint)); if (!padded_reservation.IsReserved()) break; // Find such a sub-region inside the reservation that it's middle is // |base_alignment|-aligned. Address address = RoundUp(padded_reservation.address() + kPtrComprIsolateRootBias, base_alignment) - kPtrComprIsolateRootBias; CHECK(padded_reservation.InVM(address, reservation_size)); #if defined(V8_OS_FUCHSIA) // Fuchsia does not respect given hints so as a workaround we will use // overreserved address space region instead of trying to re-reserve // a subregion. bool overreserve = true; #else // For the last attempt use the overreserved region to avoid an OOM crash. // This case can happen if there are many isolates being created in // parallel that race for reserving the regions. bool overreserve = (attempt == kMaxAttempts - 1); #endif if (overreserve) { if (padded_reservation.InVM(address, reservation_size)) { reservation_ = std::move(padded_reservation); return address; } } else { // Now free the padded reservation and immediately try to reserve an exact // region at aligned address. We have to do this dancing because the // reservation address requirement is more complex than just a certain // alignment and not all operating systems support freeing parts of // reserved address space regions. padded_reservation.Free(); VirtualMemory reservation(platform_page_allocator, reservation_size, reinterpret_cast<void*>(address)); if (!reservation.IsReserved()) break; // The reservation could still be somewhere else but we can accept it // if the reservation has the required alignment. Address aligned_address = RoundUp(reservation.address() + kPtrComprIsolateRootBias, base_alignment) - kPtrComprIsolateRootBias; if (reservation.address() == aligned_address) { reservation_ = std::move(reservation); CHECK_EQ(reservation_.size(), reservation_size); return aligned_address; } } } V8::FatalProcessOutOfMemory(nullptr, "Failed to reserve memory for new V8 Isolate"); return kNullAddress; } void IsolateAllocator::CommitPagesForIsolate(Address heap_address) { CHECK(reservation_.InVM(heap_address, kPtrComprHeapReservationSize)); Address isolate_root = heap_address + kPtrComprIsolateRootBias; CHECK(IsAligned(isolate_root, kPtrComprIsolateRootAlignment)); v8::PageAllocator* platform_page_allocator = GetPlatformPageAllocator(); // Simplify BoundedPageAllocator's life by configuring it to use same page // size as the Heap will use (MemoryChunk::kPageSize). size_t page_size = RoundUp(size_t{1} << kPageSizeBits, platform_page_allocator->AllocatePageSize()); page_allocator_instance_ = base::make_unique<base::BoundedPageAllocator>( platform_page_allocator, heap_address, kPtrComprHeapReservationSize, page_size); page_allocator_ = page_allocator_instance_.get(); Address isolate_address = isolate_root - Isolate::isolate_root_bias(); Address isolate_end = isolate_address + sizeof(Isolate); // Inform the bounded page allocator about reserved pages. { Address reserved_region_address = RoundDown(isolate_address, page_size); size_t reserved_region_size = RoundUp(isolate_end, page_size) - reserved_region_address; CHECK(page_allocator_instance_->AllocatePagesAt( reserved_region_address, reserved_region_size, PageAllocator::Permission::kNoAccess)); } // Commit pages where the Isolate will be stored. { size_t commit_page_size = platform_page_allocator->CommitPageSize(); Address committed_region_address = RoundDown(isolate_address, commit_page_size); size_t committed_region_size = RoundUp(isolate_end, commit_page_size) - committed_region_address; // We are using |reservation_| directly here because |page_allocator_| has // bigger commit page size than we actually need. CHECK(reservation_.SetPermissions(committed_region_address, committed_region_size, PageAllocator::kReadWrite)); if (Heap::ShouldZapGarbage()) { for (Address address = committed_region_address; address < committed_region_size; address += kSystemPointerSize) { base::Memory<Address>(address) = static_cast<Address>(kZapValue); } } } isolate_memory_ = reinterpret_cast<void*>(isolate_address); } #endif // V8_TARGET_ARCH_64_BIT } // namespace internal } // namespace v8