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

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

Issue 765673004: Oilpan: support eager tracing of objects when marking. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: For eager tracing, check for cross-heap access Created 6 years 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
Index: Source/platform/heap/Heap.cpp
diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp
index 74d925287637d70286165d267790ba432bb02ff4..29b52c1b91dd6db59f717495936b05bcee8af94b 100644
--- a/Source/platform/heap/Heap.cpp
+++ b/Source/platform/heap/Heap.cpp
@@ -581,12 +581,12 @@ static bool isUninitializedMemory(void* objectPointer, size_t objectSize)
template<>
void LargeObject<FinalizedHeapObjectHeader>::mark(Visitor* visitor)
{
- if (heapObjectHeader()->hasVTable() && !vTableInitialized(payload())) {
- FinalizedHeapObjectHeader* header = heapObjectHeader();
+ FinalizedHeapObjectHeader* header = heapObjectHeader();
+ if (header->hasVTable() && !vTableInitialized(payload())) {
visitor->markNoTracing(header);
ASSERT(isUninitializedMemory(header->payload(), header->payloadSize()));
} else {
- visitor->mark(heapObjectHeader(), heapObjectHeader()->traceCallback());
+ visitor->mark(header, header->traceCallback());
}
}
@@ -1969,27 +1969,27 @@ public:
typedef HashMap<uintptr_t, std::pair<uintptr_t, String> > ObjectGraph;
#endif
- MarkingVisitor(CallbackStack* markingStack) : m_markingStack(markingStack)
+ MarkingVisitor(CallbackStack* markingStack)
haraken 2014/12/02 06:16:04 Add explicit.
sof 2014/12/02 09:52:15 Done.
+ : m_markingStack(markingStack)
+ , m_checkIfNeedsTracing(false)
{
}
inline void visitHeader(HeapObjectHeader* header, const void* objectPointer, TraceCallback callback)
{
ASSERT(header);
-#if ENABLE(ASSERT)
- {
- // Check that we are not marking objects that are outside
- // the heap by calling Heap::contains. However we cannot
- // call Heap::contains when outside a GC and we call mark
- // when doing weakness for ephemerons. Hence we only check
- // when called within.
- ASSERT(!Heap::isInGC() || Heap::containedInHeapOrOrphanedPage(header));
- }
-#endif
ASSERT(objectPointer);
+ // Check that we are not marking objects that are outside
+ // the heap by calling Heap::contains. However we cannot
+ // call Heap::contains when outside a GC and we call mark
+ // when doing weakness for ephemerons. Hence we only check
+ // when called within.
+ ASSERT(!Heap::isInGC() || Heap::containedInHeapOrOrphanedPage(header));
+
if (header->isMarked())
return;
header->mark();
+
#if ENABLE(GC_PROFILE_MARKING)
MutexLocker locker(objectGraphMutex());
String className(classOf(objectPointer));
@@ -2001,21 +2001,35 @@ public:
ASSERT(result.isNewEntry);
// fprintf(stderr, "%s[%p] -> %s[%p]\n", m_hostName.ascii().data(), m_hostObject, className.ascii().data(), objectPointer);
#endif
- if (callback)
+#if ENABLE(ASSERT)
+ {
+ BaseHeapPage* page = pageFromObject(objectPointer);
+ // If you hit this ASSERT, it means that there is a dangling pointer
+ // from a live thread heap to a dead thread heap. We must eliminate
+ // the dangling pointer.
+ // Release builds don't have the ASSERT, but it is OK because
+ // release builds will crash at the following item->call
haraken 2014/12/02 06:16:04 Update this comment. Now we don't have "the follow
+ // because all the entries of the orphaned heaps are zeroed out and
+ // thus the item does not have a valid vtable.
+ ASSERT(!page->orphaned());
+ }
+#endif
+ if (callback) {
+ if (UNLIKELY(m_checkIfNeedsTracing && !needsTracing(objectPointer)))
+ return;
+
Heap::pushTraceCallback(m_markingStack, const_cast<void*>(objectPointer), callback);
+ }
}
+ // We need both HeapObjectHeader and FinalizedHeapObjectHeader versions to correctly find the payload.
virtual void mark(HeapObjectHeader* header, TraceCallback callback) override
{
- // We need both the HeapObjectHeader and FinalizedHeapObjectHeader
- // version to correctly find the payload.
visitHeader(header, header->payload(), callback);
}
virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) override
{
- // We need both the HeapObjectHeader and FinalizedHeapObjectHeader
- // version to correctly find the payload.
visitHeader(header, header->payload(), callback);
}
@@ -2054,6 +2068,57 @@ public:
return FinalizedHeapObjectHeader::fromPayload(objectPointer)->isMarked();
}
+ virtual bool ensureMarked(const void* objectPointer) override
+ {
+ if (!objectPointer)
+ return false;
+#if ENABLE(ASSERT)
+ if (isMarked(objectPointer))
+ return false;
+
+ markNoTracing(objectPointer);
+#else
+ FinalizedHeapObjectHeader* header =
+ FinalizedHeapObjectHeader::fromPayload(objectPointer);
+ if (header->isMarked())
+ return false;
+ header->mark();
+
+ if (UNLIKELY(m_checkIfNeedsTracing && !needsTracing(objectPointer)))
haraken 2014/12/02 06:16:04 Hmm, it's a bit unfortunate we need to have this b
sof 2014/12/02 06:19:27 As I said in the previous comment, I don't see a w
sof 2014/12/02 09:52:15 Had a go at the former; acceptable?
+ return false;
+#endif
+ return true;
+ }
+
+#if ENABLE(ASSERT)
+#define DEFINE_ENSURE_MARKED_METHOD(Type) \
+ virtual bool ensureMarked(const Type* objectPointer) override \
+ { \
+ if (!objectPointer) \
+ return false; \
+ COMPILE_ASSERT(!NeedsAdjustAndMark<Type>::value, CanOnlyUseIsMarkedOnNonAdjustedTypes); \
+ if (isMarked(objectPointer)) \
+ return false; \
+ markNoTracing(objectPointer); \
+ return true; \
+ }
+#else
+#define DEFINE_ENSURE_MARKED_METHOD(Type) \
+ virtual bool ensureMarked(const Type* objectPointer) override \
+ { \
+ if (!objectPointer) \
+ return false; \
+ HeapObjectHeader* header = \
+ HeapObjectHeader::fromPayload(objectPointer); \
+ if (header->isMarked()) \
+ return false; \
+ header->mark(); \
+ if (UNLIKELY(m_checkIfNeedsTracing && !needsTracing(objectPointer))) \
+ return false; \
+ return true; \
+ }
+#endif
+
// This macro defines the necessary visitor methods for typed heaps
#define DEFINE_VISITOR_METHODS(Type) \
virtual void mark(const Type* objectPointer, TraceCallback callback) override \
@@ -2067,7 +2132,8 @@ public:
virtual bool isMarked(const Type* objectPointer) override \
{ \
return HeapObjectHeader::fromPayload(objectPointer)->isMarked(); \
- }
+ } \
+ DEFINE_ENSURE_MARKED_METHOD(Type)
FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
#undef DEFINE_VISITOR_METHODS
@@ -2168,6 +2234,19 @@ public:
}
#endif
+ static inline bool needsTracing(const void* objectPointer)
+ {
+ BaseHeapPage* page = pageFromObject(objectPointer);
+ ASSERT(!page->orphaned());
+ // When doing a thread local GC, the marker checks if
+ // the object resides in another thread's heap. The
+ // object should not be traced, if it does.
+ if (!page->terminating())
+ return false;
+
+ return true;
+ }
+
protected:
virtual void registerWeakCell(void** cell, WeakPointerCallback callback) override
{
@@ -2175,7 +2254,29 @@ protected:
}
private:
+ friend class ThreadLocalMarkingScope;
+
CallbackStack* m_markingStack;
+ bool m_checkIfNeedsTracing;
+};
+
+class ThreadLocalMarkingScope {
+ STACK_ALLOCATED();
+public:
+ ThreadLocalMarkingScope(MarkingVisitor* visitor)
+ : m_visitor(visitor)
+ {
+ ASSERT(m_visitor);
+ m_visitor->m_checkIfNeedsTracing = true;
+ }
+
+ ~ThreadLocalMarkingScope()
+ {
+ m_visitor->m_checkIfNeedsTracing = false;
+ }
+
+private:
+ MarkingVisitor* m_visitor;
};
void Heap::init()
@@ -2328,42 +2429,16 @@ String Heap::createBacktraceString()
void Heap::pushTraceCallback(CallbackStack* stack, void* object, TraceCallback callback)
{
-#if ENABLE(ASSERT)
- {
- ASSERT(Heap::containedInHeapOrOrphanedPage(object));
- }
-#endif
+ ASSERT(Heap::containedInHeapOrOrphanedPage(object));
CallbackStack::Item* slot = stack->allocateEntry();
*slot = CallbackStack::Item(object, callback);
}
-template<CallbackInvocationMode Mode>
bool Heap::popAndInvokeTraceCallback(CallbackStack* stack, Visitor* visitor)
{
CallbackStack::Item* item = stack->pop();
if (!item)
return false;
-#if ENABLE(ASSERT)
- if (Mode == GlobalMarking) {
- BaseHeapPage* page = pageFromObject(item->object());
- // If you hit this ASSERT, it means that there is a dangling pointer
- // from a live thread heap to a dead thread heap. We must eliminate
- // the dangling pointer.
- // Release builds don't have the ASSERT, but it is OK because
- // release builds will crash at the following item->call
- // because all the entries of the orphaned heaps are zeroed out and
- // thus the item does not have a valid vtable.
- ASSERT(!page->orphaned());
- }
-#endif
- if (Mode == ThreadLocalMarking) {
- BaseHeapPage* page = pageFromObject(item->object());
- ASSERT(!page->orphaned());
- // When doing a thread local GC, don't trace an object located in
- // a heap of another thread.
- if (!page->terminating())
- return true;
- }
#if ENABLE(GC_PROFILE_MARKING)
visitor->setHostInfo(item->object(), classOf(item->object()));
@@ -2499,7 +2574,7 @@ void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::Cause
ThreadState::visitPersistentRoots(s_markingVisitor);
// 2. trace objects reachable from the persistent roots including ephemerons.
- processMarkingStack<GlobalMarking>();
+ processMarkingStack();
// 3. trace objects reachable from the stack. We do this independent of the
// given stackState since other threads might have a different stack state.
@@ -2508,9 +2583,8 @@ void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::Cause
// 4. trace objects reachable from the stack "roots" including ephemerons.
// Only do the processing if we found a pointer to an object on one of the
// thread stacks.
- if (lastGCWasConservative()) {
- processMarkingStack<GlobalMarking>();
- }
+ if (lastGCWasConservative())
+ processMarkingStack();
postMarkingProcessing();
globalWeakProcessing();
@@ -2549,21 +2623,25 @@ void Heap::collectGarbageForTerminatingThread(ThreadState* state)
enterGC();
state->preGC();
- // 1. trace the thread local persistent roots. For thread local GCs we
- // don't trace the stack (ie. no conservative scanning) since this is
- // only called during thread shutdown where there should be no objects
- // on the stack.
- // We also assume that orphaned pages have no objects reachable from
- // persistent handles on other threads or CrossThreadPersistents. The
- // only cases where this could happen is if a subsequent conservative
- // global GC finds a "pointer" on the stack or due to a programming
- // error where an object has a dangling cross-thread pointer to an
- // object on this heap.
- state->visitPersistents(s_markingVisitor);
-
- // 2. trace objects reachable from the thread's persistent roots
- // including ephemerons.
- processMarkingStack<ThreadLocalMarking>();
+ {
+ ThreadLocalMarkingScope markingScope(static_cast<MarkingVisitor*>(s_markingVisitor));
+
+ // 1. trace the thread local persistent roots. For thread local GCs we
+ // don't trace the stack (ie. no conservative scanning) since this is
+ // only called during thread shutdown where there should be no objects
+ // on the stack.
+ // We also assume that orphaned pages have no objects reachable from
+ // persistent handles on other threads or CrossThreadPersistents. The
+ // only cases where this could happen is if a subsequent conservative
+ // global GC finds a "pointer" on the stack or due to a programming
+ // error where an object has a dangling cross-thread pointer to an
+ // object on this heap.
+ state->visitPersistents(s_markingVisitor);
+
+ // 2. trace objects reachable from the thread's persistent roots
+ // including ephemerons.
+ processMarkingStack();
+ }
postMarkingProcessing();
globalWeakProcessing();
@@ -2574,18 +2652,15 @@ void Heap::collectGarbageForTerminatingThread(ThreadState* state)
state->performPendingSweep();
}
-template<CallbackInvocationMode Mode>
void Heap::processMarkingStack()
{
// Ephemeron fixed point loop.
do {
{
// Iteratively mark all objects that are reachable from the objects
- // currently pushed onto the marking stack. If Mode is ThreadLocalMarking
- // don't continue tracing if the trace hits an object on another thread's
- // heap.
+ // currently pushed onto the marking stack.
TRACE_EVENT0("blink_gc", "Heap::processMarkingStackSingleThreaded");
- while (popAndInvokeTraceCallback<Mode>(s_markingStack, s_markingVisitor)) { }
+ while (popAndInvokeTraceCallback(s_markingStack, s_markingVisitor)) { }
}
{

Powered by Google App Engine
This is Rietveld 408576698