Changeset 208579 in webkit


Ignore:
Timestamp:
Nov 10, 2016 10:08:18 PM (7 years ago)
Author:
Yusuke Suzuki
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.
Location:
trunk
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r208576 r208579  
     12016-11-10  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [DOMJIT] Document#body should have DOMJIT patchpoint
     4        https://bugs.webkit.org/show_bug.cgi?id=164627
     5
     6        Reviewed by Darin Adler.
     7
     8        * js/dom/domjit-accessor-document-body-expected.txt: Added.
     9        * js/dom/domjit-accessor-document-body.html: Added.
     10
    1112016-11-10  John Wilander  <wilander@apple.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r208578 r208579  
     12016-11-10  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [DOMJIT] Document#body should have DOMJIT patchpoint
     4        https://bugs.webkit.org/show_bug.cgi?id=164627
     5
     6        Reviewed by Darin Adler.
     7
     8        This patch implements document.body accessor. To implement it, we need,
     9
     10        1. DOM traversing ability from ASM.
     11        2. Checking HTMLElement.
     12        3. Checking HTMLElement's localName.
     13
     14        The above features are already implemented in CSSJIT.
     15        We extract some of utilities from CSSJIT to share them with DOMJIT.
     16
     17        Test: js/dom/domjit-accessor-document-body.html
     18
     19        * cssjit/SelectorCompiler.cpp:
     20        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToParentElement):
     21        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToNextAdjacentElement):
     22        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateWalkToPreviousAdjacentElement):
     23        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeMatching):
     24        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeValueExactMatching):
     25        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeFunctionCallValueMatching):
     26        (WebCore::SelectorCompiler::jumpIfElementIsNotEmpty):
     27        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasTagName):
     28        (WebCore::SelectorCompiler::testIsElementFlagOnNode): Deleted.
     29        (WebCore::SelectorCompiler::testIsHTMLFlagOnNode): Deleted.
     30        * dom/Document.idl:
     31        * dom/Element.h:
     32        * dom/QualifiedName.h:
     33        * domjit/DOMJITAbstractHeapRepository.yaml:
     34        * domjit/DOMJITHelpers.h:
     35        (WebCore::DOMJIT::branchTestIsElementFlagOnNode):
     36        (WebCore::DOMJIT::branchTestIsHTMLFlagOnNode):
     37        * domjit/JSDocumentDOMJIT.cpp:
     38        (WebCore::DocumentBodyDOMJIT::checkDOM):
     39        (WebCore::loadLocalName):
     40        (WebCore::DocumentBodyDOMJIT::callDOMGetter):
     41
    1422016-11-10  John Wilander  <wilander@apple.com>
    243
  • trunk/Source/WebCore/cssjit/SelectorCompiler.cpp

    r208267 r208579  
    20222022}
    20232023
    2024 static inline Assembler::Jump testIsElementFlagOnNode(Assembler::ResultCondition condition, Assembler& assembler, Assembler::RegisterID nodeAddress)
    2025 {
    2026     return assembler.branchTest32(condition, Assembler::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsElement()));
    2027 }
    2028 
    20292024void SelectorCodeGenerator::generateRightmostTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
    20302025{
     
    20442039    generateWalkToParentNode(targetRegister);
    20452040    failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, targetRegister));
    2046     failureCases.append(testIsElementFlagOnNode(Assembler::Zero, m_assembler, targetRegister));
     2041    failureCases.append(DOMJIT::branchTestIsElementFlagOnNode(m_assembler, Assembler::Zero, targetRegister));
    20472042}
    20482043
     
    20972092    m_assembler.loadPtr(Assembler::Address(workRegister, Node::nextSiblingMemoryOffset()), workRegister);
    20982093    failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, workRegister));
    2099     testIsElementFlagOnNode(Assembler::Zero, m_assembler, workRegister).linkTo(loopStart, &m_assembler);
     2094    DOMJIT::branchTestIsElementFlagOnNode(m_assembler, Assembler::Zero, workRegister).linkTo(loopStart, &m_assembler);
    21002095}
    21012096
     
    21052100    m_assembler.loadPtr(Assembler::Address(workRegister, Node::previousSiblingMemoryOffset()), workRegister);
    21062101    failureCases.append(m_assembler.branchTestPtr(Assembler::Zero, workRegister));
    2107     testIsElementFlagOnNode(Assembler::Zero, m_assembler, workRegister).linkTo(loopStart, &m_assembler);
     2102    DOMJIT::branchTestIsElementFlagOnNode(m_assembler, Assembler::Zero, workRegister).linkTo(loopStart, &m_assembler);
    21082103}
    21092104
     
    26522647}
    26532648
    2654 static inline Assembler::Jump testIsHTMLFlagOnNode(Assembler::ResultCondition condition, Assembler& assembler, Assembler::RegisterID nodeAddress)
    2655 {
    2656     return assembler.branchTest32(condition, Assembler::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsHTML()));
    2657 }
    2658 
    26592649static inline bool canMatchStyleAttribute(const SelectorFragment& fragment)
    26602650{
     
    27992789    else {
    28002790        m_assembler.move(Assembler::TrustedImmPtr(canonicalLocalName), localNameToMatch);
    2801         Assembler::Jump elementIsHTML = testIsHTMLFlagOnNode(Assembler::NonZero, m_assembler, elementAddressRegister);
     2791        Assembler::Jump elementIsHTML = DOMJIT::branchTestIsHTMLFlagOnNode(m_assembler, Assembler::NonZero, elementAddressRegister);
    28022792        m_assembler.move(Assembler::TrustedImmPtr(localName), localNameToMatch);
    28032793        elementIsHTML.link(&m_assembler);
     
    29812971        // Taking the contrapositive, if we find the element is not HTML or is not in a HTML document, the condition above
    29822972        // sould be sufficient and we can fail early.
    2983         failureCases.append(testIsHTMLFlagOnNode(Assembler::Zero, m_assembler, elementAddressRegister));
     2973        failureCases.append(DOMJIT::branchTestIsHTMLFlagOnNode(m_assembler, Assembler::Zero, elementAddressRegister));
    29842974
    29852975        {
     
    30313021    case AttributeCaseSensitivity::HTMLLegacyCaseInsensitive: {
    30323022        Assembler::JumpList shouldUseCaseSensitiveComparison;
    3033         shouldUseCaseSensitiveComparison.append(testIsHTMLFlagOnNode(Assembler::Zero, m_assembler, elementAddressRegister));
     3023        shouldUseCaseSensitiveComparison.append(DOMJIT::branchTestIsHTMLFlagOnNode(m_assembler, Assembler::Zero, elementAddressRegister));
    30343024        {
    30353025            LocalRegister scratchRegister(m_registerAllocator);
     
    31173107    Assembler::Jump noMoreChildren = assembler.branchTestPtr(Assembler::Zero, currentChild);
    31183108
    3119     notEmptyCases.append(testIsElementFlagOnNode(Assembler::NonZero, assembler, currentChild));
     3109    notEmptyCases.append(DOMJIT::branchTestIsElementFlagOnNode(assembler, Assembler::NonZero, currentChild));
    31203110
    31213111    {
     
    34123402        } else {
    34133403            Assembler::JumpList caseSensitiveCases;
    3414             caseSensitiveCases.append(testIsHTMLFlagOnNode(Assembler::Zero, m_assembler, elementAddressRegister));
     3404            caseSensitiveCases.append(DOMJIT::branchTestIsHTMLFlagOnNode(m_assembler, Assembler::Zero, elementAddressRegister));
    34153405            {
    34163406                LocalRegister document(m_registerAllocator);
  • trunk/Source/WebCore/dom/Document.idl

    r208144 r208579  
    102102    [GetterMayThrowException, SetterMayThrowException] attribute USVString cookie;
    103103
    104     [CEReactions, ImplementedAs=bodyOrFrameset, SetterMayThrowException] attribute HTMLElement? body;
     104    [CEReactions, DOMJIT, ImplementedAs=bodyOrFrameset, SetterMayThrowException] attribute HTMLElement? body;
    105105
    106106    readonly attribute HTMLHeadElement? head;
  • trunk/Source/WebCore/dom/Element.h

    r208347 r208579  
    203203
    204204    const QualifiedName& tagQName() const { return m_tagName; }
    205 #if ENABLE(CSS_SELECTOR_JIT)
     205#if ENABLE(JIT)
    206206    static ptrdiff_t tagQNameMemoryOffset() { return OBJECT_OFFSETOF(Element, m_tagName); }
    207 #endif // ENABLE(CSS_SELECTOR_JIT)
     207#endif // ENABLE(JIT)
    208208    String tagName() const { return nodeName(); }
    209209    bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
  • trunk/Source/WebCore/dom/QualifiedName.h

    r208179 r208579  
    5454        mutable AtomicString m_localNameUpper;
    5555
    56 #if ENABLE(CSS_SELECTOR_JIT)
     56#if ENABLE(JIT)
    5757        static ptrdiff_t localNameMemoryOffset() { return OBJECT_OFFSETOF(QualifiedNameImpl, m_localName); }
    5858        static ptrdiff_t namespaceMemoryOffset() { return OBJECT_OFFSETOF(QualifiedNameImpl, m_namespace); }
    59 #endif // ENABLE(CSS_SELECTOR_JIT)
     59#endif // ENABLE(JIT)
    6060
    6161    private:
     
    9595
    9696    QualifiedNameImpl* impl() const { return m_impl.get(); }
    97 #if ENABLE(CSS_SELECTOR_JIT)
     97#if ENABLE(JIT)
    9898    static ptrdiff_t implMemoryOffset() { return OBJECT_OFFSETOF(QualifiedName, m_impl); }
    99 #endif // ENABLE(CSS_SELECTOR_JIT)
     99#endif // ENABLE(JIT)
    100100   
    101101    // Init routine for globals
  • trunk/Source/WebCore/domjit/DOMJITAbstractHeapRepository.yaml

    r208320 r208579  
    1010        Document:
    1111            - Document_documentElement
     12            - Document_body
  • trunk/Source/WebCore/domjit/DOMJITHelpers.h

    r208412 r208579  
    2828
    2929#include "JSDOMWrapper.h"
    30 #include "ScriptWrappable.h"
     30#include "Node.h"
    3131#include <domjit/DOMJITPatchpoint.h>
    3232#include <domjit/DOMJITPatchpointParams.h>
     
    176176void loadDocumentElement(MacroAssembler&, GPRReg document, GPRReg output);
    177177
     178inline CCallHelpers::Jump branchTestIsElementFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
     179{
     180    return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsElement()));
     181}
     182
     183inline CCallHelpers::Jump branchTestIsHTMLFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
     184{
     185    return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsHTML()));
     186}
     187
    178188} }
    179189
  • trunk/Source/WebCore/domjit/JSDocumentDOMJIT.cpp

    r208320 r208579  
    3535#include "JSDOMWrapper.h"
    3636#include "JSElement.h"
     37#include "JSHTMLElement.h"
    3738#include <domjit/DOMJITPatchpoint.h>
    3839#include <domjit/DOMJITPatchpointParams.h>
     
    7475}
    7576
     77Ref<JSC::DOMJIT::Patchpoint> DocumentBodyDOMJIT::checkDOM()
     78{
     79    return DOMJIT::checkDOM<Document>();
     80}
     81
     82static void loadLocalName(CCallHelpers& jit, GPRReg htmlElement, GPRReg localNameImpl)
     83{
     84    jit.loadPtr(CCallHelpers::Address(htmlElement, Element::tagQNameMemoryOffset() + QualifiedName::implMemoryOffset()), localNameImpl);
     85    jit.loadPtr(CCallHelpers::Address(localNameImpl, QualifiedName::QualifiedNameImpl::localNameMemoryOffset()), localNameImpl);
     86}
     87
     88Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> DocumentBodyDOMJIT::callDOMGetter()
     89{
     90    Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> patchpoint = JSC::DOMJIT::CallDOMGetterPatchpoint::create();
     91    patchpoint->numGPScratchRegisters = 2;
     92    patchpoint->setGenerator([=](CCallHelpers& jit, JSC::DOMJIT::PatchpointParams& params) {
     93        JSValueRegs result = params[0].jsValueRegs();
     94        GPRReg document = params[1].gpr();
     95        GPRReg globalObject = params[2].gpr();
     96        JSValue globalObjectValue = params[2].value();
     97        GPRReg scratch1 = params.gpScratch(0);
     98        GPRReg scratch2 = params.gpScratch(1);
     99
     100        jit.loadPtr(CCallHelpers::Address(document, JSDocument::offsetOfWrapped()), scratch1);
     101        DOMJIT::loadDocumentElement(jit, scratch1, scratch1);
     102
     103        CCallHelpers::JumpList nullCases;
     104        CCallHelpers::JumpList successCases;
     105        nullCases.append(jit.branchTestPtr(CCallHelpers::Zero, scratch1));
     106        nullCases.append(DOMJIT::branchTestIsHTMLFlagOnNode(jit, CCallHelpers::Zero, scratch1));
     107        // We ensured that the name of the given element is HTML qualified.
     108        // It allows us to perform local name comparison!
     109        loadLocalName(jit, scratch1, scratch2);
     110        nullCases.append(jit.branchPtr(CCallHelpers::NotEqual, scratch2, CCallHelpers::TrustedImmPtr(HTMLNames::htmlTag.localName().impl())));
     111
     112        RELEASE_ASSERT(!CAST_OFFSET(Node*, ContainerNode*));
     113        RELEASE_ASSERT(!CAST_OFFSET(Node*, Element*));
     114        RELEASE_ASSERT(!CAST_OFFSET(Node*, HTMLElement*));
     115
     116        // Node* node = current.firstChild();
     117        // while (node && !is<HTMLElement>(*node))
     118        //     node = node->nextSibling();
     119        // return downcast<HTMLElement>(node);
     120        jit.loadPtr(CCallHelpers::Address(scratch1, ContainerNode::firstChildMemoryOffset()), scratch1);
     121
     122        CCallHelpers::Label loopStart = jit.label();
     123        nullCases.append(jit.branchTestPtr(CCallHelpers::Zero, scratch1));
     124        auto notHTMLElementCase = DOMJIT::branchTestIsHTMLFlagOnNode(jit, CCallHelpers::Zero, scratch1);
     125        // We ensured that the name of the given element is HTML qualified.
     126        // It allows us to perform local name comparison!
     127        loadLocalName(jit, scratch1, scratch2);
     128        successCases.append(jit.branchPtr(CCallHelpers::Equal, scratch2, CCallHelpers::TrustedImmPtr(HTMLNames::bodyTag.localName().impl())));
     129        successCases.append(jit.branchPtr(CCallHelpers::Equal, scratch2, CCallHelpers::TrustedImmPtr(HTMLNames::framesetTag.localName().impl())));
     130
     131        notHTMLElementCase.link(&jit);
     132        jit.loadPtr(CCallHelpers::Address(scratch1, Node::nextSiblingMemoryOffset()), scratch1);
     133        jit.jump().linkTo(loopStart, &jit);
     134
     135        successCases.link(&jit);
     136        DOMJIT::toWrapper<HTMLElement>(jit, params, scratch1, globalObject, result, DOMJIT::toWrapperSlow<HTMLElement>, globalObjectValue);
     137        auto done = jit.jump();
     138
     139        nullCases.link(&jit);
     140        jit.moveValue(jsNull(), result);
     141        done.link(&jit);
     142
     143        return CCallHelpers::JumpList();
     144    });
     145    patchpoint->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Document_body);
     146    return patchpoint;
     147}
     148
    76149}
    77150
Note: See TracChangeset for help on using the changeset viewer.