Title: [208579] trunk
Revision
208579
Author
utatane....@gmail.com
Date
2016-11-10 22:08:18 -0800 (Thu, 10 Nov 2016)

Log Message

[DOMJIT] Document#body should have DOMJIT patchpoint
https://bugs.webkit.org/show_bug.cgi?id=164627

Reviewed by Darin Adler.

Source/WebCore:

This patch implements document.body accessor. To implement it, we need,

1. DOM traversing ability from ASM.
2. Checking HTMLElement.
3. Checking HTMLElement's localName.

The above features are already implemented in CSSJIT.
We extract some of utilities from CSSJIT to share them with DOMJIT.

Test: js/dom/domjit-accessor-document-body.html

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToParentElement):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToNextAdjacentElement):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToPreviousAdjacentElement):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeMatching):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeValueExactMatching):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeFunctionCallValueMatching):
(WebCore::SelectorCompiler::jumpIfElementIsNotEmpty):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasTagName):
(WebCore::SelectorCompiler::testIsElementFlagOnNode): Deleted.
(WebCore::SelectorCompiler::testIsHTMLFlagOnNode): Deleted.
* dom/Document.idl:
* dom/Element.h:
* dom/QualifiedName.h:
* domjit/DOMJITAbstractHeapRepository.yaml:
* domjit/DOMJITHelpers.h:
(WebCore::DOMJIT::branchTestIsElementFlagOnNode):
(WebCore::DOMJIT::branchTestIsHTMLFlagOnNode):
* domjit/JSDocumentDOMJIT.cpp:
(WebCore::DocumentBodyDOMJIT::checkDOM):
(WebCore::loadLocalName):
(WebCore::DocumentBodyDOMJIT::callDOMGetter):

LayoutTests:

* js/dom/domjit-accessor-document-body-expected.txt: Added.
* js/dom/domjit-accessor-document-body.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (208578 => 208579)


--- trunk/LayoutTests/ChangeLog	2016-11-11 04:37:06 UTC (rev 208578)
+++ trunk/LayoutTests/ChangeLog	2016-11-11 06:08:18 UTC (rev 208579)
@@ -1,3 +1,13 @@
+2016-11-10  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [DOMJIT] Document#body should have DOMJIT patchpoint
+        https://bugs.webkit.org/show_bug.cgi?id=164627
+
+        Reviewed by Darin Adler.
+
+        * js/dom/domjit-accessor-document-body-expected.txt: Added.
+        * js/dom/domjit-accessor-document-body.html: Added.
+
 2016-11-10  John Wilander  <wilan...@apple.com>
 
         Add link information to data transfer pasteboard for drag and drop links

Added: trunk/LayoutTests/js/dom/domjit-accessor-document-body-expected.txt (0 => 208579)


--- trunk/LayoutTests/js/dom/domjit-accessor-document-body-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/dom/domjit-accessor-document-body-expected.txt	2016-11-11 06:08:18 UTC (rev 208579)
@@ -0,0 +1,79 @@
+Test DOMJIT document.body accessor works.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS (
+            function testHTMLDocument(element, result)
+            {
+                for (var i = 0; i < 1e4; ++i) {
+                    if (element.body !== result)
+                        return false;
+                }
+                return true;
+            }
+        )(target, result) is true
+PASS (
+            function testXMLDocument(element, result)
+            {
+                for (var i = 0; i < 1e4; ++i) {
+                    if (element.body !== result)
+                        return false;
+                }
+                return true;
+            }
+        )(target, result) is true
+PASS (
+            function testXMLDocument2(element, result)
+            {
+                for (var i = 0; i < 1e4; ++i) {
+                    if (element.body !== result)
+                        return false;
+                }
+                return true;
+            }
+        )(target, result) is true
+PASS (
+            function testNull(element, result)
+            {
+                for (var i = 0; i < 1e4; ++i) {
+                    if (element.body !== result)
+                        return false;
+                }
+                return true;
+            }
+        )(target, result) is true
+PASS (
+            function testHTMLElement(element, result)
+            {
+                for (var i = 0; i < 1e4; ++i) {
+                    if (element.body !== result)
+                        return false;
+                }
+                return true;
+            }
+        )(target, result) is true
+PASS (
+            function testNoHTML(element, result)
+            {
+                for (var i = 0; i < 1e4; ++i) {
+                    if (element.body !== result)
+                        return false;
+                }
+                return true;
+            }
+        )(target, result) is true
+PASS (
+            function testFrameset(element, result)
+            {
+                for (var i = 0; i < 1e4; ++i) {
+                    if (element.body !== result)
+                        return false;
+                }
+                return true;
+            }
+        )(target, result) is true
+ 

Added: trunk/LayoutTests/js/dom/domjit-accessor-document-body.html (0 => 208579)


--- trunk/LayoutTests/js/dom/domjit-accessor-document-body.html	                        (rev 0)
+++ trunk/LayoutTests/js/dom/domjit-accessor-document-body.html	2016-11-11 06:08:18 UTC (rev 208579)
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<iframe id="xmlframe" _onload_="frameLoaded()" style="height:0px" src="" version='1.0' encoding='UTF-8'?><body/>"></iframe>
+<iframe id="xmlframe2" _onload_="frameLoaded()" style="height:0px" src="" version='1.0' encoding='UTF-8'?><body/>"></iframe>
+<script>
+description('Test DOMJIT document.body accessor works.');
+
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+var target = null;
+var result = null;
+function runTest()
+{
+    var xmlDocument = document.getElementById('xmlframe').contentDocument;
+    var xmlDocument2 = document.getElementById('xmlframe2').contentDocument;
+    var html = document.createElement('html');
+    var body = document.createElement('body');
+
+    var htmlOnly = document.implementation.createDocument('', null, null);
+    htmlOnly.appendChild(htmlOnly.createElement('html'));
+
+    var noHTML = document.implementation.createDocument('', null, null);
+    var first = noHTML.createElement('nohtml');
+    first.appendChild(noHTML.createElement('body'));
+    noHTML.appendChild(first);
+
+    var framesetDoc = document.implementation.createDocument('', null, null);
+    var first = document.createElement('html');
+    var frameset = document.createElement('frameset');
+    first.appendChild(frameset);
+    framesetDoc.appendChild(first);
+
+    var targets = [
+        ['HTMLDocument', document, document.getElementsByTagName('body')[0]],
+        ['XMLDocument', xmlDocument, null],
+        ['XMLDocument2', xmlDocument2, body],
+        ['Null', document.implementation.createDocument('', null, null), null],
+        ['HTMLElement', htmlOnly, null],
+        ['NoHTML', noHTML, null],
+        ['Frameset', framesetDoc, frameset],
+    ];
+
+    // Put HTMLBodyElement in XMLDocument!
+    html.appendChild(body);
+    xmlDocument2.replaceChild(html, xmlDocument2.firstChild);
+
+    for ([name, target, result] of targets) {
+        var text = `
+            function test${name}(element, result)
+            {
+                for (var i = 0; i < 1e4; ++i) {
+                    if (element.body !== result)
+                        return false;
+                }
+                return true;
+            }
+        `;
+        shouldBeTrue(`(${text})(target, result)`);
+    }
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+var count = 0;
+function frameLoaded()
+{
+    if (++count === 2)
+        runTest();
+}
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (208578 => 208579)


--- trunk/Source/WebCore/ChangeLog	2016-11-11 04:37:06 UTC (rev 208578)
+++ trunk/Source/WebCore/ChangeLog	2016-11-11 06:08:18 UTC (rev 208579)
@@ -1,3 +1,44 @@
+2016-11-10  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [DOMJIT] Document#body should have DOMJIT patchpoint
+        https://bugs.webkit.org/show_bug.cgi?id=164627
+
+        Reviewed by Darin Adler.
+
+        This patch implements document.body accessor. To implement it, we need,
+
+        1. DOM traversing ability from ASM.
+        2. Checking HTMLElement.
+        3. Checking HTMLElement's localName.
+
+        The above features are already implemented in CSSJIT.
+        We extract some of utilities from CSSJIT to share them with DOMJIT.
+
+        Test: js/dom/domjit-accessor-document-body.html
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToParentElement):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToNextAdjacentElement):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToPreviousAdjacentElement):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeMatching):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeValueExactMatching):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeFunctionCallValueMatching):
+        (WebCore::SelectorCompiler::jumpIfElementIsNotEmpty):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasTagName):
+        (WebCore::SelectorCompiler::testIsElementFlagOnNode): Deleted.
+        (WebCore::SelectorCompiler::testIsHTMLFlagOnNode): Deleted.
+        * dom/Document.idl:
+        * dom/Element.h:
+        * dom/QualifiedName.h:
+        * domjit/DOMJITAbstractHeapRepository.yaml:
+        * domjit/DOMJITHelpers.h:
+        (WebCore::DOMJIT::branchTestIsElementFlagOnNode):
+        (WebCore::DOMJIT::branchTestIsHTMLFlagOnNode):
+        * domjit/JSDocumentDOMJIT.cpp:
+        (WebCore::DocumentBodyDOMJIT::checkDOM):
+        (WebCore::loadLocalName):
+        (WebCore::DocumentBodyDOMJIT::callDOMGetter):
+
 2016-11-10  John Wilander  <wilan...@apple.com>
 
         Remove unused parameter name to fix build error on iOS

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (208578 => 208579)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2016-11-11 04:37:06 UTC (rev 208578)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2016-11-11 06:08:18 UTC (rev 208579)
@@ -2021,11 +2021,6 @@
     }
 }
 
-static inline Assembler::Jump testIsElementFlagOnNode(Assembler::ResultCondition condition, Assembler& assembler, Assembler::RegisterID nodeAddress)
-{
-    return assembler.branchTest32(condition, Assembler::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsElement()));
-}
-
 void SelectorCodeGenerator::generateRightmostTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
 {
     generateElementMatching(failureCases, failureCases, fragment);
@@ -2043,7 +2038,7 @@
     //         failure
     generateWalkToParentNode(targetRegister);
     failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, targetRegister));
-    failureCases.append(testIsElementFlagOnNode(Assembler::Zero, m_assembler, targetRegister));
+    failureCases.append(DOMJIT::branchTestIsElementFlagOnNode(m_assembler, Assembler::Zero, targetRegister));
 }
 
 void SelectorCodeGenerator::generateParentElementTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
@@ -2096,7 +2091,7 @@
     Assembler::Label loopStart = m_assembler.label();
     m_assembler.loadPtr(Assembler::Address(workRegister, Node::nextSiblingMemoryOffset()), workRegister);
     failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, workRegister));
-    testIsElementFlagOnNode(Assembler::Zero, m_assembler, workRegister).linkTo(loopStart, &m_assembler);
+    DOMJIT::branchTestIsElementFlagOnNode(m_assembler, Assembler::Zero, workRegister).linkTo(loopStart, &m_assembler);
 }
 
 inline void SelectorCodeGenerator::generateWalkToPreviousAdjacentElement(Assembler::JumpList& failureCases, Assembler::RegisterID workRegister)
@@ -2104,7 +2099,7 @@
     Assembler::Label loopStart = m_assembler.label();
     m_assembler.loadPtr(Assembler::Address(workRegister, Node::previousSiblingMemoryOffset()), workRegister);
     failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, workRegister));
-    testIsElementFlagOnNode(Assembler::Zero, m_assembler, workRegister).linkTo(loopStart, &m_assembler);
+    DOMJIT::branchTestIsElementFlagOnNode(m_assembler, Assembler::Zero, workRegister).linkTo(loopStart, &m_assembler);
 }
 
 void SelectorCodeGenerator::generateWalkToPreviousAdjacent(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
@@ -2651,11 +2646,6 @@
         generateElementIsLink(failureCases);
 }
 
-static inline Assembler::Jump testIsHTMLFlagOnNode(Assembler::ResultCondition condition, Assembler& assembler, Assembler::RegisterID nodeAddress)
-{
-    return assembler.branchTest32(condition, Assembler::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsHTML()));
-}
-
 static inline bool canMatchStyleAttribute(const SelectorFragment& fragment)
 {
     for (unsigned i = 0; i < fragment.attributes.size(); ++i) {
@@ -2798,7 +2788,7 @@
         m_assembler.move(Assembler::TrustedImmPtr(canonicalLocalName), localNameToMatch);
     else {
         m_assembler.move(Assembler::TrustedImmPtr(canonicalLocalName), localNameToMatch);
-        Assembler::Jump elementIsHTML = testIsHTMLFlagOnNode(Assembler::NonZero, m_assembler, elementAddressRegister);
+        Assembler::Jump elementIsHTML = DOMJIT::branchTestIsHTMLFlagOnNode(m_assembler, Assembler::NonZero, elementAddressRegister);
         m_assembler.move(Assembler::TrustedImmPtr(localName), localNameToMatch);
         elementIsHTML.link(&m_assembler);
     }
@@ -2980,7 +2970,7 @@
         // If the element is an HTML element, in a HTML dcoument (not including XHTML), value matching is case insensitive.
         // Taking the contrapositive, if we find the element is not HTML or is not in a HTML document, the condition above
         // sould be sufficient and we can fail early.
-        failureCases.append(testIsHTMLFlagOnNode(Assembler::Zero, m_assembler, elementAddressRegister));
+        failureCases.append(DOMJIT::branchTestIsHTMLFlagOnNode(m_assembler, Assembler::Zero, elementAddressRegister));
 
         {
             LocalRegister document(m_registerAllocator);
@@ -3030,7 +3020,7 @@
     }
     case AttributeCaseSensitivity::HTMLLegacyCaseInsensitive: {
         Assembler::JumpList shouldUseCaseSensitiveComparison;
-        shouldUseCaseSensitiveComparison.append(testIsHTMLFlagOnNode(Assembler::Zero, m_assembler, elementAddressRegister));
+        shouldUseCaseSensitiveComparison.append(DOMJIT::branchTestIsHTMLFlagOnNode(m_assembler, Assembler::Zero, elementAddressRegister));
         {
             LocalRegister scratchRegister(m_registerAllocator);
             // scratchRegister = pointer to treeScope.
@@ -3116,7 +3106,7 @@
     Assembler::Label loopStart(assembler.label());
     Assembler::Jump noMoreChildren = assembler.branchTestPtr(Assembler::Zero, currentChild);
 
-    notEmptyCases.append(testIsElementFlagOnNode(Assembler::NonZero, assembler, currentChild));
+    notEmptyCases.append(DOMJIT::branchTestIsElementFlagOnNode(assembler, Assembler::NonZero, currentChild));
 
     {
         Assembler::Jump skipTextNodeCheck = assembler.branchTest32(Assembler::Zero, Assembler::Address(currentChild, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsText()));
@@ -3411,7 +3401,7 @@
             failureCases.append(m_assembler.branchPtr(Assembler::NotEqual, Assembler::Address(qualifiedNameImpl, QualifiedName::QualifiedNameImpl::localNameMemoryOffset()), constantRegister));
         } else {
             Assembler::JumpList caseSensitiveCases;
-            caseSensitiveCases.append(testIsHTMLFlagOnNode(Assembler::Zero, m_assembler, elementAddressRegister));
+            caseSensitiveCases.append(DOMJIT::branchTestIsHTMLFlagOnNode(m_assembler, Assembler::Zero, elementAddressRegister));
             {
                 LocalRegister document(m_registerAllocator);
                 DOMJIT::loadDocument(m_assembler, elementAddressRegister, document);

Modified: trunk/Source/WebCore/dom/Document.idl (208578 => 208579)


--- trunk/Source/WebCore/dom/Document.idl	2016-11-11 04:37:06 UTC (rev 208578)
+++ trunk/Source/WebCore/dom/Document.idl	2016-11-11 06:08:18 UTC (rev 208579)
@@ -101,7 +101,7 @@
 
     [GetterMayThrowException, SetterMayThrowException] attribute USVString cookie;
 
-    [CEReactions, ImplementedAs=bodyOrFrameset, SetterMayThrowException] attribute HTMLElement? body;
+    [CEReactions, DOMJIT, ImplementedAs=bodyOrFrameset, SetterMayThrowException] attribute HTMLElement? body;
 
     readonly attribute HTMLHeadElement? head;
     readonly attribute HTMLCollection images;

Modified: trunk/Source/WebCore/dom/Element.h (208578 => 208579)


--- trunk/Source/WebCore/dom/Element.h	2016-11-11 04:37:06 UTC (rev 208578)
+++ trunk/Source/WebCore/dom/Element.h	2016-11-11 06:08:18 UTC (rev 208579)
@@ -202,9 +202,9 @@
     virtual CSSStyleDeclaration* cssomStyle();
 
     const QualifiedName& tagQName() const { return m_tagName; }
-#if ENABLE(CSS_SELECTOR_JIT)
+#if ENABLE(JIT)
     static ptrdiff_t tagQNameMemoryOffset() { return OBJECT_OFFSETOF(Element, m_tagName); }
-#endif // ENABLE(CSS_SELECTOR_JIT)
+#endif // ENABLE(JIT)
     String tagName() const { return nodeName(); }
     bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
     bool hasTagName(const HTMLQualifiedName& tagName) const { return ContainerNode::hasTagName(tagName); }

Modified: trunk/Source/WebCore/dom/QualifiedName.h (208578 => 208579)


--- trunk/Source/WebCore/dom/QualifiedName.h	2016-11-11 04:37:06 UTC (rev 208578)
+++ trunk/Source/WebCore/dom/QualifiedName.h	2016-11-11 06:08:18 UTC (rev 208579)
@@ -53,10 +53,10 @@
         const AtomicString m_namespace;
         mutable AtomicString m_localNameUpper;
 
-#if ENABLE(CSS_SELECTOR_JIT)
+#if ENABLE(JIT)
         static ptrdiff_t localNameMemoryOffset() { return OBJECT_OFFSETOF(QualifiedNameImpl, m_localName); }
         static ptrdiff_t namespaceMemoryOffset() { return OBJECT_OFFSETOF(QualifiedNameImpl, m_namespace); }
-#endif // ENABLE(CSS_SELECTOR_JIT)
+#endif // ENABLE(JIT)
 
     private:
         QualifiedNameImpl(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI)
@@ -94,9 +94,9 @@
     WEBCORE_EXPORT String toString() const;
 
     QualifiedNameImpl* impl() const { return m_impl.get(); }
-#if ENABLE(CSS_SELECTOR_JIT)
+#if ENABLE(JIT)
     static ptrdiff_t implMemoryOffset() { return OBJECT_OFFSETOF(QualifiedName, m_impl); }
-#endif // ENABLE(CSS_SELECTOR_JIT)
+#endif // ENABLE(JIT)
     
     // Init routine for globals
     static void init();

Modified: trunk/Source/WebCore/domjit/DOMJITAbstractHeapRepository.yaml (208578 => 208579)


--- trunk/Source/WebCore/domjit/DOMJITAbstractHeapRepository.yaml	2016-11-11 04:37:06 UTC (rev 208578)
+++ trunk/Source/WebCore/domjit/DOMJITAbstractHeapRepository.yaml	2016-11-11 06:08:18 UTC (rev 208579)
@@ -9,3 +9,4 @@
             - Node_ownerDocument
         Document:
             - Document_documentElement
+            - Document_body

Modified: trunk/Source/WebCore/domjit/DOMJITHelpers.h (208578 => 208579)


--- trunk/Source/WebCore/domjit/DOMJITHelpers.h	2016-11-11 04:37:06 UTC (rev 208578)
+++ trunk/Source/WebCore/domjit/DOMJITHelpers.h	2016-11-11 06:08:18 UTC (rev 208579)
@@ -27,7 +27,7 @@
 #pragma once
 
 #include "JSDOMWrapper.h"
-#include "ScriptWrappable.h"
+#include "Node.h"
 #include <domjit/DOMJITPatchpoint.h>
 #include <domjit/DOMJITPatchpointParams.h>
 #include <interpreter/FrameTracers.h>
@@ -175,6 +175,16 @@
 void loadDocument(MacroAssembler&, GPRReg node, GPRReg output);
 void loadDocumentElement(MacroAssembler&, GPRReg document, GPRReg output);
 
+inline CCallHelpers::Jump branchTestIsElementFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
+{
+    return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsElement()));
+}
+
+inline CCallHelpers::Jump branchTestIsHTMLFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
+{
+    return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsHTML()));
+}
+
 } }
 
 #endif

Modified: trunk/Source/WebCore/domjit/JSDocumentDOMJIT.cpp (208578 => 208579)


--- trunk/Source/WebCore/domjit/JSDocumentDOMJIT.cpp	2016-11-11 04:37:06 UTC (rev 208578)
+++ trunk/Source/WebCore/domjit/JSDocumentDOMJIT.cpp	2016-11-11 06:08:18 UTC (rev 208579)
@@ -34,6 +34,7 @@
 #include "Document.h"
 #include "JSDOMWrapper.h"
 #include "JSElement.h"
+#include "JSHTMLElement.h"
 #include <domjit/DOMJITPatchpoint.h>
 #include <domjit/DOMJITPatchpointParams.h>
 
@@ -73,6 +74,78 @@
     return patchpoint;
 }
 
+Ref<JSC::DOMJIT::Patchpoint> DocumentBodyDOMJIT::checkDOM()
+{
+    return DOMJIT::checkDOM<Document>();
 }
 
+static void loadLocalName(CCallHelpers& jit, GPRReg htmlElement, GPRReg localNameImpl)
+{
+    jit.loadPtr(CCallHelpers::Address(htmlElement, Element::tagQNameMemoryOffset() + QualifiedName::implMemoryOffset()), localNameImpl);
+    jit.loadPtr(CCallHelpers::Address(localNameImpl, QualifiedName::QualifiedNameImpl::localNameMemoryOffset()), localNameImpl);
+}
+
+Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> DocumentBodyDOMJIT::callDOMGetter()
+{
+    Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> patchpoint = JSC::DOMJIT::CallDOMGetterPatchpoint::create();
+    patchpoint->numGPScratchRegisters = 2;
+    patchpoint->setGenerator([=](CCallHelpers& jit, JSC::DOMJIT::PatchpointParams& params) {
+        JSValueRegs result = params[0].jsValueRegs();
+        GPRReg document = params[1].gpr();
+        GPRReg globalObject = params[2].gpr();
+        JSValue globalObjectValue = params[2].value();
+        GPRReg scratch1 = params.gpScratch(0);
+        GPRReg scratch2 = params.gpScratch(1);
+
+        jit.loadPtr(CCallHelpers::Address(document, JSDocument::offsetOfWrapped()), scratch1);
+        DOMJIT::loadDocumentElement(jit, scratch1, scratch1);
+
+        CCallHelpers::JumpList nullCases;
+        CCallHelpers::JumpList successCases;
+        nullCases.append(jit.branchTestPtr(CCallHelpers::Zero, scratch1));
+        nullCases.append(DOMJIT::branchTestIsHTMLFlagOnNode(jit, CCallHelpers::Zero, scratch1));
+        // We ensured that the name of the given element is HTML qualified.
+        // It allows us to perform local name comparison!
+        loadLocalName(jit, scratch1, scratch2);
+        nullCases.append(jit.branchPtr(CCallHelpers::NotEqual, scratch2, CCallHelpers::TrustedImmPtr(HTMLNames::htmlTag.localName().impl())));
+
+        RELEASE_ASSERT(!CAST_OFFSET(Node*, ContainerNode*));
+        RELEASE_ASSERT(!CAST_OFFSET(Node*, Element*));
+        RELEASE_ASSERT(!CAST_OFFSET(Node*, HTMLElement*));
+
+        // Node* node = current.firstChild();
+        // while (node && !is<HTMLElement>(*node))
+        //     node = node->nextSibling();
+        // return downcast<HTMLElement>(node);
+        jit.loadPtr(CCallHelpers::Address(scratch1, ContainerNode::firstChildMemoryOffset()), scratch1);
+
+        CCallHelpers::Label loopStart = jit.label();
+        nullCases.append(jit.branchTestPtr(CCallHelpers::Zero, scratch1));
+        auto notHTMLElementCase = DOMJIT::branchTestIsHTMLFlagOnNode(jit, CCallHelpers::Zero, scratch1);
+        // We ensured that the name of the given element is HTML qualified.
+        // It allows us to perform local name comparison!
+        loadLocalName(jit, scratch1, scratch2);
+        successCases.append(jit.branchPtr(CCallHelpers::Equal, scratch2, CCallHelpers::TrustedImmPtr(HTMLNames::bodyTag.localName().impl())));
+        successCases.append(jit.branchPtr(CCallHelpers::Equal, scratch2, CCallHelpers::TrustedImmPtr(HTMLNames::framesetTag.localName().impl())));
+
+        notHTMLElementCase.link(&jit);
+        jit.loadPtr(CCallHelpers::Address(scratch1, Node::nextSiblingMemoryOffset()), scratch1);
+        jit.jump().linkTo(loopStart, &jit);
+
+        successCases.link(&jit);
+        DOMJIT::toWrapper<HTMLElement>(jit, params, scratch1, globalObject, result, DOMJIT::toWrapperSlow<HTMLElement>, globalObjectValue);
+        auto done = jit.jump();
+
+        nullCases.link(&jit);
+        jit.moveValue(jsNull(), result);
+        done.link(&jit);
+
+        return CCallHelpers::JumpList();
+    });
+    patchpoint->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Document_body);
+    return patchpoint;
+}
+
+}
+
 #endif
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to