]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 2008, 2012, 2013 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 "JITCode.h" | |
28 | ||
29 | #include "LLIntThunks.h" | |
30 | #include "JSCInlines.h" | |
31 | #include "ProtoCallFrame.h" | |
32 | #include "RegisterPreservationWrapperGenerator.h" | |
33 | #include <wtf/PrintStream.h> | |
34 | ||
35 | namespace JSC { | |
36 | ||
37 | JITCode::JITCode(JITType jitType) | |
38 | : m_jitType(jitType) | |
39 | { | |
40 | } | |
41 | ||
42 | JITCode::~JITCode() | |
43 | { | |
44 | } | |
45 | ||
46 | const char* JITCode::typeName(JITType jitType) | |
47 | { | |
48 | switch (jitType) { | |
49 | case None: | |
50 | return "None"; | |
51 | case HostCallThunk: | |
52 | return "Host"; | |
53 | case InterpreterThunk: | |
54 | return "LLInt"; | |
55 | case BaselineJIT: | |
56 | return "Baseline"; | |
57 | case DFGJIT: | |
58 | return "DFG"; | |
59 | case FTLJIT: | |
60 | return "FTL"; | |
61 | default: | |
62 | CRASH(); | |
63 | return ""; | |
64 | } | |
65 | } | |
66 | ||
67 | void JITCode::validateReferences(const TrackedReferences&) | |
68 | { | |
69 | } | |
70 | ||
71 | JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame) | |
72 | { | |
73 | void* entryAddress; | |
74 | JSFunction* function = jsDynamicCast<JSFunction*>(protoCallFrame->callee()); | |
75 | ||
76 | if (!function || !protoCallFrame->needArityCheck()) { | |
77 | ASSERT(!protoCallFrame->needArityCheck()); | |
78 | entryAddress = executableAddress(); | |
79 | } else | |
80 | entryAddress = addressForCall(*vm, function->executable(), MustCheckArity, RegisterPreservationNotRequired).executableAddress(); | |
81 | JSValue result = JSValue::decode(vmEntryToJavaScript(entryAddress, vm, protoCallFrame)); | |
82 | return vm->exception() ? jsNull() : result; | |
83 | } | |
84 | ||
85 | DFG::CommonData* JITCode::dfgCommon() | |
86 | { | |
87 | RELEASE_ASSERT_NOT_REACHED(); | |
88 | return 0; | |
89 | } | |
90 | ||
91 | DFG::JITCode* JITCode::dfg() | |
92 | { | |
93 | RELEASE_ASSERT_NOT_REACHED(); | |
94 | return 0; | |
95 | } | |
96 | ||
97 | FTL::JITCode* JITCode::ftl() | |
98 | { | |
99 | RELEASE_ASSERT_NOT_REACHED(); | |
100 | return 0; | |
101 | } | |
102 | ||
103 | FTL::ForOSREntryJITCode* JITCode::ftlForOSREntry() | |
104 | { | |
105 | RELEASE_ASSERT_NOT_REACHED(); | |
106 | return 0; | |
107 | } | |
108 | ||
109 | JITCodeWithCodeRef::JITCodeWithCodeRef(JITType jitType) | |
110 | : JITCode(jitType) | |
111 | { | |
112 | } | |
113 | ||
114 | JITCodeWithCodeRef::JITCodeWithCodeRef(CodeRef ref, JITType jitType) | |
115 | : JITCode(jitType) | |
116 | , m_ref(ref) | |
117 | { | |
118 | } | |
119 | ||
120 | JITCodeWithCodeRef::~JITCodeWithCodeRef() | |
121 | { | |
122 | } | |
123 | ||
124 | void* JITCodeWithCodeRef::executableAddressAtOffset(size_t offset) | |
125 | { | |
126 | RELEASE_ASSERT(m_ref); | |
127 | return reinterpret_cast<char*>(m_ref.code().executableAddress()) + offset; | |
128 | } | |
129 | ||
130 | void* JITCodeWithCodeRef::dataAddressAtOffset(size_t offset) | |
131 | { | |
132 | RELEASE_ASSERT(m_ref); | |
133 | ASSERT(offset <= size()); // use <= instead of < because it is valid to ask for an address at the exclusive end of the code. | |
134 | return reinterpret_cast<char*>(m_ref.code().dataLocation()) + offset; | |
135 | } | |
136 | ||
137 | unsigned JITCodeWithCodeRef::offsetOf(void* pointerIntoCode) | |
138 | { | |
139 | RELEASE_ASSERT(m_ref); | |
140 | intptr_t result = reinterpret_cast<intptr_t>(pointerIntoCode) - reinterpret_cast<intptr_t>(m_ref.code().executableAddress()); | |
141 | ASSERT(static_cast<intptr_t>(static_cast<unsigned>(result)) == result); | |
142 | return static_cast<unsigned>(result); | |
143 | } | |
144 | ||
145 | size_t JITCodeWithCodeRef::size() | |
146 | { | |
147 | RELEASE_ASSERT(m_ref); | |
148 | return m_ref.size(); | |
149 | } | |
150 | ||
151 | bool JITCodeWithCodeRef::contains(void* address) | |
152 | { | |
153 | RELEASE_ASSERT(m_ref); | |
154 | return m_ref.executableMemory()->contains(address); | |
155 | } | |
156 | ||
157 | DirectJITCode::DirectJITCode(JITType jitType) | |
158 | : JITCodeWithCodeRef(jitType) | |
159 | { | |
160 | } | |
161 | ||
162 | DirectJITCode::DirectJITCode(JITCode::CodeRef ref, JITCode::CodePtr withArityCheck, JITType jitType) | |
163 | : JITCodeWithCodeRef(ref, jitType) | |
164 | , m_withArityCheck(withArityCheck) | |
165 | { | |
166 | } | |
167 | ||
168 | DirectJITCode::~DirectJITCode() | |
169 | { | |
170 | } | |
171 | ||
172 | void DirectJITCode::initializeCodeRef(JITCode::CodeRef ref, JITCode::CodePtr withArityCheck) | |
173 | { | |
174 | RELEASE_ASSERT(!m_ref); | |
175 | m_ref = ref; | |
176 | m_withArityCheck = withArityCheck; | |
177 | } | |
178 | ||
179 | DirectJITCode::RegisterPreservationWrappers* DirectJITCode::ensureWrappers() | |
180 | { | |
181 | if (!m_wrappers) | |
182 | m_wrappers = std::make_unique<RegisterPreservationWrappers>(); | |
183 | return m_wrappers.get(); | |
184 | } | |
185 | ||
186 | JITCode::CodePtr DirectJITCode::addressForCall( | |
187 | VM& vm, ExecutableBase* executable, ArityCheckMode arity, | |
188 | RegisterPreservationMode registers) | |
189 | { | |
190 | switch (arity) { | |
191 | case ArityCheckNotRequired: | |
192 | switch (registers) { | |
193 | case RegisterPreservationNotRequired: | |
194 | RELEASE_ASSERT(m_ref); | |
195 | return m_ref.code(); | |
196 | case MustPreserveRegisters: { | |
197 | #if ENABLE(JIT) | |
198 | RegisterPreservationWrappers* wrappers = ensureWrappers(); | |
199 | if (!wrappers->withoutArityCheck) | |
200 | wrappers->withoutArityCheck = generateRegisterPreservationWrapper(vm, executable, m_ref.code()); | |
201 | return wrappers->withoutArityCheck.code(); | |
202 | #else | |
203 | UNUSED_PARAM(vm); | |
204 | UNUSED_PARAM(executable); | |
205 | RELEASE_ASSERT_NOT_REACHED(); | |
206 | #endif | |
207 | } } | |
208 | case MustCheckArity: | |
209 | switch (registers) { | |
210 | case RegisterPreservationNotRequired: | |
211 | RELEASE_ASSERT(m_withArityCheck); | |
212 | return m_withArityCheck; | |
213 | case MustPreserveRegisters: { | |
214 | #if ENABLE(JIT) | |
215 | RegisterPreservationWrappers* wrappers = ensureWrappers(); | |
216 | if (!wrappers->withArityCheck) | |
217 | wrappers->withArityCheck = generateRegisterPreservationWrapper(vm, executable, m_withArityCheck); | |
218 | return wrappers->withArityCheck.code(); | |
219 | #else | |
220 | RELEASE_ASSERT_NOT_REACHED(); | |
221 | #endif | |
222 | } } | |
223 | } | |
224 | RELEASE_ASSERT_NOT_REACHED(); | |
225 | return CodePtr(); | |
226 | } | |
227 | ||
228 | NativeJITCode::NativeJITCode(JITType jitType) | |
229 | : JITCodeWithCodeRef(jitType) | |
230 | { | |
231 | } | |
232 | ||
233 | NativeJITCode::NativeJITCode(CodeRef ref, JITType jitType) | |
234 | : JITCodeWithCodeRef(ref, jitType) | |
235 | { | |
236 | } | |
237 | ||
238 | NativeJITCode::~NativeJITCode() | |
239 | { | |
240 | } | |
241 | ||
242 | void NativeJITCode::initializeCodeRef(CodeRef ref) | |
243 | { | |
244 | ASSERT(!m_ref); | |
245 | m_ref = ref; | |
246 | } | |
247 | ||
248 | JITCode::CodePtr NativeJITCode::addressForCall( | |
249 | VM&, ExecutableBase*, ArityCheckMode, RegisterPreservationMode) | |
250 | { | |
251 | RELEASE_ASSERT(!!m_ref); | |
252 | return m_ref.code(); | |
253 | } | |
254 | ||
255 | } // namespace JSC | |
256 | ||
257 | namespace WTF { | |
258 | ||
259 | void printInternal(PrintStream& out, JSC::JITCode::JITType type) | |
260 | { | |
261 | out.print(JSC::JITCode::typeName(type)); | |
262 | } | |
263 | ||
264 | } // namespace WTF | |
265 |