JavaScriptCore does not have speculative->baseline OSR
https://bugs.webkit.org/show_bug.cgi?id=67826
Reviewed by Oliver Hunt.
This adds the ability to bail out of DFG speculative JIT execution by
performing an on-stack replacement (OSR) that results in the control
flow going to the equivalent code generated by the old JIT.
This required a number of new features, as well as taking advantage of
some features that happened to already be present:
We already had a policy of storing the bytecode index for which a DFG
node was generated inside the DFG::Node class. This was previously
called exceptionInfo. It's now renamed to codeOrigin to reflect that
it's used for more than just excpetions. OSR uses this to figure out
which bytecode index to use to look up the machine code location in
the code generated by the old JIT that we should be jumping to.
CodeBlock now stores a mapping between bytecode indices and machine
code offsets for code generated by the old JIT. This is implemented
by CompactJITCodeMap, which tries to compress this data a bit. The
OSR compiler decodes this and uses it to find the machine code
locations it should be jumping to.
We already had a mechanism that emitted SetLocal nodes in the DFG graph
that told us the time at which the old JIT would have stored something
into its register file, and the DFG::Node that corresponds to the value
that it would have stored. These SetLocal's were mostly dead-code-
eliminated, but our DCE leaves the nodes intact except for making them
have 0 as the ref count. This allows the OSR compiler to construct a
mapping between the state as it would have been seen by the old JIT
and the state as the DFG JIT sees it. The OSR compiler uses this to
generate code that reshapes the call frame so that it is like what the
old JIT would expect.
Finally, when DFG_OSR is enabled (the default for TIERED_COMPILATION)
we no longer emit the non-speculative path.
- JavaScriptCore.xcodeproj/project.pbxproj:
- bytecode/CodeBlock.h:
- dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::currentCodeOrigin):
(JSC::DFG::ByteCodeParser::addToGraph):
- dfg/DFGGPRInfo.h:
- dfg/DFGGenerationInfo.h:
(JSC::DFG::GenerationInfo::alive):
(JSC::DFG::Graph::dump):
- dfg/DFGJITCodeGenerator.cpp:
(JSC::DFG::JITCodeGenerator::emitCall):
- dfg/DFGJITCodeGenerator.h:
(JSC::DFG::JITCodeGenerator::appendCallWithExceptionCheck):
(JSC::DFG::JITCompiler::exitSpeculativeWithOSR):
(JSC::DFG::JITCompiler::linkOSRExits):
(JSC::DFG::JITCompiler::compileBody):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::CallRecord::CallRecord):
(JSC::DFG::JITCompiler::notifyCall):
(JSC::DFG::JITCompiler::appendCallWithExceptionCheck):
(JSC::DFG::JITCompiler::appendCallWithFastExceptionCheck):
(JSC::DFG::JITCompiler::addJSCall):
(JSC::DFG::JITCompiler::JSCallRecord::JSCallRecord):
(JSC::DFG::CodeOrigin::CodeOrigin):
(JSC::DFG::CodeOrigin::isSet):
(JSC::DFG::CodeOrigin::bytecodeIndex):
(JSC::DFG::Node::Node):
(JSC::DFG::Node::child1Unchecked):
- dfg/DFGNonSpeculativeJIT.cpp:
(JSC::DFG::NonSpeculativeJIT::compile):
- dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::ValueSource::dump):
(JSC::DFG::ValueRecovery::dump):
(JSC::DFG::OSRExit::OSRExit):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileMovHint):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
(JSC::DFG::ValueSource::ValueSource):
(JSC::DFG::ValueSource::isSet):
(JSC::DFG::ValueSource::nodeIndex):
(JSC::DFG::ValueRecovery::ValueRecovery):
(JSC::DFG::ValueRecovery::alreadyInRegisterFile):
(JSC::DFG::ValueRecovery::inGPR):
(JSC::DFG::ValueRecovery::inFPR):
(JSC::DFG::ValueRecovery::displacedInRegisterFile):
(JSC::DFG::ValueRecovery::constant):
(JSC::DFG::ValueRecovery::technique):
(JSC::DFG::ValueRecovery::gpr):
(JSC::DFG::ValueRecovery::fpr):
(JSC::DFG::ValueRecovery::virtualRegister):
(JSC::DFG::OSRExit::numberOfRecoveries):
(JSC::DFG::OSRExit::valueRecovery):
(JSC::DFG::OSRExit::isArgument):
(JSC::DFG::OSRExit::argumentForIndex):
(JSC::DFG::OSRExit::variableForIndex):
(JSC::DFG::OSRExit::operandForIndex):
(JSC::DFG::SpeculativeJIT::osrExits):
(JSC::DFG::SpeculativeJIT::speculationCheck):
(JSC::DFG::SpeculativeJIT::valueSourceForOperand):
(JSC::DFG::SpeculativeJIT::setNodeIndexForOperand):
(JSC::DFG::SpeculativeJIT::valueSourceReferenceForOperand):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
(JSC::DFG::SpeculationCheckIndexIterator::SpeculationCheckIndexIterator):
(JSC::DFG::SpeculativeJIT::SpeculativeJIT):
- jit/CompactJITCodeMap.h: Added.
(JSC::BytecodeAndMachineOffset::BytecodeAndMachineOffset):
(JSC::BytecodeAndMachineOffset::getBytecodeIndex):
(JSC::BytecodeAndMachineOffset::getMachineCodeOffset):
(JSC::CompactJITCodeMap::~CompactJITCodeMap):
(JSC::CompactJITCodeMap::decode):
(JSC::CompactJITCodeMap::CompactJITCodeMap):
(JSC::CompactJITCodeMap::at):
(JSC::CompactJITCodeMap::decodeNumber):
(JSC::CompactJITCodeMap::Encoder::Encoder):
(JSC::CompactJITCodeMap::Encoder::~Encoder):
(JSC::CompactJITCodeMap::Encoder::append):
(JSC::CompactJITCodeMap::Encoder::finish):
(JSC::CompactJITCodeMap::Encoder::appendByte):
(JSC::CompactJITCodeMap::Encoder::encodeNumber):
(JSC::CompactJITCodeMap::Encoder::ensureCapacityFor):
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompile):
- jit/JIT.h:
- runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::~JSGlobalData):
(JSC::JSGlobalData::osrScratchBufferForSize):
(JSC::JSValue::description):