Title: [167733] trunk/Source/_javascript_Core
- Revision
- 167733
- Author
- mark....@apple.com
- Date
- 2014-04-23 17:43:15 -0700 (Wed, 23 Apr 2014)
Log Message
The GC should only resume compiler threads that it suspended in the same GC pass.
<https://webkit.org/b/132088>
Reviewed by Mark Hahnenberg.
Previously, this scenario can occur:
1. Thread 1 starts a GC and tries to suspend DFG worklist threads. However,
no worklists were created yet at the that time.
2. Thread 2 starts to compile some functions and creates a DFG worklist, and
acquires the worklist thread's lock.
3. Thread 1's GC completes and tries to resume suspended DFG worklist thread.
This time, it sees the worklist created by Thread 2 and ends up unlocking
the worklist thread's lock that is supposedly held by Thread 2.
Thereafter, chaos ensues.
The fix is to cache the worklists that were actually suspended by each GC pass,
and only resume those when the GC is done.
This issue was discovered by enabling COLLECT_ON_EVERY_ALLOCATION and running
the fast/workers layout tests.
* heap/Heap.cpp:
(JSC::Heap::visitCompilerWorklists):
(JSC::Heap::deleteAllCompiledCode):
(JSC::Heap::suspendCompilerThreads):
(JSC::Heap::resumeCompilerThreads):
* heap/Heap.h:
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (167732 => 167733)
--- trunk/Source/_javascript_Core/ChangeLog 2014-04-24 00:32:14 UTC (rev 167732)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-04-24 00:43:15 UTC (rev 167733)
@@ -1,3 +1,33 @@
+2014-04-23 Mark Lam <mark....@apple.com>
+
+ The GC should only resume compiler threads that it suspended in the same GC pass.
+ <https://webkit.org/b/132088>
+
+ Reviewed by Mark Hahnenberg.
+
+ Previously, this scenario can occur:
+ 1. Thread 1 starts a GC and tries to suspend DFG worklist threads. However,
+ no worklists were created yet at the that time.
+ 2. Thread 2 starts to compile some functions and creates a DFG worklist, and
+ acquires the worklist thread's lock.
+ 3. Thread 1's GC completes and tries to resume suspended DFG worklist thread.
+ This time, it sees the worklist created by Thread 2 and ends up unlocking
+ the worklist thread's lock that is supposedly held by Thread 2.
+ Thereafter, chaos ensues.
+
+ The fix is to cache the worklists that were actually suspended by each GC pass,
+ and only resume those when the GC is done.
+
+ This issue was discovered by enabling COLLECT_ON_EVERY_ALLOCATION and running
+ the fast/workers layout tests.
+
+ * heap/Heap.cpp:
+ (JSC::Heap::visitCompilerWorklists):
+ (JSC::Heap::deleteAllCompiledCode):
+ (JSC::Heap::suspendCompilerThreads):
+ (JSC::Heap::resumeCompilerThreads):
+ * heap/Heap.h:
+
2014-04-23 Mark Hahnenberg <mhahnenb...@apple.com>
Arguments::copyBackingStore needs to update m_registers in tandem with m_registerArray
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (167732 => 167733)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2014-04-24 00:32:14 UTC (rev 167732)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2014-04-24 00:43:15 UTC (rev 167733)
@@ -626,10 +626,8 @@
{
#if ENABLE(DFG_JIT)
GCPHASE(VisitDFGWorklists);
- for (unsigned i = DFG::numberOfWorklists(); i--;) {
- if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
- worklist->visitChildren(m_slotVisitor, m_codeBlocks);
- }
+ for (auto worklist : m_suspendedCompilerWorklists)
+ worklist->visitChildren(m_slotVisitor, m_codeBlocks);
if (Options::logGC() == GCLogging::Verbose)
dataLog("DFG Worklists:\n", m_slotVisitor);
@@ -881,11 +879,9 @@
// means that we are running some hot JS code right now. Maybe causing
// recompilations isn't a good idea.
#if ENABLE(DFG_JIT)
- for (unsigned i = DFG::numberOfWorklists(); i--;) {
- if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i)) {
- if (worklist->isActiveForVM(*vm()))
- return;
- }
+ for (auto worklist : m_suspendedCompilerWorklists) {
+ if (worklist->isActiveForVM(*vm()))
+ return;
}
#endif // ENABLE(DFG_JIT)
@@ -1022,9 +1018,12 @@
{
#if ENABLE(DFG_JIT)
GCPHASE(SuspendCompilerThreads);
+ ASSERT(m_suspendedCompilerWorklists.isEmpty());
for (unsigned i = DFG::numberOfWorklists(); i--;) {
- if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
+ if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i)) {
+ m_suspendedCompilerWorklists.append(worklist);
worklist->suspendAllThreads();
+ }
}
#endif
}
@@ -1227,10 +1226,9 @@
{
#if ENABLE(DFG_JIT)
GCPHASE(ResumeCompilerThreads);
- for (unsigned i = DFG::numberOfWorklists(); i--;) {
- if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
- worklist->resumeAllThreads();
- }
+ for (auto worklist : m_suspendedCompilerWorklists)
+ worklist->resumeAllThreads();
+ m_suspendedCompilerWorklists.clear();
#endif
}
Modified: trunk/Source/_javascript_Core/heap/Heap.h (167732 => 167733)
--- trunk/Source/_javascript_Core/heap/Heap.h 2014-04-24 00:32:14 UTC (rev 167732)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2014-04-24 00:43:15 UTC (rev 167733)
@@ -71,6 +71,10 @@
class WeakGCHandlePool;
class SlotVisitor;
+namespace DFG {
+class Worklist;
+}
+
typedef std::pair<JSValue, WTF::String> ValueStringPair;
typedef HashCountedSet<JSCell*> ProtectCountSet;
typedef HashCountedSet<const char*> TypeCountSet;
@@ -373,6 +377,7 @@
Vector<MarkedBlock*> m_blockSnapshot;
unsigned m_deferralDepth;
+ Vector<DFG::Worklist*> m_suspendedCompilerWorklists;
};
} // namespace JSC
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes