Bug 962256 yet another part. Eliminate some unnecessary roots in HTMLDocumentBinding::DOMProxyHandler::get. r=bholley
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 26 Feb 2014 12:40:57 -0500
changeset 171047 960a7f055c95d6d304a2f2e82f7ffebedf36414d
parent 171046 0c8703fab0c991df30768f53ca2ca9c3c6d1e42f
child 171048 85a14a1db91ebb94d57ef0e65cbc5d8347d40b2c
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersbholley
bugs962256
milestone30.0a1
Bug 962256 yet another part. Eliminate some unnecessary roots in HTMLDocumentBinding::DOMProxyHandler::get. r=bholley
dom/bindings/Codegen.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -294,26 +294,31 @@ def PrototypeIDAndDepth(descriptor):
         depth = "0"
     return (prototypeID, depth)
 
 def UseHolderForUnforgeable(descriptor):
     return (descriptor.concrete and
             descriptor.proxy and
             any(m for m in descriptor.interface.members if m.isAttr() and m.isUnforgeable()))
 
-def CallOnUnforgeableHolder(descriptor, code, isXrayCheck=None):
+def CallOnUnforgeableHolder(descriptor, code, isXrayCheck=None,
+                            useSharedRoot=False):
     """
     Generate the code to execute the code in "code" on an unforgeable holder if
     needed. code should be a string containing the code to execute. If it
     contains a ${holder} string parameter it will be replaced with the
     unforgeable holder object.
 
     If isXrayCheck is not None it should be a string that contains a statement
     returning whether proxy is an Xray. If isXrayCheck is None the generated
     code won't try to unwrap Xrays.
+
+    If useSharedRoot is true, we will use an existing
+    JS::Rooted<JSObject*> sharedRoot for storing our unforgeable holder instead
+    of declaring a new Rooted.
     """
     code = string.Template(code).substitute({ "holder": "unforgeableHolder" })
     if not isXrayCheck is None:
         pre = """// Scope for 'global', 'ac' and 'unforgeableHolder'
 {
   JS::Rooted<JSObject*> global(cx);
   Maybe<JSAutoCompartment> ac;
   if (""" + isXrayCheck + """) {
@@ -322,21 +327,26 @@ def CallOnUnforgeableHolder(descriptor, 
   } else {
     global = js::GetGlobalForObjectCrossCompartment(proxy);
   }"""
     else:
         pre = """// Scope for 'global' and 'unforgeableHolder'
 {
   JSObject* global = js::GetGlobalForObjectCrossCompartment(proxy);"""
 
+    if useSharedRoot:
+        holderDecl = "JS::Rooted<JSObject*>& unforgeableHolder(sharedRoot)"
+    else:
+        holderDecl = "JS::Rooted<JSObject*> unforgeableHolder(cx)"
     return (pre + """
-  JS::Rooted<JSObject*> unforgeableHolder(cx, GetUnforgeableHolder(global, prototypes::id::%s));
+  %s;
+  unforgeableHolder = GetUnforgeableHolder(global, prototypes::id::%s);
 """ + CGIndenter(CGGeneric(code)).define() + """
 }
-""") % descriptor.name
+""") % (holderDecl, descriptor.name)
 
 class CGPrototypeJSClass(CGThing):
     def __init__(self, descriptor, properties):
         CGThing.__init__(self)
         self.descriptor = descriptor
         self.properties = properties
     def declare(self):
         # We're purely for internal consumption
@@ -4773,31 +4783,19 @@ def getRetvalDeclarationForType(returnTy
             result = CGTemplatedType("nsRefPtr", result)
         else:
             result = CGWrapper(result, post="*")
         return result, False, None, None
     if returnType.isCallback():
         name = returnType.unroll().identifier.name
         return CGGeneric("nsRefPtr<%s>" % name), False, None, None
     if returnType.isAny():
-        result = CGGeneric("JS::Value")
-        if isMember:
-            resultArgs = None
-        else:
-            result = CGTemplatedType("JS::Rooted", result)
-            resultArgs = "cx"
-        return result, False, None, resultArgs
+        return CGGeneric("JS::Value"), False, None, None
     if returnType.isObject() or returnType.isSpiderMonkeyInterface():
-        result = CGGeneric("JSObject*")
-        if isMember:
-            resultArgs = None
-        else:
-            result = CGTemplatedType("JS::Rooted", result)
-            resultArgs = "cx"
-        return result, False, None, resultArgs
+        return CGGeneric("JSObject*"), False, None, None
     if returnType.isSequence():
         nullable = returnType.nullable()
         if nullable:
             returnType = returnType.inner
         # If our result is already addrefed, use the right type in the
         # sequence argument here.
         (result, _, _, _) = getRetvalDeclarationForType(returnType.inner,
                                                         descriptorProvider,
@@ -8538,40 +8536,43 @@ class CGDOMJSProxyHandler_get(ClassMetho
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('JS::Handle<JSObject*>', 'receiver'),
                 Argument('JS::Handle<jsid>', 'id'),
                 Argument('JS::MutableHandle<JS::Value>', 'vp')]
         ClassMethod.__init__(self, "get", "bool", args)
         self.descriptor = descriptor
     def getBody(self):
+        getUnforgeableOrExpando = "JS::Rooted<JSObject*> sharedRoot(cx);\n"
         if UseHolderForUnforgeable(self.descriptor):
             hasUnforgeable = (
                 "bool hasUnforgeable;\n"
                  "if (!JS_AlreadyHasOwnPropertyById(cx, ${holder}, id, &hasUnforgeable)) {\n"
                  "  return false;\n"
                  "}\n"
                  "if (hasUnforgeable) {\n"
                  "  return JS_ForwardGetPropertyTo(cx, ${holder}, id, proxy, vp);\n"
                  "}")
-            getUnforgeableOrExpando = CallOnUnforgeableHolder(self.descriptor,
-                                                              hasUnforgeable)
-        else:
-            getUnforgeableOrExpando = ""
-        getUnforgeableOrExpando += """JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
-if (expando) {
-  bool hasProp;
-  if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
-    return false;
-  }
-
-  if (hasProp) {
-    // Forward the get to the expando object, but our receiver is whatever our
-    // receiver is.
-    return JS_ForwardGetPropertyTo(cx, expando, id, receiver, vp);
+            getUnforgeableOrExpando += CallOnUnforgeableHolder(self.descriptor,
+                                                               hasUnforgeable,
+                                                               useSharedRoot=True)
+        getUnforgeableOrExpando += """{ // Scope for expando
+  JS::Rooted<JSObject*>& expando(sharedRoot);
+  expando = DOMProxyHandler::GetExpandoObject(proxy);
+  if (expando) {
+    bool hasProp;
+    if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
+      return false;
+    }
+
+    if (hasProp) {
+      // Forward the get to the expando object, but our receiver is whatever our
+      // receiver is.
+      return JS_ForwardGetPropertyTo(cx, expando, id, receiver, vp);
+    }
   }
 }"""
 
         templateValues = {'jsvalRef': 'vp', 'jsvalHandle': 'vp', 'obj': 'proxy'}
 
         if self.descriptor.supportsIndexedProperties():
             getIndexedOrExpando = ("int32_t index = GetArrayIndexFromId(cx, id);\n" +
                                    "if (IsArrayIndex(index)) {\n" +