]> git.saurik.com Git - apple/javascriptcore.git/blame - assembler/MacroAssemblerCodeRef.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / assembler / MacroAssemblerCodeRef.h
CommitLineData
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
80namespace JSC {
81
82// FunctionPtr:
83//
84// FunctionPtr should be used to wrap pointers to C/C++ functions in JSC
85// (particularly, the stub functions).
86class FunctionPtr {
87public:
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
227private:
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.
237class ReturnAddressPtr {
238public:
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
263private:
264 void* m_value;
265};
266
267// MacroAssemblerCodePtr:
268//
269// MacroAssemblerCodePtr should be used to wrap pointers to JIT generated code.
270class MacroAssemblerCodePtr {
271public:
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 358private:
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
365struct 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.
379class MacroAssemblerCodeRef {
6fe7ccc8
A
380private:
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
389public:
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
450private:
451 MacroAssemblerCodePtr m_codePtr;
452 RefPtr<ExecutableMemoryHandle> m_executableMemory;
ba379fdc
A
453};
454
455} // namespace JSC
456
81345200
A
457namespace WTF {
458
459template<typename T> struct DefaultHash;
460template<> struct DefaultHash<JSC::MacroAssemblerCodePtr> {
461 typedef JSC::MacroAssemblerCodePtrHash Hash;
462};
463
464template<typename T> struct HashTraits;
465template<> struct HashTraits<JSC::MacroAssemblerCodePtr> : public CustomHashTraits<JSC::MacroAssemblerCodePtr> { };
466
467} // namespace WTF
468
ba379fdc 469#endif // MacroAssemblerCodeRef_h