[JSC] Do not even allocate JIT worklists in non-JIT mode
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Feb 2019 09:27:42 +0000 (09:27 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Feb 2019 09:27:42 +0000 (09:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194693

Reviewed by Mark Lam.

Heap always allocates JIT worklists for Baseline, DFG, and FTL. While they do not have actual threads, Worklist itself already allocates some memory.
And we do not perform any GC operations that are only meaningful in JIT environment.

1. We add VM::canUseJIT() check in Heap's ensureXXXWorklist things to prevent them from being allocated.
2. We remove DFG marking constraint in non-JIT mode.
3. We do not gather conservative roots from scratch buffers under the non-JIT mode (BTW, # of scratch buffers are always zero in non-JIT mode)
4. We do not visit JITStubRoutineSet.
5. Align JITWorklist function names to the other worklists.

* dfg/DFGOSRExitPreparation.cpp:
(JSC::DFG::prepareCodeOriginForOSRExit):
* dfg/DFGPlan.h:
* dfg/DFGWorklist.cpp:
(JSC::DFG::markCodeBlocks): Deleted.
* dfg/DFGWorklist.h:
* heap/Heap.cpp:
(JSC::Heap::completeAllJITPlans):
(JSC::Heap::iterateExecutingAndCompilingCodeBlocks):
(JSC::Heap::gatherScratchBufferRoots):
(JSC::Heap::removeDeadCompilerWorklistEntries):
(JSC::Heap::stopThePeriphery):
(JSC::Heap::suspendCompilerThreads):
(JSC::Heap::resumeCompilerThreads):
(JSC::Heap::addCoreConstraints):
* jit/JITWorklist.cpp:
(JSC::JITWorklist::existingGlobalWorklistOrNull):
(JSC::JITWorklist::ensureGlobalWorklist):
(JSC::JITWorklist::instance): Deleted.
* jit/JITWorklist.h:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::jitCompileAndSetHeuristics):
* runtime/VM.cpp:
(JSC::VM::~VM):
(JSC::VM::gatherScratchBufferRoots):
(JSC::VM::gatherConservativeRoots): Deleted.
* runtime/VM.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@241582 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp
Source/JavaScriptCore/dfg/DFGPlan.h
Source/JavaScriptCore/dfg/DFGWorklist.cpp
Source/JavaScriptCore/dfg/DFGWorklist.h
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/jit/JITWorklist.cpp
Source/JavaScriptCore/jit/JITWorklist.h
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h

index 1bc6350..8fc4900 100644 (file)
@@ -1,3 +1,47 @@
+2019-02-15  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Do not even allocate JIT worklists in non-JIT mode
+        https://bugs.webkit.org/show_bug.cgi?id=194693
+
+        Reviewed by Mark Lam.
+
+        Heap always allocates JIT worklists for Baseline, DFG, and FTL. While they do not have actual threads, Worklist itself already allocates some memory.
+        And we do not perform any GC operations that are only meaningful in JIT environment.
+
+        1. We add VM::canUseJIT() check in Heap's ensureXXXWorklist things to prevent them from being allocated.
+        2. We remove DFG marking constraint in non-JIT mode.
+        3. We do not gather conservative roots from scratch buffers under the non-JIT mode (BTW, # of scratch buffers are always zero in non-JIT mode)
+        4. We do not visit JITStubRoutineSet.
+        5. Align JITWorklist function names to the other worklists.
+
+        * dfg/DFGOSRExitPreparation.cpp:
+        (JSC::DFG::prepareCodeOriginForOSRExit):
+        * dfg/DFGPlan.h:
+        * dfg/DFGWorklist.cpp:
+        (JSC::DFG::markCodeBlocks): Deleted.
+        * dfg/DFGWorklist.h:
+        * heap/Heap.cpp:
+        (JSC::Heap::completeAllJITPlans):
+        (JSC::Heap::iterateExecutingAndCompilingCodeBlocks):
+        (JSC::Heap::gatherScratchBufferRoots):
+        (JSC::Heap::removeDeadCompilerWorklistEntries):
+        (JSC::Heap::stopThePeriphery):
+        (JSC::Heap::suspendCompilerThreads):
+        (JSC::Heap::resumeCompilerThreads):
+        (JSC::Heap::addCoreConstraints):
+        * jit/JITWorklist.cpp:
+        (JSC::JITWorklist::existingGlobalWorklistOrNull):
+        (JSC::JITWorklist::ensureGlobalWorklist):
+        (JSC::JITWorklist::instance): Deleted.
+        * jit/JITWorklist.h:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::jitCompileAndSetHeuristics):
+        * runtime/VM.cpp:
+        (JSC::VM::~VM):
+        (JSC::VM::gatherScratchBufferRoots):
+        (JSC::VM::gatherConservativeRoots): Deleted.
+        * runtime/VM.h:
+
 2019-02-15  Saam barati  <sbarati@apple.com>
 
         [WebAssembly] Write a new register allocator for Air O0 and make BBQ use it
index 646c7e4..a94170a 100644 (file)
@@ -43,7 +43,7 @@ void prepareCodeOriginForOSRExit(ExecState* exec, CodeOrigin codeOrigin)
     
     for (; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->directCaller) {
         CodeBlock* codeBlock = codeOrigin.inlineCallFrame->baselineCodeBlock.get();
-        JITWorklist::instance()->compileNow(codeBlock);
+        JITWorklist::ensureGlobalWorklist().compileNow(codeBlock);
     }
 }
 
index 6d5f668..9afd458 100644 (file)
@@ -70,7 +70,6 @@ public:
     
     CompilationKey key();
     
-    void markCodeBlocks(SlotVisitor&);
     template<typename Func>
     void iterateCodeBlocksForGC(const Func&);
     void checkLivenessAndVisitChildren(SlotVisitor&);
index dece70e..8fd16ef 100644 (file)
@@ -661,10 +661,6 @@ void completeAllPlansForVM(VM&)
 {
 }
 
-void markCodeBlocks(VM&, SlotVisitor&)
-{
-}
-
 #endif // ENABLE(DFG_JIT)
 
 } } // namespace JSC::DFG
index 8a5de18..396ebb8 100644 (file)
@@ -144,7 +144,6 @@ Worklist& existingWorklistForIndex(unsigned index);
 #endif // ENABLE(DFG_JIT)
 
 void completeAllPlansForVM(VM&);
-void markCodeBlocks(VM&, SlotVisitor&);
 
 template<typename Func>
 void iterateCodeBlocksForGC(VM&, const Func&);
index 5f2bc83..c0d2383 100644 (file)
@@ -599,8 +599,10 @@ void Heap::didFinishIterating()
 
 void Heap::completeAllJITPlans()
 {
+    if (!VM::canUseJIT())
+        return;
 #if ENABLE(JIT)
-    JITWorklist::instance()->completeAllForVM(*m_vm);
+    JITWorklist::ensureGlobalWorklist().completeAllForVM(*m_vm);
 #endif // ENABLE(JIT)
     DFG::completeAllPlansForVM(*m_vm);
 }
@@ -609,7 +611,8 @@ template<typename Func>
 void Heap::iterateExecutingAndCompilingCodeBlocks(const Func& func)
 {
     m_codeBlocks->iterateCurrentlyExecuting(func);
-    DFG::iterateCodeBlocksForGC(*m_vm, func);
+    if (VM::canUseJIT())
+        DFG::iterateCodeBlocksForGC(*m_vm, func);
 }
 
 template<typename Func>
@@ -667,7 +670,9 @@ void Heap::gatherJSStackRoots(ConservativeRoots& roots)
 void Heap::gatherScratchBufferRoots(ConservativeRoots& roots)
 {
 #if ENABLE(DFG_JIT)
-    m_vm->gatherConservativeRoots(roots);
+    if (!VM::canUseJIT())
+        return;
+    m_vm->gatherScratchBufferRoots(roots);
 #else
     UNUSED_PARAM(roots);
 #endif
@@ -684,6 +689,8 @@ void Heap::beginMarking()
 void Heap::removeDeadCompilerWorklistEntries()
 {
 #if ENABLE(DFG_JIT)
+    if (!VM::canUseJIT())
+        return;
     for (unsigned i = DFG::numberOfWorklists(); i--;)
         DFG::existingWorklistForIndex(i).removeDeadPlans(*m_vm);
 #endif
@@ -1586,9 +1593,9 @@ void Heap::stopThePeriphery(GCConductor conn)
         });
 
 #if ENABLE(JIT)
-    {
+    if (VM::canUseJIT()) {
         DeferGCForAWhile awhile(*this);
-        if (JITWorklist::instance()->completeAllForVM(*m_vm)
+        if (JITWorklist::ensureGlobalWorklist().completeAllForVM(*m_vm)
             && conn == GCConductor::Collector)
             setGCDidJIT();
     }
@@ -2093,6 +2100,8 @@ void Heap::suspendCompilerThreads()
     // We ensure the worklists so that it's not possible for the mutator to start a new worklist
     // after we have suspended the ones that he had started before. That's not very expensive since
     // the worklists use AutomaticThreads anyway.
+    if (!VM::canUseJIT())
+        return;
     for (unsigned i = DFG::numberOfWorklists(); i--;)
         DFG::ensureWorklistForIndex(i).suspendAllThreads();
 #endif
@@ -2310,6 +2319,8 @@ void Heap::didFinishCollection()
 void Heap::resumeCompilerThreads()
 {
 #if ENABLE(DFG_JIT)
+    if (!VM::canUseJIT())
+        return;
     for (unsigned i = DFG::numberOfWorklists(); i--;)
         DFG::existingWorklistForIndex(i).resumeAllThreads();
 #endif
@@ -2640,7 +2651,7 @@ void Heap::addCoreConstraints()
                 SetRootMarkReasonScope rootScope(slotVisitor, SlotVisitor::RootMarkReason::ConservativeScan);
                 slotVisitor.append(conservativeRoots);
             }
-            {
+            if (VM::canUseJIT()) {
                 // JITStubRoutines must be visited after scanning ConservativeRoots since JITStubRoutines depend on the hook executed during gathering ConservativeRoots.
                 SetRootMarkReasonScope rootScope(slotVisitor, SlotVisitor::RootMarkReason::JITStubRoutines);
                 m_jitStubRoutines->traceMarkedStubRoutines(slotVisitor);
@@ -2744,26 +2755,28 @@ void Heap::addCoreConstraints()
         ConstraintParallelism::Parallel);
     
 #if ENABLE(DFG_JIT)
-    m_constraintSet->add(
-        "Dw", "DFG Worklists",
-        [this] (SlotVisitor& slotVisitor) {
-            SetRootMarkReasonScope rootScope(slotVisitor, SlotVisitor::RootMarkReason::DFGWorkLists);
-
-            for (unsigned i = DFG::numberOfWorklists(); i--;)
-                DFG::existingWorklistForIndex(i).visitWeakReferences(slotVisitor);
-            
-            // FIXME: This is almost certainly unnecessary.
-            // https://bugs.webkit.org/show_bug.cgi?id=166829
-            DFG::iterateCodeBlocksForGC(
-                *m_vm,
-                [&] (CodeBlock* codeBlock) {
-                    slotVisitor.appendUnbarriered(codeBlock);
-                });
-            
-            if (Options::logGC() == GCLogging::Verbose)
-                dataLog("DFG Worklists:\n", slotVisitor);
-        },
-        ConstraintVolatility::GreyedByMarking);
+    if (VM::canUseJIT()) {
+        m_constraintSet->add(
+            "Dw", "DFG Worklists",
+            [this] (SlotVisitor& slotVisitor) {
+                SetRootMarkReasonScope rootScope(slotVisitor, SlotVisitor::RootMarkReason::DFGWorkLists);
+
+                for (unsigned i = DFG::numberOfWorklists(); i--;)
+                    DFG::existingWorklistForIndex(i).visitWeakReferences(slotVisitor);
+                
+                // FIXME: This is almost certainly unnecessary.
+                // https://bugs.webkit.org/show_bug.cgi?id=166829
+                DFG::iterateCodeBlocksForGC(
+                    *m_vm,
+                    [&] (CodeBlock* codeBlock) {
+                        slotVisitor.appendUnbarriered(codeBlock);
+                    });
+                
+                if (Options::logGC() == GCLogging::Verbose)
+                    dataLog("DFG Worklists:\n", slotVisitor);
+            },
+            ConstraintVolatility::GreyedByMarking);
+    }
 #endif
     
     m_constraintSet->add(
index 4c6ef4f..1f369fc 100644 (file)
@@ -322,16 +322,24 @@ void JITWorklist::finalizePlans(Plans& myPlans)
     }
 }
 
-JITWorklist* JITWorklist::instance()
+static JITWorklist* theGlobalJITWorklist { nullptr };
+
+JITWorklist* JITWorklist::existingGlobalWorklistOrNull()
+{
+    return theGlobalJITWorklist;
+}
+
+JITWorklist& JITWorklist::ensureGlobalWorklist()
 {
-    static JITWorklist* worklist;
     static std::once_flag once;
     std::call_once(
         once,
         [] {
-            worklist = new JITWorklist();
+            auto* worklist = new JITWorklist();
+            WTF::storeStoreFence();
+            theGlobalJITWorklist = worklist;
         });
-    return worklist;
+    return *theGlobalJITWorklist;
 }
 
 } // namespace JSC
index adf9fb9..eb6f551 100644 (file)
@@ -57,7 +57,8 @@ public:
     
     void compileNow(CodeBlock*, unsigned loopOSREntryBytecodeOffset = 0);
     
-    static JITWorklist* instance();
+    static JITWorklist& ensureGlobalWorklist();
+    static JITWorklist* existingGlobalWorklistOrNull();
     
 private:
     JITWorklist();
index a9a8550..0406c92 100644 (file)
@@ -369,6 +369,7 @@ inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec, un
 {
     VM& vm = exec->vm();
     DeferGCForAWhile deferGC(vm.heap); // My callers don't set top callframe, so we don't want to GC here at all.
+    ASSERT(VM::canUseJIT());
     
     codeBlock->updateAllValueProfilePredictions();
 
@@ -379,7 +380,7 @@ inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec, un
         return false;
     }
     
-    JITWorklist::instance()->poll(vm);
+    JITWorklist::ensureGlobalWorklist().poll(vm);
     
     switch (codeBlock->jitType()) {
     case JITCode::BaselineJIT: {
@@ -389,7 +390,7 @@ inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec, un
         return true;
     }
     case JITCode::InterpreterThunk: {
-        JITWorklist::instance()->compileLater(codeBlock, loopOSREntryBytecodeOffset);
+        JITWorklist::ensureGlobalWorklist().compileLater(codeBlock, loopOSREntryBytecodeOffset);
         return codeBlock->jitType() == JITCode::BaselineJIT;
     }
     default:
index 3d1f724..79022d6 100644 (file)
@@ -497,8 +497,8 @@ VM::~VM()
     Gigacage::removePrimitiveDisableCallback(primitiveGigacageDisabledCallback, this);
     promiseDeferredTimer->stopRunningTasks();
 #if ENABLE(WEBASSEMBLY)
-    if (Wasm::existingWorklistOrNull())
-        Wasm::ensureWorklist().stopAllPlansForContext(wasmContext);
+    if (Wasm::Worklist* worklist = Wasm::existingWorklistOrNull())
+        worklist->stopAllPlansForContext(wasmContext);
 #endif
     if (UNLIKELY(m_watchdog))
         m_watchdog->willDestroyVM(this);
@@ -516,7 +516,8 @@ VM::~VM()
 #endif // ENABLE(SAMPLING_PROFILER)
     
 #if ENABLE(JIT)
-    JITWorklist::instance()->completeAllForVM(*this);
+    if (JITWorklist* worklist = JITWorklist::existingGlobalWorklistOrNull())
+        worklist->completeAllForVM(*this);
 #endif // ENABLE(JIT)
 
 #if ENABLE(DFG_JIT)
@@ -921,7 +922,7 @@ inline void VM::updateStackLimits()
 }
 
 #if ENABLE(DFG_JIT)
-void VM::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
+void VM::gatherScratchBufferRoots(ConservativeRoots& conservativeRoots)
 {
     auto lock = holdLock(m_scratchBufferLock);
     for (auto* scratchBuffer : m_scratchBuffers) {
index bb9366a..5ab352f 100644 (file)
@@ -740,7 +740,7 @@ public:
         return m_exceptionFuzzBuffer.get();
     }
 
-    void gatherConservativeRoots(ConservativeRoots&);
+    void gatherScratchBufferRoots(ConservativeRoots&);
 
     VMEntryScope* entryScope;