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
27#pragma once
28
29#include "JSDOMWrapper.h"
30#include "Node.h"
31#include <JavaScriptCore/FrameTracers.h>
32#include <JavaScriptCore/SnippetParams.h>
33
34#if ENABLE(JIT)
35
36namespace WebCore { namespace DOMJIT {
37
38using JSC::CCallHelpers;
39using JSC::GPRReg;
40using JSC::JSValueRegs;
41using JSC::MacroAssembler;
42
43static_assert(std::is_same<GPRReg, MacroAssembler::RegisterID>::value, "GPRReg is the alias to the MacroAssembler::RegisterID");
44
45inline CCallHelpers::Jump branchIfNotWorldIsNormal(CCallHelpers& jit, GPRReg globalObject)
46{
47 return jit.branchTest8(CCallHelpers::Zero, CCallHelpers::Address(globalObject, JSDOMGlobalObject::offsetOfWorldIsNormal()));
48}
49
50inline CCallHelpers::Jump branchIfNotWeakIsLive(CCallHelpers& jit, GPRReg weakImpl)
51{
52 return jit.branchTestPtr(CCallHelpers::NonZero, CCallHelpers::Address(weakImpl, JSC::WeakImpl::offsetOfWeakHandleOwner()), CCallHelpers::TrustedImm32(JSC::WeakImpl::StateMask));
53}
54
55template<typename WrappedNode>
56JSC::EncodedJSValue JIT_OPERATION toWrapperSlow(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject, void* result)
57{
58 ASSERT(exec);
59 ASSERT(result);
60 ASSERT(globalObject);
61 JSC::NativeCallFrameTracer tracer(&exec->vm(), exec);
62 return JSC::JSValue::encode(toJS(exec, static_cast<JSDOMGlobalObject*>(globalObject), *static_cast<WrappedNode*>(result)));
63}
64
65template<typename WrappedType>
66void tryLookUpWrapperCache(CCallHelpers& jit, CCallHelpers::JumpList& failureCases, GPRReg wrapped, GPRReg resultGPR)
67{
68 jit.loadPtr(CCallHelpers::Address(wrapped, ScriptWrappable::offsetOfWrapper<WrappedType>()), resultGPR);
69 failureCases.append(jit.branchTestPtr(CCallHelpers::Zero, resultGPR));
70 failureCases.append(branchIfNotWeakIsLive(jit, resultGPR));
71 jit.loadPtr(CCallHelpers::Address(resultGPR, JSC::WeakImpl::offsetOfJSValue() + JSC::JSValue::offsetOfPayload()), resultGPR);
72}
73
74template<typename WrappedType, typename ToJSFunction>
75void toWrapper(CCallHelpers& jit, JSC::SnippetParams& params, GPRReg wrapped, GPRReg globalObject, JSValueRegs result, ToJSFunction function, JSC::JSValue globalObjectConstant)
76{
77 ASSERT(wrapped != result.payloadGPR());
78 ASSERT(globalObject != result.payloadGPR());
79 GPRReg payloadGPR = result.payloadGPR();
80 CCallHelpers::JumpList slowCases;
81
82 if (globalObjectConstant) {
83 if (!JSC::jsCast<JSDOMGlobalObject*>(globalObjectConstant)->worldIsNormal()) {
84 slowCases.append(jit.jump());
85 params.addSlowPathCall(slowCases, jit, function, result, globalObject, wrapped);
86 return;
87 }
88 } else
89 slowCases.append(branchIfNotWorldIsNormal(jit, globalObject));
90
91 tryLookUpWrapperCache<WrappedType>(jit, slowCases, wrapped, payloadGPR);
92 jit.boxCell(payloadGPR, result);
93 params.addSlowPathCall(slowCases, jit, function, result, globalObject, wrapped);
94}
95
96inline CCallHelpers::Jump branchIfDOMWrapper(CCallHelpers& jit, GPRReg target)
97{
98 return jit.branch8(
99 CCallHelpers::AboveOrEqual,
100 CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
101 CCallHelpers::TrustedImm32(JSC::JSType(JSDOMWrapperType)));
102}
103
104inline CCallHelpers::Jump branchIfNotDOMWrapper(CCallHelpers& jit, GPRReg target)
105{
106 return jit.branch8(
107 CCallHelpers::Below,
108 CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
109 CCallHelpers::TrustedImm32(JSC::JSType(JSDOMWrapperType)));
110}
111
112inline CCallHelpers::Jump branchIfEvent(CCallHelpers& jit, GPRReg target)
113{
114 return jit.branchIfType(target, JSC::JSType(JSEventType));
115}
116
117inline CCallHelpers::Jump branchIfNotEvent(CCallHelpers& jit, GPRReg target)
118{
119 return jit.branchIfNotType(target, JSC::JSType(JSEventType));
120}
121
122inline CCallHelpers::Jump branchIfNode(CCallHelpers& jit, GPRReg target)
123{
124 return jit.branch8(
125 CCallHelpers::AboveOrEqual,
126 CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
127 CCallHelpers::TrustedImm32(JSC::JSType(JSNodeType)));
128}
129
130inline CCallHelpers::Jump branchIfNotNode(CCallHelpers& jit, GPRReg target)
131{
132 return jit.branch8(
133 CCallHelpers::Below,
134 CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
135 CCallHelpers::TrustedImm32(JSC::JSType(JSNodeType)));
136}
137
138inline CCallHelpers::Jump branchIfElement(CCallHelpers& jit, GPRReg target)
139{
140 return jit.branch8(
141 CCallHelpers::AboveOrEqual,
142 CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
143 CCallHelpers::TrustedImm32(JSC::JSType(JSElementType)));
144}
145
146inline CCallHelpers::Jump branchIfNotElement(CCallHelpers& jit, GPRReg target)
147{
148 return jit.branch8(
149 CCallHelpers::Below,
150 CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
151 CCallHelpers::TrustedImm32(JSC::JSType(JSElementType)));
152}
153
154inline CCallHelpers::Jump branchIfDocumentFragment(CCallHelpers& jit, GPRReg target)
155{
156 return jit.branchIfType(target, JSC::JSType(JSDocumentFragmentNodeType));
157}
158
159inline CCallHelpers::Jump branchIfNotDocumentFragment(CCallHelpers& jit, GPRReg target)
160{
161 return jit.branchIfNotType(target, JSC::JSType(JSDocumentFragmentNodeType));
162}
163
164inline CCallHelpers::Jump branchIfDocumentWrapper(CCallHelpers& jit, GPRReg target)
165{
166 return jit.branchIfType(target, JSC::JSType(JSDocumentWrapperType));
167}
168
169inline CCallHelpers::Jump branchIfNotDocumentWrapper(CCallHelpers& jit, GPRReg target)
170{
171 return jit.branchIfNotType(target, JSC::JSType(JSDocumentWrapperType));
172}
173
174void loadDocument(MacroAssembler&, GPRReg node, GPRReg output);
175void loadDocumentElement(MacroAssembler&, GPRReg document, GPRReg output);
176
177inline CCallHelpers::Jump branchTestIsElementFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
178{
179 return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsElement()));
180}
181
182inline CCallHelpers::Jump branchTestIsShadowRootFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
183{
184 return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsShadowRoot()));
185}
186
187inline CCallHelpers::Jump branchTestIsElementOrShadowRootFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
188{
189 return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()),
190 CCallHelpers::TrustedImm32(Node::flagIsShadowRoot() | Node::flagIsElement()));
191}
192
193inline CCallHelpers::Jump branchTestIsHTMLFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
194{
195 return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsHTML()));
196}
197
198} }
199
200#endif
201