Bug 497119 - Don't assume that we have a cx->fp (or that fp is on cx->fp at all). Set up display as it would have been when fp was active, though. r=brendan
authorBlake Kaplan <mrbkap@gmail.com>
Thu, 11 Jun 2009 14:12:23 -0700
changeset 29100 551a20151798d86f2e55e4e88df712d4e46cea06
parent 29099 11e357b100c088137855d75e05c6a31b266f661c
child 29102 04040160e7daf6e203728a4b81cc53fc2b4e82c7
push id7419
push usermrbkap@mozilla.com
push dateThu, 11 Jun 2009 21:52:44 +0000
treeherdermozilla-central@551a20151798 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbrendan
bugs497119
milestone1.9.2a1pre
Bug 497119 - Don't assume that we have a cx->fp (or that fp is on cx->fp at all). Set up display as it would have been when fp was active, though. r=brendan
js/src/jsdbgapi.cpp
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -1267,22 +1267,46 @@ JS_EvaluateUCInStackFrame(JSContext *cx,
 
     if (!script)
         return JS_FALSE;
 
     JSStackFrame *displayCopy[JS_DISPLAY_SIZE];
     if (cx->fp != fp) {
         memcpy(displayCopy, cx->display, sizeof displayCopy);
 
-        /* This API requires an active fp on cx, so fp2 can't go null here. */
-        for (JSStackFrame *fp2 = cx->fp; fp2 != fp; fp2 = fp2->down) {
-            if (fp2->displaySave) {
-                JS_ASSERT(fp2->script->staticLevel < JS_DISPLAY_SIZE);
-                cx->display[fp2->script->staticLevel] = fp2->displaySave;
-            }
+        /*
+         * Set up cx->display as it would have been when fp was active.
+         *
+         * NB: To reconstruct cx->display for fp, we have to follow the frame
+         * chain from oldest to youngest, in the opposite direction to its
+         * single linkge. To avoid the obvious recursive reversal algorithm,
+         * which might use too much stack, we reverse in place and reverse
+         * again as we reconstruct the display. This is safe because cx is
+         * thread-local and we can't cause GC until the call to js_Execute
+         * below.
+         */
+        JSStackFrame *fp2 = fp, *last = NULL;
+        while (fp2) {
+            JSStackFrame *next = fp2->down;
+            fp2->down = last;
+            last = fp2;
+            fp2 = next;
+        }
+
+        fp2 = last;
+        last = NULL;
+        while (fp2) {
+            JSStackFrame *next = fp2->down;
+            fp2->down = last;
+            last = fp2;
+
+            JSScript *script = fp2->script;
+            if (script && script->staticLevel < JS_DISPLAY_SIZE)
+                cx->display[script->staticLevel] = fp2;
+            fp2 = next;
         }
     }
 
     ok = js_Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL,
                     rval);
 
     if (cx->fp != fp)
         memcpy(cx->display, displayCopy, sizeof cx->display);