[DOM] Add JSEventType
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Oct 2016 03:56:50 +0000 (03:56 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Oct 2016 03:56:50 +0000 (03:56 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164096

Reviewed by Darin Adler.

Event is inherited by many Event classes. But, Event's accessors and interfaces are
frequently called. For example, event.{type, target, srcElement} for accessors. And
event.stopPropagation() and event.preventDefault() functions.

However, since the user-visible event instance is typically the instance of the subclass,
jsDynamicCast<JSEvent*>() walks several classes before it succeeds. It is costly.

In this patch, we add a new WebCore JSType JSEventType for JSEvent and add a new
function jsEventCast. That supports a super fast cast operation. And it paves the way
for implementing DOM accessors of Event in DOMJIT.

No behavior change.

* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSDOMWrapper.h:
* bindings/js/JSEventCustom.h: Added.
(WebCore::jsEventCast):
* bindings/scripts/CodeGeneratorJS.pm:
(GetJSTypeForNode):
(GenerateHeader):
(GetCastingHelperForThisObject):
* bindings/scripts/test/JS/JSTestEventConstructor.h:
(WebCore::JSTestEventConstructor::createStructure):
* dom/Event.idl:
* domjit/DOMJITHelpers.h:
(WebCore::DOMJIT::branchIfEvent):
(WebCore::DOMJIT::branchIfNotEvent):

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

Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSDOMWrapper.h
Source/WebCore/bindings/js/JSEventCustom.h [new file with mode: 0644]
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestEventConstructor.h
Source/WebCore/dom/Event.idl
Source/WebCore/domjit/DOMJITHelpers.h

index fbe0bfb..615412f 100644 (file)
@@ -1,3 +1,38 @@
+2016-10-27  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [DOM] Add JSEventType
+        https://bugs.webkit.org/show_bug.cgi?id=164096
+
+        Reviewed by Darin Adler.
+
+        Event is inherited by many Event classes. But, Event's accessors and interfaces are
+        frequently called. For example, event.{type, target, srcElement} for accessors. And
+        event.stopPropagation() and event.preventDefault() functions.
+
+        However, since the user-visible event instance is typically the instance of the subclass,
+        jsDynamicCast<JSEvent*>() walks several classes before it succeeds. It is costly.
+
+        In this patch, we add a new WebCore JSType JSEventType for JSEvent and add a new
+        function jsEventCast. That supports a super fast cast operation. And it paves the way
+        for implementing DOM accessors of Event in DOMJIT.
+
+        No behavior change.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSDOMWrapper.h:
+        * bindings/js/JSEventCustom.h: Added.
+        (WebCore::jsEventCast):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GetJSTypeForNode):
+        (GenerateHeader):
+        (GetCastingHelperForThisObject):
+        * bindings/scripts/test/JS/JSTestEventConstructor.h:
+        (WebCore::JSTestEventConstructor::createStructure):
+        * dom/Event.idl:
+        * domjit/DOMJITHelpers.h:
+        (WebCore::DOMJIT::branchIfEvent):
+        (WebCore::DOMJIT::branchIfNotEvent):
+
 2016-10-27  Simon Fraser  <simon.fraser@apple.com>
 
         Rename StyleRareNonInheritedData::opacity to m_opacity
index 4138cdd..cda1a07 100644 (file)
                E1FF8F6D180DB5BE00132674 /* CryptoAlgorithmRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FF8F6B180DB5BE00132674 /* CryptoAlgorithmRegistry.h */; };
                E3150EA61DA7219000194012 /* JSNodeDOMJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3AFA9641DA6E908002861BD /* JSNodeDOMJIT.cpp */; };
                E3150EA71DA7219300194012 /* DOMJITHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = E3150EA51DA7218D00194012 /* DOMJITHelpers.h */; };
+               E3565B7B1DC2D6C900217DBD /* JSEventCustom.h in Headers */ = {isa = PBXBuildFile; fileRef = E34EE49F1DC2D57500EAA9D3 /* JSEventCustom.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35CA14D1DBC3A3F00F83516 /* DOMJITAbstractHeapRepository.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E35CA14B1DBC3A3C00F83516 /* DOMJITAbstractHeapRepository.cpp */; };
                E35CA14E1DBC3A4200F83516 /* DOMJITAbstractHeapRepository.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA14C1DBC3A3C00F83516 /* DOMJITAbstractHeapRepository.h */; };
                E377FE4D1DADE16500CDD025 /* NodeConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D049931DADC04500718F3C /* NodeConstants.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E1FF8F6A180DB5BE00132674 /* CryptoAlgorithmRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CryptoAlgorithmRegistry.cpp; sourceTree = "<group>"; };
                E1FF8F6B180DB5BE00132674 /* CryptoAlgorithmRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoAlgorithmRegistry.h; sourceTree = "<group>"; };
                E3150EA51DA7218D00194012 /* DOMJITHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITHelpers.h; sourceTree = "<group>"; };
+               E34EE49F1DC2D57500EAA9D3 /* JSEventCustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEventCustom.h; sourceTree = "<group>"; };
                E35CA14B1DBC3A3C00F83516 /* DOMJITAbstractHeapRepository.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMJITAbstractHeapRepository.cpp; sourceTree = "<group>"; };
                E35CA14C1DBC3A3C00F83516 /* DOMJITAbstractHeapRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITAbstractHeapRepository.h; sourceTree = "<group>"; };
                E38838941BAD145F00D62EE3 /* ScriptModuleLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptModuleLoader.cpp; sourceTree = "<group>"; };
                                65E0E9431133C89F00B4CB10 /* JSDOMWrapper.h */,
                                F3D461461161D53200CA0D09 /* JSErrorHandler.cpp */,
                                F3D461471161D53200CA0D09 /* JSErrorHandler.h */,
+                               E34EE49F1DC2D57500EAA9D3 /* JSEventCustom.h */,
                                BC60901E0E91B8EC000C68B5 /* JSEventTargetCustom.cpp */,
                                46B63F6B1C6E8CDF002E914B /* JSEventTargetCustom.h */,
                                3314ACE910892086000F0E56 /* JSExceptionBase.cpp */,
                                B885E8D511E06DD2009FFBF4 /* InspectorApplicationCacheAgent.h in Headers */,
                                1C81B95C0E97330800266E07 /* InspectorClient.h in Headers */,
                                1C81B95A0E97330800266E07 /* InspectorController.h in Headers */,
+                               E3565B7B1DC2D6C900217DBD /* JSEventCustom.h in Headers */,
                                82AB1744124B99EC00C5069D /* InspectorCSSAgent.h in Headers */,
                                4A9CC82116BF9BB400EC645A /* InspectorCSSOMWrappers.h in Headers */,
                                7AB0B1C11211A62200A76940 /* InspectorDatabaseAgent.h in Headers */,
index 319c775..38529bb 100644 (file)
@@ -30,13 +30,18 @@ namespace WebCore {
 class JSDOMWindow;
 class ScriptExecutionContext;
 
-// We encode Node type into JSType. The format is the following.
-// offset | 7 | 6 5 4 | 3 2 1 0  |
-// value  | 1 | Kind  | NodeType |
+// JSC allows us to extend JSType. If the highest bit is set, we can add any Object types and they are
+// recognized as OtherObj in JSC. And we encode Node type into JSType if the given JSType is subclass of Node.
+// offset | 7 | 6 | 5   4 | 3   2   1   0  |
+// value  | 1 | 0 |  Non-node DOM types    |
+// If the given JSType is a subclass of Node, the format is the following.
+// offset | 7 | 6 | 5   4 | 3   2   1   0  |
+// value  | 1 | 1 |  Kind |       NodeType |
 static const uint8_t JSNodeTypeMask                  = 0b00001111;
 
 static const uint8_t JSDOMWrapperType                = 0b10000000;
-static const uint8_t JSNodeType                      = 0b10010000;
+static const uint8_t JSEventType                     = 0b10000001;
+static const uint8_t JSNodeType                      = 0b11000000;
 static const uint8_t JSTextNodeType                  = JSNodeType | NodeConstants::TEXT_NODE;
 static const uint8_t JSProcessingInstructionNodeType = JSNodeType | NodeConstants::PROCESSING_INSTRUCTION_NODE;
 static const uint8_t JSDocumentTypeNodeType          = JSNodeType | NodeConstants::DOCUMENT_TYPE_NODE;
@@ -45,7 +50,7 @@ static const uint8_t JSDocumentWrapperType           = JSNodeType | NodeConstant
 static const uint8_t JSCommentNodeType               = JSNodeType | NodeConstants::COMMENT_NODE;
 static const uint8_t JSCDATASectionNodeType          = JSNodeType | NodeConstants::CDATA_SECTION_NODE;
 static const uint8_t JSAttrNodeType                  = JSNodeType | NodeConstants::ATTRIBUTE_NODE;
-static const uint8_t JSElementType                   = 0b10100000 | NodeConstants::ELEMENT_NODE;
+static const uint8_t JSElementType                   = 0b11010000 | NodeConstants::ELEMENT_NODE;
 
 static_assert(JSDOMWrapperType > JSC::LastJSCObjectType, "JSC::JSType offers the highest bit.");
 static_assert(NodeConstants::LastNodeType <= JSNodeTypeMask, "NodeType should be represented in 4bit.");
diff --git a/Source/WebCore/bindings/js/JSEventCustom.h b/Source/WebCore/bindings/js/JSEventCustom.h
new file mode 100644 (file)
index 0000000..5599f4c
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSDOMBinding.h"
+
+namespace WebCore {
+
+ALWAYS_INLINE JSEvent* jsEventCast(JSC::JSValue value)
+{
+    if (UNLIKELY(!value.isCell()))
+        return nullptr;
+    return value.asCell()->type() == JSEventType ? JSC::jsCast<JSEvent*>(value) : nullptr;
+}
+
+} // namespace WebCore
index 594e59c..7cb22a2 100644 (file)
@@ -1216,7 +1216,7 @@ sub GenerateDictionariesImplementationContent
 
 sub GetJSTypeForNode
 {
-    my ($codeGenerator, $interface) = @_;
+    my ($interface) = @_;
 
     if ($codeGenerator->InheritsInterface($interface, "Document")) {
         return "JSDocumentWrapperType";
@@ -1446,8 +1446,10 @@ sub GenerateHeader
     if (IsDOMGlobalObject($interface)) {
         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags), info());\n");
     } elsif ($codeGenerator->InheritsInterface($interface, "Node")) {
-        my $type = GetJSTypeForNode($codeGenerator, $interface);
+        my $type = GetJSTypeForNode($interface);
         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType($type), StructureFlags), info());\n");
+    } elsif ($codeGenerator->InheritsInterface($interface, "Event")) {
+        push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSEventType), StructureFlags), info());\n");
     } else {
         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n");
     }
@@ -2488,6 +2490,7 @@ sub GetCastingHelperForThisObject
     return "jsElementCast" if $interfaceName eq "Element";
     return "jsDocumentCast" if $interfaceName eq "Document";
     return "jsEventTargetCast" if $interfaceName eq "EventTarget";
+    return "jsEventCast" if $interfaceName eq "Event";
     return "jsDynamicCast<JS$interfaceName*>";
 }
 
index 48a5c44..a3a6d4e 100644 (file)
@@ -44,7 +44,7 @@ public:
 
     static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
     {
-        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSEventType), StructureFlags), info());
     }
 
     static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
index 637d4cf..49ff53c 100644 (file)
@@ -27,6 +27,7 @@ typedef unsigned long long DOMTimeStamp;
     CustomToJSObject,
     ExportToWrappedFunction,
     Exposed=(Window,Worker),
+    JSCustomHeader,
 ] interface Event {
     // PhaseType
     const unsigned short NONE = 0;
index 2b4b003..f1c1a89 100644 (file)
@@ -98,6 +98,16 @@ inline CCallHelpers::Jump branchIfNotDOMWrapper(CCallHelpers& jit, GPRReg target
         CCallHelpers::TrustedImm32(JSC::JSType(JSDOMWrapperType)));
 }
 
+inline CCallHelpers::Jump branchIfEvent(CCallHelpers& jit, GPRReg target)
+{
+    return jit.branchIfType(target, JSC::JSType(JSEventType));
+}
+
+inline CCallHelpers::Jump branchIfNotEvent(CCallHelpers& jit, GPRReg target)
+{
+    return jit.branchIfNotType(target, JSC::JSType(JSEventType));
+}
+
 inline CCallHelpers::Jump branchIfNode(CCallHelpers& jit, GPRReg target)
 {
     return jit.branch8(