Bug 470374 - Decompiler fixes from bug 469625 (r=jorendorff).
authorBrendan Eich <brendan@mozilla.org>
Mon, 29 Dec 2008 23:22:23 -0800
changeset 23230 d0e8862aa513f3509a176006ef2bf43f6d3120a4
parent 23229 a2d17feae1836b45d31816e31fd079e1fbdad1d9
child 23232 1fea65b442c89f8e5fc34b57caae85fbcc5430c9
push id4405
push userrsayre@mozilla.com
push dateThu, 01 Jan 2009 22:27:02 +0000
treeherdermozilla-central@5a1e6eac685c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs470374, 469625
milestone1.9.2a1pre
Bug 470374 - Decompiler fixes from bug 469625 (r=jorendorff).
js/src/jsopcode.cpp
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -880,17 +880,17 @@ GetOff(SprintStack *ss, uintN i)
     char *bytes;
 
     off = ss->offsets[i];
     if (off >= 0)
         return off;
 
     JS_ASSERT(off <= -2);
     JS_ASSERT(ss->printer->pcstack);
-    if (off < -2 && ss->printer->pcstack) {
+    if (off <= -2 && ss->printer->pcstack) {
         pc = ss->printer->pcstack[-2 - off];
         bytes = DecompileExpression(ss->sprinter.context, ss->printer->script,
                                     ss->printer->fun, pc);
         if (!bytes)
             return 0;
         if (bytes != FAILED_EXPRESSION_DECOMPILER) {
             off = SprintCString(&ss->sprinter, bytes);
             if (off < 0)
@@ -1245,22 +1245,29 @@ GetLocal(SprintStack *ss, jsint i)
     off = ss->offsets[i];
     if (off >= 0)
         return OFF2STR(&ss->sprinter, off);
 
     /*
      * We must be called from js_DecompileValueGenerator (via Decompile) when
      * dereferencing a local that's undefined or null. Search script->objects
      * for the block containing this local by its stack index, i.
+     *
+     * In case of destructuring's use of JSOP_GETLOCAL, however, there may be
+     * no such local. This could mean no blocks (no script objects at all, or
+     * none of the script's object literals are blocks), or the stack slot i is
+     * not in a block. In either case, return GetStr(ss, i).
      */
     cx = ss->sprinter.context;
     script = ss->printer->script;
-    LOCAL_ASSERT(script->objectsOffset != 0);
+    if (script->objectsOffset == 0)
+        return GetStr(ss, i);
     for (j = 0, n = JS_SCRIPT_OBJECTS(script)->length; ; j++) {
-        LOCAL_ASSERT(j < n);
+        if (j == n)
+            return GetStr(ss, i);
         JS_GET_SCRIPT_OBJECT(script, j, obj);
         if (OBJ_GET_CLASS(cx, obj) == &js_BlockClass) {
             depth = OBJ_BLOCK_DEPTH(cx, obj);
             count = OBJ_BLOCK_COUNT(cx, obj);
             if ((jsuint)(i - depth) < (jsuint)count)
                 break;
         }
     }
@@ -2788,17 +2795,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                     atom = GetArgOrVarAtom(jp, i);
                     LOCAL_ASSERT(atom);
                     goto do_name;
                 }
                 LOCAL_ASSERT((uintN)i < ss->top);
                 sn = js_GetSrcNote(jp->script, pc);
 
 #if JS_HAS_DESTRUCTURING
-                if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN) {
+                if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN && len > JSOP_GETLOCAL_LENGTH) {
                     pc = DecompileGroupAssignment(ss, pc, endpc, sn, &todo);
                     if (!pc)
                         return NULL;
                     LOCAL_ASSERT(*pc == JSOP_POPN);
                     len = oplen = JSOP_POPN_LENGTH;
                     goto end_groupassignment;
                 }
 #endif
@@ -5068,16 +5075,22 @@ DecompileExpression(JSContext *cx, JSScr
     }
 
     op = (JSOp) *pc;
 
     /* None of these stack-writing ops generates novel values. */
     JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX &&
               op != JSOP_DUP && op != JSOP_DUP2);
 
+    /* JSOP_PUSH is used to generate undefined for group assignment holes. */
+    if (op == JSOP_PUSH) {
+        name = JS_strdup(cx, js_undefined_str);
+        goto out;
+    }
+
     /*
      * |this| could convert to a very long object initialiser, so cite it by
      * its keyword name instead.
      */
     if (op == JSOP_THIS) {
         name = JS_strdup(cx, js_this_str);
         goto out;
     }