Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8677)

Unified Diff: Source/platform/heap/Heap.cpp

Issue 271703002: Simplify and speed up address-to-page cache for conservative stack scanning. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Merge up Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/platform/heap/Heap.h ('k') | Source/platform/heap/HeapTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/heap/Heap.cpp
diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp
index a22210a99087c2470bffceac5fc53ca83faa6e46..01b16804b1e214ba49a8f086903e1898843cccef 100644
--- a/Source/platform/heap/Heap.cpp
+++ b/Source/platform/heap/Heap.cpp
@@ -131,6 +131,7 @@ public:
WARN_UNUSED_RETURN bool commit()
{
+ ASSERT(Heap::heapDoesNotContainCacheIsEmpty());
#if OS(POSIX)
int err = mprotect(m_base, m_size, PROT_READ | PROT_WRITE);
if (!err) {
@@ -204,6 +205,7 @@ public:
// unmap the excess memory before returning.
size_t allocationSize = payloadSize + 2 * osPageSize() + blinkPageSize;
+ ASSERT(Heap::heapDoesNotContainCacheIsEmpty());
#if OS(POSIX)
Address base = static_cast<Address>(mmap(0, allocationSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0));
RELEASE_ASSERT(base != MAP_FAILED);
@@ -426,16 +428,15 @@ bool LargeHeapObject<Header>::isMarked()
}
template<typename Header>
-bool LargeHeapObject<Header>::checkAndMarkPointer(Visitor* visitor, Address address)
+void LargeHeapObject<Header>::checkAndMarkPointer(Visitor* visitor, Address address)
{
- if (contains(address)) {
+ ASSERT(contains(address));
+ if (!objectContains(address))
+ return;
#if ENABLE(GC_TRACING)
- visitor->setHostInfo(&address, "stack");
+ visitor->setHostInfo(&address, "stack");
#endif
- mark(visitor);
- return true;
- }
- return false;
+ mark(visitor);
}
template<>
@@ -558,13 +559,10 @@ BaseHeapPage* ThreadHeap<Header>::heapPageFromAddress(Address address)
if (page->contains(address))
return page;
}
- return 0;
-}
-
-template<typename Header>
-BaseHeapPage* ThreadHeap<Header>::largeHeapObjectFromAddress(Address address)
-{
for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; current = current->next()) {
+ // Check that large pages are blinkPageSize aligned (modulo the
+ // osPageSize for the guard page).
+ ASSERT(reinterpret_cast<Address>(current) - osPageSize() == roundToBlinkPageStart(reinterpret_cast<Address>(current)));
if (current->contains(address))
return current;
}
@@ -584,16 +582,6 @@ const GCInfo* ThreadHeap<Header>::findGCInfoOfLargeHeapObject(Address address)
#endif
template<typename Header>
-bool ThreadHeap<Header>::checkAndMarkLargeHeapObject(Visitor* visitor, Address address)
-{
- for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; current = current->next()) {
- if (current->checkAndMarkPointer(visitor, address))
- return true;
- }
- return false;
-}
-
-template<typename Header>
void ThreadHeap<Header>::addToFreeList(Address address, size_t size)
{
ASSERT(heapPageFromAddress(address));
@@ -647,6 +635,7 @@ Address ThreadHeap<Header>::allocateLargeObject(size_t size, const GCInfo* gcInf
#endif
if (threadState()->shouldGC())
threadState()->setGCRequested();
+ Heap::flushHeapDoesNotContainCache();
PageMemory* pageMemory = PageMemory::allocate(allocationSize);
Address largeObjectAddress = pageMemory->writableStart();
Address headerAddress = largeObjectAddress + sizeof(LargeHeapObject<Header>) + headerPadding<Header>();
@@ -668,6 +657,7 @@ Address ThreadHeap<Header>::allocateLargeObject(size_t size, const GCInfo* gcInf
template<typename Header>
void ThreadHeap<Header>::freeLargeObject(LargeHeapObject<Header>* object, LargeHeapObject<Header>** previousNext)
{
+ flushHeapContainsCache();
object->unlink(previousNext);
object->finalize();
@@ -704,6 +694,7 @@ void ThreadHeap<Header>::clearPagePool()
template<typename Header>
PageMemory* ThreadHeap<Header>::takePageFromPool()
{
+ Heap::flushHeapDoesNotContainCache();
while (PagePoolEntry* entry = m_pagePool) {
m_pagePool = entry->next();
PageMemory* storage = entry->storage();
@@ -722,6 +713,7 @@ PageMemory* ThreadHeap<Header>::takePageFromPool()
template<typename Header>
void ThreadHeap<Header>::addPageToPool(HeapPage<Header>* unused)
{
+ flushHeapContainsCache();
PageMemory* storage = unused->storage();
PagePoolEntry* entry = new PagePoolEntry(storage, m_pagePool);
m_pagePool = entry;
@@ -731,7 +723,7 @@ void ThreadHeap<Header>::addPageToPool(HeapPage<Header>* unused)
template<typename Header>
void ThreadHeap<Header>::allocatePage(const GCInfo* gcInfo)
{
- heapContainsCache()->flush();
+ Heap::flushHeapDoesNotContainCache();
PageMemory* pageMemory = takePageFromPool();
if (!pageMemory) {
pageMemory = PageMemory::allocate(blinkPagePayloadSize());
@@ -782,6 +774,7 @@ void ThreadHeap<Header>::sweep()
bool pagesRemoved = false;
while (page) {
if (page->isEmpty()) {
+ flushHeapContainsCache();
HeapPage<Header>* unused = page;
page = page->next();
HeapPage<Header>::unlink(unused, previous);
@@ -793,7 +786,7 @@ void ThreadHeap<Header>::sweep()
}
}
if (pagesRemoved)
- heapContainsCache()->flush();
+ flushHeapContainsCache();
LargeHeapObject<Header>** previousNext = &m_firstLargeHeapObject;
for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current;) {
@@ -867,7 +860,7 @@ void ThreadHeap<Header>::clearMarks()
template<typename Header>
void ThreadHeap<Header>::deletePages()
{
- heapContainsCache()->flush();
+ flushHeapContainsCache();
// Add all pages in the pool to the heap's list of pages before deleting
clearPagePool();
@@ -1079,11 +1072,12 @@ Header* HeapPage<Header>::findHeaderFromAddress(Address address)
}
template<typename Header>
-bool HeapPage<Header>::checkAndMarkPointer(Visitor* visitor, Address address)
+void HeapPage<Header>::checkAndMarkPointer(Visitor* visitor, Address address)
{
+ ASSERT(contains(address));
Header* header = findHeaderFromAddress(address);
if (!header)
- return false;
+ return;
#if ENABLE(GC_TRACING)
visitor->setHostInfo(&address, "stack");
@@ -1092,7 +1086,6 @@ bool HeapPage<Header>::checkAndMarkPointer(Visitor* visitor, Address address)
visitor->markConservatively(header);
else
visitor->mark(header, traceCallback(header));
- return true;
}
#if ENABLE(GC_TRACING)
@@ -1174,18 +1167,18 @@ void LargeHeapObject<Header>::getStats(HeapStats& stats)
stats.increaseObjectSpace(payloadSize());
}
-HeapContainsCache::HeapContainsCache()
- : m_entries(adoptArrayPtr(new Entry[HeapContainsCache::numberOfEntries]))
-{
-}
-
-void HeapContainsCache::flush()
+template<typename Entry>
+void HeapExtentCache<Entry>::flush()
{
- for (int i = 0; i < numberOfEntries; i++)
- m_entries[i] = Entry();
+ if (m_hasEntries) {
+ for (int i = 0; i < numberOfEntries; i++)
+ m_entries[i] = Entry();
+ m_hasEntries = false;
+ }
}
-size_t HeapContainsCache::hash(Address address)
+template<typename Entry>
+size_t HeapExtentCache<Entry>::hash(Address address)
{
size_t value = (reinterpret_cast<size_t>(address) >> blinkPageSizeLog2);
value ^= value >> numberOfEntriesLog2;
@@ -1194,31 +1187,46 @@ size_t HeapContainsCache::hash(Address address)
return value & ~1; // Returns only even number.
}
-bool HeapContainsCache::lookup(Address address, BaseHeapPage** page)
+template<typename Entry>
+typename Entry::LookupResult HeapExtentCache<Entry>::lookup(Address address)
{
- ASSERT(page);
size_t index = hash(address);
ASSERT(!(index & 1));
Address cachePage = roundToBlinkPageStart(address);
- if (m_entries[index].address() == cachePage) {
- *page = m_entries[index].containingPage();
- return true;
- }
- if (m_entries[index + 1].address() == cachePage) {
- *page = m_entries[index + 1].containingPage();
- return true;
- }
- *page = 0;
- return false;
+ if (m_entries[index].address() == cachePage)
+ return m_entries[index].result();
+ if (m_entries[index + 1].address() == cachePage)
+ return m_entries[index + 1].result();
+ return 0;
}
-void HeapContainsCache::addEntry(Address address, BaseHeapPage* page)
+template<typename Entry>
+void HeapExtentCache<Entry>::addEntry(Address address, typename Entry::LookupResult entry)
{
+ m_hasEntries = true;
size_t index = hash(address);
ASSERT(!(index & 1));
Address cachePage = roundToBlinkPageStart(address);
m_entries[index + 1] = m_entries[index];
- m_entries[index] = Entry(cachePage, page);
+ m_entries[index] = Entry(cachePage, entry);
+}
+
+// These should not be needed, but it seems impossible to persuade clang to
+// instantiate the template functions and export them from a shared library, so
+// we add these in the non-templated subclass, which does not have that issue.
+void HeapContainsCache::addEntry(Address address, BaseHeapPage* page)
+{
+ HeapExtentCache<PositiveEntry>::addEntry(address, page);
+}
+
+BaseHeapPage* HeapContainsCache::lookup(Address address)
+{
+ return HeapExtentCache<PositiveEntry>::lookup(address);
+}
+
+void Heap::flushHeapDoesNotContainCache()
+{
+ s_heapDoesNotContainCache->flush();
}
void CallbackStack::init(CallbackStack** first)
@@ -1492,6 +1500,7 @@ void Heap::init()
ThreadState::init();
CallbackStack::init(&s_markingStack);
CallbackStack::init(&s_weakCallbackStack);
+ s_heapDoesNotContainCache = new HeapDoesNotContainCache();
s_markingVisitor = new MarkingVisitor();
}
@@ -1511,6 +1520,8 @@ void Heap::doShutdown()
ASSERT(!ThreadState::attachedThreads().size());
delete s_markingVisitor;
s_markingVisitor = 0;
+ delete s_heapDoesNotContainCache;
+ s_heapDoesNotContainCache = 0;
CallbackStack::shutdown(&s_weakCallbackStack);
CallbackStack::shutdown(&s_markingStack);
ThreadState::shutdown();
@@ -1531,16 +1542,28 @@ BaseHeapPage* Heap::contains(Address address)
Address Heap::checkAndMarkPointer(Visitor* visitor, Address address)
{
ASSERT(ThreadState::isAnyThreadInGC());
- if (!address)
+
+#ifdef NDEBUG
+ if (s_heapDoesNotContainCache->lookup(address))
return 0;
+#endif
ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads();
for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
if ((*it)->checkAndMarkPointer(visitor, address)) {
- // Pointer found and marked.
+ // Pointer was in a page of that thread. If it actually pointed
+ // into an object then that object was found and marked.
+ ASSERT(!s_heapDoesNotContainCache->lookup(address));
return address;
}
}
+
+#ifdef NDEBUG
+ s_heapDoesNotContainCache->addEntry(address, true);
+#else
+ if (!s_heapDoesNotContainCache->lookup(address))
+ s_heapDoesNotContainCache->addEntry(address, true);
+#endif
return 0;
}
@@ -1701,5 +1724,6 @@ template class ThreadHeap<HeapObjectHeader>;
Visitor* Heap::s_markingVisitor;
CallbackStack* Heap::s_markingStack;
CallbackStack* Heap::s_weakCallbackStack;
+HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache;
bool Heap::s_shutdownCalled = false;
}
« no previous file with comments | « Source/platform/heap/Heap.h ('k') | Source/platform/heap/HeapTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698