-
oliver@apple.com authored
fourthTier: add heuristics to reduce the likelihood of a trivially inlineable function being independently compiled by the concurrent JIT https://bugs.webkit.org/show_bug.cgi?id=116557 Reviewed by Geoffrey Garen. This introduces a fairly comprehensive mechanism for preventing trivially inlineable functions from being compiled independently of all of the things into which they end up being inlined. The trick is CodeBlock::m_shouldAlwaysBeInlined, or SABI for short (that's what the debug logging calls it). A SABI function is one that we currently believe should never be DFG optimized because it should always be inlined into the functions that call it. SABI follows "innocent until proven guilty": all functions start out SABI and have SABI set to false if we see proof that that function may be called in some possibly non-inlineable way. So long as a function is SABI, it will not tier up to the DFG: cti_optimize will perpetually postpone its optimization. Because SABI has such a severe effect, we make the burden of proof of guilt quite low. SABI gets cleared if any of the following happen: - You get called from native code (either through CallData or CachedCall). - You get called from an eval, since eval code takes a long time to get DFG optimized. - You get called from global code, since often global code doesn't tier-up since it's run-once. - You get called recursively, where recursion is detected by a stack walk of depth Options::maximumInliningDepth(). - You get called through an unlinked virtual call. - You get called from DFG code, since if the caller was already DFG optimized and didn't inline you then obviously, you might not get inlined. - You've tiered up to the baseline JIT and you get called from the interpreter. The idea here is that this kind of ensures that you stay SABI only if you're called no more frequently than any of your callers. - You get called from a code block that isn't a DFG candidate. - You aren't an inlining candidate. Most of the heuristics for SABI are in CodeBlock::noticeIncomingCall(). This is neutral on SunSpider and V8Spider, and appears to be a slight speed-up on V8v7, which was previously adversely affected by concurrent compilation. I also confirmed that for example on V8/richards, it dramatically reduces the number of code blocks that get DFG compiled. It is a speed-up on those V8v7 benchmarks that saw regressions from concurrent compilation. * bytecode/CodeBlock.cpp: (JSC::CodeBlock::dumpAssumingJITType): (JSC::CodeBlock::CodeBlock): (JSC::CodeBlock::linkIncomingCall): (JSC): (JSC::CodeBlock::noticeIncomingCall): * bytecode/CodeBlock.h: (CodeBlock): * dfg/DFGCapabilities.h: (JSC::DFG::mightInlineFunction): (DFG): * dfg/DFGPlan.cpp: (JSC::DFG::Plan::compileInThread): * dfg/DFGRepatch.cpp: (JSC::DFG::dfgLinkFor): * interpreter/Interpreter.cpp: (JSC::Interpreter::executeCall): (JSC::Interpreter::executeConstruct): (JSC::Interpreter::prepareForRepeatCall): * jit/JIT.cpp: (JSC::JIT::privateCompile): (JSC::JIT::linkFor): * jit/JIT.h: (JIT): * jit/JITStubs.cpp: (JSC::DEFINE_STUB_FUNCTION): (JSC::lazyLinkFor): * llint/LLIntSlowPaths.cpp: (JSC::LLInt::setUpCall): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153180 268f45cc-cd09-0410-ab3c-d52691b4dbfc
d2cdd316