���� 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/heap/ |
// Copyright 2019 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/heap/read-only-heap.h" #include <cstring> #include "src/base/lsan.h" #include "src/base/once.h" #include "src/heap/heap-inl.h" #include "src/heap/heap-write-barrier-inl.h" #include "src/heap/spaces.h" #include "src/objects/heap-object-inl.h" #include "src/objects/objects-inl.h" #include "src/objects/smi.h" #include "src/snapshot/read-only-deserializer.h" namespace v8 { namespace internal { #ifdef V8_SHARED_RO_HEAP V8_DECLARE_ONCE(setup_ro_heap_once); ReadOnlyHeap* ReadOnlyHeap::shared_ro_heap_ = nullptr; #endif // static void ReadOnlyHeap::SetUp(Isolate* isolate, ReadOnlyDeserializer* des) { DCHECK_NOT_NULL(isolate); #ifdef V8_SHARED_RO_HEAP bool call_once_ran = false; base::Optional<Checksum> des_checksum; #ifdef DEBUG if (des != nullptr) des_checksum = des->GetChecksum(); #endif // DEBUG base::CallOnce(&setup_ro_heap_once, [isolate, des, des_checksum, &call_once_ran]() { USE(des_checksum); shared_ro_heap_ = CreateAndAttachToIsolate(isolate); if (des != nullptr) { #ifdef DEBUG shared_ro_heap_->read_only_blob_checksum_ = des_checksum; #endif // DEBUG shared_ro_heap_->DeseralizeIntoIsolate(isolate, des); } call_once_ran = true; }); USE(call_once_ran); USE(des_checksum); #ifdef DEBUG const base::Optional<Checksum> last_checksum = shared_ro_heap_->read_only_blob_checksum_; if (last_checksum || des_checksum) { // The read-only heap was set up from a snapshot. Make sure it's the always // the same snapshot. CHECK_EQ(last_checksum, des_checksum); } else { // The read-only heap objects were created. Make sure this happens only // once, during this call. CHECK(call_once_ran); } #endif // DEBUG isolate->SetUpFromReadOnlyHeap(shared_ro_heap_); if (des != nullptr) { void* const isolate_ro_roots = reinterpret_cast<void*>( isolate->roots_table().read_only_roots_begin().address()); std::memcpy(isolate_ro_roots, shared_ro_heap_->read_only_roots_, kEntriesCount * sizeof(Address)); } #else auto* ro_heap = CreateAndAttachToIsolate(isolate); if (des != nullptr) ro_heap->DeseralizeIntoIsolate(isolate, des); #endif // V8_SHARED_RO_HEAP } void ReadOnlyHeap::DeseralizeIntoIsolate(Isolate* isolate, ReadOnlyDeserializer* des) { DCHECK_NOT_NULL(des); des->DeserializeInto(isolate); InitFromIsolate(isolate); } void ReadOnlyHeap::OnCreateHeapObjectsComplete(Isolate* isolate) { DCHECK_NOT_NULL(isolate); InitFromIsolate(isolate); } // static ReadOnlyHeap* ReadOnlyHeap::CreateAndAttachToIsolate(Isolate* isolate) { auto* ro_heap = new ReadOnlyHeap(new ReadOnlySpace(isolate->heap())); isolate->SetUpFromReadOnlyHeap(ro_heap); return ro_heap; } void ReadOnlyHeap::InitFromIsolate(Isolate* isolate) { DCHECK(!init_complete_); #ifdef V8_SHARED_RO_HEAP void* const isolate_ro_roots = reinterpret_cast<void*>( isolate->roots_table().read_only_roots_begin().address()); std::memcpy(read_only_roots_, isolate_ro_roots, kEntriesCount * sizeof(Address)); // N.B. Since pages are manually allocated with mmap, Lsan doesn't track // their pointers. Seal explicitly ignores the necessary objects. LSAN_IGNORE_OBJECT(this); read_only_space_->Seal(ReadOnlySpace::SealMode::kDetachFromHeapAndForget); #else read_only_space_->Seal(ReadOnlySpace::SealMode::kDoNotDetachFromHeap); #endif init_complete_ = true; } void ReadOnlyHeap::OnHeapTearDown() { #ifndef V8_SHARED_RO_HEAP delete read_only_space_; delete this; #endif } // static void ReadOnlyHeap::ClearSharedHeapForTest() { #ifdef V8_SHARED_RO_HEAP DCHECK_NOT_NULL(shared_ro_heap_); // TODO(v8:7464): Just leak read-only space for now. The paged-space heap // is null so there isn't a nice way to do this. shared_ro_heap_ = nullptr; setup_ro_heap_once = 0; #endif } // static bool ReadOnlyHeap::Contains(HeapObject object) { return MemoryChunk::FromHeapObject(object)->InReadOnlySpace(); } Object* ReadOnlyHeap::ExtendReadOnlyObjectCache() { read_only_object_cache_.push_back(Smi::kZero); return &read_only_object_cache_.back(); } Object ReadOnlyHeap::cached_read_only_object(size_t i) const { DCHECK_LE(i, read_only_object_cache_.size()); return read_only_object_cache_[i]; } bool ReadOnlyHeap::read_only_object_cache_is_initialized() const { return read_only_object_cache_.size() > 0; } ReadOnlyHeapObjectIterator::ReadOnlyHeapObjectIterator(ReadOnlyHeap* ro_heap) : ReadOnlyHeapObjectIterator(ro_heap->read_only_space()) {} ReadOnlyHeapObjectIterator::ReadOnlyHeapObjectIterator(ReadOnlySpace* ro_space) : ro_space_(ro_space), current_page_(ro_space->first_page()), current_addr_(current_page_->area_start()) {} HeapObject ReadOnlyHeapObjectIterator::Next() { if (current_page_ == nullptr) { return HeapObject(); } for (;;) { DCHECK_LE(current_addr_, current_page_->area_end()); if (current_addr_ == current_page_->area_end()) { // Progress to the next page. current_page_ = current_page_->next_page(); if (current_page_ == nullptr) { return HeapObject(); } current_addr_ = current_page_->area_start(); } if (current_addr_ == ro_space_->top() && current_addr_ != ro_space_->limit()) { current_addr_ = ro_space_->limit(); continue; } HeapObject object = HeapObject::FromAddress(current_addr_); const int object_size = object.Size(); current_addr_ += object_size; if (object.IsFiller()) { continue; } DCHECK_OBJECT_SIZE(object_size); return object; } } } // namespace internal } // namespace v8