]>
Commit | Line | Data |
---|---|---|
ba379fdc | 1 | /* |
93a37866 | 2 | * Copyright (C) 2009, 2012 Apple Inc. All rights reserved. |
ba379fdc A |
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 | #ifndef MacroAssemblerCodeRef_h | |
27 | #define MacroAssemblerCodeRef_h | |
28 | ||
93a37866 | 29 | #include "Disassembler.h" |
ba379fdc | 30 | #include "ExecutableAllocator.h" |
93a37866 A |
31 | #include "LLIntData.h" |
32 | #include <wtf/DataLog.h> | |
6fe7ccc8 | 33 | #include <wtf/PassRefPtr.h> |
81345200 | 34 | #include <wtf/PrintStream.h> |
6fe7ccc8 | 35 | #include <wtf/RefPtr.h> |
ba379fdc A |
36 | |
37 | // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid | |
38 | // instruction address on the platform (for example, check any alignment requirements). | |
81345200 A |
39 | #if CPU(ARM_THUMB2) && ENABLE(JIT) |
40 | // ARM instructions must be 16-bit aligned. Thumb2 code pointers to be loaded into | |
41 | // into the processor are decorated with the bottom bit set, while traditional ARM has | |
42 | // the lower bit clear. Since we don't know what kind of pointer, we check for both | |
43 | // decorated and undecorated null. | |
ba379fdc | 44 | #define ASSERT_VALID_CODE_POINTER(ptr) \ |
81345200 | 45 | ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1) |
ba379fdc A |
46 | #define ASSERT_VALID_CODE_OFFSET(offset) \ |
47 | ASSERT(!(offset & 1)) // Must be multiple of 2. | |
48 | #else | |
49 | #define ASSERT_VALID_CODE_POINTER(ptr) \ | |
50 | ASSERT(ptr) | |
51 | #define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes! | |
52 | #endif | |
53 | ||
6fe7ccc8 A |
54 | #if CPU(X86) && OS(WINDOWS) |
55 | #define CALLING_CONVENTION_IS_STDCALL 1 | |
56 | #ifndef CDECL | |
57 | #if COMPILER(MSVC) | |
58 | #define CDECL __cdecl | |
59 | #else | |
60 | #define CDECL __attribute__ ((__cdecl)) | |
61 | #endif // COMPILER(MSVC) | |
62 | #endif // CDECL | |
63 | #else | |
64 | #define CALLING_CONVENTION_IS_STDCALL 0 | |
65 | #endif | |
66 | ||
67 | #if CPU(X86) | |
68 | #define HAS_FASTCALL_CALLING_CONVENTION 1 | |
69 | #ifndef FASTCALL | |
70 | #if COMPILER(MSVC) | |
71 | #define FASTCALL __fastcall | |
72 | #else | |
73 | #define FASTCALL __attribute__ ((fastcall)) | |
74 | #endif // COMPILER(MSVC) | |
75 | #endif // FASTCALL | |
76 | #else | |
77 | #define HAS_FASTCALL_CALLING_CONVENTION 0 | |
78 | #endif // CPU(X86) | |
79 | ||
ba379fdc A |
80 | namespace JSC { |
81 | ||
82 | // FunctionPtr: | |
83 | // | |
84 | // FunctionPtr should be used to wrap pointers to C/C++ functions in JSC | |
85 | // (particularly, the stub functions). | |
86 | class FunctionPtr { | |
87 | public: | |
88 | FunctionPtr() | |
89 | : m_value(0) | |
90 | { | |
91 | } | |
92 | ||
14957cd0 A |
93 | template<typename returnType> |
94 | FunctionPtr(returnType(*value)()) | |
95 | : m_value((void*)value) | |
96 | { | |
97 | ASSERT_VALID_CODE_POINTER(m_value); | |
98 | } | |
99 | ||
100 | template<typename returnType, typename argType1> | |
101 | FunctionPtr(returnType(*value)(argType1)) | |
102 | : m_value((void*)value) | |
103 | { | |
104 | ASSERT_VALID_CODE_POINTER(m_value); | |
105 | } | |
106 | ||
107 | template<typename returnType, typename argType1, typename argType2> | |
108 | FunctionPtr(returnType(*value)(argType1, argType2)) | |
109 | : m_value((void*)value) | |
110 | { | |
111 | ASSERT_VALID_CODE_POINTER(m_value); | |
112 | } | |
113 | ||
114 | template<typename returnType, typename argType1, typename argType2, typename argType3> | |
115 | FunctionPtr(returnType(*value)(argType1, argType2, argType3)) | |
116 | : m_value((void*)value) | |
117 | { | |
118 | ASSERT_VALID_CODE_POINTER(m_value); | |
119 | } | |
120 | ||
121 | template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4> | |
122 | FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4)) | |
123 | : m_value((void*)value) | |
124 | { | |
125 | ASSERT_VALID_CODE_POINTER(m_value); | |
126 | } | |
127 | ||
93a37866 A |
128 | template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4, typename argType5> |
129 | FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4, argType5)) | |
130 | : m_value((void*)value) | |
131 | { | |
132 | ASSERT_VALID_CODE_POINTER(m_value); | |
133 | } | |
134 | ||
6fe7ccc8 A |
135 | // MSVC doesn't seem to treat functions with different calling conventions as |
136 | // different types; these methods already defined for fastcall, below. | |
137 | #if CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS) | |
138 | ||
139 | template<typename returnType> | |
140 | FunctionPtr(returnType (CDECL *value)()) | |
141 | : m_value((void*)value) | |
142 | { | |
143 | ASSERT_VALID_CODE_POINTER(m_value); | |
144 | } | |
145 | ||
146 | template<typename returnType, typename argType1> | |
147 | FunctionPtr(returnType (CDECL *value)(argType1)) | |
148 | : m_value((void*)value) | |
149 | { | |
150 | ASSERT_VALID_CODE_POINTER(m_value); | |
151 | } | |
152 | ||
153 | template<typename returnType, typename argType1, typename argType2> | |
154 | FunctionPtr(returnType (CDECL *value)(argType1, argType2)) | |
155 | : m_value((void*)value) | |
156 | { | |
157 | ASSERT_VALID_CODE_POINTER(m_value); | |
158 | } | |
159 | ||
160 | template<typename returnType, typename argType1, typename argType2, typename argType3> | |
161 | FunctionPtr(returnType (CDECL *value)(argType1, argType2, argType3)) | |
162 | : m_value((void*)value) | |
163 | { | |
164 | ASSERT_VALID_CODE_POINTER(m_value); | |
165 | } | |
166 | ||
167 | template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4> | |
168 | FunctionPtr(returnType (CDECL *value)(argType1, argType2, argType3, argType4)) | |
169 | : m_value((void*)value) | |
170 | { | |
171 | ASSERT_VALID_CODE_POINTER(m_value); | |
172 | } | |
173 | #endif | |
174 | ||
175 | #if HAS_FASTCALL_CALLING_CONVENTION | |
176 | ||
177 | template<typename returnType> | |
178 | FunctionPtr(returnType (FASTCALL *value)()) | |
179 | : m_value((void*)value) | |
180 | { | |
181 | ASSERT_VALID_CODE_POINTER(m_value); | |
182 | } | |
183 | ||
184 | template<typename returnType, typename argType1> | |
185 | FunctionPtr(returnType (FASTCALL *value)(argType1)) | |
186 | : m_value((void*)value) | |
187 | { | |
188 | ASSERT_VALID_CODE_POINTER(m_value); | |
189 | } | |
190 | ||
191 | template<typename returnType, typename argType1, typename argType2> | |
192 | FunctionPtr(returnType (FASTCALL *value)(argType1, argType2)) | |
193 | : m_value((void*)value) | |
194 | { | |
195 | ASSERT_VALID_CODE_POINTER(m_value); | |
196 | } | |
197 | ||
198 | template<typename returnType, typename argType1, typename argType2, typename argType3> | |
199 | FunctionPtr(returnType (FASTCALL *value)(argType1, argType2, argType3)) | |
200 | : m_value((void*)value) | |
201 | { | |
202 | ASSERT_VALID_CODE_POINTER(m_value); | |
203 | } | |
204 | ||
205 | template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4> | |
206 | FunctionPtr(returnType (FASTCALL *value)(argType1, argType2, argType3, argType4)) | |
207 | : m_value((void*)value) | |
208 | { | |
209 | ASSERT_VALID_CODE_POINTER(m_value); | |
210 | } | |
211 | #endif | |
212 | ||
ba379fdc A |
213 | template<typename FunctionType> |
214 | explicit FunctionPtr(FunctionType* value) | |
14957cd0 A |
215 | // Using a C-ctyle cast here to avoid compiler error on RVTC: |
216 | // Error: #694: reinterpret_cast cannot cast away const or other type qualifiers | |
217 | // (I guess on RVTC function pointers have a different constness to GCC/MSVC?) | |
218 | : m_value((void*)value) | |
ba379fdc A |
219 | { |
220 | ASSERT_VALID_CODE_POINTER(m_value); | |
221 | } | |
222 | ||
223 | void* value() const { return m_value; } | |
224 | void* executableAddress() const { return m_value; } | |
225 | ||
226 | ||
227 | private: | |
228 | void* m_value; | |
229 | }; | |
230 | ||
231 | // ReturnAddressPtr: | |
232 | // | |
233 | // ReturnAddressPtr should be used to wrap return addresses generated by processor | |
234 | // 'call' instructions exectued in JIT code. We use return addresses to look up | |
235 | // exception and optimization information, and to repatch the call instruction | |
236 | // that is the source of the return address. | |
237 | class ReturnAddressPtr { | |
238 | public: | |
239 | ReturnAddressPtr() | |
240 | : m_value(0) | |
241 | { | |
242 | } | |
243 | ||
244 | explicit ReturnAddressPtr(void* value) | |
245 | : m_value(value) | |
246 | { | |
247 | ASSERT_VALID_CODE_POINTER(m_value); | |
248 | } | |
249 | ||
250 | explicit ReturnAddressPtr(FunctionPtr function) | |
251 | : m_value(function.value()) | |
252 | { | |
253 | ASSERT_VALID_CODE_POINTER(m_value); | |
254 | } | |
255 | ||
256 | void* value() const { return m_value; } | |
81345200 A |
257 | |
258 | void dump(PrintStream& out) const | |
259 | { | |
260 | out.print(RawPointer(m_value)); | |
261 | } | |
ba379fdc A |
262 | |
263 | private: | |
264 | void* m_value; | |
265 | }; | |
266 | ||
267 | // MacroAssemblerCodePtr: | |
268 | // | |
269 | // MacroAssemblerCodePtr should be used to wrap pointers to JIT generated code. | |
270 | class MacroAssemblerCodePtr { | |
271 | public: | |
272 | MacroAssemblerCodePtr() | |
273 | : m_value(0) | |
274 | { | |
275 | } | |
276 | ||
277 | explicit MacroAssemblerCodePtr(void* value) | |
f9bf01c6 | 278 | #if CPU(ARM_THUMB2) |
ba379fdc A |
279 | // Decorate the pointer as a thumb code pointer. |
280 | : m_value(reinterpret_cast<char*>(value) + 1) | |
281 | #else | |
282 | : m_value(value) | |
283 | #endif | |
284 | { | |
285 | ASSERT_VALID_CODE_POINTER(m_value); | |
286 | } | |
6fe7ccc8 A |
287 | |
288 | static MacroAssemblerCodePtr createFromExecutableAddress(void* value) | |
289 | { | |
290 | ASSERT_VALID_CODE_POINTER(value); | |
291 | MacroAssemblerCodePtr result; | |
292 | result.m_value = value; | |
293 | return result; | |
294 | } | |
ba379fdc | 295 | |
81345200 | 296 | static MacroAssemblerCodePtr createLLIntCodePtr(OpcodeID codeId) |
6fe7ccc8 | 297 | { |
93a37866 | 298 | return createFromExecutableAddress(LLInt::getCodePtr(codeId)); |
6fe7ccc8 | 299 | } |
93a37866 | 300 | |
ba379fdc A |
301 | explicit MacroAssemblerCodePtr(ReturnAddressPtr ra) |
302 | : m_value(ra.value()) | |
303 | { | |
304 | ASSERT_VALID_CODE_POINTER(m_value); | |
305 | } | |
306 | ||
307 | void* executableAddress() const { return m_value; } | |
f9bf01c6 | 308 | #if CPU(ARM_THUMB2) |
ba379fdc A |
309 | // To use this pointer as a data address remove the decoration. |
310 | void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast<char*>(m_value) - 1; } | |
311 | #else | |
312 | void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; } | |
313 | #endif | |
314 | ||
81345200 A |
315 | typedef void* (MacroAssemblerCodePtr::*UnspecifiedBoolType); |
316 | operator UnspecifiedBoolType*() const | |
ba379fdc | 317 | { |
81345200 A |
318 | return !!m_value ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; |
319 | } | |
320 | ||
321 | bool operator==(const MacroAssemblerCodePtr& other) const | |
322 | { | |
323 | return m_value == other.m_value; | |
ba379fdc A |
324 | } |
325 | ||
81345200 A |
326 | void dumpWithName(const char* name, PrintStream& out) const |
327 | { | |
328 | if (executableAddress() == dataLocation()) { | |
329 | out.print(name, "(", RawPointer(executableAddress()), ")"); | |
330 | return; | |
331 | } | |
332 | out.print(name, "(executable = ", RawPointer(executableAddress()), ", dataLocation = ", RawPointer(dataLocation()), ")"); | |
333 | } | |
334 | ||
335 | void dump(PrintStream& out) const | |
336 | { | |
337 | dumpWithName("CodePtr", out); | |
338 | } | |
339 | ||
340 | enum EmptyValueTag { EmptyValue }; | |
341 | enum DeletedValueTag { DeletedValue }; | |
342 | ||
343 | MacroAssemblerCodePtr(EmptyValueTag) | |
344 | : m_value(emptyValue()) | |
345 | { | |
346 | } | |
347 | ||
348 | MacroAssemblerCodePtr(DeletedValueTag) | |
349 | : m_value(deletedValue()) | |
350 | { | |
351 | } | |
352 | ||
353 | bool isEmptyValue() const { return m_value == emptyValue(); } | |
354 | bool isDeletedValue() const { return m_value == deletedValue(); } | |
355 | ||
356 | unsigned hash() const { return PtrHash<void*>::hash(m_value); } | |
357 | ||
ba379fdc | 358 | private: |
81345200 A |
359 | static void* emptyValue() { return bitwise_cast<void*>(static_cast<intptr_t>(1)); } |
360 | static void* deletedValue() { return bitwise_cast<void*>(static_cast<intptr_t>(2)); } | |
361 | ||
ba379fdc A |
362 | void* m_value; |
363 | }; | |
364 | ||
81345200 A |
365 | struct MacroAssemblerCodePtrHash { |
366 | static unsigned hash(const MacroAssemblerCodePtr& ptr) { return ptr.hash(); } | |
367 | static bool equal(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b) | |
368 | { | |
369 | return a == b; | |
370 | } | |
371 | static const bool safeToCompareToEmptyOrDeleted = true; | |
372 | }; | |
373 | ||
ba379fdc A |
374 | // MacroAssemblerCodeRef: |
375 | // | |
376 | // A reference to a section of JIT generated code. A CodeRef consists of a | |
377 | // pointer to the code, and a ref pointer to the pool from within which it | |
378 | // was allocated. | |
379 | class MacroAssemblerCodeRef { | |
6fe7ccc8 A |
380 | private: |
381 | // This is private because it's dangerous enough that we want uses of it | |
382 | // to be easy to find - hence the static create method below. | |
383 | explicit MacroAssemblerCodeRef(MacroAssemblerCodePtr codePtr) | |
384 | : m_codePtr(codePtr) | |
385 | { | |
386 | ASSERT(m_codePtr); | |
387 | } | |
388 | ||
ba379fdc A |
389 | public: |
390 | MacroAssemblerCodeRef() | |
ba379fdc A |
391 | { |
392 | } | |
393 | ||
6fe7ccc8 A |
394 | MacroAssemblerCodeRef(PassRefPtr<ExecutableMemoryHandle> executableMemory) |
395 | : m_codePtr(executableMemory->start()) | |
396 | , m_executableMemory(executableMemory) | |
ba379fdc | 397 | { |
6fe7ccc8 A |
398 | ASSERT(m_executableMemory->isManaged()); |
399 | ASSERT(m_executableMemory->start()); | |
400 | ASSERT(m_codePtr); | |
ba379fdc | 401 | } |
6fe7ccc8 A |
402 | |
403 | // Use this only when you know that the codePtr refers to code that is | |
404 | // already being kept alive through some other means. Typically this means | |
405 | // that codePtr is immortal. | |
406 | static MacroAssemblerCodeRef createSelfManagedCodeRef(MacroAssemblerCodePtr codePtr) | |
407 | { | |
408 | return MacroAssemblerCodeRef(codePtr); | |
409 | } | |
410 | ||
411 | // Helper for creating self-managed code refs from LLInt. | |
81345200 | 412 | static MacroAssemblerCodeRef createLLIntCodeRef(OpcodeID codeId) |
6fe7ccc8 | 413 | { |
93a37866 | 414 | return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(codeId))); |
6fe7ccc8 | 415 | } |
93a37866 | 416 | |
6fe7ccc8 A |
417 | ExecutableMemoryHandle* executableMemory() const |
418 | { | |
419 | return m_executableMemory.get(); | |
420 | } | |
421 | ||
422 | MacroAssemblerCodePtr code() const | |
423 | { | |
424 | return m_codePtr; | |
425 | } | |
426 | ||
427 | size_t size() const | |
428 | { | |
429 | if (!m_executableMemory) | |
430 | return 0; | |
431 | return m_executableMemory->sizeInBytes(); | |
432 | } | |
433 | ||
93a37866 A |
434 | bool tryToDisassemble(const char* prefix) const |
435 | { | |
436 | return JSC::tryToDisassemble(m_codePtr, size(), prefix, WTF::dataFile()); | |
437 | } | |
438 | ||
81345200 A |
439 | typedef void* (MacroAssemblerCodeRef::*UnspecifiedBoolType); |
440 | operator UnspecifiedBoolType*() const | |
441 | { | |
442 | return !!m_codePtr ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; | |
443 | } | |
444 | ||
445 | void dump(PrintStream& out) const | |
446 | { | |
447 | m_codePtr.dumpWithName("CodeRef", out); | |
448 | } | |
ba379fdc | 449 | |
6fe7ccc8 A |
450 | private: |
451 | MacroAssemblerCodePtr m_codePtr; | |
452 | RefPtr<ExecutableMemoryHandle> m_executableMemory; | |
ba379fdc A |
453 | }; |
454 | ||
455 | } // namespace JSC | |
456 | ||
81345200 A |
457 | namespace WTF { |
458 | ||
459 | template<typename T> struct DefaultHash; | |
460 | template<> struct DefaultHash<JSC::MacroAssemblerCodePtr> { | |
461 | typedef JSC::MacroAssemblerCodePtrHash Hash; | |
462 | }; | |
463 | ||
464 | template<typename T> struct HashTraits; | |
465 | template<> struct HashTraits<JSC::MacroAssemblerCodePtr> : public CustomHashTraits<JSC::MacroAssemblerCodePtr> { }; | |
466 | ||
467 | } // namespace WTF | |
468 | ||
ba379fdc | 469 | #endif // MacroAssemblerCodeRef_h |