Changeset 162652 in webkit


Ignore:
Timestamp:
Jan 23, 2014 3:13:23 PM (10 years ago)
Author:
mark.lam@apple.com
Message:

Enable DFG for the Debugger and Profiler.
<https://webkit.org/b/122847>

Reviewed by Geoffrey Garen.

In this patch, we implement DFG op_debug as a series of 3 checks:

  1. Check if the debugger pointer is non-null. This is needed in case the debugger has been detached but the DFG code is still running on the stack.
  2. Check if Debugger::m_shouldPause is true.
  3. Check if CodeBlock::m_numBreakpoints is non-zero.

These are the same 3 checks done in the LLINT and baselineJIT. But unlike
the LLINT and baselineJIT, these DFG checks are implemented as
speculationChecks. If the check fails, we OSR exit to the baselineJIT and
let it do the work of servicing the op_debug callback.

Stepping through code in the debugger would work the same way. The top
function being debugged has to be a LLINT or baselineJIT function because
we would have OSR exited if there is a breakpoint in that function. When
we step out of that function to its caller, we expect that the caller will
call back to the debugger at the next op_debug. If the caller function is
a DFG function, the op_debug site will fail its speculation check on
Debugger::m_shouldPause and deopt into a baselineJIT function. Execution
continues from there as usual, and the debugger gets its callback.

For the profile, op_profile_will_call and op_profile_did_call are
implemented as simple runtime calls to service the profiler.

With this patch, Octane performance with the WebInspector open jump from
~2000 to ~2500 (25% progression).

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::numBreakpointsAddress):

  • bytecode/ExitKind.cpp:

(JSC::exitKindToString):

  • bytecode/ExitKind.h:
  • debugger/Debugger.cpp:

(JSC::Debugger::toggleBreakpoint):

  • removed an obsolete assertion. The debugger can now handle DFG CodeBlocks too.
  • debugger/Debugger.h:
  • dfg/DFGAbstractInterpreterInlines.h:

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

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNodeType.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::debuggerAddress):

Location:
trunk/Source/JavaScriptCore
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r162644 r162652  
     12014-01-23  Mark Lam  <mark.lam@apple.com>
     2
     3        Enable DFG for the Debugger and Profiler.
     4        <https://webkit.org/b/122847>
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        In this patch, we implement DFG op_debug as a series of 3 checks:
     9        1. Check if the debugger pointer is non-null. This is needed in case
     10           the debugger has been detached but the DFG code is still running
     11           on the stack.
     12        2. Check if Debugger::m_shouldPause is true.
     13        3. Check if CodeBlock::m_numBreakpoints is non-zero.
     14
     15        These are the same 3 checks done in the LLINT and baselineJIT. But unlike
     16        the LLINT and baselineJIT, these DFG checks are implemented as
     17        speculationChecks. If the check fails, we OSR exit to the baselineJIT and
     18        let it do the work of servicing the op_debug callback.
     19
     20        Stepping through code in the debugger would work the same way. The top
     21        function being debugged has to be a LLINT or baselineJIT function because
     22        we would have OSR exited if there is a breakpoint in that function. When
     23        we step out of that function to its caller, we expect that the caller will
     24        call back to the debugger at the next op_debug. If the caller function is
     25        a DFG function, the op_debug site will fail its speculation check on
     26        Debugger::m_shouldPause and deopt into a baselineJIT function. Execution
     27        continues from there as usual, and the debugger gets its callback.
     28
     29        For the profile, op_profile_will_call and op_profile_did_call are
     30        implemented as simple runtime calls to service the profiler.
     31
     32        With this patch, Octane performance with the WebInspector open jump from
     33        ~2000 to ~2500 (25% progression).
     34
     35        * bytecode/CodeBlock.h:
     36        (JSC::CodeBlock::numBreakpointsAddress):
     37        * bytecode/ExitKind.cpp:
     38        (JSC::exitKindToString):
     39        * bytecode/ExitKind.h:
     40        * debugger/Debugger.cpp:
     41        (JSC::Debugger::toggleBreakpoint):
     42        - removed an obsolete assertion. The debugger can now handle DFG
     43          CodeBlocks too.
     44        * debugger/Debugger.h:
     45        * dfg/DFGAbstractInterpreterInlines.h:
     46        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     47        * dfg/DFGByteCodeParser.cpp:
     48        (JSC::DFG::ByteCodeParser::parseBlock):
     49        * dfg/DFGCapabilities.cpp:
     50        (JSC::DFG::capabilityLevel):
     51        * dfg/DFGClobberize.h:
     52        (JSC::DFG::clobberize):
     53        * dfg/DFGFixupPhase.cpp:
     54        (JSC::DFG::FixupPhase::fixupNode):
     55        * dfg/DFGNodeType.h:
     56        * dfg/DFGPredictionPropagationPhase.cpp:
     57        (JSC::DFG::PredictionPropagationPhase::propagate):
     58        * dfg/DFGSafeToExecute.h:
     59        (JSC::DFG::safeToExecute):
     60        * dfg/DFGSpeculativeJIT.h:
     61        (JSC::DFG::SpeculativeJIT::callOperation):
     62        * dfg/DFGSpeculativeJIT32_64.cpp:
     63        (JSC::DFG::SpeculativeJIT::compile):
     64        * dfg/DFGSpeculativeJIT64.cpp:
     65        (JSC::DFG::SpeculativeJIT::compile):
     66        * runtime/JSGlobalObject.h:
     67        (JSC::JSGlobalObject::debuggerAddress):
     68
    1692014-01-23  Max Vujovic  <mvujovic@adobe.com>
    270
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r162598 r162652  
    874874    int numBreakpoints() const { return m_numBreakpoints; }
    875875    static ptrdiff_t numBreakpointsOffset() { return OBJECT_OFFSETOF(CodeBlock, m_numBreakpoints); }
     876    void* numBreakpointsAddress() { return &m_numBreakpoints; }
    876877
    877878    void addBreakpoint(int numBreakpoints) { m_numBreakpoints += numBreakpoints; }
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp

    r160347 r162652  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    7979    case WatchdogTimerFired:
    8080        return "WatchdogTimerFired";
     81    case DebuggerEvent:
     82        return "DebuggerEvent";
    8183    }
    8284    RELEASE_ASSERT_NOT_REACHED();
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.h

    r160347 r162652  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5151    UncountableInvalidation, // We exited because the code block was invalidated; this means that we've already counted the reasons why the code block was invalidated.
    5252    UncountableWatchpoint, // We exited because of a watchpoint, which isn't counted because watchpoints do tracking themselves.
    53     WatchdogTimerFired // We exited because we need to service the watchdog timer.
     53    WatchdogTimerFired, // We exited because we need to service the watchdog timer.
     54    DebuggerEvent // We exited because we need to service the debugger.
    5455};
    5556
  • trunk/Source/JavaScriptCore/debugger/Debugger.cpp

    r162598 r162652  
    212212void Debugger::toggleBreakpoint(CodeBlock* codeBlock, Breakpoint& breakpoint, BreakpointState enabledOrNot)
    213213{
    214     ASSERT(codeBlock->jitCode()->jitType() == JITCode::InterpreterThunk
    215         || codeBlock->jitCode()->jitType() == JITCode::BaselineJIT);
    216 
    217214    ScriptExecutable* executable = codeBlock->ownerExecutable();
    218215
  • trunk/Source/JavaScriptCore/debugger/Debugger.h

    r162598 r162652  
    5151    bool shouldPause() const { return m_shouldPause; }
    5252    static ptrdiff_t shouldPauseOffset() { return OBJECT_OFFSETOF(Debugger, m_shouldPause); }
     53    void* shouldPauseAddress() { return &m_shouldPause; }
    5354
    5455    JSC::DebuggerCallFrame* currentDebuggerCallFrame() const;
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r161574 r162652  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    17371737    case Flush:
    17381738    case PhantomLocal:
    1739     case Breakpoint:
    17401739        break;
    17411740           
     
    17551754        node->setCanExit(true);
    17561755        break;
    1757            
     1756
     1757    case Breakpoint:
    17581758    case CheckWatchdogTimer:
    17591759        node->setCanExit(true);
    17601760        break;
    1761            
     1761
     1762    case ProfileWillCall:
     1763    case ProfileDidCall:
    17621764    case Phantom:
    17631765    case Check:
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r161465 r162652  
    11/*
    2  * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    21472147        // === Misc operations ===
    21482148
    2149 #if ENABLE(DEBUG_WITH_BREAKPOINT)
    21502149        case op_debug:
    21512150            addToGraph(Breakpoint);
    21522151            NEXT_OPCODE(op_debug);
    2153 #endif
     2152
     2153        case op_profile_will_call: {
     2154            Node* profile = get(VirtualRegister(currentInstruction[1].u.operand));
     2155            addToGraph(ProfileWillCall, profile);
     2156            NEXT_OPCODE(op_profile_will_call);
     2157        }
     2158
     2159        case op_profile_did_call: {
     2160            Node* profile = get(VirtualRegister(currentInstruction[1].u.operand));
     2161            addToGraph(ProfileDidCall, profile);
     2162            NEXT_OPCODE(op_profile_did_call);
     2163        }
     2164
    21542165        case op_mov: {
    21552166            Node* op = get(VirtualRegister(currentInstruction[2].u.operand));
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r160587 r162652  
    11/*
    2  * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    101101    case op_mod:
    102102    case op_div:
    103 #if ENABLE(DEBUG_WITH_BREAKPOINT)
    104103    case op_debug:
    105 #endif
     104    case op_profile_will_call:
     105    case op_profile_did_call:
    106106    case op_mov:
    107107    case op_captured_mov:
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r161218 r162652  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    140140    case PhantomLocal:
    141141    case SetArgument:
    142     case Breakpoint:
     142    case ProfileWillCall:
     143    case ProfileDidCall:
    143144    case PhantomArguments:
    144145    case Jump:
     
    620621        return;
    621622       
     623    case Breakpoint:
    622624    case CountExecution:
    623625    case CheckWatchdogTimer:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r161465 r162652  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    992992        case NewRegexp:
    993993        case Breakpoint:
     994        case ProfileWillCall:
     995        case ProfileDidCall:
    994996        case IsUndefined:
    995997        case IsBoolean:
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r161218 r162652  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    231231    \
    232232    /* Nodes for misc operations. */\
    233     macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
     233    macro(Breakpoint, NodeMustGenerate) \
     234    macro(ProfileWillCall, NodeMustGenerate | NodeClobbersWorld) \
     235    macro(ProfileDidCall, NodeMustGenerate | NodeClobbersWorld) \
    234236    macro(CheckHasInstance, NodeMustGenerate) \
    235237    macro(InstanceOf, NodeResultBoolean) \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r161465 r162652  
    11/*
    2  * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    555555        case Switch:
    556556        case Breakpoint:
     557        case ProfileWillCall:
     558        case ProfileDidCall:
    557559        case CheckHasInstance:
    558560        case ThrowReferenceError:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r161126 r162652  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    194194    case NewRegexp:
    195195    case Breakpoint:
     196    case ProfileWillCall:
     197    case ProfileDidCall:
    196198    case CheckHasInstance:
    197199    case InstanceOf:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r161399 r162652  
    11/*
    2  * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    13731373        return appendCallWithExceptionCheck(operation);
    13741374    }
     1375    JITCompiler::Call callOperation(V_JITOperation_EJ operation, GPRReg arg1)
     1376    {
     1377        m_jit.setupArgumentsWithExecState(arg1);
     1378        return appendCallWithExceptionCheck(operation);
     1379    }
    13751380    JITCompiler::Call callOperation(V_JITOperation_EJPP operation, GPRReg arg1, GPRReg arg2, void* pointer)
    13761381    {
     
    16281633    {
    16291634        m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3);
     1635        return appendCallWithExceptionCheck(operation);
     1636    }
     1637
     1638    JITCompiler::Call callOperation(V_JITOperation_EJ operation, GPRReg arg1Tag, GPRReg arg1Payload)
     1639    {
     1640        m_jit.setupArgumentsWithExecState(arg1Tag, arg1Payload);
    16301641        return appendCallWithExceptionCheck(operation);
    16311642    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r161411 r162652  
    11/*
    2  * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 * Copyright (C) 2011 Intel Corporation. All rights reserved.
    44 *
     
    3535#include "DFGOperations.h"
    3636#include "DFGSlowPathGenerator.h"
     37#include "Debugger.h"
    3738#include "JSActivation.h"
    3839#include "ObjectPrototype.h"
     
    42324233        break;
    42334234
    4234     case Breakpoint:
    4235 #if ENABLE(DEBUG_WITH_BREAKPOINT)
    4236         m_jit.breakpoint();
    4237 #else
    4238         RELEASE_ASSERT_NOT_REACHED();
    4239 #endif
    4240         break;
    4241        
     4235    case Breakpoint: {
     4236        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin);
     4237        GPRTemporary temp(this);
     4238        m_jit.loadPtr(globalObject->debuggerAddress(), temp.gpr());
     4239        speculationCheck(
     4240            DebuggerEvent, JSValueRegs(), 0,
     4241            m_jit.branchTestPtr(JITCompiler::Zero, temp.gpr()));
     4242
     4243        ASSERT(globalObject->hasDebugger());
     4244        speculationCheck(
     4245            DebuggerEvent, JSValueRegs(), 0,
     4246            m_jit.branchTest8(
     4247                JITCompiler::NonZero,
     4248                JITCompiler::AbsoluteAddress(globalObject->debugger()->shouldPauseAddress())));
     4249
     4250        GPRReg numBreakpointsGPR = temp.gpr();
     4251        m_jit.load32(m_jit.codeBlock()->numBreakpointsAddress(), numBreakpointsGPR);
     4252        speculationCheck(
     4253            DebuggerEvent, JSValueRegs(), 0,
     4254            m_jit.branchTest32(JITCompiler::NonZero, numBreakpointsGPR));
     4255        break;
     4256    }
     4257       
     4258    case ProfileWillCall: {
     4259        JSValueOperand profile(this, node->child1());
     4260        GPRReg profileTagGPR = profile.tagGPR();
     4261        GPRReg profilePayloadGPR = profile.payloadGPR();
     4262        silentSpillAllRegisters(InvalidGPRReg);
     4263        callOperation(operationProfileWillCall, profileTagGPR, profilePayloadGPR);
     4264        silentFillAllRegisters(InvalidGPRReg);
     4265        noResult(node);
     4266        break;
     4267    }
     4268
     4269    case ProfileDidCall: {
     4270        JSValueOperand profile(this, node->child1());
     4271        GPRReg profileTagGPR = profile.tagGPR();
     4272        GPRReg profilePayloadGPR = profile.payloadGPR();
     4273        silentSpillAllRegisters(InvalidGPRReg);
     4274        callOperation(operationProfileWillCall, profileTagGPR, profilePayloadGPR);
     4275        silentFillAllRegisters(InvalidGPRReg);
     4276        noResult(node);
     4277        break;
     4278    }
     4279
    42424280    case Call:
    42434281    case Construct:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r162139 r162652  
    11/*
    2  * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535#include "DFGOperations.h"
    3636#include "DFGSlowPathGenerator.h"
     37#include "Debugger.h"
    3738#include "JSCJSValueInlines.h"
    3839#include "ObjectPrototype.h"
     
    45094510        break;
    45104511
    4511     case Breakpoint:
    4512 #if ENABLE(DEBUG_WITH_BREAKPOINT)
    4513         m_jit.breakpoint();
    4514 #else
    4515         RELEASE_ASSERT_NOT_REACHED();
    4516 #endif
    4517         break;
    4518        
     4512    case Breakpoint: {
     4513        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin);
     4514        speculationCheck(
     4515            DebuggerEvent, JSValueRegs(), 0,
     4516            m_jit.branchTestPtr(
     4517                JITCompiler::Zero,
     4518                JITCompiler::AbsoluteAddress(globalObject->debuggerAddress())));
     4519
     4520        ASSERT(globalObject->hasDebugger());
     4521        speculationCheck(
     4522            DebuggerEvent, JSValueRegs(), 0,
     4523            m_jit.branchTest8(
     4524                JITCompiler::NonZero,
     4525                JITCompiler::AbsoluteAddress(globalObject->debugger()->shouldPauseAddress())));
     4526
     4527        GPRTemporary temp(this);
     4528        GPRReg numBreakpointsGPR = temp.gpr();
     4529        m_jit.load32(m_jit.codeBlock()->numBreakpointsAddress(), numBreakpointsGPR);
     4530        speculationCheck(
     4531            DebuggerEvent, JSValueRegs(), 0,
     4532            m_jit.branchTest32(JITCompiler::NonZero, numBreakpointsGPR));
     4533        break;
     4534    }
     4535       
     4536    case ProfileWillCall: {
     4537        JSValueOperand profile(this, node->child1());
     4538        GPRReg profileGPR = profile.gpr();
     4539        silentSpillAllRegisters(InvalidGPRReg);
     4540        callOperation(operationProfileWillCall, profileGPR);
     4541        silentFillAllRegisters(InvalidGPRReg);
     4542        noResult(node);
     4543        break;
     4544    }
     4545
     4546    case ProfileDidCall: {
     4547        JSValueOperand profile(this, node->child1());
     4548        GPRReg profileGPR = profile.gpr();
     4549        silentSpillAllRegisters(InvalidGPRReg);
     4550        callOperation(operationProfileDidCall, profileGPR);
     4551        silentFillAllRegisters(InvalidGPRReg);
     4552        noResult(node);
     4553        break;
     4554    }
     4555
    45194556    case Call:
    45204557    case Construct:
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r161241 r162652  
    11/*
    22 *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
    3  *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2007, 2008, 2009, 2014 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    474474    void setDebugger(Debugger* debugger) { m_debugger = debugger; }
    475475    static ptrdiff_t debuggerOffset() { return OBJECT_OFFSETOF(JSGlobalObject, m_debugger); }
     476    void* debuggerAddress() { return &m_debugger; }
    476477
    477478    const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }
Note: See TracChangeset for help on using the changeset viewer.