Bug 503286 - Use the right sp for sp_adj to account for tree calls fiddling with state.sp after we've deep bailed. r=jorendorff a=gal/vlad/blocking1.9.1.1+
authorBlake Kaplan <mrbkap@gmail.com>
Mon, 13 Jul 2009 15:44:33 -0700
changeset 26056 a1a6b17a22da99da1b9e4c94a3e215c16799b3ae
parent 26055 a6f2586c52dc016475bbb6ffb1c8c33ef951cfc1
child 26057 f223409207c069b8da64aacf03c646889befaf68
push id1764
push usermrbkap@mozilla.com
push dateTue, 14 Jul 2009 08:54:42 +0000
reviewersjorendorff, gal, vlad, blocking1.9.1.1
bugs503286
milestone1.9.1.1pre
Bug 503286 - Use the right sp for sp_adj to account for tree calls fiddling with state.sp after we've deep bailed. r=jorendorff a=gal/vlad/blocking1.9.1.1+
js/src/jstracer.cpp
js/src/jstracer.h
js/src/xpconnect/crashtests/503286-1.html
js/src/xpconnect/crashtests/crashtests.list
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -4617,20 +4617,28 @@ LeaveTree(InterpState& state, VMSideExit
                          js_ReconstructStackDepth(cx, cx->fp->script, cx->fp->regs->pc) ==
                          cx->fp->regs->sp);
 
             /*
              * The return value was not available when we reconstructed the stack,
              * but we have it now. Box it.
              */
             uint8* typeMap = getStackTypeMap(innermost);
+
+            /*
+             * If there's a tree call around the point that we deep exited at,
+             * then state.sp and state.rp were restored to their original
+             * values before the tree call and sp might be less than deepBailSp,
+             * which we sampled when we were told to deep bail.
+             */
+            JS_ASSERT(state.deepBailSp >= state.stackBase && state.sp <= state.deepBailSp);
             NativeToValue(cx,
                           cx->fp->regs->sp[-1],
                           typeMap[innermost->numStackSlots - 1],
-                          (jsdouble *) state.sp + innermost->sp_adj / sizeof(jsdouble) - 1);
+                          (jsdouble *) state.deepBailSp + innermost->sp_adj / sizeof(jsdouble) - 1);
         }
         JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
         if (tm->prohibitFlush && --tm->prohibitFlush == 0 && tm->needFlush)
             FlushJITCache(cx);
         return;
     }
 
     JS_ARENA_RELEASE(&cx->stackPool, state.stackMark);
@@ -5471,17 +5479,20 @@ js_DeepBail(JSContext *cx)
     /* It's a bug if a non-FAIL_STATUS builtin gets here. */
     JS_ASSERT(tracecx->bailExit);
 
     tm->tracecx = NULL;
     tm->prohibitFlush++;
     debug_only_v(printf("Deep bail.\n");)
     LeaveTree(*tracecx->interpState, tracecx->bailExit);
     tracecx->bailExit = NULL;
-    tracecx->interpState->builtinStatus |= JSBUILTIN_BAILED;
+
+    InterpState* state = tracecx->interpState;
+    state->builtinStatus |= JSBUILTIN_BAILED;
+    state->deepBailSp = state->sp;
 }
 
 JS_REQUIRES_STACK jsval&
 TraceRecorder::argval(unsigned n) const
 {
     JS_ASSERT(n < cx->fp->fun->nargs);
     return cx->fp->argv[n];
 }
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -411,16 +411,19 @@ struct InterpState
     InterpState*   prev;
 
     /*
      * Used by _FAIL builtins; see jsbuiltins.h. The builtin sets the
      * JSBUILTIN_BAILED bit if it bails off trace and the JSBUILTIN_ERROR bit
      * if an error or exception occurred.
      */
     uint32         builtinStatus;
+
+    // Used to communicate the location of the return value in case of a deep bail.
+    double*        deepBailSp;
 };
 
 static JS_INLINE void
 js_SetBuiltinError(JSContext *cx)
 {
     cx->interpState->builtinStatus |= JSBUILTIN_ERROR;
 }
 
new file mode 100644
--- /dev/null
+++ b/js/src/xpconnect/crashtests/503286-1.html
@@ -0,0 +1,23 @@
+<html><head><title>Firefox 3.5 crash</title>
+
+<script language=JavaScript>
+
+function escapeData(data){
+   var escData='';
+   for(var i=0;i<data.length;i++) {
+      var c=data.charAt(i);
+      if( c==' ') c = escape(c);
+      escData+=c;
+    }
+    return escData;
+}
+
+var a = ["a", "a  ", "a", "a "]
+
+var html = "";
+for (i=0;i<a.length;i++){
+    html += escapeData("a")+escapeData(a[i])
+}
+</script>
+</body></html>
+
--- a/js/src/xpconnect/crashtests/crashtests.list
+++ b/js/src/xpconnect/crashtests/crashtests.list
@@ -13,8 +13,9 @@ load 403356-1.html
 load 418139-1.svg
 load 420513-1.html
 load 453935-1.html
 load 462926.html
 load 468552-1.html
 load 471366-1.html
 load 475185-1.html
 load 475291-1.html
+load 503286-1.html