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

Reply via email to