JavaScriptCore should discard baseline code after some time
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Sep 2015 00:28:34 +0000 (00:28 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Sep 2015 00:28:34 +0000 (00:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149220

Reviewed by Saam Barati.

This is a bit more complicated than discarding optimized code because
the engine previously assumed that we would never discard baseline code.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock): Record creation time (and compute time since
creation) instead of install time because CodeBlocks can be installed
more than once, and we don't want to have to worry about edge cases
created by CodeBlocks seeming to get younger.

(JSC::CodeBlock::visitAggregate): Be explicit about only doing the
weak reference fixpoint for optimized CodeBlocks. We used to avoid the
fixpoint for baseline CodeBlocks implicitly, since they would always
visit themselves strongly right away. But now baseline CodeBlocks might
not visit themselves strongly, since they might choose to jettison due
to old age.

(JSC::CodeBlock::shouldVisitStrongly): Add old age as a reason not to
visit ourselves strongly, so that baseline CodeBlocks can jettison due
to old age.

(JSC::CodeBlock::shouldJettisonDueToWeakReference): Be explicit about
only jettisoning optimized CodeBlocks due to weak references so that we
don't confuse ourselves into thinking that we will jettison a baseline
CodeBlock due to weak references.

(JSC::CodeBlock::shouldJettisonDueToOldAge): Updated to use creation time.

(JSC::CodeBlock::visitOSRExitTargets): Clarify a comment and add an
ASSERT to help record some things I discovered while debugging.

(JSC::CodeBlock::jettison): Allow a baseline CodeBlock to jettison. Don't
assume that we have an alternative or a profiler.

(JSC::CodeBlock::install): Deleted.
* bytecode/CodeBlock.h:
(JSC::CodeBlock::releaseAlternative): Deleted.
(JSC::CodeBlock::setInstallTime): Deleted.
(JSC::CodeBlock::timeSinceInstall): Deleted.

* dfg/DFGOSRExitPreparation.cpp:
(JSC::DFG::prepareCodeOriginForOSRExit): Simplified the computation of
baseline CodeBlock.

* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::checkLivenessAndVisitChildren): Be sure to strongly
visit our inline callframes because we assume that an optimized CodeBlock
will keep its OSR exit targets alive, but the CodeBlock object won't be
able to mark them for itself until compilation has completed (since it
won't have a JITCode object yet).

* dfg/DFGToFTLDeferredCompilationCallback.cpp:
(JSC::DFG::ToFTLDeferredCompilationCallback::compilationDidComplete):
Updated for interface change.

* jit/JITCode.h:
(JSC::JITCode::timeToLive): Provide a time to live for interpreter and
baseline code, so they will jettison when old. Use seconds in our
code so that we don't need comments. Make DFG 2X interpreter+baseline,
and FTL 2X DFG+interpreter+baseline, also matching the time we allot
before throwing away all code.

* jit/JITToDFGDeferredCompilationCallback.cpp:
(JSC::JITToDFGDeferredCompilationCallback::compilationDidComplete):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::jitCompileAndSetHeuristics): Updated for interface change.

* runtime/Executable.cpp:
(JSC::ScriptExecutable::installCode): Allow our caller to install nullptr,
since we need to do this when jettisoning a baseline CodeBlock. Require
our caller to specify the details of the installation because we can't
rely on a non-null CodeBlock in order to compute them.

(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::prepareForExecutionImpl):
* runtime/Executable.h:
(JSC::ScriptExecutable::recordParse): Updated for interface change.

* runtime/Options.h: Renamed the CodeBlock liveness option since it now
controls baseline and optimized code.

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

12 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp
Source/JavaScriptCore/dfg/DFGPlan.cpp
Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp
Source/JavaScriptCore/jit/JITCode.h
Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/Options.h

index 9082458..8966c68 100644 (file)
@@ -1,5 +1,92 @@
 2015-09-16  Geoffrey Garen  <ggaren@apple.com>
 
+        JavaScriptCore should discard baseline code after some time
+        https://bugs.webkit.org/show_bug.cgi?id=149220
+
+        Reviewed by Saam Barati.
+
+        This is a bit more complicated than discarding optimized code because
+        the engine previously assumed that we would never discard baseline code.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock): Record creation time (and compute time since
+        creation) instead of install time because CodeBlocks can be installed
+        more than once, and we don't want to have to worry about edge cases
+        created by CodeBlocks seeming to get younger.
+
+        (JSC::CodeBlock::visitAggregate): Be explicit about only doing the 
+        weak reference fixpoint for optimized CodeBlocks. We used to avoid the
+        fixpoint for baseline CodeBlocks implicitly, since they would always
+        visit themselves strongly right away. But now baseline CodeBlocks might
+        not visit themselves strongly, since they might choose to jettison due
+        to old age.
+
+        (JSC::CodeBlock::shouldVisitStrongly): Add old age as a reason not to
+        visit ourselves strongly, so that baseline CodeBlocks can jettison due
+        to old age.
+
+        (JSC::CodeBlock::shouldJettisonDueToWeakReference): Be explicit about
+        only jettisoning optimized CodeBlocks due to weak references so that we
+        don't confuse ourselves into thinking that we will jettison a baseline
+        CodeBlock due to weak references.
+
+        (JSC::CodeBlock::shouldJettisonDueToOldAge): Updated to use creation time.
+
+        (JSC::CodeBlock::visitOSRExitTargets): Clarify a comment and add an
+        ASSERT to help record some things I discovered while debugging.
+
+        (JSC::CodeBlock::jettison): Allow a baseline CodeBlock to jettison. Don't
+        assume that we have an alternative or a profiler.
+
+        (JSC::CodeBlock::install): Deleted.
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::releaseAlternative): Deleted.
+        (JSC::CodeBlock::setInstallTime): Deleted.
+        (JSC::CodeBlock::timeSinceInstall): Deleted.
+
+        * dfg/DFGOSRExitPreparation.cpp:
+        (JSC::DFG::prepareCodeOriginForOSRExit): Simplified the computation of
+        baseline CodeBlock.
+
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::checkLivenessAndVisitChildren): Be sure to strongly
+        visit our inline callframes because we assume that an optimized CodeBlock
+        will keep its OSR exit targets alive, but the CodeBlock object won't be
+        able to mark them for itself until compilation has completed (since it
+        won't have a JITCode object yet).
+
+        * dfg/DFGToFTLDeferredCompilationCallback.cpp:
+        (JSC::DFG::ToFTLDeferredCompilationCallback::compilationDidComplete):
+        Updated for interface change.
+
+        * jit/JITCode.h:
+        (JSC::JITCode::timeToLive): Provide a time to live for interpreter and
+        baseline code, so they will jettison when old. Use seconds in our
+        code so that we don't need comments. Make DFG 2X interpreter+baseline,
+        and FTL 2X DFG+interpreter+baseline, also matching the time we allot
+        before throwing away all code.
+
+        * jit/JITToDFGDeferredCompilationCallback.cpp:
+        (JSC::JITToDFGDeferredCompilationCallback::compilationDidComplete):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::jitCompileAndSetHeuristics): Updated for interface change.
+
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::installCode): Allow our caller to install nullptr,
+        since we need to do this when jettisoning a baseline CodeBlock. Require
+        our caller to specify the details of the installation because we can't
+        rely on a non-null CodeBlock in order to compute them.
+
+        (JSC::ScriptExecutable::newCodeBlockFor):
+        (JSC::ScriptExecutable::prepareForExecutionImpl):
+        * runtime/Executable.h:
+        (JSC::ScriptExecutable::recordParse): Updated for interface change.
+
+        * runtime/Options.h: Renamed the CodeBlock liveness option since it now
+        controls baseline and optimized code.
+
+2015-09-16  Geoffrey Garen  <ggaren@apple.com>
+
         Remove obsolete code for deleting CodeBlocks
         https://bugs.webkit.org/show_bug.cgi?id=149231
 
index 788c799..56676db 100644 (file)
@@ -1617,6 +1617,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
     , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
     , m_reoptimizationRetryCounter(0)
+    , m_creationTime(std::chrono::steady_clock::now())
     , m_hash(other.m_hash)
 #if ENABLE(JIT)
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
@@ -1672,6 +1673,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
     , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
     , m_reoptimizationRetryCounter(0)
+    , m_creationTime(std::chrono::steady_clock::now())
 #if ENABLE(JIT)
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
 #endif
@@ -2150,6 +2152,7 @@ CodeBlock::CodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObj
     , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
     , m_reoptimizationRetryCounter(0)
+    , m_creationTime(std::chrono::steady_clock::now())
 #if ENABLE(JIT)
     , m_capabilityLevelState(DFG::CannotCompile)
 #endif
@@ -2272,6 +2275,9 @@ void CodeBlock::visitAggregate(SlotVisitor& visitor)
         return;
     }
     
+    if (!JITCode::isOptimizingJIT(jitType()))
+        return;
+
     // There are two things that we use weak reference harvesters for: DFG fixpoint for
     // jettisoning, and trying to find structures that would be live based on some
     // inline cache. So it makes sense to register them regardless.
@@ -2291,27 +2297,24 @@ void CodeBlock::visitAggregate(SlotVisitor& visitor)
     
     propagateTransitions(visitor);
     determineLiveness(visitor);
-#else // ENABLE(DFG_JIT)
-    RELEASE_ASSERT_NOT_REACHED();
 #endif // ENABLE(DFG_JIT)
 }
 
 bool CodeBlock::shouldVisitStrongly()
 {
-#if ENABLE(DFG_JIT)
+    if (Options::forceCodeBlockLiveness())
+        return true;
+
+    if (shouldJettisonDueToOldAge())
+        return false;
+
     // Interpreter and Baseline JIT CodeBlocks don't need to be jettisoned when
     // their weak references go stale. So if a basline JIT CodeBlock gets
     // scanned, we can assume that this means that it's live.
     if (!JITCode::isOptimizingJIT(jitType()))
         return true;
 
-    if (Options::forceDFGCodeBlockLiveness())
-        return true;
-
     return false;
-#else
-    return true;
-#endif
 }
 
 bool CodeBlock::isKnownToBeLiveDuringGC()
@@ -2339,6 +2342,8 @@ bool CodeBlock::isKnownToBeLiveDuringGC()
 
 bool CodeBlock::shouldJettisonDueToWeakReference()
 {
+    if (!JITCode::isOptimizingJIT(jitType()))
+        return false;
     return !isKnownToBeLiveDuringGC();
 }
 
@@ -2347,10 +2352,7 @@ bool CodeBlock::shouldJettisonDueToOldAge()
     if (m_visitStronglyHasBeenCalled.load(std::memory_order_relaxed))
         return false;
 
-    if (!JITCode::isOptimizingJIT(jitType()))
-        return false;
-
-    if (timeSinceInstall() < JITCode::timeToLive(jitType()))
+    if (timeSinceCreation() < JITCode::timeToLive(jitType()))
         return false;
 
     return true;
@@ -2739,17 +2741,20 @@ CallLinkInfo* CodeBlock::getCallLinkInfoForBytecodeIndex(unsigned index)
 
 void CodeBlock::visitOSRExitTargets(SlotVisitor& visitor)
 {
-    // OSR exits, once compiled, link themselves directly to their targets.
-    // We need to keep those targets alive in order to keep OSR exit from
-    // jumping to an invalid destination.
+    // We strongly visit OSR exits targets because we don't want to deal with
+    // the complexity of generating an exit target CodeBlock on demand and
+    // guaranteeing that it matches the details of the CodeBlock we compiled
+    // the OSR exit against.
 
     alternative()->visitStrongly(visitor);
 
 #if ENABLE(DFG_JIT)
     DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
     if (dfgCommon->inlineCallFrames) {
-        for (auto* inlineCallFrame : *dfgCommon->inlineCallFrames)
+        for (auto* inlineCallFrame : *dfgCommon->inlineCallFrames) {
+            ASSERT(inlineCallFrame->baselineCodeBlock());
             inlineCallFrame->baselineCodeBlock()->visitStrongly(visitor);
+        }
     }
 #endif
 }
@@ -2967,11 +2972,6 @@ void CodeBlock::linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo* inco
     m_incomingLLIntCalls.push(incoming);
 }
 
-void CodeBlock::install()
-{
-    ownerScriptExecutable()->installCode(this);
-}
-
 PassRefPtr<CodeBlock> CodeBlock::newReplacement()
 {
     return ownerScriptExecutable()->newReplacementCodeBlockFor(specializationKind());
@@ -3035,6 +3035,11 @@ DFG::CapabilityLevel WebAssemblyCodeBlock::capabilityLevelInternal()
 
 void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
 {
+#if !ENABLE(DFG_JIT)
+    UNUSED_PARAM(mode);
+    UNUSED_PARAM(detail);
+#endif
+
     RELEASE_ASSERT(reason != Profiler::NotJettisoned);
     
 #if ENABLE(DFG_JIT)
@@ -3069,19 +3074,20 @@ void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mod
             }
         }
     }
+#endif // ENABLE(DFG_JIT)
 
     DeferGCForAWhile deferGC(*m_heap);
-    RELEASE_ASSERT(JITCode::isOptimizingJIT(jitType()));
-    
-    if (Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get())
-        compilation->setJettisonReason(reason, detail);
     
     // We want to accomplish two things here:
     // 1) Make sure that if this CodeBlock is on the stack right now, then if we return to it
     //    we should OSR exit at the top of the next bytecode instruction after the return.
     // 2) Make sure that if we call the owner executable, then we shouldn't call this CodeBlock.
 
+#if ENABLE(DFG_JIT)
     if (reason != Profiler::JettisonDueToOldAge) {
+        if (Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get())
+            compilation->setJettisonReason(reason, detail);
+        
         // This accomplishes (1), and does its own book-keeping about whether it has already happened.
         if (!jitCode()->dfgCommon()->invalidate()) {
             // We've already been invalidated.
@@ -3102,24 +3108,26 @@ void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mod
             dataLog("    Did count reoptimization for ", *this, "\n");
     }
     
-    // This accomplishes (2).
     if (this != replacement()) {
         // This means that we were never the entrypoint. This can happen for OSR entry code
         // blocks.
         return;
     }
-    alternative()->optimizeAfterWarmUp();
+
+    if (alternative())
+        alternative()->optimizeAfterWarmUp();
 
     if (reason != Profiler::JettisonDueToOldAge)
         tallyFrequentExitSites();
+#endif // ENABLE(DFG_JIT)
+
+    // This accomplishes (2).
+    ownerScriptExecutable()->installCode(
+        m_globalObject->vm(), alternative(), codeType(), specializationKind());
 
-    alternative()->install();
+#if ENABLE(DFG_JIT)
     if (DFG::shouldShowDisassembly())
         dataLog("    Did install baseline version of ", *this, "\n");
-#else // ENABLE(DFG_JIT)
-    UNUSED_PARAM(mode);
-    UNUSED_PARAM(detail);
-    UNREACHABLE_FOR_PLATFORM();
 #endif // ENABLE(DFG_JIT)
 }
 
index 53d234f..2310bb5 100644 (file)
@@ -126,7 +126,6 @@ public:
     static ptrdiff_t offsetOfNumParameters() { return OBJECT_OFFSETOF(CodeBlock, m_numParameters); }
 
     CodeBlock* alternative() { return m_alternative.get(); }
-    PassRefPtr<CodeBlock> releaseAlternative() { return m_alternative.release(); }
     void setAlternative(PassRefPtr<CodeBlock> alternative) { m_alternative = alternative; }
 
     template <typename Functor> void forEachRelatedCodeBlock(Functor&& functor)
@@ -265,9 +264,6 @@ public:
 
     unsigned instructionCount() const { return m_instructions.size(); }
 
-    // Exactly equivalent to codeBlock->ownerExecutable()->installCode(codeBlock);
-    void install();
-    
     // Exactly equivalent to codeBlock->ownerExecutable()->newReplacementCodeBlockFor(codeBlock->specializationKind())
     PassRefPtr<CodeBlock> newReplacement();
     
@@ -834,8 +830,6 @@ public:
     void updateAllArrayPredictions();
     void updateAllPredictions();
 
-    void setInstallTime(std::chrono::steady_clock::time_point installTime) { m_installTime = installTime; }
-
     unsigned frameRegisterCount();
     int stackPointerOffset();
 
@@ -989,10 +983,10 @@ private:
     void stronglyVisitWeakReferences(SlotVisitor&);
     void visitOSRExitTargets(SlotVisitor&);
 
-    std::chrono::milliseconds timeSinceInstall()
+    std::chrono::milliseconds timeSinceCreation()
     {
         return std::chrono::duration_cast<std::chrono::milliseconds>(
-            std::chrono::steady_clock::now() - m_installTime);
+            std::chrono::steady_clock::now() - m_creationTime);
     }
 
     void createRareDataIfNecessary()
@@ -1077,7 +1071,7 @@ private:
     uint16_t m_optimizationDelayCounter;
     uint16_t m_reoptimizationRetryCounter;
 
-    std::chrono::steady_clock::time_point m_installTime;
+    std::chrono::steady_clock::time_point m_creationTime;
 
     mutable CodeBlockHash m_hash;
 
index 51d6e5a..60bc7fb 100644 (file)
@@ -42,16 +42,13 @@ void prepareCodeOriginForOSRExit(ExecState* exec, CodeOrigin codeOrigin)
     DeferGC deferGC(vm.heap);
     
     for (; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
-        FunctionExecutable* executable =
-            static_cast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get());
-        CodeBlock* codeBlock = executable->baselineCodeBlockFor(
-            codeOrigin.inlineCallFrame->specializationKind());
-        
+        CodeBlock* codeBlock = codeOrigin.inlineCallFrame->baselineCodeBlock();
         if (codeBlock->jitType() == JSC::JITCode::BaselineJIT)
             continue;
+
         ASSERT(codeBlock->jitType() == JSC::JITCode::InterpreterThunk);
         JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);
-        codeBlock->install();
+        codeBlock->ownerScriptExecutable()->installCode(codeBlock);
     }
 }
 
index ab14b5a..ec1ff46 100644 (file)
@@ -626,6 +626,13 @@ void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor)
     if (profiledDFGCodeBlock)
         profiledDFGCodeBlock->visitStrongly(visitor);
 
+    if (inlineCallFrames) {
+        for (auto* inlineCallFrame : *inlineCallFrames) {
+            ASSERT(inlineCallFrame->baselineCodeBlock());
+            inlineCallFrame->baselineCodeBlock()->visitStrongly(visitor);
+        }
+    }
+
     weakReferences.visitChildren(visitor);
     transitions.visitChildren(visitor);
 }
index dd8108a..faebdd0 100644 (file)
@@ -80,7 +80,7 @@ void ToFTLDeferredCompilationCallback::compilationDidComplete(
     }
     
     if (result == CompilationSuccessful)
-        codeBlock->install();
+        codeBlock->ownerScriptExecutable()->installCode(codeBlock);
     
     m_dfgCodeBlock->jitCode()->dfg()->setOptimizationThresholdBasedOnCompilationResult(
         m_dfgCodeBlock.get(), result);
index 923a632..7273fe3 100644 (file)
@@ -125,10 +125,20 @@ public:
     static std::chrono::milliseconds timeToLive(JITType jitType)
     {
         switch (jitType) {
+        case InterpreterThunk:
+            return std::chrono::duration_cast<std::chrono::milliseconds>(
+                std::chrono::seconds(5));
+        case BaselineJIT:
+            // Effectively 10 additional seconds, since BaselineJIT and
+            // InterpreterThunk share a CodeBlock.
+            return std::chrono::duration_cast<std::chrono::milliseconds>(
+                std::chrono::seconds(15));
         case DFGJIT:
-            return std::chrono::milliseconds(10000); // 10s
+            return std::chrono::duration_cast<std::chrono::milliseconds>(
+                std::chrono::seconds(20));
         case FTLJIT:
-            return std::chrono::milliseconds(100000); // 100s
+            return std::chrono::duration_cast<std::chrono::milliseconds>(
+                std::chrono::seconds(60));
         default:
             return std::chrono::milliseconds::max();
         }
index f7f0ab9..b42464f 100644 (file)
@@ -62,7 +62,7 @@ void JITToDFGDeferredCompilationCallback::compilationDidComplete(
         dataLog("Optimizing compilation of ", *codeBlock, " result: ", result, "\n");
     
     if (result == CompilationSuccessful)
-        codeBlock->install();
+        codeBlock->ownerScriptExecutable()->installCode(codeBlock);
     
     codeBlock->alternative()->setOptimizationThresholdBasedOnCompilationResult(result);
 
index 445dd5c..bb13f74 100644 (file)
@@ -324,7 +324,7 @@ inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec)
         case CompilationSuccessful:
             if (Options::verboseOSR())
                 dataLogF("    JIT compilation successful.\n");
-            codeBlock->install();
+            codeBlock->ownerScriptExecutable()->installCode(codeBlock);
             codeBlock->jitSoon();
             return true;
         default:
index a862eea..f299996 100644 (file)
@@ -116,41 +116,18 @@ void ScriptExecutable::destroy(JSCell* cell)
     static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
 }
 
-void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
+void ScriptExecutable::installCode(CodeBlock* codeBlock)
+{
+    installCode(*codeBlock->vm(), codeBlock, codeBlock->codeType(), codeBlock->specializationKind());
+}
+
+void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType codeType, CodeSpecializationKind kind)
 {
-    RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
-    RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
-    
-    if (Options::verboseOSR())
-        dataLog("Installing ", *genericCodeBlock, "\n");
-    
-    VM& vm = *genericCodeBlock->vm();
-    
-    if (vm.m_perBytecodeProfiler)
-        vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
-    
     ASSERT(vm.heap.isDeferred());
     
-    CodeSpecializationKind kind = genericCodeBlock->specializationKind();
-    
     RefPtr<CodeBlock> oldCodeBlock;
     
-    switch (kind) {
-    case CodeForCall:
-        m_jitCodeForCall = genericCodeBlock->jitCode();
-        m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
-        m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
-        m_numParametersForCall = genericCodeBlock->numParameters();
-        break;
-    case CodeForConstruct:
-        m_jitCodeForConstruct = genericCodeBlock->jitCode();
-        m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
-        m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
-        m_numParametersForConstruct = genericCodeBlock->numParameters();
-        break;
-    }
-    
-    switch (genericCodeBlock->codeType()) {
+    switch (codeType) {
     case GlobalCode: {
         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
         ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
@@ -199,18 +176,42 @@ void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
             break;
         }
         break;
-    } }
+    }
+    }
+
+    switch (kind) {
+    case CodeForCall:
+        m_jitCodeForCall = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;
+        m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
+        m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
+        m_numParametersForCall = genericCodeBlock ? genericCodeBlock->numParameters() : NUM_PARAMETERS_NOT_COMPILED;
+        break;
+    case CodeForConstruct:
+        m_jitCodeForConstruct = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;
+        m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
+        m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
+        m_numParametersForConstruct = genericCodeBlock ? genericCodeBlock->numParameters() : NUM_PARAMETERS_NOT_COMPILED;
+        break;
+    }
+
+    if (genericCodeBlock) {
+        RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
+        RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
+        
+        if (Options::verboseOSR())
+            dataLog("Installing ", *genericCodeBlock, "\n");
+        
+        if (vm.m_perBytecodeProfiler)
+            vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
+        
+        if (Debugger* debugger = genericCodeBlock->globalObject()->debugger())
+            debugger->registerCodeBlock(genericCodeBlock);
+    }
 
     if (oldCodeBlock)
         oldCodeBlock->unlinkIncomingCalls();
 
-    Debugger* debugger = genericCodeBlock->globalObject()->debugger();
-    if (debugger)
-        debugger->registerCodeBlock(genericCodeBlock);
-
-    genericCodeBlock->setInstallTime(std::chrono::steady_clock::now());
-
-    Heap::heap(this)->writeBarrier(this);
+    vm.heap.writeBarrier(this);
 }
 
 RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
@@ -367,7 +368,7 @@ JSObject* ScriptExecutable::prepareForExecutionImpl(
     else
         setupJIT(vm, codeBlock.get());
     
-    installCode(codeBlock.get());
+    installCode(*codeBlock->vm(), codeBlock.get(), codeBlock->codeType(), codeBlock->specializationKind());
     return 0;
 }
 
index 4221e81..ac64f6c 100644 (file)
@@ -420,6 +420,7 @@ public:
     }
 
     void installCode(CodeBlock*);
+    void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
     RefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
     PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
     
index 303eb9b..3ba65f0 100644 (file)
@@ -118,7 +118,7 @@ typedef const char* optionString;
     v(bool, crashIfCantAllocateJITMemory, false, nullptr) \
     v(unsigned, jitMemoryReservationSize, 0, nullptr) \
     \
-    v(bool, forceDFGCodeBlockLiveness, false, nullptr) \
+    v(bool, forceCodeBlockLiveness, false, nullptr) \
     v(bool, forceICFailure, false, nullptr) \
     \
     v(bool, dumpGeneratedBytecodes, false, nullptr) \