Changeset 157746 in webkit


Ignore:
Timestamp:
Oct 21, 2013, 3:00:40 PM (11 years ago)
Author:
mark.lam@apple.com
Message:

Avoid JSC debugger overhead unless needed.
https://bugs.webkit.org/show_bug.cgi?id=123084.

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

  • If no breakpoints are set, we now avoid calling the debug hook callbacks.
  • If no break on exception is set, we also avoid exception event debug callbacks.
  • When we return from the ScriptDebugServer to the JSC::Debugger, we may no longer call the debug hook callbacks if not needed. Hence, the m_currentCallFrame pointer in the ScriptDebugServer may become stale. To avoid this issue, before returning, the ScriptDebugServer will clear its m_currentCallFrame if needsOpDebugCallbacks() is false.
  • debugger/Debugger.cpp:

(JSC::Debugger::Debugger):
(JSC::Debugger::setNeedsExceptionCallbacks):
(JSC::Debugger::setShouldPause):
(JSC::Debugger::updateNumberOfBreakpoints):
(JSC::Debugger::updateNeedForOpDebugCallbacks):

  • debugger/Debugger.h:
  • interpreter/Interpreter.cpp:

(JSC::Interpreter::unwind):
(JSC::Interpreter::debug):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_debug):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_debug):

  • llint/LLIntOffsetsExtractor.cpp:
  • llint/LowLevelInterpreter.asm:

Source/WebCore:

No new tests.

  • If no breakpoints are set, we now avoid calling the debug hook callbacks.
  • If no break on exception is set, we also avoid exception event debug callbacks.
  • When we return from the ScriptDebugServer to the JSC::Debugger, we may no longer call the debug hook callbacks if not needed. Hence, the m_currentCallFrame pointer in the ScriptDebugServer may become stale. To avoid this issue, before returning, the ScriptDebugServer will clear its m_currentCallFrame if needsOpDebugCallbacks() is false.
  • bindings/js/ScriptDebugServer.cpp:

(WebCore::ScriptDebugServer::setBreakpoint):
(WebCore::ScriptDebugServer::removeBreakpoint):
(WebCore::ScriptDebugServer::clearBreakpoints):
(WebCore::ScriptDebugServer::setPauseOnExceptionsState):
(WebCore::ScriptDebugServer::setPauseOnNextStatement):
(WebCore::ScriptDebugServer::breakProgram):
(WebCore::ScriptDebugServer::stepIntoStatement):
(WebCore::ScriptDebugServer::dispatchDidContinue):
(WebCore::ScriptDebugServer::exception):
(WebCore::ScriptDebugServer::didReachBreakpoint):

  • inspector/InspectorDebuggerAgent.cpp:

(WebCore::InspectorDebuggerAgent::reset):

Source/WebKit/mac:

  • WebView/WebScriptDebugger.mm:

(WebScriptDebugger::WebScriptDebugger):

Location:
trunk/Source
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r157737 r157746  
     12013-10-20  Mark Lam  <mark.lam@apple.com>
     2
     3        Avoid JSC debugger overhead unless needed.
     4        https://bugs.webkit.org/show_bug.cgi?id=123084.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        - If no breakpoints are set, we now avoid calling the debug hook callbacks.
     9        - If no break on exception is set, we also avoid exception event debug callbacks.
     10        - When we return from the ScriptDebugServer to the JSC::Debugger, we may no
     11          longer call the debug hook callbacks if not needed. Hence, the m_currentCallFrame
     12          pointer in the ScriptDebugServer may become stale. To avoid this issue, before
     13          returning, the ScriptDebugServer will clear its m_currentCallFrame if
     14          needsOpDebugCallbacks() is false.
     15
     16        * debugger/Debugger.cpp:
     17        (JSC::Debugger::Debugger):
     18        (JSC::Debugger::setNeedsExceptionCallbacks):
     19        (JSC::Debugger::setShouldPause):
     20        (JSC::Debugger::updateNumberOfBreakpoints):
     21        (JSC::Debugger::updateNeedForOpDebugCallbacks):
     22        * debugger/Debugger.h:
     23        * interpreter/Interpreter.cpp:
     24        (JSC::Interpreter::unwind):
     25        (JSC::Interpreter::debug):
     26        * jit/JITOpcodes.cpp:
     27        (JSC::JIT::emit_op_debug):
     28        * jit/JITOpcodes32_64.cpp:
     29        (JSC::JIT::emit_op_debug):
     30        * llint/LLIntOffsetsExtractor.cpp:
     31        * llint/LowLevelInterpreter.asm:
     32
    1332013-10-21  Brent Fulgham  <bfulgham@apple.com>
    234
  • trunk/Source/JavaScriptCore/debugger/Debugger.cpp

    r157468 r157746  
    9292namespace JSC {
    9393
     94Debugger::Debugger()
     95    : m_needsExceptionCallbacks(false)
     96    , m_needsOpDebugCallbacks(false)
     97    , m_shouldPause(false)
     98    , m_numberOfBreakpoints(0)
     99{
     100}
     101
    94102Debugger::~Debugger()
    95103{
     
    113121}
    114122
     123void Debugger::setNeedsExceptionCallbacks(bool value)
     124{
     125    m_needsExceptionCallbacks = value;
     126}
     127
     128void Debugger::setShouldPause(bool value)
     129{
     130    m_shouldPause = value;
     131    updateNeedForOpDebugCallbacks();
     132}
     133
    115134void Debugger::recompileAllJSFunctions(VM* vm)
    116135{
     
    128147}
    129148
     149void Debugger::updateNumberOfBreakpoints(int numberOfBreakpoints)
     150{
     151    ASSERT(numberOfBreakpoints >= 0);
     152    m_numberOfBreakpoints = numberOfBreakpoints;
     153    updateNeedForOpDebugCallbacks();
     154}
     155
     156void Debugger::updateNeedForOpDebugCallbacks()
     157{
     158    m_needsOpDebugCallbacks = m_shouldPause || m_numberOfBreakpoints;
     159}
     160
    130161} // namespace JSC
  • trunk/Source/JavaScriptCore/debugger/Debugger.h

    r156936 r157746  
    3838class JS_EXPORT_PRIVATE Debugger {
    3939public:
     40    Debugger();
    4041    virtual ~Debugger();
     42
     43    bool needsOpDebugCallbacks() const { return m_needsOpDebugCallbacks; }
     44    static ptrdiff_t needsOpDebugCallbacksOffset() { return OBJECT_OFFSETOF(Debugger, m_needsOpDebugCallbacks); }
     45
     46    bool shouldPause() const { return m_shouldPause; }
     47    void setShouldPause(bool);
     48
     49    bool needsExceptionCallbacks() const { return m_needsExceptionCallbacks; }
     50    void setNeedsExceptionCallbacks(bool);
     51
     52    void incNumberOfBreakpoints() { updateNumberOfBreakpoints(m_numberOfBreakpoints + 1); }
     53    void decNumberOfBreakpoints()  { updateNumberOfBreakpoints(m_numberOfBreakpoints - 1); }
     54    void updateNumberOfBreakpoints(int);
    4155
    4256    void attach(JSGlobalObject*);
     
    5771
    5872private:
     73    void updateNeedForOpDebugCallbacks();
     74
    5975    HashSet<JSGlobalObject*> m_globalObjects;
     76
     77    bool m_needsExceptionCallbacks;
     78    bool m_needsOpDebugCallbacks;
     79    bool m_shouldPause;
     80    int m_numberOfBreakpoints;
     81
     82    friend class LLIntOffsetsExtractor;
    6083};
    6184
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r156984 r157746  
    651651    ASSERT(!exceptionValue.isObject() || asObject(exceptionValue)->hasProperty(callFrame, callFrame->vm().propertyNames->stack));
    652652
    653     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
     653    Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
     654    if (debugger && debugger->needsExceptionCallbacks()) {
    654655        // We need to clear the exception and the exception stack here in order to see if a new exception happens.
    655656        // Afterwards, the values are put back to continue processing this error.
     
    12521253{
    12531254    Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
    1254     if (!debugger)
     1255    if (!debugger || !debugger->needsOpDebugCallbacks())
    12551256        return;
    12561257
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r157636 r157746  
    3131#include "Arguments.h"
    3232#include "CopiedSpaceInlines.h"
     33#include "Debugger.h"
    3334#include "Heap.h"
    3435#include "JITInlines.h"
     
    728729    breakpoint();
    729730#else
     731    JSGlobalObject* globalObject = codeBlock()->globalObject();
     732    Debugger* debugger = globalObject->debugger();
     733    char* debuggerAddress = reinterpret_cast<char*>(globalObject) + JSGlobalObject::debuggerOffset();
     734    Jump noDebugger = branchTestPtr(Zero, AbsoluteAddress(debuggerAddress));
     735    char* flagAddress = reinterpret_cast<char*>(debugger) + Debugger::needsOpDebugCallbacksOffset();
     736    Jump skipDebugHook = branchTest8(Zero, AbsoluteAddress(flagAddress));
    730737    callOperation(operationDebug, currentInstruction[1].u.operand);
     738    skipDebugHook.link(this);
     739    noDebugger.link(this);
    731740#endif
    732741}
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r157636 r157746  
    3232
    3333#include "CCallHelpers.h"
     34#include "Debugger.h"
    3435#include "JITInlines.h"
    3536#include "JSArray.h"
     
    10521053    breakpoint();
    10531054#else
     1055    JSGlobalObject* globalObject = codeBlock()->globalObject();
     1056    Debugger* debugger = globalObject->debugger();
     1057    char* debuggerAddress = reinterpret_cast<char*>(globalObject) + JSGlobalObject::debuggerOffset();
     1058    loadPtr(debuggerAddress, regT0);
     1059    Jump noDebugger = branchTestPtr(Zero, regT0);
     1060    char* flagAddress = reinterpret_cast<char*>(debugger) + Debugger::needsOpDebugCallbacksOffset();
     1061    Jump skipDebugHook = branchTest8(Zero, AbsoluteAddress(flagAddress));
    10541062    callOperation(operationDebug, currentInstruction[1].u.operand);
     1063    skipDebugHook.link(this);
     1064    noDebugger.link(this);
    10551065#endif
    10561066}
  • trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp

    r148696 r157746  
    2828#include "ArrayProfile.h"
    2929#include "CodeBlock.h"
     30#include "Debugger.h"
    3031#include "Executable.h"
    3132#include "Heap.h"
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r157474 r157746  
    798798_llint_op_debug:
    799799    traceExecution()
     800    loadp CodeBlock[cfr], t0
     801    loadp CodeBlock::m_globalObject[t0], t0
     802    loadp JSGlobalObject::m_debugger[t0], t0
     803    btiz t0, .opDebugDone
     804    loadb Debugger::m_needsOpDebugCallbacks[t0], t0
     805    btbz t0, .opDebugDone
     806
    800807    callSlowPath(_llint_slow_path_debug)
     808.opDebugDone:                   
    801809    dispatch(2)
    802810
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r157267 r157746  
    468468    Debugger* debugger() const { return m_debugger; }
    469469    void setDebugger(Debugger* debugger) { m_debugger = debugger; }
     470    static ptrdiff_t debuggerOffset() { return OBJECT_OFFSETOF(JSGlobalObject, m_debugger); }
    470471
    471472    const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }
  • trunk/Source/WebCore/ChangeLog

    r157739 r157746  
     12013-10-20  Mark Lam  <mark.lam@apple.com>
     2
     3        Avoid JSC debugger overhead unless needed.
     4        https://bugs.webkit.org/show_bug.cgi?id=123084.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        No new tests.
     9
     10        - If no breakpoints are set, we now avoid calling the debug hook callbacks.
     11        - If no break on exception is set, we also avoid exception event debug callbacks.
     12        - When we return from the ScriptDebugServer to the JSC::Debugger, we may no
     13          longer call the debug hook callbacks if not needed. Hence, the m_currentCallFrame
     14          pointer in the ScriptDebugServer may become stale. To avoid this issue, before
     15          returning, the ScriptDebugServer will clear its m_currentCallFrame if
     16          needsOpDebugCallbacks() is false.
     17
     18        * bindings/js/ScriptDebugServer.cpp:
     19        (WebCore::ScriptDebugServer::setBreakpoint):
     20        (WebCore::ScriptDebugServer::removeBreakpoint):
     21        (WebCore::ScriptDebugServer::clearBreakpoints):
     22        (WebCore::ScriptDebugServer::setPauseOnExceptionsState):
     23        (WebCore::ScriptDebugServer::setPauseOnNextStatement):
     24        (WebCore::ScriptDebugServer::breakProgram):
     25        (WebCore::ScriptDebugServer::stepIntoStatement):
     26        (WebCore::ScriptDebugServer::dispatchDidContinue):
     27        (WebCore::ScriptDebugServer::exception):
     28        (WebCore::ScriptDebugServer::didReachBreakpoint):
     29        * inspector/InspectorDebuggerAgent.cpp:
     30        (WebCore::InspectorDebuggerAgent::reset):
     31
    1322013-10-21  Myles C. Maxfield  <mmaxfield@apple.com>
    233
  • trunk/Source/WebCore/bindings/js/ScriptDebugServer.cpp

    r157215 r157746  
    116116    }
    117117    breaksVector.append(scriptBreakpoint);
     118    incNumberOfBreakpoints();
    118119
    119120    *actualLineNumber = scriptBreakpoint.lineNumber;
     
    151152        if (breaksVector.at(i).columnNumber == static_cast<int>(columnNumber)) {
    152153            breaksVector.remove(i);
     154            decNumberOfBreakpoints();
    153155            break;
    154156        }
     
    246248{
    247249    m_sourceIdToBreakpoints.clear();
     250    updateNumberOfBreakpoints(0);
    248251}
    249252
     
    256259{
    257260    m_pauseOnExceptionsState = pause;
     261    setNeedsExceptionCallbacks(pause != DontPauseOnExceptions);
    258262}
    259263
     
    261265{
    262266    m_pauseOnNextStatement = pause;
     267    if (pause)
     268        setShouldPause(true);
    263269}
    264270
     
    269275
    270276    m_pauseOnNextStatement = true;
     277    setShouldPause(true);
    271278    pauseIfNeeded(m_currentCallFrame);
    272279}
     
    287294
    288295    m_pauseOnNextStatement = true;
     296    setShouldPause(true);
    289297    m_doneProcessingDebuggerEvents = true;
    290298}
     
    354362{
    355363    listener->didContinue();
     364    if (!m_pauseOnNextStatement && !m_pauseOnCallFrame) {
     365        setShouldPause(false);
     366        if (!needsOpDebugCallbacks())
     367            m_currentCallFrame = 0;
     368    }
    356369}
    357370
     
    477490    updateCallFrame(callFrame);
    478491    pauseIfNeeded(callFrame);
     492    if (!needsOpDebugCallbacks())
     493        m_currentCallFrame = 0;
    479494}
    480495
     
    530545void ScriptDebugServer::callEvent(CallFrame* callFrame)
    531546{
    532     if (!m_paused) {
    533         updateCallFrame(callFrame);
    534         pauseIfNeeded(callFrame);
    535     }
     547    if (!m_paused)
     548        updateCallFrameAndPauseIfNeeded(callFrame);
    536549}
    537550
     
    565578        return;
    566579
    567     if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasHandler))
     580    if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasHandler)) {
    568581        m_pauseOnNextStatement = true;
     582        setShouldPause(true);
     583    }
    569584
    570585    updateCallFrameAndPauseIfNeeded(callFrame);
     
    573588void ScriptDebugServer::willExecuteProgram(CallFrame* callFrame)
    574589{
    575     if (!m_paused) {
    576         updateCallFrame(callFrame);
    577         pauseIfNeeded(callFrame);
    578     }
     590    if (!m_paused)
     591        updateCallFrameAndPauseIfNeeded(callFrame);
    579592}
    580593
     
    603616
    604617    m_pauseOnNextStatement = true;
     618    setShouldPause(true);
    605619    updateCallFrameAndPauseIfNeeded(callFrame);
    606620}
  • trunk/Source/WebCore/inspector/InspectorDebuggerAgent.cpp

    r157653 r157746  
    824824void InspectorDebuggerAgent::reset()
    825825{
     826    scriptDebugServer().clearBreakpoints();
    826827    m_scripts.clear();
    827828    m_breakpointIdToDebugServerBreakpointIds.clear();
  • trunk/Source/WebKit/mac/ChangeLog

    r157697 r157746  
     12013-10-20  Mark Lam  <mark.lam@apple.com>
     2
     3        Avoid JSC debugger overhead unless needed.
     4        https://bugs.webkit.org/show_bug.cgi?id=123084.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * WebView/WebScriptDebugger.mm:
     9        (WebScriptDebugger::WebScriptDebugger):
     10
    1112013-10-19  Jer Noble  <jer.noble@apple.com>
    212
  • trunk/Source/WebKit/mac/WebView/WebScriptDebugger.mm

    r157215 r157746  
    7777{
    7878    attach(globalObject);
     79    setNeedsExceptionCallbacks(true);
    7980}
    8081
Note: See TracChangeset for help on using the changeset viewer.