WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
121969
Change ScriptDebugServer to use DebuggerCallFrame instead of JavaScriptCallFrame
https://bugs.webkit.org/show_bug.cgi?id=121969
Summary
Change ScriptDebugServer to use DebuggerCallFrame instead of JavaScriptCallFrame
Mark Lam
Reported
2013-09-26 12:07:19 PDT
Change ScriptDebugServer to use DebuggerCallFrame instead of JavaScriptCallFrame as the data structure for tracking the current frame of execution. This entails: 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 invalidates DebuggerCallFrames that have been "popped". 3. ScriptDebugServer now only creates a JavaScriptCallFrame when it actually needs it i.e. when the debugger needs to pause. 4. JavaScriptCallFrame only creates its caller JavaScriptCallFrame when it is needed i.e. when the client calls caller(). 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.
Attachments
the patch.
(34.21 KB, patch)
2013-09-26 12:09 PDT
,
Mark Lam
ggaren
: review-
Details
Formatted Diff
Diff
patch 2: Create a new DebuggerCallFrame for every pause callback to the ScriptDebugServer's client.
(45.79 KB, patch)
2013-09-27 19:28 PDT
,
Mark Lam
mark.lam
: review-
Details
Formatted Diff
Diff
patch 3: fixed DebuggerCallFrame::invalidate(), and applied the UnsignedWithZeroKeyHashTraits to the LineToBreakpointsMap.
(47.18 KB, patch)
2013-09-28 02:16 PDT
,
Mark Lam
mark.lam
: review-
Details
Formatted Diff
Diff
patch 4: applied feedback from Geoff and Oliver. Still need tests.
(47.31 KB, patch)
2013-10-03 15:39 PDT
,
Mark Lam
eflews.bot
: commit-queue-
Details
Formatted Diff
Diff
patch 5: fixed typo from patch 4.
(47.31 KB, patch)
2013-10-03 15:59 PDT
,
Mark Lam
buildbot
: commit-queue-
Details
Formatted Diff
Diff
Archive of layout-test-results from webkit-ews-02 for mac-mountainlion
(535.43 KB, application/zip)
2013-10-03 17:09 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from webkit-ews-16 for mac-mountainlion-wk2
(467.69 KB, application/zip)
2013-10-03 18:02 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from webkit-ews-04 for mac-mountainlion
(484.00 KB, application/zip)
2013-10-03 18:26 PDT
,
Build Bot
no flags
Details
Archive of layout-test-results from webkit-ews-10 for mac-mountainlion-wk2
(470.72 KB, application/zip)
2013-10-03 19:05 PDT
,
Build Bot
no flags
Details
patch 6: with new tests (plus fixing up an old test)
(70.95 KB, patch)
2013-10-04 17:15 PDT
,
Mark Lam
ggaren
: review+
Details
Formatted Diff
Diff
Show Obsolete
(9)
View All
Add attachment
proposed patch, testcase, etc.
Mark Lam
Comment 1
2013-09-26 12:09:43 PDT
Created
attachment 212734
[details]
the patch.
Geoffrey Garen
Comment 2
2013-09-26 12:39:51 PDT
Another important detail: If you pause twice in the same function, we'll create two JavaScriptCallFrames instead of one. That is the most important detail, since it has the possibility of causing compatibility problems with front-end code, if that code depends on == for JavaScriptCallFrame objects. How did you test whether this patch caused compatibility issues for the inspector?
Geoffrey Garen
Comment 3
2013-09-26 12:45:30 PDT
> Another important detail: If you pause twice in the same function, we'll create two JavaScriptCallFrames instead of one.
Actually, it looks like you didn't make this change, so this patch is wrong.
Geoffrey Garen
Comment 4
2013-09-26 12:47:39 PDT
Comment on
attachment 212734
[details]
the patch. View in context:
https://bugs.webkit.org/attachment.cgi?id=212734&action=review
> Source/WebCore/bindings/js/ScriptDebugServer.cpp:535 > > // Treat stepping over a return statement like stepping out. > if (m_currentCallFrame == m_pauseOnCallFrame) > - m_pauseOnCallFrame = m_currentCallFrame->caller(); > - m_currentCallFrame = m_currentCallFrame->caller(); > + m_pauseOnCallFrame = m_currentCallFrame->caller().get(); > + > + setCurrentCallFrame(m_currentCallFrame->caller()); > }
This is wrong. You've designed the system such that it's a strict requirement that we get a callback from every JavaScript function before it returns. How are you going to arrange to get those callbacks without harming performance?
Timothy Hatcher
Comment 5
2013-09-26 20:21:37 PDT
(In reply to
comment #2
)
> Another important detail: If you pause twice in the same function, we'll create two JavaScriptCallFrames instead of one. > > That is the most important detail, since it has the possibility of causing compatibility problems with front-end code, if that code depends on == for JavaScriptCallFrame objects. > > How did you test whether this patch caused compatibility issues for the inspector?
I don't think this will affect us. We rebuild the stack UI each time we step.
Mark Lam
Comment 6
2013-09-27 19:13:57 PDT
Status update (based on Step 1 specified at
https://bugs.webkit.org/show_bug.cgi?id=121796#c13
): ============================================================= (1a) Add JSLocking to DebuggerCallFrame. Done. (1b) Rewrite member functions [of ScriptDebugServer] to use DebuggerCallFrame directly. - Instead of doing this across the board, I'll only create the DebuggerCallFrame when I need to call back to the ScriptDebugServer's client to pause (or execute relevant actions). For everything else in ScriptDebugServer, I will continue using JSC::CallFrame directly. This should be ok because the sections of code that uses CallFrame directly will be the parts moved into JSC::Debugger later. If we discover a violation of this rule when we do that move, I'll fix it then. Based on this more defined plan, this task is done. (1c) Rewrite ScriptDebugServer::dispatchDidPause to create a new JavaScriptCallFrame for each callback. Test to verify that the front-end doesn't depend on object identity here. Done. JavaScriptCore tests and layout tests have been run and shows no regression. I've also tested on the WebInspector by stepping through some JS code. I verified that the Inspector's shown JS stack trace line numbers do update with the steps. This confirms that Inspector is using the new JavaScriptCallFrame on every pause. I also have assertions in DebuggerCallFrame's methods to ensure that an invalidated DebuggerCallFrame is not used. Previously, I mentioned to Geoff in person that I saw these assertions fail. That was due to a bug in my management of the DebuggerCallFrame life cycle at that time. That bug is now fixed, and I no longer see any of these assertions fail. With the WebInspector, I also set some breakpoints, and did some step in, step over, step outs to so a smoke check of general debugger functionality. Everything works as expected. Patch coming soon.
Mark Lam
Comment 7
2013-09-27 19:28:29 PDT
Created
attachment 212870
[details]
patch 2: Create a new DebuggerCallFrame for every pause callback to the ScriptDebugServer's client.
Mark Lam
Comment 8
2013-09-27 19:33:59 PDT
Comment on
attachment 212870
[details]
patch 2: Create a new DebuggerCallFrame for every pause callback to the ScriptDebugServer's client. Need to fix DebuggerCallFrame::invalidate() to recursively invalidate all its caller frames as well.
Geoffrey Garen
Comment 9
2013-09-27 20:13:02 PDT
Comment on
attachment 212870
[details]
patch 2: Create a new DebuggerCallFrame for every pause callback to the ScriptDebugServer's client. View in context:
https://bugs.webkit.org/attachment.cgi?id=212870&action=review
> Source/WebCore/bindings/js/ScriptDebugServer.cpp:110 > + // We add 1 to the lineNumber before using it as a key to the LineToBreakpointMap > + // because lineNumber is 0-based (hence, can be 0) and LineToBreakpointMap (which > + // is a HashMap) does not allow 0 as a key value. > LineToBreakpointMap::iterator breaksIt = it->value.find(scriptBreakpoint.lineNumber + 1);
Please use UnsignedWithZeroKeyHashTraits. Then you can avoid the + 1 adjustments, and allow 0 in the table.
Mark Lam
Comment 10
2013-09-27 22:27:10 PDT
(In reply to
comment #9
)
> Please use UnsignedWithZeroKeyHashTraits. Then you can avoid the + 1 adjustments, and allow 0 in the table.
Thanks for the tip. Will fix.
Mark Lam
Comment 11
2013-09-28 02:16:23 PDT
Created
attachment 212888
[details]
patch 3: fixed DebuggerCallFrame::invalidate(), and applied the UnsignedWithZeroKeyHashTraits to the LineToBreakpointsMap.
Mark Lam
Comment 12
2013-09-28 10:50:05 PDT
Comment on
attachment 212888
[details]
patch 3: fixed DebuggerCallFrame::invalidate(), and applied the UnsignedWithZeroKeyHashTraits to the LineToBreakpointsMap. Need to fix an uninitialized field in ScriptDebugServer.
Geoffrey Garen
Comment 13
2013-09-28 12:38:50 PDT
Comment on
attachment 212888
[details]
patch 3: fixed DebuggerCallFrame::invalidate(), and applied the UnsignedWithZeroKeyHashTraits to the LineToBreakpointsMap. View in context:
https://bugs.webkit.org/attachment.cgi?id=212888&action=review
> Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp:2 > + * Copyright (C) 2008-2013 Apple Inc. All rights reserved.
Nit: "-" should be ",", since you were not working on this file five years contiguously.
> Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp:60 > + lineAndColumnForCallFrame(m_callFrame, m_line, m_column);
This should be "getLineAndColumnForFrame", since it returns out parameters.
> Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp:108 > if (!m_callFrame->codeBlock()) > return String();
No need for this CodeBlock check, and it's wrong for host functions. Host functions have names, but do not have CodeBlocks.
> Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp:221 > + CodeBlock* codeBlock = callFrame->codeBlock(); > + if (!codeBlock) > + return 0; > + > + JSValue thisValue = callFrame->uncheckedR(codeBlock->thisRegister()).jsValue(); > + if (!thisValue.isObject()) > + return 0;
Host functions have 'this' parameters, and they can be retrieved without use of CodeBlock. Just use CallFrame::thisValue(). Please add a test for this. Also: the isObject() check and asObject() conversion are wrong in strict mode. In strict mode, primitive 'this' values are allowed. You should also remove 'Object' from the function's name and type. Please add a test for this. Also: Any access to 'this' is required to do a ToThis conversion. If the target function did not use 'this', it has not done the conversion yet, so we need to do it now. Please add a test for this. The code here should be something like: ECMAMode ecmaMode = NotStrictMode; if (callFrame->codeBlock() && callFrame->codeBlock()->isStrictMode()) ecmaMode = StrictMode; JSValue thisValue = callFrame->thisValue().toThis(callFrame, ecmaMode); return thisValue;
Oliver Hunt
Comment 14
2013-09-29 12:13:05 PDT
Comment on
attachment 212888
[details]
patch 3: fixed DebuggerCallFrame::invalidate(), and applied the UnsignedWithZeroKeyHashTraits to the LineToBreakpointsMap. View in context:
https://bugs.webkit.org/attachment.cgi?id=212888&action=review
> Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp:207 > + if (!callFrame || !callFrame->codeBlock()) > + return 0; > + return callFrame->codeBlock()->ownerExecutable()->sourceID();
Can callFrame be null here? If it isn't can we make it ASSERT(callFrame); then if (!callFrame); then CodeBlock* codeBlock = callFrame->codeBlock(); if (!codeBlock) return 0; return codeBlock->...
> Source/JavaScriptCore/debugger/DebuggerCallFrame.h:2 > + * Copyright (C) 2008-2013 Apple Inc. All rights reserved.
2008, 2013
> Source/WebCore/bindings/js/ScriptDebugServer.cpp:157 > -bool ScriptDebugServer::hasBreakpoint(intptr_t sourceID, const TextPosition& position, ScriptBreakpoint *hitBreakpoint) const > +bool ScriptDebugServer::hasBreakpoint(intptr_t sourceID, int line, int column, ScriptBreakpoint *hitBreakpoint) const
Why have we switched line/column instead of text position here?
Mark Lam
Comment 15
2013-09-30 17:08:23 PDT
Status update: I've made all the changes from Geoff and Oliver's feedback. Current tests are passing. However, I'm still trying to figure out how the plumbing that our various versions of inspector tests works. Will write new tests as soon as I have a grip on that.
Mark Lam
Comment 16
2013-10-03 15:39:15 PDT
Created
attachment 213306
[details]
patch 4: applied feedback from Geoff and Oliver. Still need tests.
EFL EWS Bot
Comment 17
2013-10-03 15:42:24 PDT
Comment on
attachment 213306
[details]
patch 4: applied feedback from Geoff and Oliver. Still need tests.
Attachment 213306
[details]
did not pass efl-ews (efl): Output:
http://webkit-queues.appspot.com/results/2948035
Mark Lam
Comment 18
2013-10-03 15:59:24 PDT
Created
attachment 213309
[details]
patch 5: fixed typo from patch 4.
Ryosuke Niwa
Comment 19
2013-10-03 16:42:31 PDT
It seems like an inspector test got flaky/failing on EWS: Unexpected flakiness: text-only failures (1) inspector/debugger/watch-expressions-panel-switch.html [ Failure Pass ] Regressions: Unexpected text-only failures (1) inspector/debugger/pause-in-internal-script.html [ Failure ]
Build Bot
Comment 20
2013-10-03 17:09:15 PDT
Comment on
attachment 213309
[details]
patch 5: fixed typo from patch 4.
Attachment 213309
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.appspot.com/results/3190006
New failing tests: inspector/debugger/pause-in-internal-script.html
Build Bot
Comment 21
2013-10-03 17:09:18 PDT
Created
attachment 213312
[details]
Archive of layout-test-results from webkit-ews-02 for mac-mountainlion The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: webkit-ews-02 Port: mac-mountainlion Platform: Mac OS X 10.8.5
Build Bot
Comment 22
2013-10-03 18:02:47 PDT
Comment on
attachment 213309
[details]
patch 5: fixed typo from patch 4.
Attachment 213309
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.appspot.com/results/3189016
New failing tests: inspector/debugger/pause-in-internal-script.html
Build Bot
Comment 23
2013-10-03 18:02:52 PDT
Created
attachment 213320
[details]
Archive of layout-test-results from webkit-ews-16 for mac-mountainlion-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: webkit-ews-16 Port: mac-mountainlion-wk2 Platform: Mac OS X 10.8.5
Build Bot
Comment 24
2013-10-03 18:26:56 PDT
Comment on
attachment 213309
[details]
patch 5: fixed typo from patch 4.
Attachment 213309
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.appspot.com/results/3190023
New failing tests: inspector/debugger/pause-in-internal-script.html
Build Bot
Comment 25
2013-10-03 18:26:59 PDT
Created
attachment 213321
[details]
Archive of layout-test-results from webkit-ews-04 for mac-mountainlion The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: webkit-ews-04 Port: mac-mountainlion Platform: Mac OS X 10.8.5
Build Bot
Comment 26
2013-10-03 19:05:33 PDT
Comment on
attachment 213309
[details]
patch 5: fixed typo from patch 4.
Attachment 213309
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.appspot.com/results/3127139
New failing tests: inspector/debugger/pause-in-internal-script.html
Build Bot
Comment 27
2013-10-03 19:05:37 PDT
Created
attachment 213323
[details]
Archive of layout-test-results from webkit-ews-10 for mac-mountainlion-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: webkit-ews-10 Port: mac-mountainlion-wk2 Platform: Mac OS X 10.8.5
Geoffrey Garen
Comment 28
2013-10-04 12:53:53 PDT
The tests we need are: (1) A host function should have a name in the backtrace. (2) A host function should have a this object (when accessed from within a backtrace). (3) A StrictMode JS function, if passed a primitive this value, should reflect a primitive this value (when accessed from within a backtrace). (4) A NotStrictMode JS function, which does not use 'this' in its body, if passed a primitive this value, should reflect an object this value (when accessed from within a backtrace). (5) A JS function, which does not use 'this' in its body, if passed an activation this value, should reflect a window object this value (when accessed from within a backtrace). Our goal here is just to exercise this code in the simplest way possible, so someone making the same mistake in the future will see a failing test.
Mark Lam
Comment 29
2013-10-04 17:15:05 PDT
Created
attachment 213422
[details]
patch 6: with new tests (plus fixing up an old test)
Geoffrey Garen
Comment 30
2013-10-04 17:41:58 PDT
Comment on
attachment 213422
[details]
patch 6: with new tests (plus fixing up an old test) r=me
Mark Lam
Comment 31
2013-10-04 17:51:01 PDT
Thanks for the review. Landed in
r156936
: <
http://trac.webkit.org/r156936
>.
Sergio Correia (qrwteyrutiyoup)
Comment 32
2013-10-05 14:28:14 PDT
Comment on
attachment 213422
[details]
patch 6: with new tests (plus fixing up an old test) View in context:
https://bugs.webkit.org/attachment.cgi?id=213422&action=review
> Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp:186 > + ASSERT(!callFrame->codeBlock() || functor.column() >= 0);
The return of both functor.line() and functor.column() are unsigned, and hence, always >= 0. Should we just ASSERT(!callFrame->codeBlock()) instead, in here?
Mark Lam
Comment 33
2013-10-07 09:01:10 PDT
(In reply to
comment #32
)
> (From update of
attachment 213422
[details]
) > View in context:
https://bugs.webkit.org/attachment.cgi?id=213422&action=review
> > > Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp:186 > > + ASSERT(!callFrame->codeBlock() || functor.column() >= 0); > > The return of both functor.line() and functor.column() are unsigned, and hence, always >= 0. Should we just ASSERT(!callFrame->codeBlock()) instead, in here?
The asserts are stale code that should have been removed.
https://bugs.webkit.org/show_bug.cgi?id=122440
is addressing this issue.
Sergio Correia (qrwteyrutiyoup)
Comment 34
2013-10-07 09:06:19 PDT
(In reply to
comment #33
)
> (In reply to
comment #32
) > > (From update of
attachment 213422
[details]
[details]) > > View in context:
https://bugs.webkit.org/attachment.cgi?id=213422&action=review
> > > > > Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp:186 > > > + ASSERT(!callFrame->codeBlock() || functor.column() >= 0); > > > > The return of both functor.line() and functor.column() are unsigned, and hence, always >= 0. Should we just ASSERT(!callFrame->codeBlock()) instead, in here? > > The asserts are stale code that should have been removed.
https://bugs.webkit.org/show_bug.cgi?id=122440
is addressing this issue.
Ah, nice :)
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug