[JSC] When entering a CheckTierUp without OSREntry, force the CheckTierUp for the...
authorbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 May 2015 20:45:34 +0000 (20:45 +0000)
committerbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 May 2015 20:45:34 +0000 (20:45 +0000)
commit1a0ff636a7bff260f2ea2fe32cd55e229a1b16d9
tree95c5e777882e288abe953fd4b742578d2da095f8
parent771c08fb0b237e6b5f5303d9547037176a277230
[JSC] When entering a CheckTierUp without OSREntry, force the CheckTierUp for the outer loops with OSR Entry
https://bugs.webkit.org/show_bug.cgi?id=145092

Reviewed by Filip Pizlo.

When we have a hot loop without OSR Entry inside a slower loop that support OSR Entry,
we get the inside loop driving the tierUpCounter and we have very little chance of
doing a CheckTierUp on the outer loop. In turn, this give almost no opportunity to tier
up in the outer loop and OSR Enter there.

This patches changes CheckTierUp to force its outer loops to do a CheckTierUp themselves.

To do that, CheckTierUp sets a flag "nestedTriggerIsSet" to force the outer loop to
enter their CheckTierUp regardless of the tier-up counter.

* bytecode/ExecutionCounter.cpp:
(JSC::ExecutionCounter<countingVariant>::setThreshold):
This is somewhat unrelated. This assertion is incorrect because it relies on
m_counter, which changes on an other thread.

I have hit it a couple of times with this patch because we are a bit more aggressive
on CheckTierUp. What happens is:
1) ExecutionCounter<countingVariant>::checkIfThresholdCrossedAndSet() first checks
   hasCrossedThreshold(), and it is false.
2) On the main thread, the hot loops keeps running and the counter becomes large
   enough to cross the threshold.
3) ExecutionCounter<countingVariant>::checkIfThresholdCrossedAndSet() runs the next
   test, setThreshold(), where the assertion is. Since the counter is now large enough,
   the assertion fails.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):

* dfg/DFGJITCode.h:
I used a uint8_t instead of a boolean to make the code generation clearer
in DFGSpeculativeJIT64.

* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:

* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
This is a bit annoying: we have the NaturalLoops analysis that provides us
everything we need to know about loops, but the TierUpCheck are conservative
and set on LoopHint.

To make the two work together, we first find all the CheckTierUp that cannot
OSR enter and we keep a list of all the natural loops containing them.

Then we do a second pass over the LoopHints, get their NaturalLoop, and check
if it contains a loop that cannot OSR enter.

* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGTierUpCheckInjectionPhase.cpp:
(JSC::DFG::TierUpCheckInjectionPhase::run):
(JSC::DFG::TierUpCheckInjectionPhase::canOSREnterAtLoopHint):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@184511 268f45cc-cd09-0410-ab3c-d52691b4dbfc
15 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/ExecutionCounter.cpp
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGJITCode.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGOperations.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp