Index: Source/platform/heap/Visitor.h |
diff --git a/Source/platform/heap/Visitor.h b/Source/platform/heap/Visitor.h |
index 096e228b24c36ddad88f7c7d331af50d573d30cf..94ca56442140c3618c1db43b080493208ec21f04 100644 |
--- a/Source/platform/heap/Visitor.h |
+++ b/Source/platform/heap/Visitor.h |
@@ -511,7 +511,16 @@ public: |
} |
#endif |
+ inline bool canTraceEagerly() const { return m_traceDepth < kMaxEagerTraceDepth; } |
+ inline void incrementTraceDepth() { m_traceDepth++; } |
+ inline void decrementTraceDepth() { ASSERT(m_traceDepth > 0); m_traceDepth--; } |
+ |
protected: |
+ Visitor() |
+ : m_traceDepth(0) |
+ { |
+ } |
+ |
virtual void registerWeakCell(void**, WeakPointerCallback) = 0; |
#if ENABLE(GC_PROFILE_MARKING) |
void* m_hostObject; |
@@ -526,6 +535,12 @@ private: |
if (*cell && !self->isAlive(*cell)) |
*cell = 0; |
} |
+ |
+ // The maximum depth of eager, unrolled trace() calls that is |
+ // considered safe and allowed. |
+ const int kMaxEagerTraceDepth = 100; |
+ |
+ int m_traceDepth; |
}; |
// We trace vectors by using the trace trait on each element, which means you |
@@ -579,9 +594,21 @@ public: |
// If the trait allows it, invoke the trace callback right here on the |
// not-yet-marked object. |
if (!DISABLE_ALL_EAGER_TRACING && TraceEagerlyTrait<T>::value) { |
- if (visitor->ensureMarked(t)) |
- TraceTrait<T>::trace(visitor, const_cast<T*>(t)); |
- return; |
+ // Protect against too deep trace call chains, and the |
+ // unbounded system stack usage they can bring about. |
+ // |
+ // Assert against deep stacks so as to flush them out, |
+ // but test and appropriately handle them should they occur |
+ // in release builds. |
+ ASSERT(visitor->canTraceEagerly()); |
+ if (LIKELY(visitor->canTraceEagerly())) { |
+ if (visitor->ensureMarked(t)) { |
+ visitor->incrementTraceDepth(); |
+ TraceTrait<T>::trace(visitor, const_cast<T*>(t)); |
+ visitor->decrementTraceDepth(); |
+ } |
+ return; |
+ } |
} |
visitor->mark(const_cast<T*>(t), &TraceTrait<T>::trace); |
} |