summaryrefslogtreecommitdiff
path: root/deps/v8/src/heap/read-only-heap.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/heap/read-only-heap.cc')
-rw-r--r--deps/v8/src/heap/read-only-heap.cc145
1 files changed, 122 insertions, 23 deletions
diff --git a/deps/v8/src/heap/read-only-heap.cc b/deps/v8/src/heap/read-only-heap.cc
index 1a5345de9b..1021bc147f 100644
--- a/deps/v8/src/heap/read-only-heap.cc
+++ b/deps/v8/src/heap/read-only-heap.cc
@@ -8,7 +8,11 @@
#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 {
@@ -21,48 +25,63 @@ ReadOnlyHeap* shared_ro_heap = nullptr;
// static
void ReadOnlyHeap::SetUp(Isolate* isolate, ReadOnlyDeserializer* des) {
+ DCHECK_NOT_NULL(isolate);
#ifdef V8_SHARED_RO_HEAP
- void* isolate_ro_roots = reinterpret_cast<void*>(
- isolate->roots_table().read_only_roots_begin().address());
- base::CallOnce(&setup_ro_heap_once, [isolate, des, isolate_ro_roots]() {
- shared_ro_heap = Init(isolate, des);
- if (des != nullptr) {
- std::memcpy(shared_ro_heap->read_only_roots_, isolate_ro_roots,
- kEntriesCount * sizeof(Address));
- }
+ // Make sure we are only sharing read-only space when deserializing. Otherwise
+ // we would be trying to create heap objects inside an already initialized
+ // read-only space. Use ClearSharedHeapForTest if you need a new read-only
+ // space.
+ DCHECK_IMPLIES(shared_ro_heap != nullptr, des != nullptr);
+
+ base::CallOnce(&setup_ro_heap_once, [isolate, des]() {
+ shared_ro_heap = CreateAndAttachToIsolate(isolate);
+ if (des != nullptr) shared_ro_heap->DeseralizeIntoIsolate(isolate, des);
});
isolate->heap()->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
- Init(isolate, des);
+ auto* ro_heap = CreateAndAttachToIsolate(isolate);
+ if (des != nullptr) ro_heap->DeseralizeIntoIsolate(isolate, des);
#endif // V8_SHARED_RO_HEAP
}
-void ReadOnlyHeap::OnCreateHeapObjectsComplete() {
- DCHECK(!deserializing_);
-#ifdef V8_SHARED_RO_HEAP
- read_only_space_->Forget();
-#endif
- read_only_space_->MarkAsReadOnly();
+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::Init(Isolate* isolate, ReadOnlyDeserializer* des) {
+ReadOnlyHeap* ReadOnlyHeap::CreateAndAttachToIsolate(Isolate* isolate) {
auto* ro_heap = new ReadOnlyHeap(new ReadOnlySpace(isolate->heap()));
isolate->heap()->SetUpFromReadOnlyHeap(ro_heap);
- if (des != nullptr) {
- des->DeserializeInto(isolate);
- ro_heap->deserializing_ = true;
+ return ro_heap;
+}
+
+void ReadOnlyHeap::InitFromIsolate(Isolate* isolate) {
+ DCHECK(!init_complete_);
#ifdef V8_SHARED_RO_HEAP
- ro_heap->read_only_space_->Forget();
+ 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));
+ read_only_space_->Seal(ReadOnlySpace::SealMode::kDetachFromHeapAndForget);
+#else
+ read_only_space_->Seal(ReadOnlySpace::SealMode::kDoNotDetachFromHeap);
#endif
- ro_heap->read_only_space_->MarkAsReadOnly();
- }
- return ro_heap;
+ init_complete_ = true;
}
void ReadOnlyHeap::OnHeapTearDown() {
@@ -73,9 +92,89 @@ void ReadOnlyHeap::OnHeapTearDown() {
}
// 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.
+ delete shared_ro_heap;
+ shared_ro_heap = nullptr;
+ setup_ro_heap_once = 0;
+#endif
+}
+
+// static
bool ReadOnlyHeap::Contains(HeapObject object) {
return Page::FromAddress(object.ptr())->owner()->identity() == RO_SPACE;
}
+// static
+ReadOnlyRoots ReadOnlyHeap::GetReadOnlyRoots(HeapObject object) {
+#ifdef V8_SHARED_RO_HEAP
+ // This fails if we are creating heap objects and the roots haven't yet been
+ // copied into the read-only heap or it has been cleared for testing.
+ if (shared_ro_heap != nullptr && shared_ro_heap->init_complete_) {
+ return ReadOnlyRoots(shared_ro_heap->read_only_roots_);
+ }
+#endif
+ return ReadOnlyRoots(GetHeapFromWritableObject(object));
+}
+
+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;
+}
+
+ReadOnlyHeapIterator::ReadOnlyHeapIterator(ReadOnlyHeap* ro_heap)
+ : ReadOnlyHeapIterator(ro_heap->read_only_space()) {}
+
+ReadOnlyHeapIterator::ReadOnlyHeapIterator(ReadOnlySpace* ro_space)
+ : ro_space_(ro_space),
+ current_page_(ro_space->first_page()),
+ current_addr_(current_page_->area_start()) {}
+
+HeapObject ReadOnlyHeapIterator::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