-
fpizlo@apple.com authored
https://bugs.webkit.org/show_bug.cgi?id=112838 Source/JavaScriptCore: Reviewed by Mark Hahnenberg. This adds the ability for the DFG to tier-up into the FTL. This works in both of the expected tier-up modes: Replacement: frequently called functions eventually have their entrypoint replaced with one that goes into FTL-compiled code. Note, this will be a slow-down for now since we don't yet have LLVM calling convention integration. OSR entry: code stuck in hot loops gets OSR'd into the FTL from the DFG. This means that if the DFG detects that a function is an FTL candidate, it inserts execution counting code similar to the kind that the baseline JIT would use. If you trip on a loop count in a loop header that is an OSR candidate (it's not an inlined loop), we do OSR; otherwise we do replacement. OSR almost always also implies future replacement. OSR entry into the FTL is really cool. It uses a specialized FTL compile of the code, where early in the DFG pipeline we replace the original root block with an OSR entrypoint block that jumps to the pre-header of the hot loop. The OSR entrypoint loads all live state at the loop pre-header using loads from a scratch buffer, which gets populated by the runtime's OSR entry preparation code (FTL::prepareOSREntry()). This approach appears to work well with all of our subsequent optimizations, including prediction propagation, CFA, and LICM. LLVM seems happy with it, too. Best of all, it works naturally with concurrent compilation: when we hit the tier-up trigger we spawn a compilation plan at the bytecode index from which we triggered; once the compilation finishes the next trigger will try to enter, at that bytecode index. If it can't - for example because the code has moved on to another loop - then we just try again. Loops that get hot enough for OSR entry (about 25,000 iterations) will probably still be running when a concurrent compile finishes, so this doesn't appear to be a big problem. This immediately gives us a 70% speed-up on imaging-gaussian-blur. We could get a bigger speed-up by adding some more intelligence and tweaking LLVM to compile code faster. Those things will happen eventually but this is a good start. Probably this code will see more tuning as we get more coverage in the FTL JIT, but I'll worry about that in future patches. * CMakeLists.txt: * GNUmakefile.list.am: * JavaScriptCore.xcodeproj/project.pbxproj: * Target.pri: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::CodeBlock): (JSC::CodeBlock::hasOptimizedReplacement): (JSC::CodeBlock::setOptimizationThresholdBasedOnCompilationResult): * bytecode/CodeBlock.h: * dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::::executeEffects): * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::parseBlock): (JSC::DFG::ByteCodeParser::parse): * dfg/DFGCFGSimplificationPhase.cpp: (JSC::DFG::CFGSimplificationPhase::run): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGDriver.cpp: (JSC::DFG::compileImpl): (JSC::DFG::compile): * dfg/DFGDriver.h: * dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupNode): * dfg/DFGGraph.cpp: (JSC::DFG::Graph::dump): (JSC::DFG::Graph::killBlockAndItsContents): (JSC::DFG::Graph::killUnreachableBlocks): * dfg/DFGGraph.h: * dfg/DFGInPlaceAbstractState.cpp: (JSC::DFG::InPlaceAbstractState::initialize): * dfg/DFGJITCode.cpp: (JSC::DFG::JITCode::reconstruct): (JSC::DFG::JITCode::checkIfOptimizationThresholdReached): (JSC::DFG::JITCode::optimizeNextInvocation): (JSC::DFG::JITCode::dontOptimizeAnytimeSoon): (JSC::DFG::JITCode::optimizeAfterWarmUp): (JSC::DFG::JITCode::optimizeSoon): (JSC::DFG::JITCode::forceOptimizationSlowPathConcurrently): (JSC::DFG::JITCode::setOptimizationThresholdBasedOnCompilationResult): * dfg/DFGJITCode.h: * dfg/DFGJITFinalizer.cpp: (JSC::DFG::JITFinalizer::finalize): (JSC::DFG::JITFinalizer::finalizeFunction): (JSC::DFG::JITFinalizer::finalizeCommon): * dfg/DFGLoopPreHeaderCreationPhase.cpp: (JSC::DFG::createPreHeader): (JSC::DFG::LoopPreHeaderCreationPhase::run): * dfg/DFGLoopPreHeaderCreationPhase.h: * dfg/DFGNode.h: (JSC::DFG::Node::hasUnlinkedLocal): (JSC::DFG::Node::unlinkedLocal): * dfg/DFGNodeType.h: * dfg/DFGOSREntry.cpp: (JSC::DFG::prepareOSREntry): * dfg/DFGOSREntrypointCreationPhase.cpp: Added. (JSC::DFG::OSREntrypointCreationPhase::OSREntrypointCreationPhase): (JSC::DFG::OSREntrypointCreationPhase::run): (JSC::DFG::performOSREntrypointCreation): * dfg/DFGOSREntrypointCreationPhase.h: Added. * dfg/DFGOperations.cpp: * dfg/DFGOperations.h: * dfg/DFGPlan.cpp: (JSC::DFG::Plan::Plan): (JSC::DFG::Plan::compileInThread): (JSC::DFG::Plan::compileInThreadImpl): * dfg/DFGPlan.h: * dfg/DFGPredictionInjectionPhase.cpp: (JSC::DFG::PredictionInjectionPhase::run): * dfg/DFGPredictionPropagationPhase.cpp: (JSC::DFG::PredictionPropagationPhase::propagate): * dfg/DFGSafeToExecute.h: (JSC::DFG::safeToExecute): * dfg/DFGSpeculativeJIT32_64.cpp: (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGTierUpCheckInjectionPhase.cpp: Added. (JSC::DFG::TierUpCheckInjectionPhase::TierUpCheckInjectionPhase): (JSC::DFG::TierUpCheckInjectionPhase::run): (JSC::DFG::performTierUpCheckInjection): * dfg/DFGTierUpCheckInjectionPhase.h: Added. * dfg/DFGToFTLDeferredCompilationCallback.cpp: Added. (JSC::DFG::ToFTLDeferredCompilationCallback::ToFTLDeferredCompilationCallback): (JSC::DFG::ToFTLDeferredCompilationCallback::~ToFTLDeferredCompilationCallback): (JSC::DFG::ToFTLDeferredCompilationCallback::create): (JSC::DFG::ToFTLDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously): (JSC::DFG::ToFTLDeferredCompilationCallback::compilationDidComplete): * dfg/DFGToFTLDeferredCompilationCallback.h: Added. * dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp: Added. (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback): (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::~ToFTLForOSREntryDeferredCompilationCallback): (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::create): (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously): (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete): * dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h: Added. * dfg/DFGWorklist.cpp: (JSC::DFG::globalWorklist): * dfg/DFGWorklist.h: * ftl/FTLCapabilities.cpp: (JSC::FTL::canCompile): * ftl/FTLCapabilities.h: * ftl/FTLForOSREntryJITCode.cpp: Added. (JSC::FTL::ForOSREntryJITCode::ForOSREntryJITCode): (JSC::FTL::ForOSREntryJITCode::~ForOSREntryJITCode): (JSC::FTL::ForOSREntryJITCode::ftlForOSREntry): (JSC::FTL::ForOSREntryJITCode::initializeEntryBuffer): * ftl/FTLForOSREntryJITCode.h: Added. (JSC::FTL::ForOSREntryJITCode::entryBuffer): (JSC::FTL::ForOSREntryJITCode::setBytecodeIndex): (JSC::FTL::ForOSREntryJITCode::bytecodeIndex): (JSC::FTL::ForOSREntryJITCode::countEntryFailure): (JSC::FTL::ForOSREntryJITCode::entryFailureCount): * ftl/FTLJITFinalizer.cpp: (JSC::FTL::JITFinalizer::finalizeFunction): * ftl/FTLLink.cpp: (JSC::FTL::link): * ftl/FTLLowerDFGToLLVM.cpp: (JSC::FTL::LowerDFGToLLVM::compileBlock): (JSC::FTL::LowerDFGToLLVM::compileNode): (JSC::FTL::LowerDFGToLLVM::compileExtractOSREntryLocal): (JSC::FTL::LowerDFGToLLVM::compileGetLocal): (JSC::FTL::LowerDFGToLLVM::addWeakReference): * ftl/FTLOSREntry.cpp: Added. (JSC::FTL::prepareOSREntry): * ftl/FTLOSREntry.h: Added. * ftl/FTLOutput.h: (JSC::FTL::Output::crashNonTerminal): (JSC::FTL::Output::crash): * ftl/FTLState.cpp: (JSC::FTL::State::State): * interpreter/Register.h: (JSC::Register::unboxedDouble): * jit/JIT.cpp: (JSC::JIT::emitEnterOptimizationCheck): * jit/JITCode.cpp: (JSC::JITCode::ftlForOSREntry): * jit/JITCode.h: * jit/JITStubs.cpp: (JSC::DEFINE_STUB_FUNCTION): * runtime/Executable.cpp: (JSC::ScriptExecutable::newReplacementCodeBlockFor): * runtime/Options.h: * runtime/VM.cpp: (JSC::VM::ensureWorklist): * runtime/VM.h: LayoutTests: Reviewed by Mark Hahnenberg. Fix marsaglia to check the result instead of printing, and add a second version that relies on OSR entry. * fast/js/regress/marsaglia-osr-entry-expected.txt: Added. * fast/js/regress/marsaglia-osr-entry.html: Added. * fast/js/regress/script-tests/marsaglia-osr-entry.js: Added. (marsaglia): * fast/js/regress/script-tests/marsaglia.js: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@155023 268f45cc-cd09-0410-ab3c-d52691b4dbfc
532f1e51