Changeset 95681 in webkit


Ignore:
Timestamp:
Sep 21, 2011 4:36:35 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG should support continuous optimization
https://bugs.webkit.org/show_bug.cgi?id=68329

Reviewed by Geoffrey Garen.

This adds the ability to reoptimize a code block if speculation
failures happen frequently. 6% speed-up on Kraken, 1% slow-down
on V8, neutral on SunSpider.

(JSC::CodeBlock::CodeBlock):
(JSC::ProgramCodeBlock::jettison):
(JSC::EvalCodeBlock::jettison):
(JSC::FunctionCodeBlock::jettison):
(JSC::CodeBlock::shouldOptimizeNow):
(JSC::CodeBlock::dumpValueProfiles):

  • bytecode/CodeBlock.h:
  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::getStrongPrediction):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::exitSpeculativeWithOSR):
(JSC::DFG::JITCompiler::compileEntry):
(JSC::DFG::JITCompiler::compileBody):

  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::noticeOSREntry):

  • dfg/DFGOSREntry.cpp:

(JSC::DFG::prepareOSREntry):

  • dfg/DFGOSREntry.h:

(JSC::DFG::getOSREntryDataBytecodeIndex):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • heap/ConservativeRoots.cpp:

(JSC::ConservativeRoots::ConservativeRoots):
(JSC::ConservativeRoots::~ConservativeRoots):
(JSC::DummyMarkHook::mark):
(JSC::ConservativeRoots::genericAddPointer):
(JSC::ConservativeRoots::genericAddSpan):
(JSC::ConservativeRoots::add):

  • heap/ConservativeRoots.h:
  • heap/Heap.cpp:

(JSC::Heap::addJettisonCodeBlock):
(JSC::Heap::markRoots):

  • heap/Heap.h:
  • heap/JettisonedCodeBlocks.cpp: Added.

(JSC::JettisonedCodeBlocks::JettisonedCodeBlocks):
(JSC::JettisonedCodeBlocks::~JettisonedCodeBlocks):
(JSC::JettisonedCodeBlocks::addCodeBlock):
(JSC::JettisonedCodeBlocks::clearMarks):
(JSC::JettisonedCodeBlocks::deleteUnmarkedCodeBlocks):
(JSC::JettisonedCodeBlocks::traceCodeBlocks):

  • heap/JettisonedCodeBlocks.h: Added.

(JSC::JettisonedCodeBlocks::mark):

  • interpreter/RegisterFile.cpp:

(JSC::RegisterFile::gatherConservativeRoots):

  • interpreter/RegisterFile.h:
  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • runtime/Executable.cpp:

(JSC::jettisonCodeBlock):
(JSC::EvalExecutable::jettisonOptimizedCode):
(JSC::ProgramExecutable::jettisonOptimizedCode):
(JSC::FunctionExecutable::jettisonOptimizedCodeForCall):
(JSC::FunctionExecutable::jettisonOptimizedCodeForConstruct):

  • runtime/Executable.h:

(JSC::FunctionExecutable::jettisonOptimizedCodeFor):

  • wtf/BitVector.h: Added.

(WTF::BitVector::BitVector):
(WTF::BitVector::~BitVector):
(WTF::BitVector::operator=):
(WTF::BitVector::size):
(WTF::BitVector::ensureSize):
(WTF::BitVector::resize):
(WTF::BitVector::clearAll):
(WTF::BitVector::get):
(WTF::BitVector::set):
(WTF::BitVector::clear):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::maxInlineBits):
(WTF::BitVector::byteCount):
(WTF::BitVector::makeInlineBits):
(WTF::BitVector::OutOfLineBits::numBits):
(WTF::BitVector::OutOfLineBits::numWords):
(WTF::BitVector::OutOfLineBits::bits):
(WTF::BitVector::OutOfLineBits::create):
(WTF::BitVector::OutOfLineBits::destroy):
(WTF::BitVector::OutOfLineBits::OutOfLineBits):
(WTF::BitVector::isInline):
(WTF::BitVector::outOfLineBits):
(WTF::BitVector::resizeOutOfLine):
(WTF::BitVector::bits):

Location:
trunk/Source/JavaScriptCore
Files:
3 added
24 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r95559 r95681  
    5050    heap/HandleHeap.cpp
    5151    heap/HandleStack.cpp
     52    heap/JettisonedCodeBlocks.cpp
    5253    heap/MachineStackMarker.cpp
    5354    heap/MarkedBlock.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r95676 r95681  
     12011-09-21  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG should support continuous optimization
     4        https://bugs.webkit.org/show_bug.cgi?id=68329
     5
     6        Reviewed by Geoffrey Garen.
     7       
     8        This adds the ability to reoptimize a code block if speculation
     9        failures happen frequently. 6% speed-up on Kraken, 1% slow-down
     10        on V8, neutral on SunSpider.
     11
     12        * CMakeLists.txt:
     13        * GNUmakefile.list.am:
     14        * JavaScriptCore.pro:
     15        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
     16        * JavaScriptCore.vcproj/WTF/WTF.vcproj:
     17        * JavaScriptCore.xcodeproj/project.pbxproj:
     18        * bytecode/CodeBlock.cpp:
     19        (JSC::CodeBlock::CodeBlock):
     20        (JSC::ProgramCodeBlock::jettison):
     21        (JSC::EvalCodeBlock::jettison):
     22        (JSC::FunctionCodeBlock::jettison):
     23        (JSC::CodeBlock::shouldOptimizeNow):
     24        (JSC::CodeBlock::dumpValueProfiles):
     25        * bytecode/CodeBlock.h:
     26        * dfg/DFGByteCodeParser.cpp:
     27        (JSC::DFG::ByteCodeParser::getStrongPrediction):
     28        * dfg/DFGJITCompiler.cpp:
     29        (JSC::DFG::JITCompiler::exitSpeculativeWithOSR):
     30        (JSC::DFG::JITCompiler::compileEntry):
     31        (JSC::DFG::JITCompiler::compileBody):
     32        * dfg/DFGJITCompiler.h:
     33        (JSC::DFG::JITCompiler::noticeOSREntry):
     34        * dfg/DFGOSREntry.cpp:
     35        (JSC::DFG::prepareOSREntry):
     36        * dfg/DFGOSREntry.h:
     37        (JSC::DFG::getOSREntryDataBytecodeIndex):
     38        * dfg/DFGSpeculativeJIT.cpp:
     39        (JSC::DFG::SpeculativeJIT::compile):
     40        * heap/ConservativeRoots.cpp:
     41        (JSC::ConservativeRoots::ConservativeRoots):
     42        (JSC::ConservativeRoots::~ConservativeRoots):
     43        (JSC::DummyMarkHook::mark):
     44        (JSC::ConservativeRoots::genericAddPointer):
     45        (JSC::ConservativeRoots::genericAddSpan):
     46        (JSC::ConservativeRoots::add):
     47        * heap/ConservativeRoots.h:
     48        * heap/Heap.cpp:
     49        (JSC::Heap::addJettisonCodeBlock):
     50        (JSC::Heap::markRoots):
     51        * heap/Heap.h:
     52        * heap/JettisonedCodeBlocks.cpp: Added.
     53        (JSC::JettisonedCodeBlocks::JettisonedCodeBlocks):
     54        (JSC::JettisonedCodeBlocks::~JettisonedCodeBlocks):
     55        (JSC::JettisonedCodeBlocks::addCodeBlock):
     56        (JSC::JettisonedCodeBlocks::clearMarks):
     57        (JSC::JettisonedCodeBlocks::deleteUnmarkedCodeBlocks):
     58        (JSC::JettisonedCodeBlocks::traceCodeBlocks):
     59        * heap/JettisonedCodeBlocks.h: Added.
     60        (JSC::JettisonedCodeBlocks::mark):
     61        * interpreter/RegisterFile.cpp:
     62        (JSC::RegisterFile::gatherConservativeRoots):
     63        * interpreter/RegisterFile.h:
     64        * jit/JITStubs.cpp:
     65        (JSC::DEFINE_STUB_FUNCTION):
     66        * runtime/Executable.cpp:
     67        (JSC::jettisonCodeBlock):
     68        (JSC::EvalExecutable::jettisonOptimizedCode):
     69        (JSC::ProgramExecutable::jettisonOptimizedCode):
     70        (JSC::FunctionExecutable::jettisonOptimizedCodeForCall):
     71        (JSC::FunctionExecutable::jettisonOptimizedCodeForConstruct):
     72        * runtime/Executable.h:
     73        (JSC::FunctionExecutable::jettisonOptimizedCodeFor):
     74        * wtf/BitVector.h: Added.
     75        (WTF::BitVector::BitVector):
     76        (WTF::BitVector::~BitVector):
     77        (WTF::BitVector::operator=):
     78        (WTF::BitVector::size):
     79        (WTF::BitVector::ensureSize):
     80        (WTF::BitVector::resize):
     81        (WTF::BitVector::clearAll):
     82        (WTF::BitVector::get):
     83        (WTF::BitVector::set):
     84        (WTF::BitVector::clear):
     85        (WTF::BitVector::bitsInPointer):
     86        (WTF::BitVector::maxInlineBits):
     87        (WTF::BitVector::byteCount):
     88        (WTF::BitVector::makeInlineBits):
     89        (WTF::BitVector::OutOfLineBits::numBits):
     90        (WTF::BitVector::OutOfLineBits::numWords):
     91        (WTF::BitVector::OutOfLineBits::bits):
     92        (WTF::BitVector::OutOfLineBits::create):
     93        (WTF::BitVector::OutOfLineBits::destroy):
     94        (WTF::BitVector::OutOfLineBits::OutOfLineBits):
     95        (WTF::BitVector::isInline):
     96        (WTF::BitVector::outOfLineBits):
     97        (WTF::BitVector::resizeOutOfLine):
     98        (WTF::BitVector::bits):
     99
    11002011-09-21  Gavin Barraclough  <barraclough@apple.com>
    2101
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r95559 r95681  
    141141        Source/JavaScriptCore/heap/HandleHeap.cpp \
    142142        Source/JavaScriptCore/heap/HandleHeap.h \
     143        Source/JavaScriptCore/heap/JettisonedCodeBlocks.cpp \
     144        Source/JavaScriptCore/heap/JettisonedCodeBlocks.h \
    143145        Source/JavaScriptCore/heap/SlotVisitor.h \
    144146        Source/JavaScriptCore/heap/HandleStack.cpp \
     
    465467        Source/JavaScriptCore/wtf/Atomics.h \
    466468        Source/JavaScriptCore/wtf/AVLTree.h \
     469        Source/JavaScriptCore/wtf/BitVector.h \
    467470        Source/JavaScriptCore/wtf/Bitmap.h \
    468471        Source/JavaScriptCore/wtf/BlockStack.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.pro

    r95559 r95681  
    7878    heap/HandleStack.cpp \
    7979    heap/Heap.cpp \
     80    heap/JettisonedCodeBlocks.cpp \
    8081    heap/MachineStackMarker.cpp \
    8182    heap/MarkStack.cpp \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r95559 r95681  
    19751975                            </File>
    19761976                            <File
     1977                                    RelativePath="..\..\heap\JettisonedCodeBlocks.cpp"
     1978                                    >
     1979                            </File>
     1980                            <File
     1981                                    RelativePath="..\..\heap\JettisonedCodeBlocks.h"
     1982                                    >
     1983                            </File>
     1984                            <File
    19771985                                    RelativePath="..\..\heap\Local.h"
    19781986                                    >
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj

    r95140 r95681  
    638638                </File>
    639639                <File
     640                        RelativePath="..\..\wtf\BitVector.h"
     641                        >
     642                </File>
     643                <File
    640644                        RelativePath="..\..\wtf\Bitmap.h"
    641645                        >
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r95655 r95681  
    7575                0FD82E9014207A5F00179C94 /* ValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E8E14207A5100179C94 /* ValueProfile.cpp */; };
    7676                0FD82EF51423075B00179C94 /* DFGIntrinsic.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82EF31423073900179C94 /* DFGIntrinsic.h */; settings = {ATTRIBUTES = (Private, ); }; };
     77                0FD82F2B1426CA6D00179C94 /* JettisonedCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82F291426CA5A00179C94 /* JettisonedCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; };
     78                0FD82F2C1426CA7400179C94 /* JettisonedCodeBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82F281426CA5A00179C94 /* JettisonedCodeBlocks.cpp */; };
     79                0FD82F4B142806A100179C94 /* BitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82F491428069200179C94 /* BitVector.h */; settings = {ATTRIBUTES = (Private, ); }; };
    7780                1400067712A6F7830064D123 /* OSAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400067612A6F7830064D123 /* OSAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
    7881                1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */; };
     
    814817                0FD82E8E14207A5100179C94 /* ValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ValueProfile.cpp; sourceTree = "<group>"; };
    815818                0FD82EF31423073900179C94 /* DFGIntrinsic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGIntrinsic.h; path = dfg/DFGIntrinsic.h; sourceTree = "<group>"; };
     819                0FD82F281426CA5A00179C94 /* JettisonedCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JettisonedCodeBlocks.cpp; sourceTree = "<group>"; };
     820                0FD82F291426CA5A00179C94 /* JettisonedCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JettisonedCodeBlocks.h; sourceTree = "<group>"; };
     821                0FD82F491428069200179C94 /* BitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitVector.h; sourceTree = "<group>"; };
    816822                1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; };
    817823                1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSAllocatorPosix.cpp; sourceTree = "<group>"; };
     
    16221628                        isa = PBXGroup;
    16231629                        children = (
     1630                                0FD82F281426CA5A00179C94 /* JettisonedCodeBlocks.cpp */,
     1631                                0FD82F291426CA5A00179C94 /* JettisonedCodeBlocks.h */,
    16241632                                A70456AF1427FB150037DA68 /* AllocationSpace.h */,
    16251633                                A70456AE1427FB030037DA68 /* AllocationSpace.cpp */,
     
    17981806                        isa = PBXGroup;
    17991807                        children = (
     1808                                0FD82F491428069200179C94 /* BitVector.h */,
    18001809                                C22C524813FAF6EF00B7DC0D /* dtoa */,
    18011810                                06D358A00DAAD9C4003B174E /* mac */,
     
    24242433                                86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
    24252434                                86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
     2435                                0FD82F4B142806A100179C94 /* BitVector.h in Headers */,
     2436                                0FD82F2B1426CA6D00179C94 /* JettisonedCodeBlocks.h in Headers */,
    24262437                                0FD82EF51423075B00179C94 /* DFGIntrinsic.h in Headers */,
    24272438                                0FD82E85141F3FE300179C94 /* BoundsCheckedPointer.h in Headers */,
     
    31143125                        buildActionMask = 2147483647;
    31153126                        files = (
     3127                                0FD82F2C1426CA7400179C94 /* JettisonedCodeBlocks.cpp in Sources */,
    31163128                                0FD82E9014207A5F00179C94 /* ValueProfile.cpp in Sources */,
    31173129                                0FD82E86141F3FF100179C94 /* PredictedType.cpp in Sources */,
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r95676 r95681  
    14291429    , m_symbolTable(symTab)
    14301430    , m_alternative(alternative)
     1431    , m_speculativeSuccessCounter(0)
     1432    , m_speculativeFailCounter(0)
    14311433    , m_optimizationDelayCounter(0)
     1434    , m_reoptimizationRetryCounter(0)
    14321435{
    14331436    ASSERT(m_source);
     
    19361939    return DFG::canCompileFunctionForCall(this);
    19371940}
     1941
     1942void ProgramCodeBlock::jettison(JSGlobalData& globalData)
     1943{
     1944    ASSERT(getJITType() != JITCode::BaselineJIT);
     1945    ASSERT(this == replacement());
     1946    static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(globalData);
     1947}
     1948
     1949void EvalCodeBlock::jettison(JSGlobalData& globalData)
     1950{
     1951    ASSERT(getJITType() != JITCode::BaselineJIT);
     1952    ASSERT(this == replacement());
     1953    static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(globalData);
     1954}
     1955
     1956void FunctionCodeBlock::jettison(JSGlobalData& globalData)
     1957{
     1958    ASSERT(getJITType() != JITCode::BaselineJIT);
     1959    ASSERT(this == replacement());
     1960    static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(globalData, m_isConstructor ? CodeForConstruct : CodeForCall);
     1961}
    19381962#endif
    19391963
     
    19751999#endif
    19762000
    1977     if ((double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles >= 0.75
    1978         && (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= 0.5)
     2001    if ((!numberOfNonArgumentValueProfiles || (double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles >= 0.75)
     2002        && (!numberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= 0.5))
    19792003        return true;
    19802004   
     
    20182042        fprintf(stderr, "   bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
    20192043    }
     2044    fprintf(stderr, "SpecialFastCaseProfile for %p:\n", this);
     2045    for (unsigned i = 0; i < numberOfSpecialFastCaseProfiles(); ++i) {
     2046        RareCaseProfile* profile = specialFastCaseProfile(i);
     2047        fprintf(stderr, "   bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
     2048    }
    20202049}
    20212050#endif
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r95676 r95681  
    3232
    3333#include "CompactJITCodeMap.h"
     34#include "DFGOSREntry.h"
    3435#include "EvalCodeCache.h"
    3536#include "Instruction.h"
     
    334335            return m_jitCodeMap.get();
    335336        }
     337       
     338        DFG::OSREntryData* appendDFGOSREntryData(unsigned bytecodeIndex, unsigned machineCodeOffset)
     339        {
     340            DFG::OSREntryData entry;
     341            entry.m_bytecodeIndex = bytecodeIndex;
     342            entry.m_machineCodeOffset = machineCodeOffset;
     343            m_dfgOSREntry.append(entry);
     344            return &m_dfgOSREntry.last();
     345        }
     346        unsigned numberOfDFGOSREntries() const { return m_dfgOSREntry.size(); }
     347        DFG::OSREntryData* dfgOSREntryData(unsigned i) { return &m_dfgOSREntry[i]; }
     348        DFG::OSREntryData* dfgOSREntryDataForBytecodeIndex(unsigned bytecodeIndex)
     349        {
     350            return binarySearch<DFG::OSREntryData, unsigned, DFG::getOSREntryDataBytecodeIndex>(m_dfgOSREntry.begin(), m_dfgOSREntry.size(), bytecodeIndex);
     351        }
    336352#endif
    337353
     
    361377        }
    362378        JITCode& getJITCode() { return m_jitCode; }
     379        MacroAssemblerCodePtr getJITCodeWithArityCheck() { return m_jitCodeWithArityCheck; }
    363380        JITCode::JITType getJITType() { return m_jitCode.jitType(); }
    364381        ExecutableMemoryHandle* executableMemory() { return getJITCode().getExecutableMemory(); }
    365382        virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0;
     383        virtual void jettison(JSGlobalData&) = 0;
    366384        virtual CodeBlock* replacement() = 0;
    367385        virtual bool canCompileWithDFG() = 0;
     
    686704        // as this is called from the CodeBlock constructor.
    687705       
     706        // When we observe a lot of speculation failures, we trigger a
     707        // reoptimization. But each time, we increase the optimization trigger
     708        // to avoid thrashing.
     709        unsigned reoptimizationRetryCounter() const
     710        {
     711            ASSERT(m_reoptimizationRetryCounter <= 18);
     712            return m_reoptimizationRetryCounter;
     713        }
     714       
     715        void countReoptimization()
     716        {
     717            m_reoptimizationRetryCounter++;
     718            if (m_reoptimizationRetryCounter > 18)
     719                m_reoptimizationRetryCounter = 18;
     720        }
     721       
    688722        // These functions are provided to support calling
    689         // optimizeAfterWarmUp() from JIT-generated code.
     723        // optimizeXYZ() methods from JIT-generated code.
     724        static int32_t counterValueForOptimizeNextInvocation()
     725        {
     726            return 0;
     727        }
     728       
    690729        int32_t counterValueForOptimizeAfterWarmUp()
    691730        {
    692             return -1000;
     731            return -1000 << reoptimizationRetryCounter();
     732        }
     733       
     734        int32_t counterValueForOptimizeAfterLongWarmUp()
     735        {
     736            return -5000 << reoptimizationRetryCounter();
    693737        }
    694738       
     
    697741            return &m_executeCounter;
    698742        }
     743       
     744        static ptrdiff_t offsetOfExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_executeCounter); }
     745
     746        int32_t executeCounter() const { return m_executeCounter; }
     747       
     748        unsigned optimizationDelayCounter() const { return m_optimizationDelayCounter; }
    699749       
    700750        // Call this to force the next optimization trigger to fire. This is
     
    703753        void optimizeNextInvocation()
    704754        {
    705             m_executeCounter = 0;
     755            m_executeCounter = counterValueForOptimizeNextInvocation();
    706756        }
    707757       
     
    725775        {
    726776            m_executeCounter = counterValueForOptimizeAfterWarmUp();
     777        }
     778       
     779        // Call this to force an optimization trigger to fire only after
     780        // a lot of warm-up.
     781        void optimizeAfterLongWarmUp()
     782        {
     783            m_executeCounter = counterValueForOptimizeAfterLongWarmUp();
    727784        }
    728785       
     
    747804        void optimizeSoon()
    748805        {
    749             m_executeCounter = -100;
    750         }
     806            m_executeCounter = -100 << reoptimizationRetryCounter();
     807        }
     808       
     809        // The speculative JIT tracks its success rate, so that we can
     810        // decide when to reoptimize. It's interesting to note that these
     811        // counters may overflow without any protection. The success
     812        // counter will overflow before the fail one does, becuase the
     813        // fail one is used as a trigger to reoptimize. So the worst case
     814        // is that the success counter overflows and we reoptimize without
     815        // needing to. But this is harmless. If a method really did
     816        // execute 2^32 times then compiling it again probably won't hurt
     817        // anyone.
     818       
     819        void countSpeculationSuccess()
     820        {
     821            m_speculativeSuccessCounter++;
     822        }
     823       
     824        void countSpeculationFailure()
     825        {
     826            m_speculativeFailCounter++;
     827        }
     828       
     829        uint32_t speculativeSuccessCounter() const { return m_speculativeSuccessCounter; }
     830        uint32_t speculativeFailCounter() const { return m_speculativeFailCounter; }
     831       
     832        uint32_t* addressOfSpeculativeSuccessCounter() { return &m_speculativeSuccessCounter; }
     833        uint32_t* addressOfSpeculativeFailCounter() { return &m_speculativeFailCounter; }
     834       
     835        static ptrdiff_t offsetOfSpeculativeSuccessCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeSuccessCounter); }
     836        static ptrdiff_t offsetOfSpeculativeFailCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeFailCounter); }
    751837       
    752838        // The amount by which the JIT will increment m_executeCounter.
    753839        static unsigned executeCounterIncrementForLoop() { return 1; }
    754840        static unsigned executeCounterIncrementForReturn() { return 15; }
     841
     842        // The success/failure ratio we want.
     843        unsigned desiredSuccessFailRatio() { return 6; }
     844       
     845        // The number of failures that triggers the use of the ratio.
     846        unsigned largeFailCountThreshold() { return 20 << alternative()->reoptimizationRetryCounter(); }
     847        unsigned largeFailCountThresholdForLoop() { return 1 << alternative()->reoptimizationRetryCounter(); }
     848       
     849        bool shouldReoptimizeNow()
     850        {
     851            return desiredSuccessFailRatio() * speculativeFailCounter() >= speculativeSuccessCounter() && speculativeFailCounter() >= largeFailCountThreshold();
     852        }
     853       
     854        bool shouldReoptimizeFromLoopNow()
     855        {
     856            return desiredSuccessFailRatio() * speculativeFailCounter() >= speculativeSuccessCounter() && speculativeFailCounter() >= largeFailCountThresholdForLoop();
     857        }
    755858       
    756859#if ENABLE(VALUE_PROFILER)
     
    759862        bool shouldOptimizeNow() { return false; }
    760863#endif
     864       
     865        void reoptimize(JSGlobalData& globalData)
     866        {
     867            ASSERT(replacement() != this);
     868            replacement()->jettison(globalData);
     869            countReoptimization();
     870            optimizeAfterWarmUp();
     871        }
    761872
    762873#if ENABLE(VERBOSE_VALUE_PROFILE)
     
    828939#if ENABLE(DFG_JIT)
    829940        OwnPtr<CompactJITCodeMap> m_jitCodeMap;
     941        Vector<DFG::OSREntryData> m_dfgOSREntry;
    830942#endif
    831943#if ENABLE(VALUE_PROFILER)
     
    852964
    853965        int32_t m_executeCounter;
     966        uint32_t m_speculativeSuccessCounter;
     967        uint32_t m_speculativeFailCounter;
    854968        uint8_t m_optimizationDelayCounter;
     969        uint8_t m_reoptimizationRetryCounter;
    855970
    856971        struct RareData {
     
    9101025    protected:
    9111026        virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
     1027        virtual void jettison(JSGlobalData&);
    9121028        virtual CodeBlock* replacement();
    9131029        virtual bool canCompileWithDFG();
     
    9361052    protected:
    9371053        virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
     1054        virtual void jettison(JSGlobalData&);
    9381055        virtual CodeBlock* replacement();
    9391056        virtual bool canCompileWithDFG();
     
    9631080    protected:
    9641081        virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
     1082        virtual void jettison(JSGlobalData&);
    9651083        virtual CodeBlock* replacement();
    9661084        virtual bool canCompileWithDFG();
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r95676 r95681  
    493493        PredictedType prediction = profile->computeUpdatedPrediction();
    494494#if ENABLE(DFG_DEBUG_VERBOSE)
    495         printf("Dynamic [%u, %u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
     495        printf("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
    496496#endif
    497497        return prediction;
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r95273 r95681  
    409409    //         particularly expensive.
    410410    //
     411    //     (d) Frequent OSR failures, even those that do not result in the code
     412    //         running in a hot loop, result in recompilation getting triggered.
     413    //
    411414    //     To ensure (c), we'd like to set the execute counter to
    412415    //     counterValueForOptimizeAfterWarmUp(). This seems like it would endanger
     
    416419    //     become non-negative and OSR entry will never be triggered. OSR entry
    417420    //     will only happen if a loop gets hot in the old JIT, which does a pretty
    418     //     good job of ensuring (a) and (b). This heuristic may need to be
    419     //     rethought in the future, particularly if we support reoptimizing code
    420     //     with new value profiles gathered from code that did OSR exit.
    421    
    422     store32(Imm32(codeBlock()->alternative()->counterValueForOptimizeAfterWarmUp()), codeBlock()->alternative()->addressOfExecuteCounter());
     421    //     good job of ensuring (a) and (b). But that doesn't take care of (d),
     422    //     since each speculation failure would reset the execute counter.
     423    //     So we check here if the number of speculation failures is significantly
     424    //     larger than the number of successes (we want 90% success rate), and if
     425    //     there have been a large enough number of failures. If so, we set the
     426    //     counter to 0; otherwise we set the counter to
     427    //     counterValueForOptimizeAfterWarmUp().
     428   
     429    move(TrustedImmPtr(codeBlock()), GPRInfo::regT0);
     430   
     431    load32(Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()), GPRInfo::regT2);
     432    load32(Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1);
     433    add32(Imm32(1), GPRInfo::regT2);
     434    add32(Imm32(-1), GPRInfo::regT1);
     435    store32(GPRInfo::regT2, Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()));
     436    store32(GPRInfo::regT1, Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()));
     437   
     438    move(TrustedImmPtr(codeBlock()->alternative()), GPRInfo::regT0);
     439   
     440    Jump fewFails = branch32(BelowOrEqual, GPRInfo::regT2, Imm32(codeBlock()->largeFailCountThreshold()));
     441    mul32(Imm32(codeBlock()->desiredSuccessFailRatio()), GPRInfo::regT2, GPRInfo::regT2);
     442   
     443    Jump lowFailRate = branch32(BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1);
     444   
     445    // Reoptimize as soon as possible.
     446    store32(Imm32(CodeBlock::counterValueForOptimizeNextInvocation()), Address(GPRInfo::regT0, CodeBlock::offsetOfExecuteCounter()));
     447    Jump doneAdjusting = jump();
     448   
     449    fewFails.link(this);
     450    lowFailRate.link(this);
     451   
     452    store32(Imm32(codeBlock()->alternative()->counterValueForOptimizeAfterLongWarmUp()), Address(GPRInfo::regT0, CodeBlock::offsetOfExecuteCounter()));
     453   
     454    doneAdjusting.link(this);
    423455   
    424456    // 12) Load the result of the last bytecode operation into regT0.
     
    482514    preserveReturnAddressAfterCall(GPRInfo::regT2);
    483515    emitPutToCallFrameHeader(GPRInfo::regT2, RegisterFile::ReturnPC);
     516   
     517    addPtr(Imm32(1), AbsoluteAddress(codeBlock()->addressOfSpeculativeSuccessCounter()));
    484518}
    485519
     
    499533    ASSERT_UNUSED(compiledSpeculative, compiledSpeculative);
    500534
    501 #if ENABLE(DFG_OSR_ENTRY)
    502     m_codeBlock->setJITCodeMap(m_jitCodeMapEncoder.finish());
    503 #endif
    504    
    505535    linkOSRExits(speculative);
    506536
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r95666 r95681  
    321321    void noticeOSREntry(BasicBlock& basicBlock)
    322322    {
    323         m_jitCodeMapEncoder.append(basicBlock.bytecodeBegin, differenceBetween(m_startOfCode, label()));
     323#if ENABLE(DFG_OSR_ENTRY)
     324        OSREntryData* entry = codeBlock()->appendDFGOSREntryData(basicBlock.bytecodeBegin, differenceBetween(m_startOfCode, label()));
     325       
     326        unsigned lastLiveArgument = 0;
     327        unsigned lastLiveLocal = 0;
     328       
     329        for (unsigned i = 0; i < basicBlock.m_arguments.size(); ++i) {
     330            if (basicBlock.m_arguments[i].value != NoNode)
     331                lastLiveArgument = i;
     332        }
     333       
     334        for (unsigned i = 0; i < basicBlock.m_locals.size(); ++i) {
     335            if (basicBlock.m_locals[i].value != NoNode)
     336                lastLiveLocal = i;
     337        }
     338       
     339        if (lastLiveArgument) {
     340            entry->m_liveArguments.resize(lastLiveArgument + 1);
     341            entry->m_liveArguments.clearAll();
     342           
     343            for (unsigned i = 0; i <= lastLiveArgument; ++i) {
     344                if (basicBlock.m_arguments[i].value != NoNode)
     345                    entry->m_liveArguments.set(i);
     346            }
     347        } else
     348            entry->m_liveArguments.clearAll();
     349       
     350        if (lastLiveLocal) {
     351            entry->m_liveVariables.resize(lastLiveLocal + 1);
     352            entry->m_liveVariables.clearAll();
     353           
     354            for (unsigned i = 0; i <= lastLiveLocal; ++i) {
     355                if (basicBlock.m_locals[i].value != NoNode)
     356                    entry->m_liveVariables.set(i);
     357            }
     358        } else
     359            entry->m_liveVariables.clearAll();
     360#else
     361        UNUSED_PARAM(basicBlock);
     362#endif
    324363    }
    325364
     
    354393    // JIT code map for OSR entrypoints.
    355394    Label m_startOfCode;
    356     CompactJITCodeMap::Encoder m_jitCodeMapEncoder;
    357395
    358396    struct PropertyAccessRecord {
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp

    r95240 r95681  
    5959    ASSERT(codeBlock->alternative());
    6060    ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT);
    61     ASSERT(codeBlock->jitCodeMap());
     61    ASSERT(!codeBlock->jitCodeMap());
     62    ASSERT(codeBlock->numberOfDFGOSREntries());
    6263
    6364#if ENABLE(JIT_VERBOSE_OSR)
     
    6768    JSGlobalData* globalData = &exec->globalData();
    6869    CodeBlock* baselineCodeBlock = codeBlock->alternative();
     70    OSREntryData* entry = codeBlock->dfgOSREntryDataForBytecodeIndex(bytecodeIndex);
     71   
     72    ASSERT(entry->m_bytecodeIndex == bytecodeIndex);
    6973   
    7074    // The code below checks if it is safe to perform OSR entry. It may find
     
    98102   
    99103    for (unsigned i = 1; i < predictions->numberOfArguments(); ++i) {
    100         if (!predictionIsValid(globalData, exec->argument(i - 1), predictions->getArgumentPrediction(i))) {
     104        if (i < entry->m_liveArguments.size() && entry->m_liveArguments.get(i)
     105            && !predictionIsValid(globalData, exec->argument(i - 1), predictions->getArgumentPrediction(i))) {
    101106#if ENABLE(JIT_VERBOSE_OSR)
    102107            printf("    OSR failed because argument %u is %s, expected %s.\n", i, exec->argument(i - 1).description(), predictionToString(predictions->getArgumentPrediction(i)));
     
    106111    }
    107112   
    108     // FIXME: we need to know if at an OSR entry, a variable is live. If it isn't
    109     // then we shouldn't try to verify its prediction.
    110    
    111113    for (unsigned i = 0; i < predictions->numberOfVariables(); ++i) {
    112         if (!predictionIsValid(globalData, exec->registers()[i].jsValue(), predictions->getPrediction(i))) {
     114        if (i < entry->m_liveVariables.size() && entry->m_liveVariables.get(i)
     115            && !predictionIsValid(globalData, exec->registers()[i].jsValue(), predictions->getPrediction(i))) {
    113116#if ENABLE(JIT_VERBOSE_OSR)
    114117            printf("    OSR failed because variable %u is %s, expected %s.\n", i, exec->registers()[i].jsValue().description(), predictionToString(predictions->getPrediction(i)));
     
    140143    exec->setCodeBlock(codeBlock);
    141144   
    142     // 4) Find and return the destination machine code address. The DFG stores
    143     //    the machine code offsets of OSR targets in a CompactJITCodeMap.
    144     //    Decoding it is not super efficient, but we expect that OSR entry
    145     //    happens sufficiently rarely, and that OSR entrypoints are sufficiently
    146     //    few, that this won't hurt throughput. Note that the only real
    147     //    reason why we use a CompactJITCodeMap is to avoid having to introduce
    148     //    yet another data structure for mapping between bytecode indices and
    149     //    machine code offsets.
     145    // 4) Find and return the destination machine code address.
    150146   
    151     CompactJITCodeMap::Decoder decoder(codeBlock->jitCodeMap());
    152     unsigned machineCodeOffset = std::numeric_limits<unsigned>::max();
    153     while (decoder.numberOfEntriesRemaining()) {
    154         unsigned currentBytecodeIndex;
    155         unsigned currentMachineCodeOffset;
    156         decoder.read(currentBytecodeIndex, currentMachineCodeOffset);
    157         if (currentBytecodeIndex == bytecodeIndex) {
    158             machineCodeOffset = currentMachineCodeOffset;
    159             break;
    160         }
    161     }
    162    
    163     ASSERT(machineCodeOffset != std::numeric_limits<unsigned>::max());
    164    
    165     void* result = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(codeBlock->getJITCode().start()) + machineCodeOffset);
     147    void* result = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(codeBlock->getJITCode().start()) + entry->m_machineCodeOffset);
    166148   
    167149#if ENABLE(JIT_VERBOSE_OSR)
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.h

    r95016 r95681  
    2727#define DFGOSREntry_h
    2828
     29#include <wtf/BitVector.h>
     30
    2931namespace JSC {
    3032
     
    3537
    3638#if ENABLE(DFG_JIT)
     39struct OSREntryData {
     40    unsigned m_bytecodeIndex;
     41    unsigned m_machineCodeOffset;
     42    BitVector m_liveArguments;
     43    BitVector m_liveVariables;
     44};
     45
     46inline unsigned getOSREntryDataBytecodeIndex(OSREntryData* osrEntryData)
     47{
     48    return osrEntryData->m_bytecodeIndex;
     49}
     50
    3751void* prepareOSREntry(ExecState*, CodeBlock*, unsigned bytecodeIndex);
    3852#else
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r95672 r95681  
    878878        }
    879879       
     880        if (shouldNotSpeculateInteger(node.child1())) {
     881            // Do it the safe way.
     882            nonSpeculativeValueToInt32(node);
     883            break;
     884        }
     885       
    880886        SpeculateIntegerOperand op1(this, node.child1());
    881887        GPRTemporary result(this, op1);
  • trunk/Source/JavaScriptCore/heap/ConservativeRoots.cpp

    r88504 r95681  
    2727#include "ConservativeRoots.h"
    2828
     29#include "JettisonedCodeBlocks.h"
     30
    2931namespace JSC {
    3032
     
    3234{
    3335    return !((intptr_t)(p) & (sizeof(char*) - 1));
     36}
     37
     38ConservativeRoots::ConservativeRoots(const MarkedBlockSet* blocks)
     39    : m_roots(m_inlineRoots)
     40    , m_size(0)
     41    , m_capacity(inlineCapacity)
     42    , m_blocks(blocks)
     43{
     44}
     45
     46ConservativeRoots::~ConservativeRoots()
     47{
     48    if (m_roots != m_inlineRoots)
     49        OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*));
    3450}
    3551
     
    4561}
    4662
    47 inline void ConservativeRoots::add(void* p, TinyBloomFilter filter)
     63class DummyMarkHook {
     64public:
     65    void mark(void*) { }
     66};
     67
     68template<typename MarkHook>
     69inline void ConservativeRoots::genericAddPointer(void* p, TinyBloomFilter filter, MarkHook& markHook)
    4870{
     71    markHook.mark(p);
     72   
    4973    MarkedBlock* candidate = MarkedBlock::blockFor(p);
    5074    if (filter.ruleOut(reinterpret_cast<Bits>(candidate))) {
     
    7195}
    7296
    73 void ConservativeRoots::add(void* begin, void* end)
     97template<typename MarkHook>
     98void ConservativeRoots::genericAddSpan(void* begin, void* end, MarkHook& markHook)
    7499{
    75100    ASSERT(begin <= end);
     
    80105    TinyBloomFilter filter = m_blocks->filter(); // Make a local copy of filter to show the compiler it won't alias, and can be register-allocated.
    81106    for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it)
    82         add(*it, filter);
     107        genericAddPointer(*it, filter, markHook);
     108}
     109
     110void ConservativeRoots::add(void* begin, void* end)
     111{
     112    DummyMarkHook dummyMarkHook;
     113    genericAddSpan(begin, end, dummyMarkHook);
     114}
     115
     116void ConservativeRoots::add(void* begin, void* end, JettisonedCodeBlocks& jettisonedCodeBlocks)
     117{
     118    genericAddSpan(begin, end, jettisonedCodeBlocks);
    83119}
    84120
  • trunk/Source/JavaScriptCore/heap/ConservativeRoots.h

    r88504 r95681  
    3434
    3535class JSCell;
     36class JettisonedCodeBlocks;
    3637class Heap;
    3738
     
    4243
    4344    void add(void* begin, void* end);
     45    void add(void* begin, void* end, JettisonedCodeBlocks&);
    4446   
    4547    size_t size();
     
    5052    static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*);
    5153   
    52     void add(void*, TinyBloomFilter);
     54    template<typename MarkHook>
     55    void genericAddPointer(void*, TinyBloomFilter, MarkHook&);
     56
     57    template<typename MarkHook>
     58    void genericAddSpan(void*, void* end, MarkHook&);
     59   
    5360    void grow();
    5461
     
    5966    JSCell* m_inlineRoots[inlineCapacity];
    6067};
    61 
    62 inline ConservativeRoots::ConservativeRoots(const MarkedBlockSet* blocks)
    63     : m_roots(m_inlineRoots)
    64     , m_size(0)
    65     , m_capacity(inlineCapacity)
    66     , m_blocks(blocks)
    67 {
    68 }
    69 
    70 inline ConservativeRoots::~ConservativeRoots()
    71 {
    72     if (m_roots != m_inlineRoots)
    73         OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*));
    74 }
    7568
    7669inline size_t ConservativeRoots::size()
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r95559 r95681  
    395395}
    396396
     397void Heap::addJettisonedCodeBlock(PassOwnPtr<CodeBlock> codeBlock)
     398{
     399    m_jettisonedCodeBlocks.addCodeBlock(codeBlock);
     400}
     401
    397402void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
    398403{
     
    457462
    458463    void* dummy;
    459 
     464   
    460465    // We gather conservative roots before clearing mark bits because conservative
    461466    // gathering uses the mark bits to determine whether a reference is valid.
     
    464469
    465470    ConservativeRoots registerFileRoots(&m_objectSpace.blocks());
    466     registerFile().gatherConservativeRoots(registerFileRoots);
     471    m_jettisonedCodeBlocks.clearMarks();
     472    registerFile().gatherConservativeRoots(registerFileRoots, m_jettisonedCodeBlocks);
     473    m_jettisonedCodeBlocks.deleteUnmarkedCodeBlocks();
    467474
    468475    clearMarks();
     
    470477    SlotVisitor& visitor = m_slotVisitor;
    471478    HeapRootVisitor heapRootVisitor(visitor);
    472 
     479   
    473480    visitor.append(machineThreadRoots);
    474481    visitor.drain();
     
    493500
    494501    m_handleStack.visit(heapRootVisitor);
     502    visitor.drain();
     503   
     504    m_jettisonedCodeBlocks.traceCodeBlocks(visitor);
    495505    visitor.drain();
    496506
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r95559 r95681  
    2626#include "HandleHeap.h"
    2727#include "HandleStack.h"
     28#include "JettisonedCodeBlocks.h"
    2829#include "MarkedBlock.h"
    2930#include "MarkedBlockSet.h"
     
    99100        void protect(JSValue);
    100101        bool unprotect(JSValue); // True when the protect count drops to 0.
     102       
     103        void addJettisonedCodeBlock(PassOwnPtr<CodeBlock>);
    101104
    102105        size_t size();
     
    192195        HandleHeap m_handleHeap;
    193196        HandleStack m_handleStack;
     197        JettisonedCodeBlocks m_jettisonedCodeBlocks;
    194198       
    195199        bool m_isSafeToCollect;
  • trunk/Source/JavaScriptCore/interpreter/RegisterFile.cpp

    r89465 r95681  
    5656}
    5757
     58void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JettisonedCodeBlocks& jettisonedCodeBlocks)
     59{
     60    conservativeRoots.add(begin(), end(), jettisonedCodeBlocks);
     61}
     62
    5863void RegisterFile::releaseExcessCapacity()
    5964{
  • trunk/Source/JavaScriptCore/interpreter/RegisterFile.h

    r89472 r95681  
    3939
    4040    class ConservativeRoots;
     41    class JettisonedCodeBlocks;
    4142
    4243    class RegisterFile {
     
    6566       
    6667        void gatherConservativeRoots(ConservativeRoots&);
     68        void gatherConservativeRoots(ConservativeRoots&, JettisonedCodeBlocks&);
    6769
    6870        Register* begin() const { return static_cast<Register*>(m_reservation.base()); }
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r95666 r95681  
    19151915    unsigned bytecodeIndex = stackFrame.args[0].int32();
    19161916
    1917     if (!codeBlock->hasOptimizedReplacement()) {
     1917#if ENABLE(JIT_VERBOSE_OSR)
     1918    printf("Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->executeCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
     1919#endif
     1920
     1921    if (codeBlock->hasOptimizedReplacement()) {
     1922#if ENABLE(JIT_VERBOSE_OSR)
     1923        printf("Considering loop OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
     1924#endif
     1925        if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
     1926#if ENABLE(JIT_VERBOSE_OSR)
     1927            printf("Triggering reoptimization of %p(%p) (in loop).\n", codeBlock, codeBlock->replacement());
     1928#endif
     1929            codeBlock->reoptimize(callFrame->globalData());
     1930            return;
     1931        }
     1932    } else {
    19181933        if (!codeBlock->shouldOptimizeNow()) {
    19191934#if ENABLE(JIT_VERBOSE_OSR)
     
    19531968
    19541969        codeBlock->optimizeSoon();
     1970        optimizedCodeBlock->countSpeculationSuccess();
    19551971        STUB_SET_RETURN_ADDRESS(address);
    19561972        return;
     
    19611977#endif
    19621978
     1979    // Count the OSR failure as a speculation failure. If this happens a lot, then
     1980    // reoptimize.
     1981    optimizedCodeBlock->countSpeculationFailure();
     1982   
     1983#if ENABLE(JIT_VERBOSE_OSR)
     1984    printf("Encountered loop OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
     1985#endif
     1986
     1987    // We are a lot more conservative about triggering reoptimization after OSR failure than
     1988    // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
     1989    // already, then we really would like to reoptimize immediately. But this case covers
     1990    // something else: there weren't many (or any) speculation failures before, but we just
     1991    // failed to enter the speculative code because some variable had the wrong value or
     1992    // because the OSR code decided for any spurious reason that it did not want to OSR
     1993    // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
     1994    // reoptimization trigger.
     1995    if (optimizedCodeBlock->shouldReoptimizeNow()) {
     1996#if ENABLE(JIT_VERBOSE_OSR)
     1997        printf("Triggering reoptimization of %p(%p) (in loop after OSR fail).\n", codeBlock, codeBlock->replacement());
     1998#endif
     1999        codeBlock->reoptimize(callFrame->globalData());
     2000        return;
     2001    }
     2002
    19632003    // OSR failed this time, but it might succeed next time! Let the code run a bit
    19642004    // longer and then try again.
     
    19732013    CodeBlock* codeBlock = callFrame->codeBlock();
    19742014   
    1975     if (codeBlock->hasOptimizedReplacement())
     2015#if ENABLE(JIT_VERBOSE_OSR)
     2016    printf("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->executeCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
     2017#endif
     2018
     2019    if (codeBlock->hasOptimizedReplacement()) {
     2020#if ENABLE(JIT_VERBOSE_OSR)
     2021        printf("Returning from old JIT call frame with optimized replacement %p(%p), with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
     2022#endif
     2023        if (codeBlock->replacement()->shouldReoptimizeNow()) {
     2024#if ENABLE(JIT_VERBOSE_OSR)
     2025            printf("Triggering reoptimization of %p(%p) (in return).\n", codeBlock, codeBlock->replacement());
     2026#endif
     2027            codeBlock->reoptimize(callFrame->globalData());
     2028        }
     2029
    19762030        return;
     2031    }
    19772032   
    19782033    if (!codeBlock->shouldOptimizeNow()) {
  • trunk/Source/JavaScriptCore/runtime/Executable.cpp

    r95672 r95681  
    8585#endif
    8686
     87// Utility method used for jettisoning code blocks.
     88template<typename T>
     89static void jettisonCodeBlock(JSGlobalData& globalData, OwnPtr<T>& codeBlock)
     90{
     91    ASSERT(codeBlock->getJITType() != JITCode::BaselineJIT);
     92    ASSERT(codeBlock->alternative());
     93    OwnPtr<T> codeBlockToJettison = codeBlock.release();
     94    codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());
     95    codeBlockToJettison->unlinkIncomingCalls();
     96    globalData.heap.addJettisonedCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release()));
     97}
     98
    8799const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0 };
    88100
     
    212224}
    213225
     226void EvalExecutable::jettisonOptimizedCode(JSGlobalData& globalData)
     227{
     228    jettisonCodeBlock(globalData, m_evalCodeBlock);
     229    m_jitCodeForCall = m_evalCodeBlock->getJITCode();
     230    ASSERT(!m_jitCodeForCallWithArityCheck);
     231}
     232
    214233void EvalExecutable::visitChildren(SlotVisitor& visitor)
    215234{
     
    329348
    330349    return 0;
     350}
     351
     352void ProgramExecutable::jettisonOptimizedCode(JSGlobalData& globalData)
     353{
     354    jettisonCodeBlock(globalData, m_programCodeBlock);
     355    m_jitCodeForCall = m_programCodeBlock->getJITCode();
     356    ASSERT(!m_jitCodeForCallWithArityCheck);
    331357}
    332358
     
    535561}
    536562
     563void FunctionExecutable::jettisonOptimizedCodeForCall(JSGlobalData& globalData)
     564{
     565    jettisonCodeBlock(globalData, m_codeBlockForCall);
     566    m_jitCodeForCall = m_codeBlockForCall->getJITCode();
     567    m_jitCodeForCallWithArityCheck = m_codeBlockForCall->getJITCodeWithArityCheck();
     568}
     569
     570void FunctionExecutable::jettisonOptimizedCodeForConstruct(JSGlobalData& globalData)
     571{
     572    jettisonCodeBlock(globalData, m_codeBlockForConstruct);
     573    m_jitCodeForConstruct = m_codeBlockForConstruct->getJITCode();
     574    m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->getJITCodeWithArityCheck();
     575}
     576
    537577void FunctionExecutable::visitChildren(SlotVisitor& visitor)
    538578{
  • trunk/Source/JavaScriptCore/runtime/Executable.h

    r95672 r95681  
    328328       
    329329        JSObject* compileOptimized(ExecState*, ScopeChainNode*);
     330       
     331        void jettisonOptimizedCode(JSGlobalData&);
    330332
    331333        EvalCodeBlock& generatedBytecode()
     
    393395
    394396        JSObject* compileOptimized(ExecState*, ScopeChainNode*);
     397       
     398        void jettisonOptimizedCode(JSGlobalData&);
    395399
    396400        ProgramCodeBlock& generatedBytecode()
     
    476480
    477481        JSObject* compileOptimizedForCall(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec = 0);
     482       
     483        void jettisonOptimizedCodeForCall(JSGlobalData&);
    478484
    479485        bool isGeneratedForCall() const
     
    499505
    500506        JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec = 0);
     507       
     508        void jettisonOptimizedCodeForConstruct(JSGlobalData&);
    501509
    502510        bool isGeneratedForConstruct() const
     
    539547        }
    540548       
     549        void jettisonOptimizedCodeFor(JSGlobalData& globalData, CodeSpecializationKind kind)
     550        {
     551            if (kind == CodeForCall)
     552                jettisonOptimizedCodeForCall(globalData);
     553            else {
     554                ASSERT(kind == CodeForConstruct);
     555                jettisonOptimizedCodeForConstruct(globalData);
     556            }
     557        }
     558       
    541559        bool isGeneratedFor(CodeSpecializationKind kind)
    542560        {
Note: See TracChangeset for help on using the changeset viewer.