Unreviewed, rolling out r238244.
[WebKit-https.git] / Source / WebCore / domjit / JSDocumentDOMJIT.cpp
1 /*
2  * Copyright (C) 2016 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSDocument.h"
28
29 #if ENABLE(JIT)
30
31 #include "DOMJITAbstractHeapRepository.h"
32 #include "DOMJITCheckDOM.h"
33 #include "DOMJITHelpers.h"
34 #include "Document.h"
35 #include "JSDOMWrapper.h"
36 #include "JSElement.h"
37 #include "JSHTMLElement.h"
38 #include <JavaScriptCore/Snippet.h>
39 #include <JavaScriptCore/SnippetParams.h>
40
41 namespace WebCore {
42 using namespace JSC;
43
44 Ref<JSC::Snippet> checkSubClassSnippetForJSDocument()
45 {
46     return DOMJIT::checkDOM<Document>();
47 }
48
49 Ref<JSC::DOMJIT::CallDOMGetterSnippet> compileDocumentDocumentElementAttribute()
50 {
51     Ref<JSC::DOMJIT::CallDOMGetterSnippet> snippet = JSC::DOMJIT::CallDOMGetterSnippet::create();
52     snippet->numGPScratchRegisters = 1;
53     snippet->setGenerator([=](CCallHelpers& jit, JSC::SnippetParams& params) {
54         JSValueRegs result = params[0].jsValueRegs();
55         GPRReg document = params[1].gpr();
56         GPRReg globalObject = params[2].gpr();
57         JSValue globalObjectValue = params[2].value();
58         GPRReg scratch = params.gpScratch(0);
59
60         jit.loadPtr(CCallHelpers::Address(document, JSDocument::offsetOfWrapped()), scratch);
61         DOMJIT::loadDocumentElement(jit, scratch, scratch);
62         auto nullCase = jit.branchTestPtr(CCallHelpers::Zero, scratch);
63         DOMJIT::toWrapper<Element>(jit, params, scratch, globalObject, result, DOMJIT::toWrapperSlow<Element>, globalObjectValue);
64         auto done = jit.jump();
65
66         nullCase.link(&jit);
67         jit.moveValue(jsNull(), result);
68         done.link(&jit);
69
70         return CCallHelpers::JumpList();
71     });
72     snippet->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Document_documentElement);
73     return snippet;
74 }
75
76 static void loadLocalName(CCallHelpers& jit, GPRReg htmlElement, GPRReg localNameImpl)
77 {
78     jit.loadPtr(CCallHelpers::Address(htmlElement, Element::tagQNameMemoryOffset() + QualifiedName::implMemoryOffset()), localNameImpl);
79     jit.loadPtr(CCallHelpers::Address(localNameImpl, QualifiedName::QualifiedNameImpl::localNameMemoryOffset()), localNameImpl);
80 }
81
82 Ref<JSC::DOMJIT::CallDOMGetterSnippet> compileDocumentBodyAttribute()
83 {
84     Ref<JSC::DOMJIT::CallDOMGetterSnippet> snippet = JSC::DOMJIT::CallDOMGetterSnippet::create();
85     snippet->numGPScratchRegisters = 2;
86     snippet->setGenerator([=](CCallHelpers& jit, JSC::SnippetParams& params) {
87         JSValueRegs result = params[0].jsValueRegs();
88         GPRReg document = params[1].gpr();
89         GPRReg globalObject = params[2].gpr();
90         JSValue globalObjectValue = params[2].value();
91         GPRReg scratch1 = params.gpScratch(0);
92         GPRReg scratch2 = params.gpScratch(1);
93
94         jit.loadPtr(CCallHelpers::Address(document, JSDocument::offsetOfWrapped()), scratch1);
95         DOMJIT::loadDocumentElement(jit, scratch1, scratch1);
96
97         CCallHelpers::JumpList nullCases;
98         CCallHelpers::JumpList successCases;
99         nullCases.append(jit.branchTestPtr(CCallHelpers::Zero, scratch1));
100         nullCases.append(DOMJIT::branchTestIsHTMLFlagOnNode(jit, CCallHelpers::Zero, scratch1));
101         // We ensured that the name of the given element is HTML qualified.
102         // It allows us to perform local name comparison!
103         loadLocalName(jit, scratch1, scratch2);
104         nullCases.append(jit.branchPtr(CCallHelpers::NotEqual, scratch2, CCallHelpers::TrustedImmPtr(HTMLNames::htmlTag->localName().impl())));
105
106         RELEASE_ASSERT(!CAST_OFFSET(Node*, ContainerNode*));
107         RELEASE_ASSERT(!CAST_OFFSET(Node*, Element*));
108         RELEASE_ASSERT(!CAST_OFFSET(Node*, HTMLElement*));
109
110         // Node* node = current.firstChild();
111         // while (node && !is<HTMLElement>(*node))
112         //     node = node->nextSibling();
113         // return downcast<HTMLElement>(node);
114         jit.loadPtr(CCallHelpers::Address(scratch1, ContainerNode::firstChildMemoryOffset()), scratch1);
115
116         CCallHelpers::Label loopStart = jit.label();
117         nullCases.append(jit.branchTestPtr(CCallHelpers::Zero, scratch1));
118         auto notHTMLElementCase = DOMJIT::branchTestIsHTMLFlagOnNode(jit, CCallHelpers::Zero, scratch1);
119         // We ensured that the name of the given element is HTML qualified.
120         // It allows us to perform local name comparison!
121         loadLocalName(jit, scratch1, scratch2);
122         successCases.append(jit.branchPtr(CCallHelpers::Equal, scratch2, CCallHelpers::TrustedImmPtr(HTMLNames::bodyTag->localName().impl())));
123         successCases.append(jit.branchPtr(CCallHelpers::Equal, scratch2, CCallHelpers::TrustedImmPtr(HTMLNames::framesetTag->localName().impl())));
124
125         notHTMLElementCase.link(&jit);
126         jit.loadPtr(CCallHelpers::Address(scratch1, Node::nextSiblingMemoryOffset()), scratch1);
127         jit.jump().linkTo(loopStart, &jit);
128
129         successCases.link(&jit);
130         DOMJIT::toWrapper<HTMLElement>(jit, params, scratch1, globalObject, result, DOMJIT::toWrapperSlow<HTMLElement>, globalObjectValue);
131         auto done = jit.jump();
132
133         nullCases.link(&jit);
134         jit.moveValue(jsNull(), result);
135         done.link(&jit);
136
137         return CCallHelpers::JumpList();
138     });
139     snippet->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Document_body);
140     return snippet;
141 }
142
143 }
144
145 #endif