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 | |
36 | namespace WebCore { namespace DOMJIT { |
37 | |
38 | using JSC::CCallHelpers; |
39 | using JSC::GPRReg; |
40 | using JSC::JSValueRegs; |
41 | using JSC::MacroAssembler; |
42 | |
43 | static_assert(std::is_same<GPRReg, MacroAssembler::RegisterID>::value, "GPRReg is the alias to the MacroAssembler::RegisterID" ); |
44 | |
45 | inline CCallHelpers::Jump branchIfNotWorldIsNormal(CCallHelpers& jit, GPRReg globalObject) |
46 | { |
47 | return jit.branchTest8(CCallHelpers::Zero, CCallHelpers::Address(globalObject, JSDOMGlobalObject::offsetOfWorldIsNormal())); |
48 | } |
49 | |
50 | inline 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 | |
55 | template<typename WrappedNode> |
56 | JSC::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 | |
65 | template<typename WrappedType> |
66 | void 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 | |
74 | template<typename WrappedType, typename ToJSFunction> |
75 | void 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 | |
96 | inline 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 | |
104 | inline 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 | |
112 | inline CCallHelpers::Jump branchIfEvent(CCallHelpers& jit, GPRReg target) |
113 | { |
114 | return jit.branchIfType(target, JSC::JSType(JSEventType)); |
115 | } |
116 | |
117 | inline CCallHelpers::Jump branchIfNotEvent(CCallHelpers& jit, GPRReg target) |
118 | { |
119 | return jit.branchIfNotType(target, JSC::JSType(JSEventType)); |
120 | } |
121 | |
122 | inline 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 | |
130 | inline 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 | |
138 | inline 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 | |
146 | inline 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 | |
154 | inline CCallHelpers::Jump branchIfDocumentFragment(CCallHelpers& jit, GPRReg target) |
155 | { |
156 | return jit.branchIfType(target, JSC::JSType(JSDocumentFragmentNodeType)); |
157 | } |
158 | |
159 | inline CCallHelpers::Jump branchIfNotDocumentFragment(CCallHelpers& jit, GPRReg target) |
160 | { |
161 | return jit.branchIfNotType(target, JSC::JSType(JSDocumentFragmentNodeType)); |
162 | } |
163 | |
164 | inline CCallHelpers::Jump branchIfDocumentWrapper(CCallHelpers& jit, GPRReg target) |
165 | { |
166 | return jit.branchIfType(target, JSC::JSType(JSDocumentWrapperType)); |
167 | } |
168 | |
169 | inline CCallHelpers::Jump branchIfNotDocumentWrapper(CCallHelpers& jit, GPRReg target) |
170 | { |
171 | return jit.branchIfNotType(target, JSC::JSType(JSDocumentWrapperType)); |
172 | } |
173 | |
174 | void loadDocument(MacroAssembler&, GPRReg node, GPRReg output); |
175 | void loadDocumentElement(MacroAssembler&, GPRReg document, GPRReg output); |
176 | |
177 | inline 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 | |
182 | inline 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 | |
187 | inline 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 | |
193 | inline 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 | |