[heap] Move support for inner pointer lookups into heap/
The GcSafe* methods rely on Heap internals and should thus belong to Heap. Bug: Change-Id: I4e6468d51c4dda1d10e94568698e05bee1b56b40 Reviewed-on: https://chromium-review.googlesource.com/789935 Commit-Queue: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#49630}
This commit is contained in:
parent
70dbac4b63
commit
9af72045af
@ -379,14 +379,10 @@ Code* StackFrame::LookupCode() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool GcSafeCodeContains(HeapObject* object, Address addr);
|
||||
#endif
|
||||
|
||||
void StackFrame::IteratePc(RootVisitor* v, Address* pc_address,
|
||||
Address* constant_pool_address, Code* holder) {
|
||||
Address pc = *pc_address;
|
||||
DCHECK(GcSafeCodeContains(holder, pc));
|
||||
DCHECK(holder->GetHeap()->GcSafeCodeContains(holder, pc));
|
||||
unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
|
||||
Object* code = holder;
|
||||
v->VisitRootPointer(Root::kTop, &code);
|
||||
@ -1421,8 +1417,7 @@ DeoptimizationData* OptimizedFrame::GetDeoptimizationData(
|
||||
// back to a slow search in this case to find the original optimized
|
||||
// code object.
|
||||
if (!code->contains(pc())) {
|
||||
code = isolate()->inner_pointer_to_code_cache()->
|
||||
GcSafeFindCodeForInnerPointer(pc());
|
||||
code = isolate()->heap()->GcSafeFindCodeForInnerPointer(pc());
|
||||
}
|
||||
DCHECK_NOT_NULL(code);
|
||||
DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
|
||||
@ -1983,79 +1978,6 @@ void InternalFrame::Iterate(RootVisitor* v) const {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
|
||||
MapWord map_word = object->map_word();
|
||||
return map_word.IsForwardingAddress() ?
|
||||
map_word.ToForwardingAddress()->map() : map_word.ToMap();
|
||||
}
|
||||
|
||||
|
||||
static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
|
||||
return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool GcSafeCodeContains(HeapObject* code, Address addr) {
|
||||
Map* map = GcSafeMapOfCodeSpaceObject(code);
|
||||
DCHECK(map == code->GetHeap()->code_map());
|
||||
Address start = code->address();
|
||||
Address end = code->address() + code->SizeFromMap(map);
|
||||
return start <= addr && addr < end;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
|
||||
Address inner_pointer) {
|
||||
Code* code = reinterpret_cast<Code*>(object);
|
||||
DCHECK(code != nullptr && GcSafeCodeContains(code, inner_pointer));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
|
||||
Address inner_pointer) {
|
||||
Heap* heap = isolate_->heap();
|
||||
|
||||
// Check if the inner pointer points into a large object chunk.
|
||||
LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
|
||||
if (large_page != nullptr) {
|
||||
return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
|
||||
}
|
||||
|
||||
if (!heap->code_space()->Contains(inner_pointer)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Iterate through the page until we reach the end or find an object starting
|
||||
// after the inner pointer.
|
||||
Page* page = Page::FromAddress(inner_pointer);
|
||||
|
||||
DCHECK_EQ(page->owner(), heap->code_space());
|
||||
heap->mark_compact_collector()->sweeper().SweepOrWaitUntilSweepingCompleted(
|
||||
page);
|
||||
|
||||
Address addr = page->skip_list()->StartFor(inner_pointer);
|
||||
|
||||
Address top = heap->code_space()->top();
|
||||
Address limit = heap->code_space()->limit();
|
||||
|
||||
while (true) {
|
||||
if (addr == top && addr != limit) {
|
||||
addr = limit;
|
||||
continue;
|
||||
}
|
||||
|
||||
HeapObject* obj = HeapObject::FromAddress(addr);
|
||||
int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
|
||||
Address next_addr = addr + obj_size;
|
||||
if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
|
||||
addr = next_addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
|
||||
InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
|
||||
isolate_->counters()->pc_to_code()->Increment();
|
||||
@ -2065,13 +1987,15 @@ InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
|
||||
InnerPointerToCodeCacheEntry* entry = cache(index);
|
||||
if (entry->inner_pointer == inner_pointer) {
|
||||
isolate_->counters()->pc_to_code_cached()->Increment();
|
||||
DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
|
||||
DCHECK(entry->code ==
|
||||
isolate_->heap()->GcSafeFindCodeForInnerPointer(inner_pointer));
|
||||
} else {
|
||||
// Because this code may be interrupted by a profiling signal that
|
||||
// also queries the cache, we cannot update inner_pointer before the code
|
||||
// has been set. Otherwise, we risk trying to use a cache entry before
|
||||
// the code has been computed.
|
||||
entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
|
||||
entry->code =
|
||||
isolate_->heap()->GcSafeFindCodeForInnerPointer(inner_pointer);
|
||||
entry->safepoint_entry.Reset();
|
||||
entry->inner_pointer = inner_pointer;
|
||||
}
|
||||
|
@ -40,9 +40,6 @@ class InnerPointerToCodeCache {
|
||||
Flush();
|
||||
}
|
||||
|
||||
Code* GcSafeFindCodeForInnerPointer(Address inner_pointer);
|
||||
Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer);
|
||||
|
||||
void Flush() {
|
||||
memset(&cache_[0], 0, sizeof(cache_));
|
||||
}
|
||||
|
@ -6569,5 +6569,70 @@ void Heap::CreateObjectStats() {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
|
||||
MapWord map_word = object->map_word();
|
||||
return map_word.IsForwardingAddress() ? map_word.ToForwardingAddress()->map()
|
||||
: map_word.ToMap();
|
||||
}
|
||||
|
||||
int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
|
||||
return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
|
||||
}
|
||||
|
||||
Code* GcSafeCastToCode(Heap* heap, HeapObject* object, Address inner_pointer) {
|
||||
Code* code = reinterpret_cast<Code*>(object);
|
||||
DCHECK_NOT_NULL(code);
|
||||
DCHECK(heap->GcSafeCodeContains(code, inner_pointer));
|
||||
return code;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool Heap::GcSafeCodeContains(HeapObject* code, Address addr) {
|
||||
Map* map = GcSafeMapOfCodeSpaceObject(code);
|
||||
DCHECK(map == code->GetHeap()->code_map());
|
||||
Address start = code->address();
|
||||
Address end = code->address() + code->SizeFromMap(map);
|
||||
return start <= addr && addr < end;
|
||||
}
|
||||
|
||||
Code* Heap::GcSafeFindCodeForInnerPointer(Address inner_pointer) {
|
||||
// Check if the inner pointer points into a large object chunk.
|
||||
LargePage* large_page = lo_space()->FindPage(inner_pointer);
|
||||
if (large_page != nullptr) {
|
||||
return GcSafeCastToCode(this, large_page->GetObject(), inner_pointer);
|
||||
}
|
||||
|
||||
if (!code_space()->Contains(inner_pointer)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Iterate through the page until we reach the end or find an object starting
|
||||
// after the inner pointer.
|
||||
Page* page = Page::FromAddress(inner_pointer);
|
||||
DCHECK_EQ(page->owner(), code_space());
|
||||
mark_compact_collector()->sweeper().SweepOrWaitUntilSweepingCompleted(page);
|
||||
|
||||
Address addr = page->skip_list()->StartFor(inner_pointer);
|
||||
Address top = code_space()->top();
|
||||
Address limit = code_space()->limit();
|
||||
|
||||
while (true) {
|
||||
if (addr == top && addr != limit) {
|
||||
addr = limit;
|
||||
continue;
|
||||
}
|
||||
|
||||
HeapObject* obj = HeapObject::FromAddress(addr);
|
||||
int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
|
||||
Address next_addr = addr + obj_size;
|
||||
if (next_addr > inner_pointer)
|
||||
return GcSafeCastToCode(this, obj, inner_pointer);
|
||||
addr = next_addr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -1580,6 +1580,18 @@ class Heap {
|
||||
void AddRetainingPathTarget(Handle<HeapObject> object,
|
||||
RetainingPathOption option);
|
||||
|
||||
// ===========================================================================
|
||||
// Stack frame support. ======================================================
|
||||
// ===========================================================================
|
||||
|
||||
// Returns the Code object for a given interior pointer. Returns nullptr if
|
||||
// {inner_pointer} is not contained within a Code object.
|
||||
Code* GcSafeFindCodeForInnerPointer(Address inner_pointer);
|
||||
|
||||
// Returns true if {addr} is contained within {code} and false otherwise.
|
||||
// Mostly useful for debugging.
|
||||
bool GcSafeCodeContains(HeapObject* code, Address addr);
|
||||
|
||||
// =============================================================================
|
||||
#ifdef VERIFY_HEAP
|
||||
// Verify the heap is in its normal state before or after a GC.
|
||||
|
@ -3337,7 +3337,7 @@ int Isolate::GenerateIdentityHash(uint32_t mask) {
|
||||
}
|
||||
|
||||
Code* Isolate::FindCodeObject(Address a) {
|
||||
return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a);
|
||||
return heap()->GcSafeFindCodeForInnerPointer(a);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user