Backed out changeset 76f7d7963692 (bug 861912) for debug mochitest b-c orange.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 16 Apr 2013 11:51:49 -0400
changeset 128933 712e8ba8219bddb5a037c92b42ee938926dc5e2b
parent 128932 d8b73ccd6725315f34a5971290e8da51af32ca95
child 128934 2f322551642defbe6547cdfe5d9c2632b1757c45
push id26578
push userryanvm@gmail.com
push dateTue, 16 Apr 2013 15:51:47 +0000
treeherdermozilla-inbound@712e8ba8219b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs861912
milestone23.0a1
backs out76f7d796369277f90462af18ba530cfe4ee236a6
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
Backed out changeset 76f7d7963692 (bug 861912) for debug mochitest b-c orange.
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -24,17 +24,16 @@
 #include "jsfriendapi.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/PrimitiveConversions.h"
 
 using namespace xpc;
 using namespace mozilla;
 using namespace mozilla::dom;
-using namespace JS;
 
 //#define STRICT_CHECK_OF_UNICODE
 #ifdef STRICT_CHECK_OF_UNICODE
 #define ILLEGAL_RANGE(c) (0!=((c) & 0xFF80))
 #else // STRICT_CHECK_OF_UNICODE
 #define ILLEGAL_RANGE(c) (0!=((c) & 0xFF00))
 #endif // STRICT_CHECK_OF_UNICODE
 
@@ -165,17 +164,17 @@ XPCConvert::NativeData2JS(XPCLazyCallCon
             XPC_LOG_ERROR(("XPCConvert::NativeData2JS : void* params not supported"));
             return false;
 
         case nsXPTType::T_IID:
             {
                 nsID* iid2 = *((nsID**)s);
                 if (!iid2)
                     break;
-                RootedObject scope(cx, lccx.GetScopeForNewJSObjects());
+                JS::RootedObject scope(cx, lccx.GetScopeForNewJSObjects());
                 JSObject* obj;
                 if (!(obj = xpc_NewIDObject(cx, scope, *iid2)))
                     return false;
                 *d = OBJECT_TO_JSVAL(obj);
                 break;
             }
 
         case nsXPTType::T_ASTRING:
@@ -826,17 +825,17 @@ XPCConvert::NativeInterface2JSObject(XPC
     // Note: If |cache->IsProxy()| is true, then it means that the object
     // implementing it doesn't want a wrapped native as its JS Object, but
     // instead it provides its own proxy object. In that case, the object
     // to use is found as cache->GetWrapper(). If that is null, then the
     // object will create (and fill the cache) from its WrapObject call.
     nsWrapperCache *cache = aHelper.GetWrapperCache();
 
     bool tryConstructSlimWrapper = false;
-    RootedObject flat(cx);
+    JS::RootedObject flat(cx);
     if (cache) {
         flat = cache->GetWrapper();
         if (cache->IsDOMBinding()) {
             XPCCallContext &ccx = lccx.GetXPCCallContext();
             if (!ccx.IsValid())
                 return false;
 
             if (!flat) {
@@ -1149,17 +1148,17 @@ public:
 
     ~AutoExceptionRestorer()
     {
         JS_SetPendingException(mContext, tvr.jsval_value());
     }
 
 private:
     JSContext * const mContext;
-    AutoValueRooter tvr;
+    JS::AutoValueRooter tvr;
 };
 
 // static
 nsresult
 XPCConvert::JSValToXPCException(XPCCallContext& ccx,
                                 jsval s,
                                 const char* ifaceName,
                                 const char* methodName,
@@ -1407,36 +1406,39 @@ XPCConvert::NativeArray2JS(XPCLazyCallCo
     JSContext* cx = ccx.GetJSContext();
     NS_ABORT_IF_FALSE(js::IsObjectInContextCompartment(lccx.GetScopeForNewJSObjects(), cx),
                       "bad scope for new JSObjects");
 
     // XXX add support for putting chars in a string rather than an array
 
     // XXX add support to indicate *which* array element was not convertable
 
-    RootedObject array(cx, JS_NewArrayObject(cx, count, nullptr));
+    JSObject *array = JS_NewArrayObject(cx, count, nullptr);
 
     if (!array)
         return false;
 
+    // root this early
     *d = OBJECT_TO_JSVAL(array);
+    AUTO_MARK_JSVAL(ccx, d);
 
     if (pErr)
         *pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
 
     uint32_t i;
-    RootedValue current(cx, JSVAL_NULL);
+    jsval current = JSVAL_NULL;
+    AUTO_MARK_JSVAL(ccx, &current);
 
-#define POPULATE(_t)                                                                    \
-    PR_BEGIN_MACRO                                                                      \
-        for (i = 0; i < count; i++) {                                                   \
-            if (!NativeData2JS(ccx, current.address(), ((_t*)*s)+i, type, iid, pErr) || \
-                !JS_SetElement(cx, array, i, current.address()))                        \
-                goto failure;                                                           \
-        }                                                                               \
+#define POPULATE(_t)                                                          \
+    PR_BEGIN_MACRO                                                            \
+        for (i = 0; i < count; i++) {                                         \
+            if (!NativeData2JS(ccx, &current, ((_t*)*s)+i, type, iid, pErr) ||\
+                !JS_SetElement(cx, array, i, &current))                       \
+                goto failure;                                                 \
+        }                                                                     \
     PR_END_MACRO
 
     // XXX check IsPtr - esp. to handle array of nsID (as opposed to nsID*)
 
     switch (type.TagPart()) {
     case nsXPTType::T_I8            : POPULATE(int8_t);         break;
     case nsXPTType::T_I16           : POPULATE(int16_t);        break;
     case nsXPTType::T_I32           : POPULATE(int32_t);        break;
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -227,16 +227,19 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
     if (!scriptEval.StartEvaluating(jsobj))
         return nullptr;
 
     // check upfront for the existence of the function property
     funid = mRuntime->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE);
     if (!JS_GetPropertyById(cx, jsobj, funid, fun.address()) || JSVAL_IS_PRIMITIVE(fun))
         return nullptr;
 
+    // protect fun so that we're sure it's alive when we call it
+    AUTO_MARK_JSVAL(cx, fun);
+
     // Ensure that we are asking for a scriptable interface.
     // NB:  It's important for security that this check is here rather
     // than later, since it prevents untrusted objects from implementing
     // some interfaces in JS and aggregating a trusted object to
     // implement intentionally (for security) unscriptable interfaces.
     // We so often ask for nsISupports that we can short-circuit the test...
     if (!aIID.Equals(NS_GET_IID(nsISupports))) {
         nsCOMPtr<nsIInterfaceInfo> info;
@@ -263,16 +266,17 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
 
         JS_SetOptions(cx, oldOpts);
 
         if (!success) {
             NS_ASSERTION(JS_IsExceptionPending(cx),
                          "JS failed without setting an exception!");
 
             RootedValue jsexception(cx, NullValue());
+            AUTO_MARK_JSVAL(cx, jsexception.address());
 
             if (JS_GetPendingException(cx, jsexception.address())) {
                 nsresult rv;
                 if (jsexception.isObject()) {
                     // XPConnect may have constructed an object to represent a
                     // C++ QI failure. See if that is the case.
                     nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
 
@@ -707,19 +711,22 @@ nsXPCWrappedJSClass::DelegatedQueryInter
             if (!checked)
                 return NS_ERROR_OUT_OF_MEMORY;
             *aInstancePtr = checked.forget().get();
             return NS_OK;
         }
     }
 
     // check if the JSObject claims to implement this interface
-    RootedObject jsobj(ccx, CallQueryInterfaceOnJSObject(ccx, self->GetJSObject(),
-                                                         aIID));
+    JSObject* jsobj = CallQueryInterfaceOnJSObject(ccx, self->GetJSObject(),
+                                                   aIID);
     if (jsobj) {
+        // protect jsobj until it is actually attached
+        AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(jsobj));
+
         // We can't use XPConvert::JSObject2NativeInterface() here
         // since that can find a XPCWrappedNative directly on the
         // proto chain, and we don't want that here. We need to find
         // the actual JS object that claimed it supports the interface
         // we're looking for or we'll potentially bypass security
         // checks etc by calling directly through to a native found on
         // the prototype chain.
         //
@@ -1279,17 +1286,18 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWra
     // we're trusting the JS engine to come up with a good global to use for
     // our object (whatever it was).
     for (i = 0; i < argc; i++) {
         const nsXPTParamInfo& param = info->params[i];
         const nsXPTType& type = param.GetType();
         nsXPTType datum_type;
         uint32_t array_count;
         bool isArray = type.IsArray();
-        RootedValue val(cx, NullValue());
+        RootedValue val(cx, JSVAL_NULL);
+        AUTO_MARK_JSVAL(ccx, val.address());
         bool isSizedString = isArray ?
                 false :
                 type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
                 type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
 
 
         // verify that null was not passed for 'out' param
         if (param.IsOut() && !nativeParams[i].val.p) {
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -498,17 +498,19 @@ XPCWrappedNative::GetNewOrUsed(XPCCallCo
     // described by the nsIClassInfo, not for the class info object
     // itself.
     const XPCNativeScriptableCreateInfo& sciWrapper =
         isClassInfo ? sci :
         GatherScriptableCreateInfo(identity, info, sciProto, sci);
 
     RootedObject parent(ccx, Scope->GetGlobalJSObject());
 
-    RootedValue newParentVal(ccx, JSVAL_NULL);
+    jsval newParentVal = JSVAL_NULL;
+    XPCMarkableJSVal newParentVal_markable(&newParentVal);
+    AutoMarkingJSVal newParentVal_automarker(ccx, &newParentVal_markable);
     JSBool needsSOW = false;
     JSBool needsCOW = false;
 
     mozilla::Maybe<JSAutoCompartment> ac;
 
     if (sciWrapper.GetFlags().WantPreCreate()) {
         // PreCreate may touch dead compartments.
         js::AutoMaybeTouchDeadZones agc(parent);
@@ -2434,16 +2436,17 @@ CallMethodHelper::GatherAndConvertResult
     for (uint8_t i = 0; i < paramCount; i++) {
         const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(i);
         if (!paramInfo.IsOut() && !paramInfo.IsDipper())
             continue;
 
         const nsXPTType& type = paramInfo.GetType();
         nsXPTCVariant* dp = GetDispatchParam(i);
         RootedValue v(mCallContext, NullValue());
+        AUTO_MARK_JSVAL(mCallContext, v.address());
         uint32_t array_count = 0;
         nsXPTType datum_type;
         bool isArray = type.IsArray();
         bool isSizedString = isArray ?
                 false :
                 type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
                 type.TagPart() == nsXPTType::T_PWSTRING_SIZE_IS;
 
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -419,16 +419,19 @@ DefinePropertyIfFound(XPCCallContext& cc
          scriptableInfo->GetFlags().DontEnumQueryInterface() &&
          id == rt->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE)))
         propFlags &= ~JSPROP_ENUMERATE;
 
     RootedValue funval(ccx);
     if (!member->NewFunctionObject(ccx, iface, obj, funval.address()))
         return false;
 
+    // protect funobj until it is actually attached
+    AUTO_MARK_JSVAL(ccx, funval);
+
 #ifdef off_DEBUG_jband
     {
         static int cloneCount = 0;
         if (!(++cloneCount%10))
             printf("<><><> %d cloned functions created\n", cloneCount);
     }
 #endif
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1588,16 +1588,17 @@ nsXPConnect::CreateSandbox(JSContext *cx
 {
     XPCCallContext ccx(NATIVE_CALLER, cx);
     if (!ccx.IsValid())
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     *_retval = nullptr;
 
     RootedValue rval(cx, JSVAL_VOID);
+    AUTO_MARK_JSVAL(ccx, rval.address());
 
     SandboxOptions options(cx);
     nsresult rv = xpc_CreateSandboxObject(cx, rval.address(), principal, options);
     NS_ASSERTION(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
                  "Bad return value from xpc_CreateSandboxObject()!");
 
     if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(rval)) {
         *_retval = XPCJSObjectHolder::newHolder(ccx, JSVAL_TO_OBJECT(rval));
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3852,16 +3852,35 @@ private:
     JS::RootedId mOld;
 #ifdef DEBUG
     JS::RootedId mCheck;
 #endif
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 /***************************************************************************/
+class XPCMarkableJSVal
+{
+public:
+    XPCMarkableJSVal(jsval val) : mVal(val), mValPtr(&mVal) {}
+    XPCMarkableJSVal(jsval *pval) : mVal(JSVAL_VOID), mValPtr(pval) {}
+    ~XPCMarkableJSVal() {}
+    void Mark() {}
+    void TraceJS(JSTracer* trc)
+    {
+        JS_CallValueTracer(trc, *mValPtr, "XPCMarkableJSVal");
+    }
+    void AutoTrace(JSTracer* trc) {}
+private:
+    XPCMarkableJSVal(); // not implemented
+    jsval  mVal;
+    jsval* mValPtr;
+};
+
+/***************************************************************************/
 // AutoMarkingPtr is the base class for the various AutoMarking pointer types
 // below. This system allows us to temporarily protect instances of our garbage
 // collected types after they are constructed but before they are safely
 // attached to other rooted objects.
 // This base class has pure virtual support for marking.
 
 class AutoMarkingPtr
 {
@@ -3930,16 +3949,17 @@ class TypedAutoMarkingPtr : public AutoM
     T* mPtr;
 };
 
 typedef TypedAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtr;
 typedef TypedAutoMarkingPtr<XPCNativeSet> AutoMarkingNativeSetPtr;
 typedef TypedAutoMarkingPtr<XPCWrappedNative> AutoMarkingWrappedNativePtr;
 typedef TypedAutoMarkingPtr<XPCWrappedNativeTearOff> AutoMarkingWrappedNativeTearOffPtr;
 typedef TypedAutoMarkingPtr<XPCWrappedNativeProto> AutoMarkingWrappedNativeProtoPtr;
+typedef TypedAutoMarkingPtr<XPCMarkableJSVal> AutoMarkingJSVal;
 typedef TypedAutoMarkingPtr<XPCNativeScriptableInfo> AutoMarkingNativeScriptableInfoPtr;
 
 template<class T>
 class ArrayAutoMarkingPtr : public AutoMarkingPtr
 {
   public:
     ArrayAutoMarkingPtr(JSContext* cx)
       : AutoMarkingPtr(cx), mPtr(nullptr), mCount(0) {}
@@ -3982,16 +4002,24 @@ class ArrayAutoMarkingPtr : public AutoM
 
   private:
     T** mPtr;
     uint32_t mCount;
 };
 
 typedef ArrayAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtrArrayPtr;
 
+#define AUTO_MARK_JSVAL_HELPER2(tok, line) tok##line
+#define AUTO_MARK_JSVAL_HELPER(tok, line) AUTO_MARK_JSVAL_HELPER2(tok, line)
+
+#define AUTO_MARK_JSVAL(cx, val)                                              \
+    XPCMarkableJSVal AUTO_MARK_JSVAL_HELPER(_val_,__LINE__)(val);             \
+    AutoMarkingJSVal AUTO_MARK_JSVAL_HELPER(_automarker_,__LINE__)            \
+    (cx, &AUTO_MARK_JSVAL_HELPER(_val_,__LINE__))
+
 /***************************************************************************/
 // Allocates a string that grants all access ("AllAccess")
 
 extern char* xpc_CloneAllAccess();
 /***************************************************************************/
 // Returns access if wideName is in list
 
 extern char * xpc_CheckAccessList(const PRUnichar* wideName, const char* list[]);