Bug 749866 part 4. Generate slightly better code when we know we're null or undefined. r=khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 05 Nov 2012 11:58:02 -0500
changeset 112320 6f08c574fb7968845fb886de1e1726f6886c7b1d
parent 112319 5b2c87bfe082d0f3619a4fb2a775213af8b81680
child 112321 b67a1dba5690052f4c4c0785732321c6a3c05fa9
push id23812
push useremorley@mozilla.com
push dateTue, 06 Nov 2012 14:01:34 +0000
treeherdermozilla-central@f4aeed115e54 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs749866
milestone19.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 749866 part 4. Generate slightly better code when we know we're null or undefined. r=khuey
dom/bindings/Codegen.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1950,16 +1950,19 @@ def getJSToNativeConversionTemplate(type
     """
     # If we have a defaultValue then we're not actually optional for
     # purposes of what we need to be declared as.
     assert(defaultValue is None or not isOptional)
 
     # Also, we should not have a defaultValue if we know we're an object
     assert(not isDefinitelyObject or defaultValue is None)
 
+    # And we can't both be an object and be null or undefined
+    assert not isDefinitelyObject or not isNullOrUndefined
+
     # Helper functions for dealing with failures due to the JS value being the
     # wrong type of value
     def onFailureNotAnObject(failureCode):
         return CGWrapper(CGGeneric(
                 failureCode or
                 'return ThrowErrorMessage(cx, MSG_NOT_OBJECT);'), post="\n")
     def onFailureBadType(failureCode, typeName):
         return CGWrapper(CGGeneric(
@@ -1990,18 +1993,24 @@ def getJSToNativeConversionTemplate(type
     def handleDefaultNull(template, codeToSetNull):
         if (defaultValue is not None and
             not isinstance(defaultValue, IDLNullValue)):
             raise TypeError("Can't handle non-null default value here")
         return handleDefault(template, codeToSetNull)
 
     # A helper function for wrapping up the template body for
     # possibly-nullable objecty stuff
-    def wrapObjectTemplate(templateBody, isDefinitelyObject, type,
-                           codeToSetNull, failureCode=None):
+    def wrapObjectTemplate(templateBody, type, codeToSetNull, failureCode=None):
+        if isNullOrUndefined:
+            assert type.nullable()
+            # Just ignore templateBody and set ourselves to null.
+            # Note that wedon't have to worry about default values
+            # here either, since we already examined this value.
+            return "%s;" % codeToSetNull
+
         if not isDefinitelyObject:
             # Handle the non-object cases by wrapping up the whole
             # thing in an if cascade.
             templateBody = (
                 "if (${val}.isObject()) {\n" +
                 CGIndenter(CGGeneric(templateBody)).define() + "\n")
             if type.nullable():
                 templateBody += (
@@ -2102,18 +2111,17 @@ for (uint32_t i = 0; i < length; ++i) {
                     {
                         "val" : "temp",
                         "valPtr": "&temp",
                         "declName" : "(*arr.AppendElement())"
                         }
                     ))).define()
 
         templateBody += "\n}"
-        templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
-                                          type,
+        templateBody = wrapObjectTemplate(templateBody, type,
                                           "const_cast< %s & >(${declName}).SetNull()" % mutableTypeName.define())
         return (templateBody, typeName, None, isOptional)
 
     if type.isUnion():
         if isMember:
             raise TypeError("Can't handle unions as members, we have a "
                             "holderType")
         nullable = type.nullable();
@@ -2422,18 +2430,18 @@ for (uint32_t i = 0; i < length; ++i) {
                     "  // We have to have a strong ref, because we got this off\n"
                     "  // some random object that might get GCed\n"
                     "  ${holderName} = tmp;\n"
                     "}\n")
 
             # And store our tmp, before it goes out of scope.
             templateBody += "${declName} = tmp;"
 
-        templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
-                                          type, "${declName} = NULL",
+        templateBody = wrapObjectTemplate(templateBody, type,
+                                          "${declName} = NULL",
                                           failureCode)
 
         declType = CGGeneric(declType)
         if holderType is not None:
             holderType = CGGeneric(holderType)
         return (templateBody, declType, holderType, isOptional)
 
     if type.isSpiderMonkeyInterface():
@@ -2478,17 +2486,17 @@ for (uint32_t i = 0; i < length; ++i) {
                 mutableDecl = "(const_cast<Optional<" + name + "*>& >(${declName}))"
                 template += "%s.Construct();\n" % mutableDecl
                 nullableTarget = "%s.Value()" % mutableDecl
             else:
                 nullableTarget = "${declName}"
             template += "%s = ${holderName}.addr();" % nullableTarget
         elif not isOptional:
             template += "${declName} = ${holderName}.addr();"
-        template = wrapObjectTemplate(template, isDefinitelyObject, type,
+        template = wrapObjectTemplate(template, type,
                                       "%s = NULL" % nullableTarget,
                                       failureCode)
 
         if holderType is not None:
             holderType = CGGeneric(holderType)
         # We handle all the optional stuff ourselves; no need for caller to do it.
         return (template, CGGeneric(declType), holderType, False)
 
@@ -2621,17 +2629,17 @@ for (uint32_t i = 0; i < length; ++i) {
                 "}" % haveCallable)
         else:
             template = wrapObjectTemplate(
                 "if (JS_ObjectIsCallable(cx, &${val}.toObject())) {\n"
                 "  ${declName} = &${val}.toObject();\n"
                 "} else {\n"
                 "%s"
                 "}" % CGIndenter(onFailureNotCallable(failureCode)).define(),
-                isDefinitelyObject, type,
+                type,
                 "${declName} = nullptr",
                 failureCode)
         return (template, declType, None, isOptional)
 
     if type.isAny():
         assert not isEnforceRange and not isClamp
 
         if isMember:
@@ -2644,17 +2652,17 @@ for (uint32_t i = 0; i < length; ++i) {
 
     if type.isObject():
         assert not isEnforceRange and not isClamp
 
         if isMember:
             raise TypeError("Can't handle member 'object'; need to sort out "
                             "rooting issues")
         template = wrapObjectTemplate("${declName} = &${val}.toObject();",
-                                      isDefinitelyObject, type,
+                                      type,
                                       "${declName} = NULL",
                                       failureCode)
         if type.nullable():
             declType = CGGeneric("JSObject*")
         else:
             declType = CGGeneric("NonNull<JSObject>")
         return (template, declType, None, isOptional)