Changeset 162940 in webkit


Ignore:
Timestamp:
Jan 28, 2014 9:43:07 AM (10 years ago)
Author:
mark.lam@apple.com
Message:

Jettison DFG code when neither breakpoints or the profiler are active.
<https://webkit.org/b/127766>

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

We need to jettison the DFG CodeBlocks under the following circumstances:

  1. When adding breakpoints to a CodeBlock, jettison it if it is a DFG CodeBlock.
  2. When enabling stepping mode in a CodeBlock, jettison it if it a DFG CodeBlock.
  3. When settign the enabled profiler in the VM, we need to jettison all DFG CodeBlocks.

Instead of emitting speculation checks, the DFG code will now treat Breakpoint,
ProfileWillCall, and ProfileDidCall as no-ops similar to a Phantom node. We
still need to track these nodes so that they match the corresponding opcodes
in the baseline JIT when we jettison and OSR exit. Without them, we would OSR
exit to the wrong location in the baseline JIT code.

In DFGDriver's compileImpl() and DFGPlan's finalizeWithoutNotifyingCallback()
we fail the compilation effort with a CompilationInvalidated result. This allows
the DFG compiler to re-attampt the compilation of the function after some time
if it is hot. The CompilationInvalidated result is supposed to cause the DFG
to exercise an exponential back off before re-attempting compilation again
(see runtime/CompilationResult.h).

This patch improves the Octane score from ~2950 to ~3067.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::addBreakpoint):
(JSC::CodeBlock::setSteppingMode):

  • bytecode/CodeBlock.h:
  • debugger/Debugger.h:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDriver.cpp:

(JSC::DFG::compileImpl):

  • dfg/DFGPlan.cpp:

(JSC::DFG::Plan::finalizeWithoutNotifyingCallback):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • profiler/LegacyProfiler.cpp:

(JSC::LegacyProfiler::startProfiling):
(JSC::LegacyProfiler::stopProfiling):

  • runtime/VM.cpp:

(JSC::VM::VM):
(JSC::SetEnabledProfilerFunctor::operator()):
(JSC::VM::setEnabledProfiler):

  • runtime/VM.h:

(JSC::VM::enabledProfiler):

LayoutTests:

Added a test to exercise setting a breakpoint in 2 DFG compiled functions:
1 not inlined, and 1 inlined.

  • inspector-protocol/debugger/resources/breakpoint.js:

(notInlineable):
(inlineable):
(notInliningFoo):
(inliningFoo):
(dfgWithoutInline):
(dfgWithInline):

  • inspector-protocol/debugger/setBreakpoint-dfg-expected.txt: Added.
  • inspector-protocol/debugger/setBreakpoint-dfg.html: Added.
Location:
trunk
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r162933 r162940  
     12014-01-28  Mark Lam  <mark.lam@apple.com>
     2
     3        Jettison DFG code when neither breakpoints or the profiler are active.
     4        <https://webkit.org/b/127766>
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Added a test to exercise setting a breakpoint in 2 DFG compiled functions:
     9        1 not inlined, and 1 inlined.
     10
     11        * inspector-protocol/debugger/resources/breakpoint.js:
     12        (notInlineable):
     13        (inlineable):
     14        (notInliningFoo):
     15        (inliningFoo):
     16        (dfgWithoutInline):
     17        (dfgWithInline):
     18        * inspector-protocol/debugger/setBreakpoint-dfg-expected.txt: Added.
     19        * inspector-protocol/debugger/setBreakpoint-dfg.html: Added.
     20
    1212014-01-28  Gurpreet Kaur  <k.gurpreet@samsung.com>
    222
  • trunk/LayoutTests/inspector-protocol/debugger/resources/breakpoint.js

    r155132 r162940  
    1818    log("inside breakpointActions a:(" + a + ") b:(" + b + ")");
    1919}
     20
     21function notInlineable(x)
     22{
     23    var func = new Function("return x + 100;");
     24    return x + 3;
     25}
     26
     27function inlineable(x)
     28{
     29    return x + 5;
     30}
     31
     32function notInliningFoo(x)
     33{
     34    return notInlineable(x);
     35}
     36
     37function inliningFoo(x)
     38{
     39    return inlineable(x);
     40}
     41
     42function dfgWithoutInline()
     43{
     44    var i;
     45    var result = 0;
     46    for (i = 0; i < 1000; i++)
     47        result += notInliningFoo(i);
     48    log("dfgWithoutInline result: " + result);   
     49}
     50
     51function dfgWithInline()
     52{
     53    var i;
     54    var result = 0;
     55    for (i = 0; i < 1000; i++)
     56        result += inliningFoo(i);
     57    log("dfgWithInline result: " + result);   
     58}
  • trunk/Source/JavaScriptCore/ChangeLog

    r162918 r162940  
     12014-01-28  Mark Lam  <mark.lam@apple.com>
     2
     3        Jettison DFG code when neither breakpoints or the profiler are active.
     4        <https://webkit.org/b/127766>
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        We need to jettison the DFG CodeBlocks under the following circumstances:
     9        1. When adding breakpoints to a CodeBlock, jettison it if it is a DFG CodeBlock.
     10        2. When enabling stepping mode in a CodeBlock, jettison it if it a DFG CodeBlock.
     11        3. When settign the enabled profiler in the VM, we need to jettison all DFG
     12           CodeBlocks.
     13
     14        Instead of emitting speculation checks, the DFG code will now treat Breakpoint,
     15        ProfileWillCall, and ProfileDidCall as no-ops similar to a Phantom node. We
     16        still need to track these nodes so that they match the corresponding opcodes
     17        in the baseline JIT when we jettison and OSR exit. Without them, we would OSR
     18        exit to the wrong location in the baseline JIT code.
     19
     20        In DFGDriver's compileImpl() and DFGPlan's finalizeWithoutNotifyingCallback()
     21        we fail the compilation effort with a CompilationInvalidated result. This allows
     22        the DFG compiler to re-attampt the compilation of the function after some time
     23        if it is hot. The CompilationInvalidated result is supposed to cause the DFG
     24        to exercise an exponential back off before re-attempting compilation again
     25        (see runtime/CompilationResult.h).
     26
     27        This patch improves the Octane score from ~2950 to ~3067.
     28
     29        * bytecode/CodeBlock.cpp:
     30        (JSC::CodeBlock::addBreakpoint):
     31        (JSC::CodeBlock::setSteppingMode):
     32        * bytecode/CodeBlock.h:
     33        * debugger/Debugger.h:
     34        * dfg/DFGAbstractInterpreterInlines.h:
     35        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     36        * dfg/DFGClobberize.h:
     37        (JSC::DFG::clobberize):
     38        * dfg/DFGDriver.cpp:
     39        (JSC::DFG::compileImpl):
     40        * dfg/DFGPlan.cpp:
     41        (JSC::DFG::Plan::finalizeWithoutNotifyingCallback):
     42        * dfg/DFGSpeculativeJIT32_64.cpp:
     43        (JSC::DFG::SpeculativeJIT::compile):
     44        * dfg/DFGSpeculativeJIT64.cpp:
     45        (JSC::DFG::SpeculativeJIT::compile):
     46        * profiler/LegacyProfiler.cpp:
     47        (JSC::LegacyProfiler::startProfiling):
     48        (JSC::LegacyProfiler::stopProfiling):
     49        * runtime/VM.cpp:
     50        (JSC::VM::VM):
     51        (JSC::SetEnabledProfilerFunctor::operator()):
     52        (JSC::VM::setEnabledProfiler):
     53        * runtime/VM.h:
     54        (JSC::VM::enabledProfiler):
     55
    1562014-01-27  Joseph Pecoraro  <pecoraro@apple.com>
    257
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r162906 r162940  
    35323532}
    35333533
     3534void CodeBlock::addBreakpoint(unsigned numBreakpoints)
     3535{
     3536    m_numBreakpoints += numBreakpoints;
     3537    ASSERT(m_numBreakpoints);
     3538    if (jitType() == JITCode::DFGJIT)
     3539        jettison();
     3540}
     3541
     3542void CodeBlock::setSteppingMode(CodeBlock::SteppingMode mode)
     3543{
     3544    m_steppingMode = mode;
     3545    if (mode == SteppingModeEnabled && jitType() == JITCode::DFGJIT)
     3546        jettison();
     3547}
     3548
    35343549} // namespace JSC
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r162845 r162940  
    873873    void* debuggerRequestsAddress() { return &m_debuggerRequests; }
    874874
    875     void addBreakpoint(unsigned numBreakpoints) { m_numBreakpoints += numBreakpoints; }
     875    void addBreakpoint(unsigned numBreakpoints);
    876876    void removeBreakpoint(unsigned numBreakpoints)
    877877    {
     
    884884        SteppingModeEnabled
    885885    };
    886     void setSteppingMode(SteppingMode mode) { m_steppingMode = mode; }
     886    void setSteppingMode(SteppingMode);
    887887
    888888    void clearDebuggerRequests() { m_debuggerRequests = 0; }
  • trunk/Source/JavaScriptCore/debugger/Debugger.h

    r162735 r162940  
    9191
    9292    bool isPaused() { return m_isPaused; }
     93    bool isStepping() const { return m_steppingMode == SteppingModeEnabled; }
    9394
    9495    virtual void sourceParsed(ExecState*, SourceProvider*, int errorLineNumber, const WTF::String& errorMessage) = 0;
     
    171172    };
    172173    void setSteppingMode(SteppingMode);
    173     bool isStepping() const { return m_steppingMode == SteppingModeEnabled; }
    174174
    175175    enum BreakpointState {
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r162718 r162940  
    17551755        break;
    17561756
     1757    case CheckWatchdogTimer:
     1758        node->setCanExit(true);
     1759        break;
     1760
    17571761    case Breakpoint:
    17581762    case ProfileWillCall:
    17591763    case ProfileDidCall:
    1760     case CheckWatchdogTimer:
    1761         node->setCanExit(true);
    1762         break;
    1763 
    17641764    case Phantom:
    17651765    case Check:
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r162718 r162940  
    8989    case Identity:
    9090    case Phantom:
     91    case Breakpoint:
     92    case ProfileWillCall:
     93    case ProfileDidCall:
    9194    case BitAnd:
    9295    case BitOr:
     
    619622        return;
    620623       
    621     case Breakpoint:
    622     case ProfileWillCall:
    623     case ProfileDidCall:
    624624    case CountExecution:
    625625    case CheckWatchdogTimer:
  • trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp

    r159276 r162940  
    3535#include "DFGThunks.h"
    3636#include "DFGWorklist.h"
     37#include "Debugger.h"
    3738#include "JITCode.h"
    3839#include "Operations.h"
     
    7475        return CompilationFailed;
    7576   
     77    if (vm.enabledProfiler())
     78        return CompilationInvalidated;
     79
     80    Debugger* debugger = codeBlock->globalObject()->debugger();
     81    if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests()))
     82        return CompilationInvalidated;
     83
    7684    if (logCompilationChanges())
    7785        dataLog("DFG(Driver) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
  • trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp

    r160796 r162940  
    6363#include "DFGVirtualRegisterAllocationPhase.h"
    6464#include "DFGWatchpointCollectionPhase.h"
     65#include "Debugger.h"
    6566#include "OperandsInlines.h"
    6667#include "Operations.h"
     
    347348    if (!isStillValid())
    348349        return CompilationInvalidated;
    349    
     350
     351    if (vm.enabledProfiler())
     352        return CompilationInvalidated;
     353
     354    Debugger* debugger = codeBlock->globalObject()->debugger();
     355    if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests()))
     356        return CompilationInvalidated;
     357
    350358    bool result;
    351359    if (codeBlock->codeType() == FunctionCode)
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r162718 r162940  
    42334233        break;
    42344234
    4235     case Breakpoint: {
    4236         GPRTemporary temp(this);
    4237         GPRReg debuggerRequestsGPR = temp.gpr();
    4238         m_jit.load32(m_jit.codeBlock()->debuggerRequestsAddress(), debuggerRequestsGPR);
    4239         speculationCheck(
    4240             DebuggerEvent, JSValueRegs(), 0,
    4241             m_jit.branchTest32(JITCompiler::NonZero, debuggerRequestsGPR));
    4242         break;
    4243     }
    4244 
    4245     case ProfileWillCall:
    4246     case ProfileDidCall: {
    4247         GPRTemporary temp(this);
    4248         m_jit.loadPtr(m_jit.vm()->enabledProfilerAddress(), temp.gpr());
    4249         speculationCheck(
    4250             DebuggerEvent, JSValueRegs(), 0,
    4251             m_jit.branchTestPtr(JITCompiler::NonZero, temp.gpr()));
    4252         break;
    4253     }
    4254 
    42554235    case Call:
    42564236    case Construct:
     
    46914671        break;
    46924672
     4673    case Breakpoint:
     4674    case ProfileWillCall:
     4675    case ProfileDidCall:
    46934676    case PhantomLocal:
    46944677    case LoopHint:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r162906 r162940  
    45254525        break;
    45264526
    4527     case Breakpoint: {
    4528         GPRTemporary temp(this);
    4529         GPRReg debuggerRequestsGPR = temp.gpr();
    4530         m_jit.load32(m_jit.codeBlock()->debuggerRequestsAddress(), debuggerRequestsGPR);
    4531         speculationCheck(
    4532             DebuggerEvent, JSValueRegs(), 0,
    4533             m_jit.branchTest32(JITCompiler::NonZero, debuggerRequestsGPR));
    4534         break;
    4535     }
    4536 
    4537     case ProfileWillCall:
    4538     case ProfileDidCall:
    4539         speculationCheck(
    4540             DebuggerEvent, JSValueRegs(), 0,
    4541             m_jit.branchTestPtr(
    4542                 JITCompiler::NonZero,
    4543                 JITCompiler::AbsoluteAddress(m_jit.vm()->enabledProfilerAddress())));
    4544         break;
    4545 
    45464527    case Call:
    45474528    case Construct:
     
    49404921        break;
    49414922       
     4923    case Breakpoint:
     4924    case ProfileWillCall:
     4925    case ProfileDidCall:
    49424926    case PhantomLocal:
    49434927    case LoopHint:
  • trunk/Source/JavaScriptCore/profiler/LegacyProfiler.cpp

    r159937 r162940  
    7676    }
    7777
    78     exec->vm().m_enabledProfiler = this;
     78    exec->vm().setEnabledProfiler(this);
    7979    RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID);
    8080    m_currentProfiles.append(profileGenerator);
     
    9595            m_currentProfiles.remove(i);
    9696            if (!m_currentProfiles.size())
    97                 exec->vm().m_enabledProfiler = 0;
     97                exec->vm().setEnabledProfiler(nullptr);
    9898           
    9999            return returnProfile;
     
    112112            m_currentProfiles.remove(i);
    113113            if (!m_currentProfiles.size())
    114                 origin->vm().m_enabledProfiler = 0;
     114                origin->vm().setEnabledProfiler(nullptr);
    115115        }
    116116    }
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r161241 r162940  
    198198    , sizeOfLastScratchBuffer(0)
    199199    , entryScope(0)
    200     , m_enabledProfiler(0)
    201200    , m_regExpCache(new RegExpCache(this))
    202201#if ENABLE(REGEXP_TRACING)
     
    223222    , m_inDefineOwnProperty(false)
    224223    , m_codeCache(CodeCache::create())
     224    , m_enabledProfiler(nullptr)
    225225{
    226226    interpreter = new Interpreter(*this);
     
    781781}
    782782
     783class SetEnabledProfilerFunctor {
     784public:
     785    bool operator()(CodeBlock* codeBlock)
     786    {
     787        if (codeBlock->jitType() == JITCode::DFGJIT)
     788            codeBlock->jettison();
     789        return false;
     790    }
     791};
     792
     793void VM::setEnabledProfiler(LegacyProfiler* profiler)
     794{
     795    m_enabledProfiler = profiler;
     796    if (m_enabledProfiler) {
     797        SetEnabledProfilerFunctor functor;
     798        heap.forEachCodeBlock(functor);
     799    }
     800}
     801
    783802} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r162718 r162940  
    305305        }
    306306
    307         LegacyProfiler* enabledProfiler()
    308         {
    309             return m_enabledProfiler;
    310         }
     307        LegacyProfiler* enabledProfiler() { return m_enabledProfiler; }
     308        void setEnabledProfiler(LegacyProfiler*);
     309
    311310        void* enabledProfilerAddress() { return &m_enabledProfiler; }
    312311
     
    433432        double cachedDateStringValue;
    434433
    435         LegacyProfiler* m_enabledProfiler;
    436434        OwnPtr<Profiler::Database> m_perBytecodeProfiler;
    437435        RefPtr<TypedArrayController> m_typedArrayController;
     
    525523        RefCountedArray<StackFrame> m_exceptionStack;
    526524
     525        LegacyProfiler* m_enabledProfiler;
     526
    527527        HashMap<String, RefPtr<WatchpointSet>> m_impurePropertyWatchpointSets;
    528528    };
Note: See TracChangeset for help on using the changeset viewer.