[heap] Start making ReadOnlySpace Pages relocatable

Adds Page::MakeHeaderRelocatable that clears pointers to objects
outside the space. In this case relocatable means the entire page
heading is position independent in memory, meaning it could be saved to
disk and reloaded at a different memory location in a new process
without there being any invalid pointers.

Currently this only affects mutex_, locate_tracker_ and reservation_.

Additionally makes VerifyHeap work when there's no mutex in a Page.

This is just a stepping stone to making the Pages headers relocatable
since heap_ and owner_ still point out of the Page.

Also removes the empty ReadOnlySpace destructor.

Bug: v8:7464
Change-Id: Ife3c06575fa73a5818c4991fb9bec30a5f43901d
Reviewed-on: https://chromium-review.googlesource.com/1054879
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53196}
This commit is contained in:
Dan Elphick 2018-05-15 12:23:12 +01:00 committed by Commit Bot
parent b1fb9e9002
commit 7485b1296b
4 changed files with 39 additions and 10 deletions

View File

@ -203,11 +203,21 @@ typedef LazyStaticInstance<RecursiveMutex,
// object was created, the LockGuard is destructed and the mutex is released.
// The LockGuard class is non-copyable.
template <typename Mutex>
// Controls whether a LockGuard always requires a valid Mutex or will just
// ignore it if it's nullptr.
enum class NullBehavior { kRequireNotNull, kIgnoreIfNull };
template <typename Mutex, NullBehavior Behavior = NullBehavior::kRequireNotNull>
class LockGuard final {
public:
explicit LockGuard(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
~LockGuard() { mutex_->Unlock(); }
explicit LockGuard(Mutex* mutex) : mutex_(mutex) {
if (Behavior == NullBehavior::kRequireNotNull || mutex_ != nullptr) {
mutex_->Lock();
}
}
~LockGuard() {
if (mutex_ != nullptr) mutex_->Unlock();
}
private:
Mutex* mutex_;

View File

@ -3804,7 +3804,10 @@ void CollectSlots(MemoryChunk* chunk, Address start, Address end,
void Heap::VerifyRememberedSetFor(HeapObject* object) {
MemoryChunk* chunk = MemoryChunk::FromAddress(object->address());
base::LockGuard<base::Mutex> lock_guard(chunk->mutex());
DCHECK_IMPLIES(chunk->mutex() == nullptr, InReadOnlySpace(object));
// In RO_SPACE chunk->mutex() may be nullptr, so just ignore it.
base::LockGuard<base::Mutex, base::NullBehavior::kIgnoreIfNull> lock_guard(
chunk->mutex());
Address start = object->address();
Address end = start + object->Size();
std::set<Address> old_to_new;

View File

@ -3190,10 +3190,24 @@ ReadOnlySpace::ReadOnlySpace(Heap* heap, AllocationSpace id,
is_string_padding_cleared_(heap->isolate()->initialized_from_snapshot()) {
}
void ReadOnlyPage::MakeHeaderRelocatable() {
if (mutex_ != nullptr) {
// TODO(v8:7464): heap_ and owner_ need to be cleared as well.
delete mutex_;
mutex_ = nullptr;
local_tracker_ = nullptr;
reservation_.Reset();
}
}
void ReadOnlySpace::SetPermissionsForPages(PageAllocator::Permission access) {
const size_t page_size = MemoryAllocator::GetCommitPageSize();
const size_t area_start_offset = RoundUp(Page::kObjectStartOffset, page_size);
for (Page* page : *this) {
for (Page* p : *this) {
ReadOnlyPage* page = static_cast<ReadOnlyPage*>(p);
if (access == PageAllocator::kRead) {
page->MakeHeaderRelocatable();
}
CHECK(SetPermissions(page->address() + area_start_offset,
page->size() - area_start_offset, access));
}

View File

@ -868,6 +868,13 @@ class Page : public MemoryChunk {
friend class MemoryAllocator;
};
class ReadOnlyPage : public Page {
public:
// Clears any pointers in the header that point out of the page that would
// otherwise make the header non-relocatable.
void MakeHeaderRelocatable();
};
class LargePage : public MemoryChunk {
public:
HeapObject* GetObject() { return HeapObject::FromAddress(area_start()); }
@ -2935,11 +2942,6 @@ class ReadOnlySpace : public PagedSpace {
ReadOnlySpace(Heap* heap, AllocationSpace id, Executability executable);
~ReadOnlySpace() {
// Mark as writable as tearing down the space writes to it.
// MarkAsReadWrite();
}
void ClearStringPaddingIfNeeded();
void MarkAsReadOnly();