<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[170680] branches/ftlopt/Source</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/170680">170680</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2014-07-01 17:12:09 -0700 (Tue, 01 Jul 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>[ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
<https://webkit.org/b/134420>
Reviewed by Geoffrey Garen.
Source/JavaScriptCore:
Previously, DebuggerCallFrame::scope() returns a JSActivation (and relevant
peers) which the WebInspector will use to introspect CallFrame variables.
Instead, we should be returning a DebuggerScope as an abstraction layer that
provides the introspection functionality that the WebInspector needs. This
is the first step towards not forcing every frame to have a JSActivation
object just because the debugger is enabled.
1. Instantiate the debuggerScopeStructure as a member of the JSGlobalObject
instead of the VM. This allows JSObject::globalObject() to be able to
return the global object for the DebuggerScope.
2. On the DebuggerScope's life-cycle management:
The DebuggerCallFrame is designed to be "valid" only during a debugging session
(while the debugger is broken) through the use of a DebuggerCallFrameScope in
Debugger::pauseIfNeeded(). Once the debugger resumes from the break, the
DebuggerCallFrameScope destructs, and the DebuggerCallFrame will be invalidated.
We can't guarantee (from this code alone) that the Inspector code isn't still
holding a ref to the DebuggerCallFrame (though they shouldn't), but by contract,
the frame will be invalidated, and any attempt to query it will return null values.
This is pre-existing behavior.
Now, we're adding the DebuggerScope into the picture. While a single debugger
pause session is in progress, the Inspector may request the scope from the
DebuggerCallFrame. While the DebuggerCallFrame is still valid, we want
DebuggerCallFrame::scope() to always return the same DebuggerScope object.
This is why we hold on to the DebuggerScope with a strong ref.
If we use a weak ref instead, the following cooky behavior can manifest:
1. The Inspector calls Debugger::scope() to get the top scope.
2. The Inspector iterates down the scope chain and is now only holding a
reference to a parent scope. It is no longer referencing the top scope.
3. A GC occurs, and the DebuggerCallFrame's weak m_scope ref to the top scope
gets cleared.
4. The Inspector calls DebuggerCallFrame::scope() to get the top scope again but gets
a different DebuggerScope instance.
5. The Inspector iterates down the scope chain but never sees the parent scope
instance that retained a ref to in step 2 above. This is because when iterating
this new DebuggerScope instance (which has no knowledge of the previous parent
DebuggerScope instance), a new DebuggerScope instance will get created for the
same parent scope.
Since the DebuggerScope is a JSObject, it's liveness is determined by its reachability.
However, it's "validity" is determined by the life-cycle of its owner DebuggerCallFrame.
When the owner DebuggerCallFrame gets invalidated, its debugger scope chain (if
instantiated) will also get invalidated. This is why we need the
DebuggerScope::invalidateChain() method. The Inspector should not be using the
DebuggerScope instance after its owner DebuggerCallFrame is invalidated. If it does,
those methods will do nothing or returned a failed status.
* debugger/Debugger.h:
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::scope):
(JSC::DebuggerCallFrame::evaluate):
(JSC::DebuggerCallFrame::invalidate):
(JSC::DebuggerCallFrame::vm):
(JSC::DebuggerCallFrame::lexicalGlobalObject):
* debugger/DebuggerCallFrame.h:
* debugger/DebuggerScope.cpp:
(JSC::DebuggerScope::DebuggerScope):
(JSC::DebuggerScope::finishCreation):
(JSC::DebuggerScope::visitChildren):
(JSC::DebuggerScope::className):
(JSC::DebuggerScope::getOwnPropertySlot):
(JSC::DebuggerScope::put):
(JSC::DebuggerScope::deleteProperty):
(JSC::DebuggerScope::getOwnPropertyNames):
(JSC::DebuggerScope::defineOwnProperty):
(JSC::DebuggerScope::next):
(JSC::DebuggerScope::invalidateChain):
(JSC::DebuggerScope::isWithScope):
(JSC::DebuggerScope::isGlobalScope):
(JSC::DebuggerScope::isFunctionScope):
* debugger/DebuggerScope.h:
(JSC::DebuggerScope::create):
(JSC::DebuggerScope::Iterator::Iterator):
(JSC::DebuggerScope::Iterator::get):
(JSC::DebuggerScope::Iterator::operator++):
(JSC::DebuggerScope::Iterator::operator==):
(JSC::DebuggerScope::Iterator::operator!=):
(JSC::DebuggerScope::isValid):
(JSC::DebuggerScope::jsScope):
(JSC::DebuggerScope::begin):
(JSC::DebuggerScope::end):
* inspector/JSJavaScriptCallFrame.cpp:
(Inspector::JSJavaScriptCallFrame::scopeType):
(Inspector::JSJavaScriptCallFrame::scopeChain):
* inspector/JavaScriptCallFrame.h:
(Inspector::JavaScriptCallFrame::scopeChain):
* inspector/ScriptDebugServer.cpp:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::debuggerScopeStructure):
* runtime/JSObject.h:
(JSC::JSObject::isWithScope):
* runtime/JSScope.h:
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
Source/WebCore:
No new tests.
* ForwardingHeaders/debugger/DebuggerCallFrame.h: Removed.
- This is not in use. Hence, we can remove it.
* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::attachDebugger):
- We should acquire the JSLock before modifying a JS global object.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesftloptSourceJavaScriptCoreChangeLog">branches/ftlopt/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredebuggerDebuggerh">branches/ftlopt/Source/JavaScriptCore/debugger/Debugger.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredebuggerDebuggerCallFramecpp">branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredebuggerDebuggerCallFrameh">branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerCallFrame.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredebuggerDebuggerScopecpp">branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredebuggerDebuggerScopeh">branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreinspectorJSJavaScriptCallFramecpp">branches/ftlopt/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreinspectorJavaScriptCallFrameh">branches/ftlopt/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreinspectorScriptDebugServercpp">branches/ftlopt/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSGlobalObjectcpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSGlobalObjecth">branches/ftlopt/Source/JavaScriptCore/runtime/JSGlobalObject.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSObjecth">branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSScopeh">branches/ftlopt/Source/JavaScriptCore/runtime/JSScope.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeVMcpp">branches/ftlopt/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeVMh">branches/ftlopt/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#branchesftloptSourceWebCoreChangeLog">branches/ftlopt/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchesftloptSourceWebCorebindingsjsScriptControllercpp">branches/ftlopt/Source/WebCore/bindings/js/ScriptController.cpp</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#branchesftloptSourceWebCoreForwardingHeadersdebuggerDebuggerCallFrameh">branches/ftlopt/Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesftloptSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/ChangeLog (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -1,3 +1,112 @@
</span><ins>+2014-07-01 Mark Lam <mark.lam@apple.com>
+
+ [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
+ <https://webkit.org/b/134420>
+
+ Reviewed by Geoffrey Garen.
+
+ Previously, DebuggerCallFrame::scope() returns a JSActivation (and relevant
+ peers) which the WebInspector will use to introspect CallFrame variables.
+ Instead, we should be returning a DebuggerScope as an abstraction layer that
+ provides the introspection functionality that the WebInspector needs. This
+ is the first step towards not forcing every frame to have a JSActivation
+ object just because the debugger is enabled.
+
+ 1. Instantiate the debuggerScopeStructure as a member of the JSGlobalObject
+ instead of the VM. This allows JSObject::globalObject() to be able to
+ return the global object for the DebuggerScope.
+
+ 2. On the DebuggerScope's life-cycle management:
+
+ The DebuggerCallFrame is designed to be "valid" only during a debugging session
+ (while the debugger is broken) through the use of a DebuggerCallFrameScope in
+ Debugger::pauseIfNeeded(). Once the debugger resumes from the break, the
+ DebuggerCallFrameScope destructs, and the DebuggerCallFrame will be invalidated.
+ We can't guarantee (from this code alone) that the Inspector code isn't still
+ holding a ref to the DebuggerCallFrame (though they shouldn't), but by contract,
+ the frame will be invalidated, and any attempt to query it will return null values.
+ This is pre-existing behavior.
+
+ Now, we're adding the DebuggerScope into the picture. While a single debugger
+ pause session is in progress, the Inspector may request the scope from the
+ DebuggerCallFrame. While the DebuggerCallFrame is still valid, we want
+ DebuggerCallFrame::scope() to always return the same DebuggerScope object.
+ This is why we hold on to the DebuggerScope with a strong ref.
+
+ If we use a weak ref instead, the following cooky behavior can manifest:
+ 1. The Inspector calls Debugger::scope() to get the top scope.
+ 2. The Inspector iterates down the scope chain and is now only holding a
+ reference to a parent scope. It is no longer referencing the top scope.
+ 3. A GC occurs, and the DebuggerCallFrame's weak m_scope ref to the top scope
+ gets cleared.
+ 4. The Inspector calls DebuggerCallFrame::scope() to get the top scope again but gets
+ a different DebuggerScope instance.
+ 5. The Inspector iterates down the scope chain but never sees the parent scope
+ instance that retained a ref to in step 2 above. This is because when iterating
+ this new DebuggerScope instance (which has no knowledge of the previous parent
+ DebuggerScope instance), a new DebuggerScope instance will get created for the
+ same parent scope.
+
+ Since the DebuggerScope is a JSObject, it's liveness is determined by its reachability.
+ However, it's "validity" is determined by the life-cycle of its owner DebuggerCallFrame.
+ When the owner DebuggerCallFrame gets invalidated, its debugger scope chain (if
+ instantiated) will also get invalidated. This is why we need the
+ DebuggerScope::invalidateChain() method. The Inspector should not be using the
+ DebuggerScope instance after its owner DebuggerCallFrame is invalidated. If it does,
+ those methods will do nothing or returned a failed status.
+
+ * debugger/Debugger.h:
+ * debugger/DebuggerCallFrame.cpp:
+ (JSC::DebuggerCallFrame::scope):
+ (JSC::DebuggerCallFrame::evaluate):
+ (JSC::DebuggerCallFrame::invalidate):
+ (JSC::DebuggerCallFrame::vm):
+ (JSC::DebuggerCallFrame::lexicalGlobalObject):
+ * debugger/DebuggerCallFrame.h:
+ * debugger/DebuggerScope.cpp:
+ (JSC::DebuggerScope::DebuggerScope):
+ (JSC::DebuggerScope::finishCreation):
+ (JSC::DebuggerScope::visitChildren):
+ (JSC::DebuggerScope::className):
+ (JSC::DebuggerScope::getOwnPropertySlot):
+ (JSC::DebuggerScope::put):
+ (JSC::DebuggerScope::deleteProperty):
+ (JSC::DebuggerScope::getOwnPropertyNames):
+ (JSC::DebuggerScope::defineOwnProperty):
+ (JSC::DebuggerScope::next):
+ (JSC::DebuggerScope::invalidateChain):
+ (JSC::DebuggerScope::isWithScope):
+ (JSC::DebuggerScope::isGlobalScope):
+ (JSC::DebuggerScope::isFunctionScope):
+ * debugger/DebuggerScope.h:
+ (JSC::DebuggerScope::create):
+ (JSC::DebuggerScope::Iterator::Iterator):
+ (JSC::DebuggerScope::Iterator::get):
+ (JSC::DebuggerScope::Iterator::operator++):
+ (JSC::DebuggerScope::Iterator::operator==):
+ (JSC::DebuggerScope::Iterator::operator!=):
+ (JSC::DebuggerScope::isValid):
+ (JSC::DebuggerScope::jsScope):
+ (JSC::DebuggerScope::begin):
+ (JSC::DebuggerScope::end):
+ * inspector/JSJavaScriptCallFrame.cpp:
+ (Inspector::JSJavaScriptCallFrame::scopeType):
+ (Inspector::JSJavaScriptCallFrame::scopeChain):
+ * inspector/JavaScriptCallFrame.h:
+ (Inspector::JavaScriptCallFrame::scopeChain):
+ * inspector/ScriptDebugServer.cpp:
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::reset):
+ (JSC::JSGlobalObject::visitChildren):
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::debuggerScopeStructure):
+ * runtime/JSObject.h:
+ (JSC::JSObject::isWithScope):
+ * runtime/JSScope.h:
+ * runtime/VM.cpp:
+ (JSC::VM::VM):
+ * runtime/VM.h:
+
</ins><span class="cx"> 2014-07-01 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> [ftlopt] DFG bytecode parser should turn PutById with nothing but a Setter stub as stuff+handleCall, and handleCall should be allowed to inline if it wants to
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredebuggerDebuggerh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/debugger/Debugger.h (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/debugger/Debugger.h        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/debugger/Debugger.h        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><ins>+class CodeBlock;
</ins><span class="cx"> class ExecState;
</span><span class="cx"> class JSGlobalObject;
</span><span class="cx"> class SourceProvider;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredebuggerDebuggerCallFramecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -30,12 +30,14 @@
</span><span class="cx"> #include "DebuggerCallFrame.h"
</span><span class="cx">
</span><span class="cx"> #include "CodeBlock.h"
</span><ins>+#include "DebuggerScope.h"
</ins><span class="cx"> #include "Interpreter.h"
</span><span class="cx"> #include "JSActivation.h"
</span><span class="cx"> #include "JSFunction.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><span class="cx"> #include "Parser.h"
</span><span class="cx"> #include "StackVisitor.h"
</span><ins>+#include "StrongInlines.h"
</ins><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><span class="lines">@@ -106,20 +108,25 @@
</span><span class="cx"> return getCalculatedDisplayName(m_callFrame, function);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-JSScope* DebuggerCallFrame::scope() const
</del><ins>+DebuggerScope* DebuggerCallFrame::scope()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isValid());
</span><span class="cx"> if (!isValid())
</span><span class="cx"> return 0;
</span><span class="cx">
</span><del>- CodeBlock* codeBlock = m_callFrame->codeBlock();
- if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) {
- JSActivation* activation = JSActivation::create(*codeBlock->vm(), m_callFrame, codeBlock);
- m_callFrame->setActivation(activation);
- m_callFrame->setScope(activation);
</del><ins>+ if (!m_scope) {
+ VM& vm = m_callFrame->vm();
+ CodeBlock* codeBlock = m_callFrame->codeBlock();
+ if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) {
+ ASSERT(!m_callFrame->scope()->isWithScope());
+ JSActivation* activation = JSActivation::create(vm, m_callFrame, codeBlock);
+ m_callFrame->setActivation(activation);
+ m_callFrame->setScope(activation);
+ }
+
+ m_scope.set(vm, DebuggerScope::create(vm, m_callFrame->scope()));
</ins><span class="cx"> }
</span><del>-
- return m_callFrame->scope();
</del><ins>+ return m_scope.get();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> DebuggerCallFrame::Type DebuggerCallFrame::type() const
</span><span class="lines">@@ -162,7 +169,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> JSValue thisValue = thisValueForCallFrame(callFrame);
</span><del>- JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope());
</del><ins>+ JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope());
</ins><span class="cx"> if (vm.exception()) {
</span><span class="cx"> exception = vm.exception();
</span><span class="cx"> vm.clearException();
</span><span class="lines">@@ -174,6 +181,10 @@
</span><span class="cx"> void DebuggerCallFrame::invalidate()
</span><span class="cx"> {
</span><span class="cx"> m_callFrame = nullptr;
</span><ins>+ if (m_scope) {
+ m_scope->invalidateChain();
+ m_scope.clear();
+ }
</ins><span class="cx"> RefPtr<DebuggerCallFrame> frame = m_caller.release();
</span><span class="cx"> while (frame) {
</span><span class="cx"> frame->m_callFrame = nullptr;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredebuggerDebuggerCallFrameh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerCallFrame.h (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerCallFrame.h        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerCallFrame.h        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -29,14 +29,18 @@
</span><span class="cx"> #ifndef DebuggerCallFrame_h
</span><span class="cx"> #define DebuggerCallFrame_h
</span><span class="cx">
</span><del>-#include "CallFrame.h"
</del><span class="cx"> #include "DebuggerPrimitives.h"
</span><ins>+#include "Strong.h"
</ins><span class="cx"> #include <wtf/PassRefPtr.h>
</span><span class="cx"> #include <wtf/RefCounted.h>
</span><span class="cx"> #include <wtf/text/TextPosition.h>
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><ins>+class DebuggerScope;
+class ExecState;
+typedef ExecState CallFrame;
+
</ins><span class="cx"> class DebuggerCallFrame : public RefCounted<DebuggerCallFrame> {
</span><span class="cx"> public:
</span><span class="cx"> enum Type { ProgramType, FunctionType };
</span><span class="lines">@@ -58,7 +62,7 @@
</span><span class="cx"> JS_EXPORT_PRIVATE const TextPosition& position() const { return m_position; }
</span><span class="cx">
</span><span class="cx"> JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject() const;
</span><del>- JS_EXPORT_PRIVATE JSScope* scope() const;
</del><ins>+ JS_EXPORT_PRIVATE DebuggerScope* scope();
</ins><span class="cx"> JS_EXPORT_PRIVATE String functionName() const;
</span><span class="cx"> JS_EXPORT_PRIVATE Type type() const;
</span><span class="cx"> JS_EXPORT_PRIVATE JSValue thisValue() const;
</span><span class="lines">@@ -78,6 +82,9 @@
</span><span class="cx"> CallFrame* m_callFrame;
</span><span class="cx"> RefPtr<DebuggerCallFrame> m_caller;
</span><span class="cx"> TextPosition m_position;
</span><ins>+ // The DebuggerCallFrameScope is responsible for calling invalidate() which,
+ // in turn, will clear this strong ref.
+ Strong<DebuggerScope> m_scope;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredebuggerDebuggerScopecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.cpp (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.cpp        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.cpp        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx">
</span><span class="cx"> #include "JSActivation.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><ins>+#include "JSWithScope.h"
</ins><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><span class="lines">@@ -35,17 +36,16 @@
</span><span class="cx">
</span><span class="cx"> const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerScope) };
</span><span class="cx">
</span><del>-DebuggerScope::DebuggerScope(VM& vm)
- : JSNonFinalObject(vm, vm.debuggerScopeStructure.get())
</del><ins>+DebuggerScope::DebuggerScope(VM& vm, JSScope* scope)
+ : JSNonFinalObject(vm, scope->globalObject()->debuggerScopeStructure())
</ins><span class="cx"> {
</span><ins>+ ASSERT(scope);
+ m_scope.set(vm, this, scope);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void DebuggerScope::finishCreation(VM& vm, JSObject* activation)
</del><ins>+void DebuggerScope::finishCreation(VM& vm)
</ins><span class="cx"> {
</span><span class="cx"> Base::finishCreation(vm);
</span><del>- ASSERT(activation);
- ASSERT(activation->isActivationObject());
- m_activation.set(vm, this, jsCast<JSActivation*>(activation));
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
</span><span class="lines">@@ -56,43 +56,108 @@
</span><span class="cx"> ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
</span><span class="cx">
</span><span class="cx"> JSObject::visitChildren(thisObject, visitor);
</span><del>- visitor.append(&thisObject->m_activation);
</del><ins>+ visitor.append(&thisObject->m_scope);
+ visitor.append(&thisObject->m_next);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> String DebuggerScope::className(const JSObject* object)
</span><span class="cx"> {
</span><del>- const DebuggerScope* thisObject = jsCast<const DebuggerScope*>(object);
- return thisObject->m_activation->methodTable()->className(thisObject->m_activation.get());
</del><ins>+ const DebuggerScope* scope = jsCast<const DebuggerScope*>(object);
+ ASSERT(scope->isValid());
+ if (!scope->isValid())
+ return String();
+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
+ return thisObject->methodTable()->className(thisObject);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
</span><span class="cx"> {
</span><del>- DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
- return thisObject->m_activation->methodTable()->getOwnPropertySlot(thisObject->m_activation.get(), exec, propertyName, slot);
</del><ins>+ DebuggerScope* scope = jsCast<DebuggerScope*>(object);
+ ASSERT(scope->isValid());
+ if (!scope->isValid())
+ return false;
+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
+ return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
</span><span class="cx"> {
</span><del>- DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
- thisObject->m_activation->methodTable()->put(thisObject->m_activation.get(), exec, propertyName, value, slot);
</del><ins>+ DebuggerScope* scope = jsCast<DebuggerScope*>(cell);
+ ASSERT(scope->isValid());
+ if (!scope->isValid())
+ return;
+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
+ thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
</span><span class="cx"> {
</span><del>- DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
- return thisObject->m_activation->methodTable()->deleteProperty(thisObject->m_activation.get(), exec, propertyName);
</del><ins>+ DebuggerScope* scope = jsCast<DebuggerScope*>(cell);
+ ASSERT(scope->isValid());
+ if (!scope->isValid())
+ return false;
+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
+ return thisObject->methodTable()->deleteProperty(thisObject, exec, propertyName);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><del>- DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
- thisObject->m_activation->methodTable()->getPropertyNames(thisObject->m_activation.get(), exec, propertyNames, mode);
</del><ins>+ DebuggerScope* scope = jsCast<DebuggerScope*>(object);
+ ASSERT(scope->isValid());
+ if (!scope->isValid())
+ return;
+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
+ thisObject->methodTable()->getPropertyNames(thisObject, exec, propertyNames, mode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
</span><span class="cx"> {
</span><del>- DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
- return thisObject->m_activation->methodTable()->defineOwnProperty(thisObject->m_activation.get(), exec, propertyName, descriptor, shouldThrow);
</del><ins>+ DebuggerScope* scope = jsCast<DebuggerScope*>(object);
+ ASSERT(scope->isValid());
+ if (!scope->isValid())
+ return false;
+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
+ return thisObject->methodTable()->defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+DebuggerScope* DebuggerScope::next()
+{
+ ASSERT(isValid());
+ if (!m_next && m_scope->next()) {
+ VM& vm = *m_scope->vm();
+ DebuggerScope* nextScope = create(vm, m_scope->next());
+ m_next.set(vm, this, nextScope);
+ }
+ return m_next.get();
+}
+
+void DebuggerScope::invalidateChain()
+{
+ DebuggerScope* scope = this;
+ while (scope) {
+ ASSERT(scope->isValid());
+ DebuggerScope* nextScope = scope->m_next.get();
+ scope->m_next.clear();
+ scope->m_scope.clear();
+ scope = nextScope;
+ }
+}
+
+bool DebuggerScope::isWithScope() const
+{
+ return m_scope->isWithScope();
+}
+
+bool DebuggerScope::isGlobalScope() const
+{
+ return m_scope->isGlobalObject();
+}
+
+bool DebuggerScope::isFunctionScope() const
+{
+ // In the current debugger implementation, every function will create an
+ // activation object. Hence, an activation object implies a function scope.
+ return m_scope->isActivationObject();
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredebuggerDebuggerScopeh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.h (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.h        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.h        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -30,15 +30,18 @@
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><ins>+class DebuggerCallFrame;
+class JSScope;
+
</ins><span class="cx"> class DebuggerScope : public JSNonFinalObject {
</span><span class="cx"> public:
</span><span class="cx"> typedef JSNonFinalObject Base;
</span><span class="cx">
</span><del>- static DebuggerScope* create(VM& vm, JSObject* object)
</del><ins>+ static DebuggerScope* create(VM& vm, JSScope* scope)
</ins><span class="cx"> {
</span><del>- DebuggerScope* activation = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm);
- activation->finishCreation(vm, object);
- return activation;
</del><ins>+ DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, scope);
+ debuggerScope->finishCreation(vm);
+ return debuggerScope;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static void visitChildren(JSCell*, SlotVisitor&);
</span><span class="lines">@@ -56,16 +59,59 @@
</span><span class="cx"> return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-protected:
</del><ins>+ class Iterator {
+ public:
+ Iterator(DebuggerScope* node)
+ : m_node(node)
+ {
+ }
+
+ DebuggerScope* get() { return m_node; }
+ Iterator& operator++() { m_node = m_node->next(); return *this; }
+ // postfix ++ intentionally omitted
+
+ bool operator==(const Iterator& other) const { return m_node == other.m_node; }
+ bool operator!=(const Iterator& other) const { return m_node != other.m_node; }
+
+ private:
+ DebuggerScope* m_node;
+ };
+
+ Iterator begin();
+ Iterator end();
+ DebuggerScope* next();
+
+ void invalidateChain();
+ bool isValid() const { return !!m_scope; }
+
+ bool isWithScope() const;
+ bool isGlobalScope() const;
+ bool isFunctionScope() const;
+
+private:
+ JS_EXPORT_PRIVATE DebuggerScope(VM&, JSScope*);
+ JS_EXPORT_PRIVATE void finishCreation(VM&);
+
+ JSScope* jsScope() const { return m_scope.get(); }
+
</ins><span class="cx"> static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
</span><span class="cx">
</span><del>- JS_EXPORT_PRIVATE void finishCreation(VM&, JSObject* activation);
</del><ins>+ WriteBarrier<JSScope> m_scope;
+ WriteBarrier<DebuggerScope> m_next;
</ins><span class="cx">
</span><del>-private:
- JS_EXPORT_PRIVATE DebuggerScope(VM&);
- WriteBarrier<JSActivation> m_activation;
</del><ins>+ friend class DebuggerCallFrame;
</ins><span class="cx"> };
</span><span class="cx">
</span><ins>+inline DebuggerScope::Iterator DebuggerScope::begin()
+{
+ return Iterator(this);
+}
+
+inline DebuggerScope::Iterator DebuggerScope::end()
+{
+ return Iterator(0);
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx">
</span><span class="cx"> #endif // DebuggerScope_h
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreinspectorJSJavaScriptCallFramecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE(INSPECTOR)
</span><span class="cx">
</span><ins>+#include "DebuggerScope.h"
</ins><span class="cx"> #include "Error.h"
</span><span class="cx"> #include "JSCJSValue.h"
</span><span class="cx"> #include "JSCellInlines.h"
</span><span class="lines">@@ -95,29 +96,30 @@
</span><span class="cx"> return jsUndefined();
</span><span class="cx"> int index = exec->argument(0).asInt32();
</span><span class="cx">
</span><del>- JSScope* scopeChain = impl().scopeChain();
- ScopeChainIterator end = scopeChain->end();
</del><ins>+ DebuggerScope* scopeChain = impl().scopeChain();
+ DebuggerScope::Iterator end = scopeChain->end();
</ins><span class="cx">
</span><del>- // FIXME: We should be identifying and returning CATCH_SCOPE appropriately.
</del><ins>+ bool foundLocalScope = false;
+ for (DebuggerScope::Iterator iter = scopeChain->begin(); iter != end; ++iter) {
+ DebuggerScope* scope = iter.get();
</ins><span class="cx">
</span><del>- bool foundLocalScope = false;
- for (ScopeChainIterator iter = scopeChain->begin(); iter != end; ++iter) {
- JSObject* scope = iter.get();
- if (scope->isActivationObject()) {
- if (!foundLocalScope) {
- // First activation object is local scope, each successive activation object is closure.
- if (!index)
- return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
- foundLocalScope = true;
- } else if (!index)
- return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
</del><ins>+ if (!foundLocalScope && scope->isFunctionScope()) {
+ // First function scope is the local scope, each successive one is a closure.
+ if (!index)
+ return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
+ foundLocalScope = true;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (!index) {
</span><del>- // Last in the chain is global scope.
- if (++iter == end)
</del><ins>+ if (scope->isWithScope())
+ return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
+ if (scope->isGlobalScope()) {
+ ASSERT(++iter == end);
</ins><span class="cx"> return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE);
</span><del>- return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
</del><ins>+ }
+ // FIXME: We should be identifying and returning CATCH_SCOPE appropriately.
+ ASSERT(scope->isFunctionScope());
+ return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> --index;
</span><span class="lines">@@ -157,9 +159,9 @@
</span><span class="cx"> if (!impl().scopeChain())
</span><span class="cx"> return jsNull();
</span><span class="cx">
</span><del>- JSScope* scopeChain = impl().scopeChain();
- ScopeChainIterator iter = scopeChain->begin();
- ScopeChainIterator end = scopeChain->end();
</del><ins>+ DebuggerScope* scopeChain = impl().scopeChain();
+ DebuggerScope::Iterator iter = scopeChain->begin();
+ DebuggerScope::Iterator end = scopeChain->end();
</ins><span class="cx">
</span><span class="cx"> // We must always have something in the scope chain.
</span><span class="cx"> ASSERT(iter != end);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreinspectorJavaScriptCallFrameh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2008, 2013-2014 Apple Inc. All Rights Reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx">
</span><span class="cx"> String functionName() const { return m_debuggerCallFrame->functionName(); }
</span><span class="cx"> JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame->type(); }
</span><del>- JSC::JSScope* scopeChain() const { return m_debuggerCallFrame->scope(); }
</del><ins>+ JSC::DebuggerScope* scopeChain() const { return m_debuggerCallFrame->scope(); }
</ins><span class="cx"> JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame->vmEntryGlobalObject(); }
</span><span class="cx">
</span><span class="cx"> JSC::JSValue thisValue() const { return m_debuggerCallFrame->thisValue(); }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreinspectorScriptDebugServercpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #if ENABLE(INSPECTOR)
</span><span class="cx">
</span><span class="cx"> #include "DebuggerCallFrame.h"
</span><ins>+#include "DebuggerScope.h"
</ins><span class="cx"> #include "JSJavaScriptCallFrame.h"
</span><span class="cx"> #include "JSLock.h"
</span><span class="cx"> #include "JavaScriptCallFrame.h"
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include "DateConstructor.h"
</span><span class="cx"> #include "DatePrototype.h"
</span><span class="cx"> #include "Debugger.h"
</span><ins>+#include "DebuggerScope.h"
</ins><span class="cx"> #include "Error.h"
</span><span class="cx"> #include "ErrorConstructor.h"
</span><span class="cx"> #include "ErrorPrototype.h"
</span><span class="lines">@@ -320,6 +321,7 @@
</span><span class="cx"> m_nameScopeStructure.set(vm, this, JSNameScope::createStructure(vm, this, jsNull()));
</span><span class="cx"> m_activationStructure.set(vm, this, JSActivation::createStructure(vm, this, jsNull()));
</span><span class="cx"> m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull()));
</span><ins>+ m_debuggerScopeStructure.set(m_vm, this, DebuggerScope::createStructure(m_vm, this, jsNull()));
</ins><span class="cx"> m_withScopeStructure.set(vm, this, JSWithScope::createStructure(vm, this, jsNull()));
</span><span class="cx">
</span><span class="cx"> m_nullPrototypeObjectStructure.set(vm, this, JSFinalObject::createStructure(vm, this, jsNull(), JSFinalObject::defaultInlineCapacity()));
</span><span class="lines">@@ -661,6 +663,7 @@
</span><span class="cx"> visitor.append(&thisObject->m_promisePrototype);
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+ visitor.append(&thisObject->m_debuggerScopeStructure);
</ins><span class="cx"> visitor.append(&thisObject->m_withScopeStructure);
</span><span class="cx"> visitor.append(&thisObject->m_strictEvalActivationStructure);
</span><span class="cx"> visitor.append(&thisObject->m_activationStructure);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSGlobalObjecth"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSGlobalObject.h (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSGlobalObject.h        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSGlobalObject.h        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -183,6 +183,7 @@
</span><span class="cx"> WriteBarrier<JSPromisePrototype> m_promisePrototype;
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+ WriteBarrier<Structure> m_debuggerScopeStructure;
</ins><span class="cx"> WriteBarrier<Structure> m_withScopeStructure;
</span><span class="cx"> WriteBarrier<Structure> m_strictEvalActivationStructure;
</span><span class="cx"> WriteBarrier<Structure> m_activationStructure;
</span><span class="lines">@@ -388,6 +389,7 @@
</span><span class="cx"> JSPromisePrototype* promisePrototype() const { return m_promisePrototype.get(); }
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+ Structure* debuggerScopeStructure() const { return m_debuggerScopeStructure.get(); }
</ins><span class="cx"> Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
</span><span class="cx"> Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
</span><span class="cx"> Structure* activationStructure() const { return m_activationStructure.get(); }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.h (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.h        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.h        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -599,6 +599,7 @@
</span><span class="cx"> bool isNameScopeObject() const;
</span><span class="cx"> bool isActivationObject() const;
</span><span class="cx"> bool isErrorInstance() const;
</span><ins>+ bool isWithScope() const;
</ins><span class="cx">
</span><span class="cx"> JS_EXPORT_PRIVATE void seal(VM&);
</span><span class="cx"> JS_EXPORT_PRIVATE void freeze(VM&);
</span><span class="lines">@@ -1147,6 +1148,11 @@
</span><span class="cx"> return type() == ErrorInstanceType;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+inline bool JSObject::isWithScope() const
+{
+ return type() == WithScopeType;
+}
+
</ins><span class="cx"> inline void JSObject::setStructureAndButterfly(VM& vm, Structure* structure, Butterfly* butterfly)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(structure);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSScopeh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSScope.h (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSScope.h        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSScope.h        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -150,7 +150,7 @@
</span><span class="cx"> friend class LLIntOffsetsExtractor;
</span><span class="cx"> static size_t offsetOfNext();
</span><span class="cx">
</span><del>- JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*);
</del><ins>+ static JSObject* objectAtScope(JSScope*);
</ins><span class="cx">
</span><span class="cx"> static JSValue resolve(ExecState*, JSScope*, const Identifier&);
</span><span class="cx"> static ResolveOp abstractResolve(ExecState*, JSScope*, const Identifier&, GetOrPut, ResolveType);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/VM.cpp (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/VM.cpp        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/VM.cpp        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -39,7 +39,6 @@
</span><span class="cx"> #include "CommonSlowPaths.h"
</span><span class="cx"> #include "DFGLongLivedState.h"
</span><span class="cx"> #include "DFGWorklist.h"
</span><del>-#include "DebuggerScope.h"
</del><span class="cx"> #include "ErrorInstance.h"
</span><span class="cx"> #include "FTLThunks.h"
</span><span class="cx"> #include "FunctionConstructor.h"
</span><span class="lines">@@ -255,7 +254,6 @@
</span><span class="cx"> propertyNames = new CommonIdentifiers(this);
</span><span class="cx"> structureStructure.set(*this, Structure::createStructure(*this));
</span><span class="cx"> structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
</span><del>- debuggerScopeStructure.set(*this, DebuggerScope::createStructure(*this, 0, jsNull()));
</del><span class="cx"> terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
</span><span class="cx"> stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
</span><span class="cx"> notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/VM.h (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/VM.h        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/VM.h        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -262,7 +262,6 @@
</span><span class="cx">
</span><span class="cx"> Strong<Structure> structureStructure;
</span><span class="cx"> Strong<Structure> structureRareDataStructure;
</span><del>- Strong<Structure> debuggerScopeStructure;
</del><span class="cx"> Strong<Structure> terminatedExecutionErrorStructure;
</span><span class="cx"> Strong<Structure> stringStructure;
</span><span class="cx"> Strong<Structure> notAnObjectStructure;
</span></span></pre></div>
<a id="branchesftloptSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/WebCore/ChangeLog (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/WebCore/ChangeLog        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/WebCore/ChangeLog        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2014-07-01 Mark Lam <mark.lam@apple.com>
+
+ [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
+ <https://webkit.org/b/134420>
+
+ Reviewed by Geoffrey Garen.
+
+ No new tests.
+
+ * ForwardingHeaders/debugger/DebuggerCallFrame.h: Removed.
+ - This is not in use. Hence, we can remove it.
+ * bindings/js/ScriptController.cpp:
+ (WebCore::ScriptController::attachDebugger):
+ - We should acquire the JSLock before modifying a JS global object.
+
</ins><span class="cx"> 2014-06-25 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint
</span></span></pre></div>
<a id="branchesftloptSourceWebCoreForwardingHeadersdebuggerDebuggerCallFrameh"></a>
<div class="delfile"><h4>Deleted: branches/ftlopt/Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -1,4 +0,0 @@
</span><del>-#ifndef WebCore_FWD_DebuggerCallFrame_h
-#define WebCore_FWD_DebuggerCallFrame_h
-#include <JavaScriptCore/DebuggerCallFrame.h>
-#endif
</del></span></pre></div>
<a id="branchesftloptSourceWebCorebindingsjsScriptControllercpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/WebCore/bindings/js/ScriptController.cpp (170679 => 170680)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/WebCore/bindings/js/ScriptController.cpp        2014-07-02 00:08:13 UTC (rev 170679)
+++ branches/ftlopt/Source/WebCore/bindings/js/ScriptController.cpp        2014-07-02 00:12:09 UTC (rev 170680)
</span><span class="lines">@@ -295,6 +295,7 @@
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> JSDOMWindow* globalObject = shell->window();
</span><ins>+ JSLockHolder lock(globalObject->vm());
</ins><span class="cx"> if (debugger)
</span><span class="cx"> debugger->attach(globalObject);
</span><span class="cx"> else if (JSC::Debugger* currentDebugger = globalObject->debugger())
</span></span></pre>
</div>
</div>
</body>
</html>