Changeset 156936 in webkit


Ignore:
Timestamp:
Oct 4, 2013 5:51:31 PM (11 years ago)
Author:
mark.lam@apple.com
Message:

Change ScriptDebugServer to use DebuggerCallFrame instead of JavaScriptCallFrame.
https://bugs.webkit.org/show_bug.cgi?id=121969.

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

  1. Make JavaScriptCallFrame a thin shell around the DebuggerCallFrame. DebuggerCallFrame now tracks whether it is valid instead of needing JavaScriptCallFrame do it.
  2. ScriptDebugServer now only instantiates an DebuggerCallFrame when needed just before it pauses and calls back to its client, and then invalidates it immediately when the callback returns. Every subsequent callback to the client will use a new instance of the DebuggerCallFrame.
  3. Similarly, ScriptDebugServer now only creates a JavaScriptCallFrame when it "pauses".
  4. DebuggerCallFrame only creates its caller DebuggerCallFrame when it is needed i.e. when the client calls callerFrame(). Similarly, JavaScriptCallFrame only creates its caller when it's requested.
  5. DebuggerCallFrame's line() and column() now returns a base-zero int.
  6. WebScriptDebugDelegate now only caches the functionName of the frame instead of the entire DebuggerCallFrame because that is all that is needed.
  7. Also removed evaluateInGlobalCallFrame() which is not used anywhere.
  • debugger/Debugger.cpp:
  • debugger/Debugger.h:
  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::DebuggerCallFrame):
(JSC::DebuggerCallFrame::callerFrame):
(JSC::DebuggerCallFrame::dynamicGlobalObject):
(JSC::DebuggerCallFrame::sourceId):
(JSC::DebuggerCallFrame::functionName):
(JSC::DebuggerCallFrame::scope):
(JSC::DebuggerCallFrame::type):
(JSC::DebuggerCallFrame::thisValue):
(JSC::DebuggerCallFrame::evaluate):
(JSC::DebuggerCallFrame::evaluateWithCallFrame):
(JSC::DebuggerCallFrame::invalidate):
(JSC::DebuggerCallFrame::positionForCallFrame):
(JSC::DebuggerCallFrame::sourceIdForCallFrame):
(JSC::DebuggerCallFrame::thisValueForCallFrame):

  • debugger/DebuggerCallFrame.h:

(JSC::DebuggerCallFrame::create):
(JSC::DebuggerCallFrame::exec):
(JSC::DebuggerCallFrame::line):
(JSC::DebuggerCallFrame::column):
(JSC::DebuggerCallFrame::position):
(JSC::DebuggerCallFrame::isValid):

  • interpreter/StackVisitor.cpp:

Source/WebCore:

Tests: inspector-protocol/debugger/call-frame-function-name.html

inspector-protocol/debugger/call-frame-this-host.html
inspector-protocol/debugger/call-frame-this-nonstrict.html
inspector-protocol/debugger/call-frame-this-strict.html

  1. Make JavaScriptCallFrame a thin shell around the DebuggerCallFrame. DebuggerCallFrame now tracks whether it is valid instead of needing JavaScriptCallFrame do it.
  2. ScriptDebugServer now only instantiates an DebuggerCallFrame when needed just before it pauses and calls back to its client, and then invalidates it immediately when the callback returns. Every subsequent callback to the client will use a new instance of the DebuggerCallFrame.
  3. Similarly, ScriptDebugServer now only creates a JavaScriptCallFrame when it "pauses".
  4. DebuggerCallFrame only creates its caller DebuggerCallFrame when it is needed i.e. when the client calls callerFrame(). Similarly, JavaScriptCallFrame only creates its caller when it's requested.
  5. DebuggerCallFrame's line() and column() now returns a base-zero int.
  6. WebScriptDebugDelegate now only caches the functionName of the frame instead of the entire DebuggerCallFrame because that is all that is needed.
  7. Also removed evaluateInGlobalCallFrame() which is not used anywhere.
  • bindings/js/JSJavaScriptCallFrameCustom.cpp:

(WebCore::JSJavaScriptCallFrame::thisObject):

  • bindings/js/JavaScriptCallFrame.cpp:

(WebCore::JavaScriptCallFrame::JavaScriptCallFrame):
(WebCore::JavaScriptCallFrame::caller):

  • bindings/js/JavaScriptCallFrame.h:

(WebCore::JavaScriptCallFrame::create):
(WebCore::JavaScriptCallFrame::sourceID):
(WebCore::JavaScriptCallFrame::position):
(WebCore::JavaScriptCallFrame::line):
(WebCore::JavaScriptCallFrame::column):
(WebCore::JavaScriptCallFrame::functionName):
(WebCore::JavaScriptCallFrame::type):
(WebCore::JavaScriptCallFrame::scopeChain):
(WebCore::JavaScriptCallFrame::dynamicGlobalObject):
(WebCore::JavaScriptCallFrame::thisValue):
(WebCore::JavaScriptCallFrame::evaluate):

  • bindings/js/ScriptDebugServer.cpp:

(WebCore::DebuggerCallFrameScope::DebuggerCallFrameScope):
(WebCore::DebuggerCallFrameScope::~DebuggerCallFrameScope):
(WebCore::ScriptDebugServer::ScriptDebugServer):
(WebCore::ScriptDebugServer::setBreakpoint):
(WebCore::ScriptDebugServer::removeBreakpoint):
(WebCore::ScriptDebugServer::hasBreakpoint):
(WebCore::ScriptDebugServer::evaluateBreakpointAction):
(WebCore::ScriptDebugServer::breakProgram):
(WebCore::ScriptDebugServer::stepOverStatement):
(WebCore::ScriptDebugServer::stepOutOfFunction):
(WebCore::ScriptDebugServer::currentDebuggerCallFrame):
(WebCore::ScriptDebugServer::dispatchDidPause):
(WebCore::ScriptDebugServer::updateCallFrame):
(WebCore::ScriptDebugServer::updateCallFrameAndPauseIfNeeded):
(WebCore::ScriptDebugServer::pauseIfNeeded):
(WebCore::ScriptDebugServer::callEvent):
(WebCore::ScriptDebugServer::returnEvent):
(WebCore::ScriptDebugServer::willExecuteProgram):
(WebCore::ScriptDebugServer::didExecuteProgram):

  • bindings/js/ScriptDebugServer.h:
  • bindings/js/WorkerScriptDebugServer.cpp:

(WebCore::WorkerScriptDebugServer::willExecuteProgram):

Source/WebKit/mac:

  1. Make JavaScriptCallFrame a thin shell around the DebuggerCallFrame. DebuggerCallFrame now tracks whether it is valid instead of needing JavaScriptCallFrame do it.
  2. ScriptDebugServer now only instantiates an DebuggerCallFrame when needed just before it pauses and calls back to its client, and then invalidates it immediately when the callback returns. Every subsequent callback to the client will use a new instance of the DebuggerCallFrame.
  3. Similarly, ScriptDebugServer now only creates a JavaScriptCallFrame when it "pauses".
  4. DebuggerCallFrame only creates its caller DebuggerCallFrame when it is needed i.e. when the client calls callerFrame(). Similarly, JavaScriptCallFrame only creates its caller when it's requested.
  5. DebuggerCallFrame's line() and column() now returns a base-zero int.
  6. WebScriptDebugDelegate now only caches the functionName of the frame instead of the entire DebuggerCallFrame because that is all that is needed.
  7. Also removed evaluateInGlobalCallFrame() which is not used anywhere.
  • WebView/WebScriptDebugDelegate.mm:

(-[WebScriptCallFramePrivate dealloc]):
(-[WebScriptCallFrame _initWithGlobalObject:functionName:exceptionValue:JSC::]):
(-[WebScriptCallFrame functionName]):
(-[WebScriptCallFrame exception]):

  • WebView/WebScriptDebugger.mm:

(WebScriptDebugger::exception):

LayoutTests:

  • http/tests/inspector/debugger-test.js:

(initialize_DebuggerTest):

  • inspector-protocol/debugger/call-frame-function-name-expected.txt: Added.
  • inspector-protocol/debugger/call-frame-function-name.html: Added.
  • inspector-protocol/debugger/call-frame-this-host-expected.txt: Added.
  • inspector-protocol/debugger/call-frame-this-host.html: Added.
  • inspector-protocol/debugger/call-frame-this-nonstrict-expected.txt: Added.
  • inspector-protocol/debugger/call-frame-this-nonstrict.html: Added.
  • inspector-protocol/debugger/call-frame-this-strict-expected.txt: Added.
  • inspector-protocol/debugger/call-frame-this-strict.html: Added.
  • inspector/debugger/pause-in-internal-script-expected.txt:
Location:
trunk
Files:
8 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r156930 r156936  
     12013-10-04  Mark Lam  <mark.lam@apple.com>
     2
     3        Change ScriptDebugServer to use DebuggerCallFrame instead of JavaScriptCallFrame.
     4        https://bugs.webkit.org/show_bug.cgi?id=121969.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * http/tests/inspector/debugger-test.js:
     9        (initialize_DebuggerTest):
     10        * inspector-protocol/debugger/call-frame-function-name-expected.txt: Added.
     11        * inspector-protocol/debugger/call-frame-function-name.html: Added.
     12        * inspector-protocol/debugger/call-frame-this-host-expected.txt: Added.
     13        * inspector-protocol/debugger/call-frame-this-host.html: Added.
     14        * inspector-protocol/debugger/call-frame-this-nonstrict-expected.txt: Added.
     15        * inspector-protocol/debugger/call-frame-this-nonstrict.html: Added.
     16        * inspector-protocol/debugger/call-frame-this-strict-expected.txt: Added.
     17        * inspector-protocol/debugger/call-frame-this-strict.html: Added.
     18        * inspector/debugger/pause-in-internal-script-expected.txt:
     19
    1202013-10-04  Frédéric Wang  <fred.wang@free.fr>
    221
  • trunk/LayoutTests/http/tests/inspector/debugger-test.js

    r147102 r156936  
    106106};
    107107
    108 InspectorTest.captureStackTrace = function(callFrames, dropLineNumbers)
     108InspectorTest.captureStackTrace = function(callFrames, dropLineNumbers, verbose)
    109109{
    110110    InspectorTest.addResult("Call stack:");
     
    114114        var url;
    115115        var lineNumber;
     116        var dropFrameLineNumber = dropLineNumbers;
    116117        if (script) {
    117118            url = WebInspector.displayNameForURL(script.sourceURL);
     
    119120        } else {
    120121            url = "(internal script)";
    121             lineNumber = "(line number)";
    122         }
    123         var s = "    " + i + ") " + frame.functionName + " (" + url + (dropLineNumbers ? "" : ":" + lineNumber) + ")";
     122            dropFrameLineNumber =  true;
     123        }
     124        var s = "    " + i + ") " + frame.functionName + " (" + url + (dropFrameLineNumber ? "" : ":" + lineNumber) + ")";
    124125        InspectorTest.addResult(s);
    125126    }
  • trunk/LayoutTests/inspector/debugger/pause-in-internal-script-expected.txt

    r91670 r156936  
    99Call stack:
    1010    0)  (pause-in-internal-script.html:14)
    11     1) testFunction (pause-in-internal-script.html:12)
     11    1) forEach ((internal script))
     12    2) testFunction (pause-in-internal-script.html:12)
    1213Script execution resumed.
    1314Script execution paused.
  • trunk/Source/JavaScriptCore/ChangeLog

    r156934 r156936  
     12013-10-04  Mark Lam  <mark.lam@apple.com>
     2
     3        Change ScriptDebugServer to use DebuggerCallFrame instead of JavaScriptCallFrame.
     4        https://bugs.webkit.org/show_bug.cgi?id=121969.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        1. Make JavaScriptCallFrame a thin shell around the DebuggerCallFrame.
     9           DebuggerCallFrame now tracks whether it is valid instead of needing
     10           JavaScriptCallFrame do it.
     11        2. ScriptDebugServer now only instantiates an DebuggerCallFrame when needed
     12           just before it pauses and calls back to its client, and then invalidates
     13           it immediately when the callback returns. Every subsequent callback to
     14           the client will use a new instance of the DebuggerCallFrame.
     15        3. Similarly, ScriptDebugServer now only creates a JavaScriptCallFrame when
     16           it "pauses".
     17        4. DebuggerCallFrame only creates its caller DebuggerCallFrame when
     18           it is needed i.e. when the client calls callerFrame(). Similarly,
     19           JavaScriptCallFrame only creates its caller when it's requested.
     20        5. DebuggerCallFrame's line() and column() now returns a base-zero int.
     21        6. WebScriptDebugDelegate now only caches the functionName of the frame
     22           instead of the entire DebuggerCallFrame because that is all that is
     23           needed.
     24        7. Also removed evaluateInGlobalCallFrame() which is not used anywhere.
     25
     26        * debugger/Debugger.cpp:
     27        * debugger/Debugger.h:
     28        * debugger/DebuggerCallFrame.cpp:
     29        (JSC::DebuggerCallFrame::DebuggerCallFrame):
     30        (JSC::DebuggerCallFrame::callerFrame):
     31        (JSC::DebuggerCallFrame::dynamicGlobalObject):
     32        (JSC::DebuggerCallFrame::sourceId):
     33        (JSC::DebuggerCallFrame::functionName):
     34        (JSC::DebuggerCallFrame::scope):
     35        (JSC::DebuggerCallFrame::type):
     36        (JSC::DebuggerCallFrame::thisValue):
     37        (JSC::DebuggerCallFrame::evaluate):
     38        (JSC::DebuggerCallFrame::evaluateWithCallFrame):
     39        (JSC::DebuggerCallFrame::invalidate):
     40        (JSC::DebuggerCallFrame::positionForCallFrame):
     41        (JSC::DebuggerCallFrame::sourceIdForCallFrame):
     42        (JSC::DebuggerCallFrame::thisValueForCallFrame):
     43        * debugger/DebuggerCallFrame.h:
     44        (JSC::DebuggerCallFrame::create):
     45        (JSC::DebuggerCallFrame::exec):
     46        (JSC::DebuggerCallFrame::line):
     47        (JSC::DebuggerCallFrame::column):
     48        (JSC::DebuggerCallFrame::position):
     49        (JSC::DebuggerCallFrame::isValid):
     50        * interpreter/StackVisitor.cpp:
     51
    1522013-10-04  Brent Fulgham  <bfulgham@apple.com>
    253
  • trunk/Source/JavaScriptCore/debugger/Debugger.cpp

    r155891 r156936  
    128128}
    129129
    130 JSValue evaluateInGlobalCallFrame(const String& script, JSValue& exception, JSGlobalObject* globalObject)
    131 {
    132     CallFrame* globalCallFrame = globalObject->globalExec();
    133     VM& vm = globalObject->vm();
    134 
    135     EvalExecutable* eval = EvalExecutable::create(globalCallFrame, makeSource(script), false);
    136     if (!eval) {
    137         exception = vm.exception();
    138         vm.clearException();
    139         return exception;
    140     }
    141 
    142     JSValue result = vm.interpreter->execute(eval, globalCallFrame, globalObject, globalCallFrame->scope());
    143     if (vm.exception()) {
    144         exception = vm.exception();
    145         vm.clearException();
    146     }
    147     ASSERT(result);
    148     return result;
    149 }
    150 
    151130} // namespace JSC
  • trunk/Source/JavaScriptCore/debugger/Debugger.h

    r156374 r156936  
    6060};
    6161
    62 // This function exists only for backwards compatibility with existing WebScriptDebugger clients.
    63 JS_EXPORT_PRIVATE JSValue evaluateInGlobalCallFrame(const WTF::String&, JSValue& exception, JSGlobalObject*);
    64 
    6562} // namespace JSC
    6663
  • trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp

    r156511 r156936  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5858    : m_callFrame(callFrame)
    5959{
    60     LineAndColumnFunctor functor;
    61     m_callFrame->iterate(functor);
    62     m_line = functor.line();
    63     m_column = functor.column();
     60    m_position = positionForCallFrame(m_callFrame);
     61}
     62
     63PassRefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame()
     64{
     65    ASSERT(isValid());
     66    if (!isValid())
     67        return 0;
     68
     69    if (m_caller)
     70        return m_caller;
     71
     72    CallFrame* callerFrame = m_callFrame->callerFrameNoFlags();
     73    if (!callerFrame)
     74        return 0;
     75
     76    m_caller = DebuggerCallFrame::create(callerFrame);
     77    return m_caller;
     78}
     79
     80JSC::JSGlobalObject* DebuggerCallFrame::dynamicGlobalObject() const
     81{
     82    ASSERT(isValid());
     83    if (!isValid())
     84        return 0;
     85    return m_callFrame->dynamicGlobalObject();
    6486}
    6587
    6688intptr_t DebuggerCallFrame::sourceId() const
    6789{
    68     return m_callFrame->codeBlock()->ownerExecutable()->sourceID();
     90    ASSERT(isValid());
     91    if (!isValid())
     92        return 0;
     93    return sourceIdForCallFrame(m_callFrame);
    6994}
    7095
    7196String DebuggerCallFrame::functionName() const
    7297{
    73     if (!m_callFrame->codeBlock())
     98    ASSERT(isValid());
     99    if (!isValid())
    74100        return String();
    75 
    76     if (!m_callFrame->callee())
    77         return String();
    78 
    79101    JSObject* function = m_callFrame->callee();
    80     if (!function || !function->inherits(JSFunction::info()))
    81         return String();
    82     return jsCast<JSFunction*>(function)->name(m_callFrame);
    83 }
    84    
    85 String DebuggerCallFrame::calculatedFunctionName() const
    86 {
    87     if (!m_callFrame->codeBlock())
    88         return String();
    89 
    90     JSObject* function = m_callFrame->callee();
    91 
    92102    if (!function)
    93103        return String();
     
    96106}
    97107
     108JSScope* DebuggerCallFrame::scope() const
     109{
     110    ASSERT(isValid());
     111    if (!isValid())
     112        return 0;
     113    return m_callFrame->scope();
     114}
     115
    98116DebuggerCallFrame::Type DebuggerCallFrame::type() const
    99117{
     118    ASSERT(isValid());
     119    if (!isValid())
     120        return ProgramType;
     121
    100122    if (m_callFrame->callee())
    101123        return FunctionType;
     
    104126}
    105127
    106 JSObject* DebuggerCallFrame::thisObject() const
    107 {
    108     CodeBlock* codeBlock = m_callFrame->codeBlock();
    109     if (!codeBlock)
    110         return 0;
    111 
    112     JSValue thisValue = m_callFrame->uncheckedR(codeBlock->thisRegister().offset()).jsValue();
    113     if (!thisValue.isObject())
    114         return 0;
    115 
    116     return asObject(thisValue);
    117 }
    118 
     128JSValue DebuggerCallFrame::thisValue() const
     129{
     130    ASSERT(isValid());
     131    return thisValueForCallFrame(m_callFrame);
     132}
     133
     134// Evaluate some JavaScript code in the scope of this frame.
    119135JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception) const
    120136{
    121     if (!m_callFrame->codeBlock())
     137    ASSERT(isValid());
     138    return evaluateWithCallFrame(m_callFrame, script, exception);
     139}
     140
     141JSValue DebuggerCallFrame::evaluateWithCallFrame(CallFrame* callFrame, const String& script, JSValue& exception)
     142{
     143    if (!callFrame)
     144        return jsNull();
     145
     146    JSLockHolder lock(callFrame);
     147
     148    if (!callFrame->codeBlock())
    122149        return JSValue();
    123150   
    124     VM& vm = m_callFrame->vm();
    125     EvalExecutable* eval = EvalExecutable::create(m_callFrame, makeSource(script), m_callFrame->codeBlock()->isStrictMode());
     151    VM& vm = callFrame->vm();
     152    EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), callFrame->codeBlock()->isStrictMode());
    126153    if (vm.exception()) {
    127154        exception = vm.exception();
     
    129156    }
    130157
    131     JSValue result = vm.interpreter->execute(eval, m_callFrame, thisObject(), m_callFrame->scope());
     158    JSValue thisValue = thisValueForCallFrame(callFrame);
     159    JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, callFrame->scope());
    132160    if (vm.exception()) {
    133161        exception = vm.exception();
     
    138166}
    139167
    140 void DebuggerCallFrame::clear()
    141 {
    142     m_callFrame = 0;
     168void DebuggerCallFrame::invalidate()
     169{
     170    m_callFrame = nullptr;
     171    RefPtr<DebuggerCallFrame> frame = m_caller.release();
     172    while (frame) {
     173        frame->m_callFrame = nullptr;
     174        frame = frame->m_caller.release();
     175    }
     176}
     177
     178TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame)
     179{
     180    if (!callFrame)
     181        return TextPosition();
     182
     183    LineAndColumnFunctor functor;
     184    callFrame->iterate(functor);
     185    ASSERT(!callFrame->codeBlock() || functor.line() >= 0);
     186    ASSERT(!callFrame->codeBlock() || functor.column() >= 0);
     187    return TextPosition(OrdinalNumber::fromOneBasedInt(functor.line()), OrdinalNumber::fromOneBasedInt(functor.column()));
     188}
     189
     190intptr_t DebuggerCallFrame::sourceIdForCallFrame(CallFrame* callFrame)
     191{
     192    ASSERT(callFrame);
     193    CodeBlock* codeBlock = callFrame->codeBlock();
     194    if (!codeBlock)
     195        return 0;
     196    return codeBlock->ownerExecutable()->sourceID();
     197}
     198
     199JSValue DebuggerCallFrame::thisValueForCallFrame(CallFrame* callFrame)
     200{
     201    if (!callFrame)
     202        return jsNull();
     203
     204    ECMAMode ecmaMode = NotStrictMode;
     205    CodeBlock* codeBlock = callFrame->codeBlock();
     206    if (codeBlock && codeBlock->isStrictMode())
     207        ecmaMode = StrictMode;
     208    JSValue thisValue = callFrame->thisValue().toThis(callFrame, ecmaMode);
     209    return thisValue;
    143210}
    144211
  • trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h

    r156374 r156936  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3131
    3232#include "CallFrame.h"
     33#include <wtf/PassRefPtr.h>
     34#include <wtf/RefCounted.h>
     35#include <wtf/text/TextPosition.h>
    3336
    3437namespace JSC {
    3538   
    36 class DebuggerCallFrame {
     39class DebuggerCallFrame : public RefCounted<DebuggerCallFrame> {
    3740public:
    3841    enum Type { ProgramType, FunctionType };
     42
     43    static PassRefPtr<DebuggerCallFrame> create(CallFrame* callFrame)
     44    {
     45        return adoptRef(new DebuggerCallFrame(callFrame));
     46    }
    3947
    4048    JS_EXPORT_PRIVATE explicit DebuggerCallFrame(CallFrame*);
    4149
    4250    CallFrame* callFrame() const { return m_callFrame; }
     51    JS_EXPORT_PRIVATE PassRefPtr<DebuggerCallFrame> callerFrame();
     52    ExecState* exec() const { return m_callFrame; }
    4353    JS_EXPORT_PRIVATE intptr_t sourceId() const;
    44     unsigned line() const { return m_line; }
    45     unsigned column() const { return m_column; }
    46     JSGlobalObject* dynamicGlobalObject() const { return m_callFrame->dynamicGlobalObject(); }
    47     JSScope* scope() const { return m_callFrame->scope(); }
     54
     55    // line and column are in base 0 e.g. the first line is line 0.
     56    int line() const { return m_position.m_line.zeroBasedInt(); }
     57    int column() const { return m_position.m_column.zeroBasedInt(); }
     58    JS_EXPORT_PRIVATE const TextPosition& position() const { return m_position; }
     59
     60    JS_EXPORT_PRIVATE JSGlobalObject* dynamicGlobalObject() const;
     61    JS_EXPORT_PRIVATE JSScope* scope() const;
    4862    JS_EXPORT_PRIVATE String functionName() const;
    49     JS_EXPORT_PRIVATE String calculatedFunctionName() const;
    5063    JS_EXPORT_PRIVATE Type type() const;
    51     JS_EXPORT_PRIVATE JSObject* thisObject() const;
     64    JS_EXPORT_PRIVATE JSValue thisValue() const;
    5265    JS_EXPORT_PRIVATE JSValue evaluate(const String&, JSValue& exception) const;
    5366
    54     void clear();
     67    bool isValid() const { return !!m_callFrame; }
     68    JS_EXPORT_PRIVATE void invalidate();
     69
     70    // The following are only public for the Debugger's use only. They will be
     71    // made private soon. Other clients should not use these.
     72
     73    JS_EXPORT_PRIVATE static JSValue evaluateWithCallFrame(CallFrame*, const String& script, JSValue& exception);
     74    JS_EXPORT_PRIVATE static TextPosition positionForCallFrame(CallFrame*);
     75    JS_EXPORT_PRIVATE static intptr_t sourceIdForCallFrame(CallFrame*);
     76    static JSValue thisValueForCallFrame(CallFrame*);
    5577
    5678private:
    5779    CallFrame* m_callFrame;
    58     unsigned m_line;
    59     unsigned m_column;
     80    RefPtr<DebuggerCallFrame> m_caller;
     81    TextPosition m_position;
    6082};
    6183
  • trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp

    r156233 r156936  
    426426
    427427// For debugging use
    428 void debugPrintCallFrame(JSC::CallFrame*);
    429 void debugPrintStack(JSC::CallFrame* topCallFrame);
     428JS_EXPORT_PRIVATE void debugPrintCallFrame(JSC::CallFrame*);
     429JS_EXPORT_PRIVATE void debugPrintStack(JSC::CallFrame* topCallFrame);
    430430
    431431class DebugPrintFrameFunctor {
  • trunk/Source/WebCore/ChangeLog

    r156932 r156936  
     12013-10-04  Mark Lam  <mark.lam@apple.com>
     2
     3        Change ScriptDebugServer to use DebuggerCallFrame instead of JavaScriptCallFrame.
     4        https://bugs.webkit.org/show_bug.cgi?id=121969.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Tests: inspector-protocol/debugger/call-frame-function-name.html
     9               inspector-protocol/debugger/call-frame-this-host.html
     10               inspector-protocol/debugger/call-frame-this-nonstrict.html
     11               inspector-protocol/debugger/call-frame-this-strict.html
     12
     13        1. Make JavaScriptCallFrame a thin shell around the DebuggerCallFrame.
     14           DebuggerCallFrame now tracks whether it is valid instead of needing
     15           JavaScriptCallFrame do it.
     16        2. ScriptDebugServer now only instantiates an DebuggerCallFrame when needed
     17           just before it pauses and calls back to its client, and then invalidates
     18           it immediately when the callback returns. Every subsequent callback to
     19           the client will use a new instance of the DebuggerCallFrame.
     20        3. Similarly, ScriptDebugServer now only creates a JavaScriptCallFrame when
     21           it "pauses".
     22        4. DebuggerCallFrame only creates its caller DebuggerCallFrame when
     23           it is needed i.e. when the client calls callerFrame(). Similarly,
     24           JavaScriptCallFrame only creates its caller when it's requested.
     25        5. DebuggerCallFrame's line() and column() now returns a base-zero int.
     26        6. WebScriptDebugDelegate now only caches the functionName of the frame
     27           instead of the entire DebuggerCallFrame because that is all that is
     28           needed.
     29        7. Also removed evaluateInGlobalCallFrame() which is not used anywhere.
     30
     31        * bindings/js/JSJavaScriptCallFrameCustom.cpp:
     32        (WebCore::JSJavaScriptCallFrame::thisObject):
     33        * bindings/js/JavaScriptCallFrame.cpp:
     34        (WebCore::JavaScriptCallFrame::JavaScriptCallFrame):
     35        (WebCore::JavaScriptCallFrame::caller):
     36        * bindings/js/JavaScriptCallFrame.h:
     37        (WebCore::JavaScriptCallFrame::create):
     38        (WebCore::JavaScriptCallFrame::sourceID):
     39        (WebCore::JavaScriptCallFrame::position):
     40        (WebCore::JavaScriptCallFrame::line):
     41        (WebCore::JavaScriptCallFrame::column):
     42        (WebCore::JavaScriptCallFrame::functionName):
     43        (WebCore::JavaScriptCallFrame::type):
     44        (WebCore::JavaScriptCallFrame::scopeChain):
     45        (WebCore::JavaScriptCallFrame::dynamicGlobalObject):
     46        (WebCore::JavaScriptCallFrame::thisValue):
     47        (WebCore::JavaScriptCallFrame::evaluate):
     48        * bindings/js/ScriptDebugServer.cpp:
     49        (WebCore::DebuggerCallFrameScope::DebuggerCallFrameScope):
     50        (WebCore::DebuggerCallFrameScope::~DebuggerCallFrameScope):
     51        (WebCore::ScriptDebugServer::ScriptDebugServer):
     52        (WebCore::ScriptDebugServer::setBreakpoint):
     53        (WebCore::ScriptDebugServer::removeBreakpoint):
     54        (WebCore::ScriptDebugServer::hasBreakpoint):
     55        (WebCore::ScriptDebugServer::evaluateBreakpointAction):
     56        (WebCore::ScriptDebugServer::breakProgram):
     57        (WebCore::ScriptDebugServer::stepOverStatement):
     58        (WebCore::ScriptDebugServer::stepOutOfFunction):
     59        (WebCore::ScriptDebugServer::currentDebuggerCallFrame):
     60        (WebCore::ScriptDebugServer::dispatchDidPause):
     61        (WebCore::ScriptDebugServer::updateCallFrame):
     62        (WebCore::ScriptDebugServer::updateCallFrameAndPauseIfNeeded):
     63        (WebCore::ScriptDebugServer::pauseIfNeeded):
     64        (WebCore::ScriptDebugServer::callEvent):
     65        (WebCore::ScriptDebugServer::returnEvent):
     66        (WebCore::ScriptDebugServer::willExecuteProgram):
     67        (WebCore::ScriptDebugServer::didExecuteProgram):
     68        * bindings/js/ScriptDebugServer.h:
     69        * bindings/js/WorkerScriptDebugServer.cpp:
     70        (WebCore::WorkerScriptDebugServer::willExecuteProgram):
     71
    1722013-10-04  Andreas Kling  <akling@apple.com>
    273
  • trunk/Source/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp

    r155589 r156936  
    5151JSValue JSJavaScriptCallFrame::thisObject(ExecState*) const
    5252{
    53     return impl()->thisObject() ? JSValue(impl()->thisObject()) : jsNull();
     53    return impl()->thisValue();
    5454}
    5555
  • trunk/Source/WebCore/bindings/js/JavaScriptCallFrame.cpp

    r155622 r156936  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
     2 * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3030#include "JavaScriptCallFrame.h"
    3131
    32 #include "JSDOMBinding.h"
    33 #include "JSDOMWindowBase.h"
    3432#include <debugger/DebuggerCallFrame.h>
    35 #include <runtime/Completion.h>
    36 #include <runtime/JSCJSValue.h>
    37 #include <runtime/JSGlobalObject.h>
    38 #include <runtime/JSLock.h>
    39 #include <runtime/JSObject.h>
    40 #include <wtf/text/WTFString.h>
    4133
    4234using namespace JSC;
    4335
    4436namespace WebCore {
    45    
    46 JavaScriptCallFrame::JavaScriptCallFrame(const DebuggerCallFrame& debuggerCallFrame, PassRefPtr<JavaScriptCallFrame> caller)
     37
     38JavaScriptCallFrame::JavaScriptCallFrame(PassRefPtr<DebuggerCallFrame> debuggerCallFrame)
    4739    : m_debuggerCallFrame(debuggerCallFrame)
    48     , m_caller(caller)
    49     , m_isValid(true)
    5040{
    5141}
     
    5343JavaScriptCallFrame* JavaScriptCallFrame::caller()
    5444{
     45    if (m_caller)
     46        return m_caller.get();
     47
     48    RefPtr<DebuggerCallFrame> debuggerCallerFrame = m_debuggerCallFrame->callerFrame();
     49    if (!debuggerCallerFrame)
     50        return 0;
     51
     52    m_caller = create(debuggerCallerFrame);
    5553    return m_caller.get();
    56 }
    57 
    58 JSC::JSScope* JavaScriptCallFrame::scopeChain() const
    59 {
    60     ASSERT(m_isValid);
    61     if (!m_isValid)
    62         return 0;
    63     return m_debuggerCallFrame.scope();
    64 }
    65 
    66 JSC::JSGlobalObject* JavaScriptCallFrame::dynamicGlobalObject() const
    67 {
    68     ASSERT(m_isValid);
    69     if (!m_isValid)
    70         return 0;
    71     return m_debuggerCallFrame.dynamicGlobalObject();
    72 }
    73 
    74 String JavaScriptCallFrame::functionName() const
    75 {
    76     ASSERT(m_isValid);
    77     if (!m_isValid)
    78         return String();
    79     String functionName = m_debuggerCallFrame.calculatedFunctionName();
    80     if (functionName.isEmpty())
    81         return String();
    82     return functionName;
    83 }
    84 
    85 DebuggerCallFrame::Type JavaScriptCallFrame::type() const
    86 {
    87     ASSERT(m_isValid);
    88     if (!m_isValid)
    89         return DebuggerCallFrame::ProgramType;
    90     return m_debuggerCallFrame.type();
    91 }
    92 
    93 JSObject* JavaScriptCallFrame::thisObject() const
    94 {
    95     ASSERT(m_isValid);
    96     if (!m_isValid)
    97         return 0;
    98     return m_debuggerCallFrame.thisObject();
    99 }
    100 
    101 ExecState* JavaScriptCallFrame::exec() const
    102 {
    103     ASSERT(m_isValid);
    104     if (!m_isValid)
    105         return 0;
    106     return m_debuggerCallFrame.callFrame();
    107 }
    108 
    109 // Evaluate some JavaScript code in the scope of this frame.
    110 JSValue JavaScriptCallFrame::evaluate(const String& script, JSValue& exception) const
    111 {
    112     ASSERT(m_isValid);
    113     if (!m_isValid)
    114         return jsNull();
    115 
    116     JSLockHolder lock(m_debuggerCallFrame.callFrame());
    117     return m_debuggerCallFrame.evaluate(script, exception);
    11854}
    11955
  • trunk/Source/WebCore/bindings/js/JavaScriptCallFrame.h

    r155622 r156936  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
     2 * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4040class JavaScriptCallFrame : public RefCounted<JavaScriptCallFrame> {
    4141public:
    42     static PassRefPtr<JavaScriptCallFrame> create(const JSC::DebuggerCallFrame& debuggerCallFrame, PassRefPtr<JavaScriptCallFrame> caller)
     42    static PassRefPtr<JavaScriptCallFrame> create(PassRefPtr<JSC::DebuggerCallFrame> debuggerCallFrame)
    4343    {
    44         return adoptRef(new JavaScriptCallFrame(debuggerCallFrame, caller));
     44        return adoptRef(new JavaScriptCallFrame(debuggerCallFrame));
    4545    }
    4646
    47     void invalidate()
    48     {
    49         m_isValid = false;
    50         m_debuggerCallFrame.clear();
    51     }
     47    JavaScriptCallFrame* caller();
     48    intptr_t sourceID() const { return m_debuggerCallFrame->sourceId(); }
     49    const TextPosition position() const { return m_debuggerCallFrame->position(); }
     50    int line() const { return m_debuggerCallFrame->line(); }
     51    int column() const { return m_debuggerCallFrame->column(); }
    5252
    53     bool isValid() const { return m_isValid; }
     53    String functionName() const { return m_debuggerCallFrame->functionName(); }
     54    JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame->type(); }
     55    JSC::JSScope* scopeChain() const { return m_debuggerCallFrame->scope(); }
     56    JSC::JSGlobalObject* dynamicGlobalObject() const { return m_debuggerCallFrame->dynamicGlobalObject(); }
    5457
    55     JavaScriptCallFrame* caller();
    56 
    57     intptr_t sourceID() const { return m_debuggerCallFrame.sourceId(); }
    58     const TextPosition position() const
    59     {
    60         OrdinalNumber line = WTF::OrdinalNumber::fromOneBasedInt(m_debuggerCallFrame.line());
    61         OrdinalNumber column = WTF::OrdinalNumber::fromOneBasedInt(m_debuggerCallFrame.column());
    62         return TextPosition(line, column);
    63     }
    64     int line() const
    65     {
    66         return WTF::OrdinalNumber::fromOneBasedInt(m_debuggerCallFrame.line()).zeroBasedInt();
    67     }
    68     int column() const
    69     {
    70         return WTF::OrdinalNumber::fromOneBasedInt(m_debuggerCallFrame.column()).zeroBasedInt();
    71     }
    72 
    73     void update(const JSC::DebuggerCallFrame& debuggerCallFrame)
    74     {
    75         m_debuggerCallFrame = debuggerCallFrame;
    76         m_isValid = true;
    77     }
    78 
    79     String functionName() const;
    80     JSC::DebuggerCallFrame::Type type() const;
    81     JSC::JSScope* scopeChain() const;
    82     JSC::JSGlobalObject* dynamicGlobalObject() const;
    83     JSC::ExecState* exec() const;
    84 
    85     JSC::JSObject* thisObject() const;
    86     JSC::JSValue evaluate(const String& script, JSC::JSValue& exception) const;
     58    JSC::JSValue thisValue() const { return m_debuggerCallFrame->thisValue(); }
     59    JSC::JSValue evaluate(const String& script, JSC::JSValue& exception) const  { return m_debuggerCallFrame->evaluate(script, exception); }
    8760   
    8861private:
    89     JavaScriptCallFrame(const JSC::DebuggerCallFrame&, PassRefPtr<JavaScriptCallFrame> caller);
     62    JavaScriptCallFrame(PassRefPtr<JSC::DebuggerCallFrame>);
    9063
    91     JSC::DebuggerCallFrame m_debuggerCallFrame;
     64    RefPtr<JSC::DebuggerCallFrame> m_debuggerCallFrame;
    9265    RefPtr<JavaScriptCallFrame> m_caller;
    93     bool m_isValid;
    9466};
    9567
  • trunk/Source/WebCore/bindings/js/ScriptDebugServer.cpp

    r156769 r156936  
    5454namespace WebCore {
    5555
     56class DebuggerCallFrameScope {
     57public:
     58    DebuggerCallFrameScope(ScriptDebugServer& debugger)
     59        : m_debugger(debugger)
     60    {
     61        ASSERT(!m_debugger.m_currentDebuggerCallFrame);
     62        if (m_debugger.m_currentCallFrame)
     63            m_debugger.m_currentDebuggerCallFrame = DebuggerCallFrame::create(debugger.m_currentCallFrame);
     64    }
     65
     66    ~DebuggerCallFrameScope()
     67    {
     68        if (m_debugger.m_currentDebuggerCallFrame) {
     69            m_debugger.m_currentDebuggerCallFrame->invalidate();
     70            m_debugger.m_currentDebuggerCallFrame = 0;
     71        }
     72    }
     73
     74private:
     75    ScriptDebugServer& m_debugger;
     76};
     77
     78
    5679ScriptDebugServer::ScriptDebugServer()
    5780    : m_callingListeners(false)
     
    6386    , m_breakpointsActivated(true)
    6487    , m_pauseOnCallFrame(0)
     88    , m_currentCallFrame(0)
    6589    , m_recompileTimer(this, &ScriptDebugServer::recompileAllJSFunctions)
    6690    , m_lastExecutedLine(-1)
     
    80104    SourceIdToBreakpointsMap::iterator it = m_sourceIdToBreakpoints.find(sourceIDValue);
    81105    if (it == m_sourceIdToBreakpoints.end())
    82         it = m_sourceIdToBreakpoints.set(sourceIDValue, LineToBreakpointMap()).iterator;
    83     LineToBreakpointMap::iterator breaksIt = it->value.find(scriptBreakpoint.lineNumber + 1);
     106        it = m_sourceIdToBreakpoints.set(sourceIDValue, LineToBreakpointsMap()).iterator;
     107    LineToBreakpointsMap::iterator breaksIt = it->value.find(scriptBreakpoint.lineNumber);
    84108    if (breaksIt == it->value.end())
    85         breaksIt = it->value.set(scriptBreakpoint.lineNumber + 1, BreakpointsInLine()).iterator;
     109        breaksIt = it->value.set(scriptBreakpoint.lineNumber, BreakpointsInLine()).iterator;
    86110
    87111    BreakpointsInLine& breaksVector = breaksIt->value;
     
    118142    if (it == m_sourceIdToBreakpoints.end())
    119143        return;
    120     LineToBreakpointMap::iterator breaksIt = it->value.find(lineNumber + 1);
     144    LineToBreakpointsMap::iterator breaksIt = it->value.find(lineNumber);
    121145    if (breaksIt == it->value.end())
    122146        return;
     
    141165        return false;
    142166
    143     int lineNumber = position.m_line.zeroBasedInt();
    144     int columnNumber = position.m_column.zeroBasedInt();
    145     if (lineNumber < 0 || columnNumber < 0)
     167    int line = position.m_line.zeroBasedInt();
     168    int column = position.m_column.zeroBasedInt();
     169    if (line < 0 || column < 0)
    146170        return false;
    147171
    148     LineToBreakpointMap::const_iterator breaksIt = it->value.find(lineNumber + 1);
     172    LineToBreakpointsMap::const_iterator breaksIt = it->value.find(line);
    149173    if (breaksIt == it->value.end())
    150174        return false;
     
    158182        int breakColumn = breaksVector.at(i).columnNumber;
    159183        // Since frontend truncates the indent, the first statement in a line must match the breakpoint (line,0).
    160         if ((lineNumber != m_lastExecutedLine && lineNumber == breakLine && !breakColumn)
    161             || (lineNumber == breakLine && columnNumber == breakColumn)) {
     184        if ((line != m_lastExecutedLine && line == breakLine && !breakColumn)
     185            || (line == breakLine && column == breakColumn)) {
    162186            hit = true;
    163187            break;
     
    175199
    176200    JSValue exception;
    177     JSValue result = m_currentCallFrame->evaluate(breaksVector.at(i).condition, exception);
     201    JSValue result = DebuggerCallFrame::evaluateWithCallFrame(m_currentCallFrame, breaksVector.at(i).condition, exception);
    178202    if (exception) {
    179203        // An erroneous condition counts as "false".
    180         reportException(m_currentCallFrame->exec(), exception);
     204        reportException(m_currentCallFrame, exception);
    181205        return false;
    182206    }
    183     return result.toBoolean(m_currentCallFrame->exec());
     207    return result.toBoolean(m_currentCallFrame);
    184208}
    185209
    186210bool ScriptDebugServer::evaluateBreakpointAction(const ScriptBreakpointAction& breakpointAction) const
    187211{
     212    DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame();
    188213    switch (breakpointAction.type) {
    189214    case ScriptBreakpointActionTypeLog: {
    190         DOMWindow* window = asJSDOMWindow(m_currentCallFrame->dynamicGlobalObject())->impl();
     215        DOMWindow* window = asJSDOMWindow(debuggerCallFrame->dynamicGlobalObject())->impl();
    191216        if (PageConsole* console = window->pageConsole())
    192217            console->addMessage(JSMessageSource, LogMessageLevel, breakpointAction.data);
     
    195220    case ScriptBreakpointActionTypeEvaluate: {
    196221        JSValue exception;
    197         m_currentCallFrame->evaluate(breakpointAction.data, exception);
     222        debuggerCallFrame->evaluate(breakpointAction.data, exception);
    198223        if (exception)
    199             reportException(m_currentCallFrame->exec(), exception);
     224            reportException(debuggerCallFrame->exec(), exception);
    200225        break;
    201226    }
     
    244269
    245270    m_pauseOnNextStatement = true;
    246     pauseIfNeeded(m_currentCallFrame->dynamicGlobalObject());
     271    pauseIfNeeded(m_currentCallFrame);
    247272}
    248273
     
    270295        return;
    271296
    272     m_pauseOnCallFrame = m_currentCallFrame.get();
     297    m_pauseOnCallFrame = m_currentCallFrame;
    273298    m_doneProcessingDebuggerEvents = true;
    274299}
     
    279304        return;
    280305
    281     m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->caller() : 0;
     306    m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->callerFrameNoFlags() : 0;
    282307    m_doneProcessingDebuggerEvents = true;
    283308}
     
    301326}
    302327
     328DebuggerCallFrame* ScriptDebugServer::currentDebuggerCallFrame() const
     329{
     330    ASSERT(m_currentDebuggerCallFrame);
     331    return m_currentDebuggerCallFrame.get();
     332}
     333
    303334void ScriptDebugServer::dispatchDidPause(ScriptDebugListener* listener)
    304335{
    305336    ASSERT(m_paused);
    306     JSGlobalObject* globalObject = m_currentCallFrame->scopeChain()->globalObject();
     337    DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame();
     338    JSGlobalObject* globalObject = debuggerCallFrame->scope()->globalObject();
    307339    JSC::ExecState* state = globalObject->globalExec();
     340    RefPtr<JavaScriptCallFrame> javaScriptCallFrame = JavaScriptCallFrame::create(debuggerCallFrame);
    308341    JSValue jsCallFrame;
    309342    {
    310         if (m_currentCallFrame->isValid() && globalObject->inherits(JSDOMGlobalObject::info())) {
     343        if (globalObject->inherits(JSDOMGlobalObject::info())) {
    311344            JSDOMGlobalObject* domGlobalObject = jsCast<JSDOMGlobalObject*>(globalObject);
    312345            JSLockHolder lock(state);
    313             jsCallFrame = toJS(state, domGlobalObject, m_currentCallFrame.get());
     346            jsCallFrame = toJS(state, domGlobalObject, javaScriptCallFrame.get());
    314347        } else
    315348            jsCallFrame = jsUndefined();
     
    430463}
    431464
    432 void ScriptDebugServer::createCallFrame(CallFrame* callFrame)
    433 {
    434     DebuggerCallFrame debuggerCallFrame(callFrame);
    435     m_currentCallFrame = JavaScriptCallFrame::create(debuggerCallFrame, m_currentCallFrame);
    436     intptr_t sourceId = m_currentCallFrame->sourceID();
     465void ScriptDebugServer::updateCallFrame(CallFrame* callFrame)
     466{
     467    m_currentCallFrame = callFrame;
     468    intptr_t sourceId = DebuggerCallFrame::sourceIdForCallFrame(callFrame);
    437469    if (m_lastExecutedSourceId != sourceId) {
    438470        m_lastExecutedLine = -1;
     
    443475void ScriptDebugServer::updateCallFrameAndPauseIfNeeded(CallFrame* callFrame)
    444476{
    445     // ASSERT(m_currentCallFrame);
    446     if (!m_currentCallFrame)
    447         return;
    448 
    449     m_currentCallFrame->update(DebuggerCallFrame(callFrame));
    450     pauseIfNeeded(callFrame->dynamicGlobalObject());
    451 }
    452 
    453 void ScriptDebugServer::pauseIfNeeded(JSGlobalObject* dynamicGlobalObject)
     477    updateCallFrame(callFrame);
     478    pauseIfNeeded(callFrame);
     479}
     480
     481void ScriptDebugServer::pauseIfNeeded(CallFrame* callFrame)
    454482{
    455483    if (m_paused)
    456484        return;
    457485 
     486    JSGlobalObject* dynamicGlobalObject = callFrame->dynamicGlobalObject();
    458487    if (!getListenersForGlobalObject(dynamicGlobalObject))
    459488        return;
     
    463492    bool pauseNow = m_pauseOnNextStatement;
    464493    pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame);
    465     pauseNow |= didHitBreakpoint = hasBreakpoint(m_currentCallFrame->sourceID(), m_currentCallFrame->position(), &breakpoint);
    466     m_lastExecutedLine = m_currentCallFrame->position().m_line.zeroBasedInt();
     494
     495    intptr_t sourceId = DebuggerCallFrame::sourceIdForCallFrame(m_currentCallFrame);
     496    TextPosition position = DebuggerCallFrame::positionForCallFrame(m_currentCallFrame);
     497    pauseNow |= didHitBreakpoint = hasBreakpoint(sourceId, position, &breakpoint);
     498    m_lastExecutedLine = position.m_line.zeroBasedInt();
    467499    if (!pauseNow)
    468500        return;
     501
     502    DebuggerCallFrameScope debuggerCallFrameScope(*this);
    469503
    470504    if (didHitBreakpoint) {
     
    497531{
    498532    if (!m_paused) {
    499         createCallFrame(callFrame);
    500         pauseIfNeeded(callFrame->dynamicGlobalObject());
     533        updateCallFrame(callFrame);
     534        pauseIfNeeded(callFrame);
    501535    }
    502536}
     
    521555    // Treat stepping over a return statement like stepping out.
    522556    if (m_currentCallFrame == m_pauseOnCallFrame)
    523         m_pauseOnCallFrame = m_currentCallFrame->caller();
    524     m_currentCallFrame = m_currentCallFrame->caller();
     557        m_pauseOnCallFrame = m_currentCallFrame->callerFrameNoFlags();
     558
     559    m_currentCallFrame = m_currentCallFrame->callerFrameNoFlags();
    525560}
    526561
     
    539574{
    540575    if (!m_paused) {
    541         createCallFrame(callFrame);
    542         pauseIfNeeded(callFrame->dynamicGlobalObject());
     576        updateCallFrame(callFrame);
     577        pauseIfNeeded(callFrame);
    543578    }
    544579}
     
    555590        return;
    556591    if (m_currentCallFrame == m_pauseOnCallFrame) {
    557         m_pauseOnCallFrame = m_currentCallFrame->caller();
     592        m_pauseOnCallFrame = m_currentCallFrame->callerFrameNoFlags();
    558593        if (!m_currentCallFrame)
    559594            return;
    560595    }
    561     m_currentCallFrame = m_currentCallFrame->caller();
     596    m_currentCallFrame = m_currentCallFrame->callerFrameNoFlags();
    562597}
    563598
  • trunk/Source/WebCore/bindings/js/ScriptDebugServer.h

    r156374 r156936  
    5151namespace WebCore {
    5252
    53 class JavaScriptCallFrame;
    5453class ScriptDebugListener;
    5554class ScriptObject;
     
    136135    void dispatchFailedToParseSource(const ListenerSet& listeners, JSC::SourceProvider*, int errorLine, const String& errorMessage);
    137136
    138     void createCallFrame(JSC::CallFrame*);
     137    // These update functions are only needed because our current breakpoints are
     138    // key'ed off the source position instead of the bytecode PC. This ensures
     139    // that we don't break on the same line more than once. Once we switch to a
     140    // bytecode PC key'ed breakpoint, we will not need these anymore and should
     141    // be able to remove them.
     142    void updateCallFrame(JSC::CallFrame*);
    139143    void updateCallFrameAndPauseIfNeeded(JSC::CallFrame*);
    140     void pauseIfNeeded(JSC::JSGlobalObject* dynamicGlobalObject);
     144    void pauseIfNeeded(JSC::CallFrame*);
     145
     146    JSC::DebuggerCallFrame* currentDebuggerCallFrame() const;
    141147
    142148    virtual void detach(JSC::JSGlobalObject*) OVERRIDE;
     
    152158
    153159    typedef Vector<ScriptBreakpoint> BreakpointsInLine;
    154     typedef HashMap<long, BreakpointsInLine> LineToBreakpointMap;
    155     typedef HashMap<intptr_t, LineToBreakpointMap> SourceIdToBreakpointsMap;
     160    typedef HashMap<int, BreakpointsInLine, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int> > LineToBreakpointsMap;
     161    typedef HashMap<intptr_t, LineToBreakpointsMap> SourceIdToBreakpointsMap;
    156162
    157163    bool m_callingListeners;
     
    162168    bool m_doneProcessingDebuggerEvents;
    163169    bool m_breakpointsActivated;
    164     JavaScriptCallFrame* m_pauseOnCallFrame;
    165     RefPtr<JavaScriptCallFrame> m_currentCallFrame;
     170    JSC::CallFrame* m_pauseOnCallFrame;
     171    JSC::CallFrame* m_currentCallFrame;
     172    RefPtr<JSC::DebuggerCallFrame> m_currentDebuggerCallFrame;
    166173    SourceIdToBreakpointsMap m_sourceIdToBreakpoints;
    167174    Timer<ScriptDebugServer> m_recompileTimer;
     
    169176    int m_lastExecutedLine;
    170177    intptr_t m_lastExecutedSourceId;
     178
     179    friend class DebuggerCallFrameScope;
    171180};
    172181
  • trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp

    r156374 r156936  
    6464{
    6565    if (!m_paused)
    66         createCallFrame(callFrame);
     66        updateCallFrame(callFrame);
    6767}
    6868
  • trunk/Source/WebKit/mac/ChangeLog

    r156921 r156936  
     12013-10-04  Mark Lam  <mark.lam@apple.com>
     2
     3        Change ScriptDebugServer to use DebuggerCallFrame instead of JavaScriptCallFrame.
     4        https://bugs.webkit.org/show_bug.cgi?id=121969.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        1. Make JavaScriptCallFrame a thin shell around the DebuggerCallFrame.
     9           DebuggerCallFrame now tracks whether it is valid instead of needing
     10           JavaScriptCallFrame do it.
     11        2. ScriptDebugServer now only instantiates an DebuggerCallFrame when needed
     12           just before it pauses and calls back to its client, and then invalidates
     13           it immediately when the callback returns. Every subsequent callback to
     14           the client will use a new instance of the DebuggerCallFrame.
     15        3. Similarly, ScriptDebugServer now only creates a JavaScriptCallFrame when
     16           it "pauses".
     17        4. DebuggerCallFrame only creates its caller DebuggerCallFrame when
     18           it is needed i.e. when the client calls callerFrame(). Similarly,
     19           JavaScriptCallFrame only creates its caller when it's requested.
     20        5. DebuggerCallFrame's line() and column() now returns a base-zero int.
     21        6. WebScriptDebugDelegate now only caches the functionName of the frame
     22           instead of the entire DebuggerCallFrame because that is all that is
     23           needed.
     24        7. Also removed evaluateInGlobalCallFrame() which is not used anywhere.
     25
     26        * WebView/WebScriptDebugDelegate.mm:
     27        (-[WebScriptCallFramePrivate dealloc]):
     28        (-[WebScriptCallFrame _initWithGlobalObject:functionName:exceptionValue:JSC::]):
     29        (-[WebScriptCallFrame functionName]):
     30        (-[WebScriptCallFrame exception]):
     31        * WebView/WebScriptDebugger.mm:
     32        (WebScriptDebugger::exception):
     33
    1342013-10-04  Anders Carlsson  <andersca@apple.com>
    235
  • trunk/Source/WebKit/mac/WebView/WebScriptDebugDelegate.mm

    r156374 r156936  
    3939#import <debugger/Debugger.h>
    4040#import <debugger/DebuggerActivation.h>
    41 #import <debugger/DebuggerCallFrame.h>
    4241#import <interpreter/CallFrame.h>
    4342#import <runtime/Completion.h>
     
    6362@public
    6463    WebScriptObject        *globalObject;   // the global object's proxy (not retained)
    65     DebuggerCallFrame* debuggerCallFrame;
     64    String functionName;
    6665    JSC::JSValue exceptionValue;
    6766}
     
    7170- (void)dealloc
    7271{
    73     delete debuggerCallFrame;
    7472    [super dealloc];
    7573}
     
    8785@implementation WebScriptCallFrame (WebScriptDebugDelegateInternal)
    8886
    89 - (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj debuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame exceptionValue:(JSC::JSValue)exceptionValue
     87- (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj functionName:(String)functionName exceptionValue:(JSC::JSValue)exceptionValue
    9088{
    9189    if ((self = [super init])) {
    9290        _private = [[WebScriptCallFramePrivate alloc] init];
    9391        _private->globalObject = globalObj;
    94         _private->debuggerCallFrame = new DebuggerCallFrame(debuggerCallFrame);
     92        _private->functionName = functionName;
    9593        _private->exceptionValue = exceptionValue;
    9694    }
     
    149147- (NSString *)functionName
    150148{
    151     if (!_private->debuggerCallFrame)
     149    if (_private->functionName.isEmpty())
    152150        return nil;
    153151
    154     String functionName = _private->debuggerCallFrame->functionName();
     152    String functionName = _private->functionName;
    155153    return nsStringNilIfEmpty(functionName);
    156154}
     
    160158- (id)exception
    161159{
    162     if (!_private->debuggerCallFrame)
     160    if (!_private->exceptionValue)
    163161        return nil;
    164162
  • trunk/Source/WebKit/mac/WebView/WebScriptDebugger.mm

    r156550 r156936  
    4747
    4848@interface WebScriptCallFrame (WebScriptDebugDelegateInternal)
    49 - (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj debuggerCallFrame:(const DebuggerCallFrame&)debuggerCallFrame exceptionValue:(JSC::JSValue)exceptionValue;
     49- (WebScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj functionName:(String)functionName exceptionValue:(JSC::JSValue)exceptionValue;
    5050@end
    5151
     
    126126    WebFrame *webFrame = toWebFrame(callFrame->dynamicGlobalObject());
    127127    WebView *webView = [webFrame webView];
    128     DebuggerCallFrame debuggerCallFrame(callFrame);
    129     RetainPtr<WebScriptCallFrame> webCallFrame = adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script().windowScriptObject() debuggerCallFrame:debuggerCallFrame exceptionValue:exceptionValue]);
     128    RefPtr<DebuggerCallFrame> debuggerCallFrame = DebuggerCallFrame::create(callFrame);
     129    String functionName = debuggerCallFrame->functionName();
     130    RetainPtr<WebScriptCallFrame> webCallFrame = adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script().windowScriptObject() functionName:functionName exceptionValue:exceptionValue]);
    130131
    131132    WebScriptDebugDelegateImplementationCache* cache = WebViewGetScriptDebugDelegateImplementations(webView);
    132133    if (cache->exceptionWasRaisedFunc) {
    133134        if (cache->exceptionWasRaisedExpectsHasHandlerFlag)
    134             CallScriptDebugDelegate(cache->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:hasHandler:sourceId:line:forWebFrame:), webCallFrame.get(), hasHandler, debuggerCallFrame.sourceId(), debuggerCallFrame.line(), webFrame);
     135            CallScriptDebugDelegate(cache->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:hasHandler:sourceId:line:forWebFrame:), webCallFrame.get(), hasHandler, debuggerCallFrame->sourceId(), debuggerCallFrame->line(), webFrame);
    135136        else
    136             CallScriptDebugDelegate(cache->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:), webCallFrame.get(), debuggerCallFrame.sourceId(), debuggerCallFrame.line(), webFrame);
     137            CallScriptDebugDelegate(cache->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:), webCallFrame.get(), debuggerCallFrame->sourceId(), debuggerCallFrame->line(), webFrame);
    137138    }
    138139
Note: See TracChangeset for help on using the changeset viewer.