Commit 9af72045 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

[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: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49630}
parent 70dbac4b
......@@ -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);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment