Fast-path for casting JS wrappers to JSNode.
authorakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Apr 2014 02:29:15 +0000 (02:29 +0000)
committerakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Apr 2014 02:29:15 +0000 (02:29 +0000)
<https://webkit.org/b/131196>

Source/JavaScriptCore:

Allow code outside of JSC (well, WebCore) to extend the JSType spectrum
a little bit. We do this by exposing a LastJSCObjectType constant so
WebCore can encode its own wrapper types after that.

Reviewed by Mark Hahnenberg and Geoff Garen.

* runtime/JSType.h:

    Added LastJSCObjectType for use by WebCore.

* runtime/JSObject.h:
(JSC::JSObject::isVariableObject):

    Updated since this can no longer assume that types >= VariableObjectType
    are all variable objects.

Source/WebCore:

Add a way to quickly determine that a given JSObject is a JSNode.
This lets us avoid walking the ClassInfo chain in the DOM bindings
for WebCore::Node.

Reviewed by Mark Hahnenberg and Geoff Garen.

* bindings/js/JSDOMWrapper.h:

    Added a JSNodeType constant that extends beyond JSC::JSType.

* bindings/js/JSNodeCustom.h:
(WebCore::jsNodeCast):

    Added. Fast cast from JSValue to JSNode.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):
(GenerateImplementation):

    Generate code that uses jsNodeCast in Node interfaces.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@166760 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSType.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSDOMWrapper.h
Source/WebCore/bindings/js/JSNodeCustom.h
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

index b781688..b6d5a71 100644 (file)
@@ -1,3 +1,24 @@
+2014-04-03  Andreas Kling  <akling@apple.com>
+
+        Fast-path for casting JS wrappers to JSNode.
+        <https://webkit.org/b/131196>
+
+        Allow code outside of JSC (well, WebCore) to extend the JSType spectrum
+        a little bit. We do this by exposing a LastJSCObjectType constant so
+        WebCore can encode its own wrapper types after that.
+
+        Reviewed by Mark Hahnenberg and Geoff Garen.
+
+        * runtime/JSType.h:
+
+            Added LastJSCObjectType for use by WebCore.
+
+        * runtime/JSObject.h:
+        (JSC::JSObject::isVariableObject):
+
+            Updated since this can no longer assume that types >= VariableObjectType
+            are all variable objects.
+
 2014-04-03  Mark Hahnenberg  <mhahnenberg@apple.com>
 
         All Heap::writeBarriers should be inline
index 2866fa5..521b5f4 100644 (file)
@@ -1122,10 +1122,9 @@ inline bool JSObject::isGlobalObject() const
 
 inline bool JSObject::isVariableObject() const
 {
-    return type() >= VariableObjectType;
+    return type() == GlobalObjectType || type() == ActivationObjectType;
 }
 
-
 inline bool JSObject::isStaticScopeObject() const
 {
     JSType type = this->type();
index 571a3ac..999ccda 100644 (file)
@@ -69,11 +69,11 @@ enum JSType : uint8_t {
     DataViewType,
 
     NameScopeObjectType,
-    // VariableObjectType must be less than MOST of the types of its subclasses and only its subclasses.
-    // We use >=VariableObjectType checks to test for Global & Activation objects, but exclude NameScopes.
-    VariableObjectType,
+
     GlobalObjectType,
     ActivationObjectType,
+
+    LastJSCObjectType = ActivationObjectType,
 };
 
 COMPILE_ASSERT(sizeof(JSType) == sizeof(uint8_t), sizeof_jstype_is_one_byte);
index 59e1b18..61cdcd8 100644 (file)
@@ -1,3 +1,29 @@
+2014-04-03  Andreas Kling  <akling@apple.com>
+
+        Fast-path for casting JS wrappers to JSNode.
+        <https://webkit.org/b/131196>
+
+        Add a way to quickly determine that a given JSObject is a JSNode.
+        This lets us avoid walking the ClassInfo chain in the DOM bindings
+        for WebCore::Node.
+
+        Reviewed by Mark Hahnenberg and Geoff Garen.
+
+        * bindings/js/JSDOMWrapper.h:
+
+            Added a JSNodeType constant that extends beyond JSC::JSType.
+
+        * bindings/js/JSNodeCustom.h:
+        (WebCore::jsNodeCast):
+
+            Added. Fast cast from JSValue to JSNode.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateHeader):
+        (GenerateImplementation):
+
+            Generate code that uses jsNodeCast in Node interfaces.
+
 2014-04-03  Bem Jones-Bey  <bjonesbe@adobe.com>
 
         Merge ShapeInfo & ShapeOutsideInfo now that ShapeInsideInfo is no more
index 026dcd9..a14c681 100644 (file)
@@ -29,6 +29,8 @@ namespace WebCore {
 
 class ScriptExecutionContext;
 
+static const uint8_t JSNodeType = JSC::LastJSCObjectType + 1;
+
 class JSDOMWrapper : public JSC::JSDestructibleObject {
 public:
     typedef JSC::JSDestructibleObject Base;
index bf7c9a1..79d4471 100644 (file)
@@ -78,6 +78,13 @@ inline void* root(Node& node)
     return root(&node);
 }
 
+ALWAYS_INLINE JSNode* jsNodeCast(JSC::JSValue value)
+{
+    if (UNLIKELY(!value.isCell()))
+        return nullptr;
+    return value.asCell()->type() == JSNodeType ? JSC::jsCast<JSNode*>(value) : nullptr;
+}
+
 } // namespace WebCore
 
 #endif // JSDOMNodeCustom_h
index d193f78..defd1a6 100644 (file)
@@ -959,6 +959,8 @@ sub GenerateHeader
     push(@headerContent, "    {\n");
     if (IsDOMGlobalObject($interface)) {
         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags), info());\n");
+    } elsif ($codeGenerator->InheritsInterface($interface, "Node")) {
+        push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSNodeType), StructureFlags), info());\n");
     } else {
         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n");
     }
@@ -2130,7 +2132,11 @@ sub GenerateImplementation
                     push(@implContent, "    ${className}* castedThis = to${className}(JSValue::decode(thisValue));\n");
                     push(@implContent, "    UNUSED_PARAM(slotBase);\n");
                 } else {
-                    push(@implContent, "    ${className}* castedThis = jsDynamicCast<$className*>(JSValue::decode(thisValue));\n");
+                    if ($interfaceName eq "Node") {
+                        push(@implContent, "    JSNode* castedThis = jsNodeCast(JSValue::decode(thisValue));\n");
+                    } else {
+                        push(@implContent, "    ${className}* castedThis = jsDynamicCast<$className*>(JSValue::decode(thisValue));\n");
+                    }
                     push(@implContent, "    UNUSED_PARAM(slotBase);\n");
                 }
                 $implIncludes{"ScriptExecutionContext.h"} = 1;