JavaScriptCore does not have baseline->speculative OSR
https://bugs.webkit.org/show_bug.cgi?id=67920
Reviewed by Oliver Hunt.
This adds the ability to on-stack-replace (OSR) from code that is
running hot in the old JIT to code compiled by the new JIT. This
ensures that long-running loops benefit from DFG optimization.
It also ensures that if code experiences a speculation failure
in DFG code, it has an opportunity to reenter the DFG once every
1,000 loop iterations or so.
This results in a 2.88x speed-up on Kraken/imaging-desaturate,
and is a pure win on the main three benchmark suites (SunSpider,
V8, Kraken), when tiered compilation is enabled.
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
(JSC::CodeBlock::CodeBlock):
(JSC::ProgramCodeBlock::compileOptimized):
(JSC::EvalCodeBlock::compileOptimized):
(JSC::FunctionCodeBlock::compileOptimized):
* bytecode/CodeBlock.h:
* bytecode/Opcode.h:
* bytecode/PredictedType.h: Added.
(JSC::isCellPrediction):
(JSC::isArrayPrediction):
(JSC::isInt32Prediction):
(JSC::isDoublePrediction):
(JSC::isNumberPrediction):
(JSC::isBooleanPrediction):
(JSC::isStrongPrediction):
(JSC::predictionToString):
(JSC::mergePredictions):
(JSC::mergePrediction):
(JSC::makePrediction):
* bytecode/PredictionTracker.h: Added.
(JSC::operandIsArgument):
(JSC::PredictionSlot::PredictionSlot):
(JSC::PredictionTracker::PredictionTracker):
(JSC::PredictionTracker::initializeSimilarTo):
(JSC::PredictionTracker::copyLocalsFrom):
(JSC::PredictionTracker::numberOfArguments):
(JSC::PredictionTracker::numberOfVariables):
(JSC::PredictionTracker::argumentIndexForOperand):
(JSC::PredictionTracker::predictArgument):
(JSC::PredictionTracker::predict):
(JSC::PredictionTracker::predictGlobalVar):
(JSC::PredictionTracker::getArgumentPrediction):
(JSC::PredictionTracker::getPrediction):
(JSC::PredictionTracker::getGlobalVarPrediction):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitLoopHint):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::DoWhileNode::emitBytecode):
(JSC::WhileNode::emitBytecode):
(JSC::ForNode::emitBytecode):
(JSC::ForInNode::emitBytecode):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.h:
(JSC::DFG::canCompileOpcode):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGGraph.h:
(JSC::DFG::BasicBlock::BasicBlock):
(JSC::DFG::Graph::predict):
(JSC::DFG::Graph::getPrediction):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::exitSpeculativeWithOSR):
(JSC::DFG::JITCompiler::compileEntry):
(JSC::DFG::JITCompiler::compileBody):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::noticeOSREntry):
* dfg/DFGNode.h:
* dfg/DFGOSREntry.cpp: Added.
(JSC::DFG::predictionIsValid):
(JSC::DFG::prepareOSREntry):
* dfg/DFGOSREntry.h: Added.
(JSC::DFG::prepareOSREntry):
* dfg/DFGPredictionTracker.h: Removed.
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::mergeUse):
(JSC::DFG::Propagator::mergePrediction):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/CompactJITCodeMap.h:
(JSC::CompactJITCodeMap::numberOfEntries):
(JSC::CompactJITCodeMap::decode):
(JSC::CompactJITCodeMap::Decoder::Decoder):
(JSC::CompactJITCodeMap::Decoder::numberOfEntriesRemaining):
(JSC::CompactJITCodeMap::Decoder::read):
* jit/JIT.cpp:
(JSC::JIT::emitOptimizationCheck):
(JSC::JIT::emitTimeoutCheck):
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
(JSC::JIT::emit_op_loop_hint):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* runtime/Executable.cpp:
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::compileForCallInternal):
(JSC::FunctionExecutable::compileForConstructInternal):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95016 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 20dbe58..b6d5a1d 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1076,6 +1076,10 @@
printf("[%4d] loop_if_greatereq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
break;
}
+ case op_loop_hint: {
+ printf("[%4d] loop_hint\n", location);
+ break;
+ }
case op_switch_imm: {
int tableIndex = (++it)->u.operand;
int defaultTarget = (++it)->u.operand;
@@ -1405,7 +1409,6 @@
CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor, PassOwnPtr<CodeBlock> alternative)
: m_globalObject(globalObject->globalData(), ownerExecutable, globalObject)
, m_heap(&m_globalObject->globalData().heap)
- , m_executeCounter(-1000) // trigger optimization when sign bit clears
, m_numCalleeRegisters(0)
, m_numVars(0)
, m_numParameters(0)
@@ -1427,6 +1430,8 @@
, m_alternative(alternative)
{
ASSERT(m_source);
+
+ optimizeAfterWarmUp();
#if DUMP_CODE_BLOCK_STATISTICS
liveCodeBlockSet.add(this);
@@ -1901,33 +1906,24 @@
JSObject* ProgramCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
{
- if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType())) {
- // No OSR yet, so make sure we don't hit this again anytime soon.
- dontOptimizeAnytimeSoon();
+ if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
return 0;
- }
JSObject* error = static_cast<ProgramExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode);
return error;
}
JSObject* EvalCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
{
- if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType())) {
- // No OSR yet, so make sure we don't hit this again anytime soon.
- dontOptimizeAnytimeSoon();
+ if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
return 0;
- }
JSObject* error = static_cast<EvalExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode);
return error;
}
JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
{
- if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType())) {
- // No OSR yet, so make sure we don't hit this again anytime soon.
- dontOptimizeAnytimeSoon();
+ if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
return 0;
- }
JSObject* error = static_cast<FunctionExecutable*>(ownerExecutable())->compileOptimizedFor(exec, scopeChainNode, m_isConstructor ? CodeForConstruct : CodeForCall);
return error;
}