Bug 780647 - use bindings, instead of CallObject's shape, in DebugScopeProxy (r=jimb)
authorLuke Wagner <luke@mozilla.com>
Mon, 06 Aug 2012 10:13:47 -0700
changeset 107980 70a7988bfd21fc86eeaf11b4912c294bf788e97a
parent 107979 cbe1f44c87496ad3a19b105240247f2a298c0e13
child 107981 abc8c217f0322a277430e02f5746836505206df8
push id1490
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 18:29:50 +0000
treeherdermozilla-beta@f335e7dacdc1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimb
bugs780647
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 780647 - use bindings, instead of CallObject's shape, in DebugScopeProxy (r=jimb)
js/src/jsscript.h
js/src/vm/ScopeObject.cpp
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -113,16 +113,17 @@ class BindingIter
     BindingIter(JSContext *cx, Bindings &bindings);
     BindingIter(JSContext *cx, Init init);
 
     void operator=(Init init);
 
     bool done() const { return shape_.empty(); }
     operator bool() const { return !done(); }
     void operator++(int) { shape_.popFront(); settle(); }
+    BindingIter &operator++() { (*this)++; return *this; }
 
     const Binding &operator*() const { JS_ASSERT(!done()); return binding_; }
     const Binding *operator->() const { JS_ASSERT(!done()); return &binding_; }
     unsigned frameIndex() const { JS_ASSERT(!done()); return shape_.front().shortid(); }
 
   private:
     const Bindings *bindings_;
     Binding binding_;
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -1086,36 +1086,34 @@ class DebugScopeProxy : public BaseProxy
      *
      * handleUnaliasedAccess returns 'true' if the access was unaliased and
      * completed by handleUnaliasedAccess.
      */
     bool handleUnaliasedAccess(JSContext *cx, Handle<DebugScopeObject*> debugScope, Handle<ScopeObject*> scope,
                                jsid id, Action action, Value *vp)
     {
         JS_ASSERT(&debugScope->scope() == scope);
-
-        Shape *shape = scope->lastProperty()->search(cx, id);
-        if (!shape)
-            return false;
-
         StackFrame *maybefp = cx->runtime->debugScopes->hasLiveFrame(*scope);
 
+        /* Handle unaliased formals, vars, and consts at function scope. */
         if (scope->isCall() && !scope->asCall().isForEval()) {
             CallObject &callobj = scope->asCall();
             JSScript *script = callobj.callee().script();
             if (!script->ensureHasTypes(cx))
                 return false;
 
             Bindings &bindings = script->bindings;
-            unsigned i = shape->slot() - CallObject::RESERVED_SLOTS;
-            bool isArg = i < bindings.numArgs();
-            bool isVar = !isArg && (i - bindings.numArgs()) < bindings.numVars();
+            BindingIter bi(cx, script->bindings);
+            while (NameToId(bi->name) != id) {
+                if (!++bi)
+                    return false;
+            }
 
-            if (isVar) {
-                unsigned i = shape->shortid();
+            if (bi->kind == VARIABLE || bi->kind == CONSTANT) {
+                unsigned i = bi.frameIndex();
                 if (script->varIsAliased(i))
                     return false;
 
                 if (maybefp) {
                     if (action == GET)
                         *vp = maybefp->unaliasedVar(i);
                     else
                         maybefp->unaliasedVar(i) = *vp;
@@ -1128,21 +1126,19 @@ class DebugScopeProxy : public BaseProxy
                     /* The unaliased value has been lost to the debugger. */
                     if (action == GET)
                         *vp = UndefinedValue();
                 }
 
                 if (action == SET)
                     TypeScript::SetLocal(cx, script, i, *vp);
 
-                return true;
-            }
-
-            if (isArg) {
-                unsigned i = shape->shortid();
+            } else {
+                JS_ASSERT(bi->kind == ARGUMENT);
+                unsigned i = bi.frameIndex();
                 if (script->formalLivesInCallObject(i))
                     return false;
 
                 if (maybefp) {
                     if (script->argsObjAliasesFormals() && maybefp->hasArgsObj()) {
                         if (action == GET)
                             *vp = maybefp->argsObj().arg(i);
                         else
@@ -1161,25 +1157,28 @@ class DebugScopeProxy : public BaseProxy
                 } else {
                     /* The unaliased value has been lost to the debugger. */
                     if (action == GET)
                         *vp = UndefinedValue();
                 }
 
                 if (action == SET)
                     TypeScript::SetArgument(cx, script, i, *vp);
-
-                return true;
             }
 
-            return false;
+            return true;
         }
 
+        /* Handle unaliased let and catch bindings at block scope. */
         if (scope->isClonedBlock()) {
             ClonedBlockObject &block = scope->asClonedBlock();
+            Shape *shape = block.lastProperty()->search(cx, id);
+            if (!shape)
+                return false;
+
             unsigned i = shape->shortid();
             if (block.staticBlock().isAliased(i))
                 return false;
 
             if (maybefp) {
                 JSScript *script = maybefp->script();
                 unsigned local = block.slotToLocalIndex(script->bindings, shape->slot());
                 if (action == GET)
@@ -1192,16 +1191,17 @@ class DebugScopeProxy : public BaseProxy
                     *vp = block.var(i, DONT_CHECK_ALIASING);
                 else
                     block.setVar(i, *vp, DONT_CHECK_ALIASING);
             }
 
             return true;
         }
 
+        /* The rest of the internal scopes do not have unaliased vars. */
         JS_ASSERT(scope->isDeclEnv() || scope->isWith() || scope->asCall().isForEval());
         return false;
     }
 
     static bool isArguments(JSContext *cx, jsid id)
     {
         return id == NameToId(cx->runtime->atomState.argumentsAtom);
     }