<!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.
&lt;https://webkit.org/b/134420&gt;

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 &quot;valid&quot; 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 &quot;validity&quot; 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  &lt;mark.lam@apple.com&gt;
+
+        [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
+        &lt;https://webkit.org/b/134420&gt;
+
+        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 &quot;valid&quot; 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 &quot;validity&quot; 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  &lt;fpizlo@apple.com&gt;
</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 &quot;DebuggerCallFrame.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><ins>+#include &quot;DebuggerScope.h&quot;
</ins><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JSActivation.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;Parser.h&quot;
</span><span class="cx"> #include &quot;StackVisitor.h&quot;
</span><ins>+#include &quot;StrongInlines.h&quot;
</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-&gt;codeBlock();
-    if (codeBlock &amp;&amp; codeBlock-&gt;needsActivation() &amp;&amp; !m_callFrame-&gt;hasActivation()) {
-        JSActivation* activation = JSActivation::create(*codeBlock-&gt;vm(), m_callFrame, codeBlock);
-        m_callFrame-&gt;setActivation(activation);
-        m_callFrame-&gt;setScope(activation);
</del><ins>+    if (!m_scope) {
+        VM&amp; vm = m_callFrame-&gt;vm();
+        CodeBlock* codeBlock = m_callFrame-&gt;codeBlock();
+        if (codeBlock &amp;&amp; codeBlock-&gt;needsActivation() &amp;&amp; !m_callFrame-&gt;hasActivation()) {
+            ASSERT(!m_callFrame-&gt;scope()-&gt;isWithScope());
+            JSActivation* activation = JSActivation::create(vm, m_callFrame, codeBlock);
+            m_callFrame-&gt;setActivation(activation);
+            m_callFrame-&gt;setScope(activation);
+        }
+
+        m_scope.set(vm, DebuggerScope::create(vm, m_callFrame-&gt;scope()));
</ins><span class="cx">     }
</span><del>-
-    return m_callFrame-&gt;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-&gt;execute(eval, callFrame, thisValue, scope());
</del><ins>+    JSValue result = vm.interpreter-&gt;execute(eval, callFrame, thisValue, scope()-&gt;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-&gt;invalidateChain();
+        m_scope.clear();
+    }
</ins><span class="cx">     RefPtr&lt;DebuggerCallFrame&gt; frame = m_caller.release();
</span><span class="cx">     while (frame) {
</span><span class="cx">         frame-&gt;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 &quot;CallFrame.h&quot;
</del><span class="cx"> #include &quot;DebuggerPrimitives.h&quot;
</span><ins>+#include &quot;Strong.h&quot;
</ins><span class="cx"> #include &lt;wtf/PassRefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/text/TextPosition.h&gt;
</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&lt;DebuggerCallFrame&gt; {
</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&amp; 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&lt;DebuggerCallFrame&gt; 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&lt;DebuggerScope&gt; 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 &quot;JSActivation.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;JSWithScope.h&quot;
</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 = { &quot;DebuggerScope&quot;, &amp;Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerScope) };
</span><span class="cx"> 
</span><del>-DebuggerScope::DebuggerScope(VM&amp; vm)
-    : JSNonFinalObject(vm, vm.debuggerScopeStructure.get())
</del><ins>+DebuggerScope::DebuggerScope(VM&amp; vm, JSScope* scope)
+    : JSNonFinalObject(vm, scope-&gt;globalObject()-&gt;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&amp; vm, JSObject* activation)
</del><ins>+void DebuggerScope::finishCreation(VM&amp; vm)
</ins><span class="cx"> {
</span><span class="cx">     Base::finishCreation(vm);
</span><del>-    ASSERT(activation);
-    ASSERT(activation-&gt;isActivationObject());
-    m_activation.set(vm, this, jsCast&lt;JSActivation*&gt;(activation));
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="lines">@@ -56,43 +56,108 @@
</span><span class="cx">     ASSERT(thisObject-&gt;structure()-&gt;typeInfo().overridesVisitChildren());
</span><span class="cx"> 
</span><span class="cx">     JSObject::visitChildren(thisObject, visitor);
</span><del>-    visitor.append(&amp;thisObject-&gt;m_activation);
</del><ins>+    visitor.append(&amp;thisObject-&gt;m_scope);
+    visitor.append(&amp;thisObject-&gt;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&lt;const DebuggerScope*&gt;(object);
-    return thisObject-&gt;m_activation-&gt;methodTable()-&gt;className(thisObject-&gt;m_activation.get());
</del><ins>+    const DebuggerScope* scope = jsCast&lt;const DebuggerScope*&gt;(object);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return String();
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    return thisObject-&gt;methodTable()-&gt;className(thisObject);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot&amp; slot)
</span><span class="cx"> {
</span><del>-    DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(object);
-    return thisObject-&gt;m_activation-&gt;methodTable()-&gt;getOwnPropertySlot(thisObject-&gt;m_activation.get(), exec, propertyName, slot);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(object);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return false;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    return thisObject-&gt;methodTable()-&gt;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&amp; slot)
</span><span class="cx"> {
</span><del>-    DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(cell);
-    thisObject-&gt;m_activation-&gt;methodTable()-&gt;put(thisObject-&gt;m_activation.get(), exec, propertyName, value, slot);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(cell);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    thisObject-&gt;methodTable()-&gt;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&lt;DebuggerScope*&gt;(cell);
-    return thisObject-&gt;m_activation-&gt;methodTable()-&gt;deleteProperty(thisObject-&gt;m_activation.get(), exec, propertyName);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(cell);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return false;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    return thisObject-&gt;methodTable()-&gt;deleteProperty(thisObject, exec, propertyName);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><del>-    DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(object);
-    thisObject-&gt;m_activation-&gt;methodTable()-&gt;getPropertyNames(thisObject-&gt;m_activation.get(), exec, propertyNames, mode);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(object);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    thisObject-&gt;methodTable()-&gt;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&amp; descriptor, bool shouldThrow)
</span><span class="cx"> {
</span><del>-    DebuggerScope* thisObject = jsCast&lt;DebuggerScope*&gt;(object);
-    return thisObject-&gt;m_activation-&gt;methodTable()-&gt;defineOwnProperty(thisObject-&gt;m_activation.get(), exec, propertyName, descriptor, shouldThrow);
</del><ins>+    DebuggerScope* scope = jsCast&lt;DebuggerScope*&gt;(object);
+    ASSERT(scope-&gt;isValid());
+    if (!scope-&gt;isValid())
+        return false;
+    JSObject* thisObject = JSScope::objectAtScope(scope-&gt;jsScope());
+    return thisObject-&gt;methodTable()-&gt;defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+DebuggerScope* DebuggerScope::next()
+{
+    ASSERT(isValid());
+    if (!m_next &amp;&amp; m_scope-&gt;next()) {
+        VM&amp; vm = *m_scope-&gt;vm();
+        DebuggerScope* nextScope = create(vm, m_scope-&gt;next());
+        m_next.set(vm, this, nextScope);
+    }
+    return m_next.get();
+}
+
+void DebuggerScope::invalidateChain()
+{
+    DebuggerScope* scope = this;
+    while (scope) {
+        ASSERT(scope-&gt;isValid());
+        DebuggerScope* nextScope = scope-&gt;m_next.get();
+        scope-&gt;m_next.clear();
+        scope-&gt;m_scope.clear();
+        scope = nextScope;
+    }
+}
+
+bool DebuggerScope::isWithScope() const
+{
+    return m_scope-&gt;isWithScope();
+}
+
+bool DebuggerScope::isGlobalScope() const
+{
+    return m_scope-&gt;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-&gt;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&amp; vm, JSObject* object)
</del><ins>+    static DebuggerScope* create(VM&amp; vm, JSScope* scope)
</ins><span class="cx">     {
</span><del>-        DebuggerScope* activation = new (NotNull, allocateCell&lt;DebuggerScope&gt;(vm.heap)) DebuggerScope(vm);
-        activation-&gt;finishCreation(vm, object);
-        return activation;
</del><ins>+        DebuggerScope* debuggerScope = new (NotNull, allocateCell&lt;DebuggerScope&gt;(vm.heap)) DebuggerScope(vm, scope);
+        debuggerScope-&gt;finishCreation(vm);
+        return debuggerScope;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</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&amp; operator++() { m_node = m_node-&gt;next(); return *this; }
+        // postfix ++ intentionally omitted
+
+        bool operator==(const Iterator&amp; other) const { return m_node == other.m_node; }
+        bool operator!=(const Iterator&amp; 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&amp;, JSScope*);
+    JS_EXPORT_PRIVATE void finishCreation(VM&amp;);
+
+    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&amp;, JSObject* activation);
</del><ins>+    WriteBarrier&lt;JSScope&gt; m_scope;
+    WriteBarrier&lt;DebuggerScope&gt; m_next;
</ins><span class="cx"> 
</span><del>-private:
-    JS_EXPORT_PRIVATE DebuggerScope(VM&amp;);
-    WriteBarrier&lt;JSActivation&gt; 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 &quot;DebuggerScope.h&quot;
</ins><span class="cx"> #include &quot;Error.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;JSCellInlines.h&quot;
</span><span class="lines">@@ -95,29 +96,30 @@
</span><span class="cx">         return jsUndefined();
</span><span class="cx">     int index = exec-&gt;argument(0).asInt32();
</span><span class="cx"> 
</span><del>-    JSScope* scopeChain = impl().scopeChain();
-    ScopeChainIterator end = scopeChain-&gt;end();
</del><ins>+    DebuggerScope* scopeChain = impl().scopeChain();
+    DebuggerScope::Iterator end = scopeChain-&gt;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-&gt;begin(); iter != end; ++iter) {
+        DebuggerScope* scope = iter.get();
</ins><span class="cx"> 
</span><del>-    bool foundLocalScope = false;
-    for (ScopeChainIterator iter = scopeChain-&gt;begin(); iter != end; ++iter) {
-        JSObject* scope = iter.get();
-        if (scope-&gt;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 &amp;&amp; scope-&gt;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-&gt;isWithScope())
+                return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
+            if (scope-&gt;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-&gt;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-&gt;begin();
-    ScopeChainIterator end = scopeChain-&gt;end();
</del><ins>+    DebuggerScope* scopeChain = impl().scopeChain();
+    DebuggerScope::Iterator iter = scopeChain-&gt;begin();
+    DebuggerScope::Iterator end = scopeChain-&gt;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-&gt;functionName(); }
</span><span class="cx">     JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame-&gt;type(); }
</span><del>-    JSC::JSScope* scopeChain() const { return m_debuggerCallFrame-&gt;scope(); }
</del><ins>+    JSC::DebuggerScope* scopeChain() const { return m_debuggerCallFrame-&gt;scope(); }
</ins><span class="cx">     JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame-&gt;vmEntryGlobalObject(); }
</span><span class="cx"> 
</span><span class="cx">     JSC::JSValue thisValue() const { return m_debuggerCallFrame-&gt;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 &quot;DebuggerCallFrame.h&quot;
</span><ins>+#include &quot;DebuggerScope.h&quot;
</ins><span class="cx"> #include &quot;JSJavaScriptCallFrame.h&quot;
</span><span class="cx"> #include &quot;JSLock.h&quot;
</span><span class="cx"> #include &quot;JavaScriptCallFrame.h&quot;
</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 &quot;DateConstructor.h&quot;
</span><span class="cx"> #include &quot;DatePrototype.h&quot;
</span><span class="cx"> #include &quot;Debugger.h&quot;
</span><ins>+#include &quot;DebuggerScope.h&quot;
</ins><span class="cx"> #include &quot;Error.h&quot;
</span><span class="cx"> #include &quot;ErrorConstructor.h&quot;
</span><span class="cx"> #include &quot;ErrorPrototype.h&quot;
</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(&amp;thisObject-&gt;m_promisePrototype);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    visitor.append(&amp;thisObject-&gt;m_debuggerScopeStructure);
</ins><span class="cx">     visitor.append(&amp;thisObject-&gt;m_withScopeStructure);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_strictEvalActivationStructure);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;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&lt;JSPromisePrototype&gt; m_promisePrototype;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    WriteBarrier&lt;Structure&gt; m_debuggerScopeStructure;
</ins><span class="cx">     WriteBarrier&lt;Structure&gt; m_withScopeStructure;
</span><span class="cx">     WriteBarrier&lt;Structure&gt; m_strictEvalActivationStructure;
</span><span class="cx">     WriteBarrier&lt;Structure&gt; 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&amp;);
</span><span class="cx">     JS_EXPORT_PRIVATE void freeze(VM&amp;);
</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&amp; 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&amp;);
</span><span class="cx">     static ResolveOp abstractResolve(ExecState*, JSScope*, const Identifier&amp;, 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 &quot;CommonSlowPaths.h&quot;
</span><span class="cx"> #include &quot;DFGLongLivedState.h&quot;
</span><span class="cx"> #include &quot;DFGWorklist.h&quot;
</span><del>-#include &quot;DebuggerScope.h&quot;
</del><span class="cx"> #include &quot;ErrorInstance.h&quot;
</span><span class="cx"> #include &quot;FTLThunks.h&quot;
</span><span class="cx"> #include &quot;FunctionConstructor.h&quot;
</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&lt;Structure&gt; structureStructure;
</span><span class="cx">         Strong&lt;Structure&gt; structureRareDataStructure;
</span><del>-        Strong&lt;Structure&gt; debuggerScopeStructure;
</del><span class="cx">         Strong&lt;Structure&gt; terminatedExecutionErrorStructure;
</span><span class="cx">         Strong&lt;Structure&gt; stringStructure;
</span><span class="cx">         Strong&lt;Structure&gt; 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  &lt;mark.lam@apple.com&gt;
+
+        [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
+        &lt;https://webkit.org/b/134420&gt;
+
+        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  &lt;fpizlo@apple.com&gt;
</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 &lt;JavaScriptCore/DebuggerCallFrame.h&gt;
-#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-&gt;window();
</span><ins>+    JSLockHolder lock(globalObject-&gt;vm());
</ins><span class="cx">     if (debugger)
</span><span class="cx">         debugger-&gt;attach(globalObject);
</span><span class="cx">     else if (JSC::Debugger* currentDebugger = globalObject-&gt;debugger())
</span></span></pre>
</div>
</div>

</body>
</html>