Bug 987111 - Make JSProto_Object COWs take precedence over Xrays. r=gabor
authorBobby Holley <bobbyholley@gmail.com>
Thu, 05 Jun 2014 22:32:38 -0700
changeset 206247 d9788144b427606456bfa6bbc5206c88bac76ac4
parent 206246 3d93bce9a4563e6d8b38e3bdfab1b9a6bf9a6404
child 206248 40b5dff1e985c4de01eedeebf96d09f1771195e1
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgabor
bugs987111
milestone32.0a1
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
Bug 987111 - Make JSProto_Object COWs take precedence over Xrays. r=gabor
js/xpconnect/wrappers/WrapperFactory.cpp
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -115,16 +115,31 @@ WrapperFactory::DoubleWrap(JSContext *cx
 {
     if (flags & WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG) {
         JSAutoCompartment ac(cx, obj);
         return WaiveXray(cx, obj);
     }
     return obj;
 }
 
+// In general, we're trying to deprecate COWs incrementally as we introduce
+// Xrays to the corresponding object types. But switching off COWs for Object
+// instances would be too tumultuous at present, so we punt on that for later.
+static bool
+ForceCOWBehavior(JSObject *obj)
+{
+    if (IdentifyStandardInstanceOrPrototype(obj) == JSProto_Object) {
+        MOZ_ASSERT(GetXrayType(obj) == XrayForJSObject,
+                   "We should use XrayWrappers for standard ES Object instances "
+                   "modulo this hack");
+        return true;
+    }
+    return false;
+}
+
 JSObject *
 WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
                                    HandleObject objArg, unsigned flags)
 {
     RootedObject obj(cx, objArg);
     // Outerize any raw inner objects at the entry point here, so that we don't
     // have to worry about them for the rest of the wrapping code.
     if (js::IsInnerObject(obj)) {
@@ -164,17 +179,17 @@ WrapperFactory::PrepareForWrapping(JSCon
     // NB: We now remap all non-subsuming access of standard prototypes.
     //
     // NB: We need to ignore domain here so that the security relationship we
     // compute here can't change over time. See the comment above the other
     // subsumes call below.
     bool subsumes = AccessCheck::subsumes(js::GetContextCompartment(cx),
                                           js::GetObjectCompartment(obj));
     XrayType xrayType = GetXrayType(obj);
-    if (!subsumes && xrayType == NotXray) {
+    if (!subsumes && (xrayType == NotXray || ForceCOWBehavior(obj))) {
         JSProtoKey key = JSProto_Null;
         {
             JSAutoCompartment ac(cx, obj);
             key = IdentifyStandardPrototype(obj);
         }
         if (key != JSProto_Null) {
             RootedObject homeProto(cx);
             if (!JS_GetClassPrototype(cx, key, &homeProto))
@@ -413,17 +428,22 @@ WrapperFactory::Rewrap(JSContext *cx, Ha
     // If UniversalXPConnect is enabled, this is just some dumb mochitest. Use
     // a vanilla CCW.
     if (xpc::IsUniversalXPConnectEnabled(target)) {
         wrapper = &CrossCompartmentWrapper::singleton;
     }
 
     // If this is a chrome object being exposed to content without Xrays, use
     // a COW.
-    else if (originIsChrome && !targetIsChrome && xrayType == NotXray) {
+    //
+    // We make an exception for Object instances, because we still rely on COWs
+    // for those in a lot of places in the tree.
+    else if (originIsChrome && !targetIsChrome &&
+             (xrayType == NotXray || ForceCOWBehavior(obj)))
+    {
         wrapper = &ChromeObjectWrapper::singleton;
     }
 
     // Normally, a non-xrayable non-waived content object that finds itself in
     // a privileged scope is wrapped with a CrossCompartmentWrapper, even though
     // the lack of a waiver _really_ should give it an opaque wrapper. This is
     // a bit too entrenched to change for content-chrome, but we can at least fix
     // it for XBL scopes.