Bug 712460 - Add missing barriers in jsexn; r=billm
☠☠ backed out by 5ddcffa2d70d ☠ ☠
authorTerrence Cole <terrence@mozilla.com>
Tue, 20 Dec 2011 14:51:25 -0800
changeset 84592 d354ab9ac1f4e3f181fe8ac0a973d614c0c96a3c
parent 84591 8eb78de9abf414b1491cea1d292fde72ae53e0b3
child 84593 5ddcffa2d70d311d5c6dcd90f4083fce6dd9f023
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs712460
milestone12.0a1
Bug 712460 - Add missing barriers in jsexn; r=billm When we create an exception object, we copy Values into a custom exception privates struct that we pass around. If any of the Values copied to this struct are gcthings in the nursery, this external array needs to root them.
js/src/jsexn.cpp
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -251,28 +251,28 @@ CopyErrorReport(JSContext *cx, JSErrorRe
 
     /* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
     copy->flags = report->flags;
 
 #undef JS_CHARS_SIZE
     return copy;
 }
 
-static jsval *
+static HeapValue *
 GetStackTraceValueBuffer(JSExnPrivate *priv)
 {
     /*
      * We use extra memory after JSExnPrivateInfo.stackElems to store jsvals
      * that helps to produce more informative stack traces. The following
      * assert allows us to assume that no gap after stackElems is necessary to
      * align the buffer properly.
      */
     JS_STATIC_ASSERT(sizeof(JSStackTraceElem) % sizeof(jsval) == 0);
 
-    return (jsval *)(priv->stackElems + priv->stackDepth);
+    return reinterpret_cast<HeapValue *>(priv->stackElems + priv->stackDepth);
 }
 
 struct SuppressErrorsGuard
 {
     JSContext *cx;
     JSErrorReporter prevReporter;
     JSExceptionState *prevState;
 
@@ -354,17 +354,17 @@ InitExnPrivate(JSContext *cx, JSObject *
         }
     }
 
     /* Do not need overflow check: the vm stack is already bigger. */
     JS_STATIC_ASSERT(sizeof(JSStackTraceElem) <= sizeof(StackFrame));
 
     size_t nbytes = offsetof(JSExnPrivate, stackElems) +
                     frames.length() * sizeof(JSStackTraceElem) +
-                    values.length() * sizeof(Value);
+                    values.length() * sizeof(HeapValue);
 
     JSExnPrivate *priv = (JSExnPrivate *)cx->malloc_(nbytes);
     if (!priv)
         return false;
 
     /* Initialize to zero so that write barriers don't witness undefined values. */
     memset(priv, 0, nbytes);
 
@@ -386,21 +386,22 @@ InitExnPrivate(JSContext *cx, JSObject *
 
     priv->message.init(message);
     priv->filename.init(filename);
     priv->lineno = lineno;
     priv->stackDepth = frames.length();
     priv->exnType = exnType;
 
     JSStackTraceElem *framesDest = priv->stackElems;
-    Value *valuesDest = reinterpret_cast<Value *>(framesDest + frames.length());
+    HeapValue *valuesDest = reinterpret_cast<HeapValue *>(framesDest + frames.length());
     JS_ASSERT(valuesDest == GetStackTraceValueBuffer(priv));
 
     PodCopy(framesDest, frames.begin(), frames.length());
-    PodCopy(valuesDest, values.begin(), values.length());
+    for (size_t i = 0; i < values.length(); ++i)
+        valuesDest[i].init(cx->compartment, values[i]);
 
     SetExnPrivate(cx, exnObject, priv);
     return true;
 }
 
 static inline JSExnPrivate *
 GetExnPrivate(JSObject *obj)
 {
@@ -409,17 +410,17 @@ GetExnPrivate(JSObject *obj)
 }
 
 static void
 exn_trace(JSTracer *trc, JSObject *obj)
 {
     JSExnPrivate *priv;
     JSStackTraceElem *elem;
     size_t vcount, i;
-    jsval *vp, v;
+    HeapValue *vp;
 
     priv = GetExnPrivate(obj);
     if (priv) {
         if (priv->message)
             MarkString(trc, priv->message, "exception message");
         if (priv->filename)
             MarkString(trc, priv->filename, "exception filename");
 
@@ -428,19 +429,17 @@ exn_trace(JSTracer *trc, JSObject *obj)
             if (elem->funName)
                 MarkString(trc, elem->funName, "stack trace function name");
             if (IS_GC_MARKING_TRACER(trc) && elem->filename)
                 js_MarkScriptFilename(elem->filename);
             vcount += elem->argc;
         }
         vp = GetStackTraceValueBuffer(priv);
         for (i = 0; i != vcount; ++i, ++vp) {
-            /* This value is read-only, so it's okay for it to be Unbarriered. */
-            v = *vp;
-            MarkValueUnbarriered(trc, v, "stack trace argument");
+            MarkValue(trc, *vp, "stack trace argument");
         }
     }
 }
 
 /* NB: An error object's private must be set through this function. */
 static void
 SetExnPrivate(JSContext *cx, JSObject *exnObject, JSExnPrivate *priv)
 {
@@ -600,17 +599,17 @@ ValueToShortSource(JSContext *cx, const 
 }
 
 static JSString *
 StackTraceToString(JSContext *cx, JSExnPrivate *priv)
 {
     jschar *stackbuf;
     size_t stacklen, stackmax;
     JSStackTraceElem *elem, *endElem;
-    jsval *values;
+    HeapValue *values;
     size_t i;
     JSString *str;
     const char *cp;
     char ulnbuf[11];
 
     /* After this point, failing control flow must goto bad. */
     stackbuf = NULL;
     stacklen = stackmax = 0;