2 * Copyright (C) 2009, 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef MacroAssemblerCodeRef_h
27 #define MacroAssemblerCodeRef_h
29 #include "Disassembler.h"
30 #include "ExecutableAllocator.h"
31 #include "LLIntData.h"
32 #include <wtf/DataLog.h>
33 #include <wtf/PassRefPtr.h>
34 #include <wtf/PrintStream.h>
35 #include <wtf/RefPtr.h>
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).
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.
44 #define ASSERT_VALID_CODE_POINTER(ptr) \
45 ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1)
46 #define ASSERT_VALID_CODE_OFFSET(offset) \
47 ASSERT(!(offset & 1)) // Must be multiple of 2.
49 #define ASSERT_VALID_CODE_POINTER(ptr) \
51 #define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes!
54 #if CPU(X86) && OS(WINDOWS)
55 #define CALLING_CONVENTION_IS_STDCALL 1
60 #define CDECL __attribute__ ((__cdecl))
61 #endif // COMPILER(MSVC)
64 #define CALLING_CONVENTION_IS_STDCALL 0
68 #define HAS_FASTCALL_CALLING_CONVENTION 1
71 #define FASTCALL __fastcall
73 #define FASTCALL __attribute__ ((fastcall))
74 #endif // COMPILER(MSVC)
77 #define HAS_FASTCALL_CALLING_CONVENTION 0
84 // FunctionPtr should be used to wrap pointers to C/C++ functions in JSC
85 // (particularly, the stub functions).
93 template<typename returnType
>
94 FunctionPtr(returnType(*value
)())
95 : m_value((void*)value
)
97 ASSERT_VALID_CODE_POINTER(m_value
);
100 template<typename returnType
, typename argType1
>
101 FunctionPtr(returnType(*value
)(argType1
))
102 : m_value((void*)value
)
104 ASSERT_VALID_CODE_POINTER(m_value
);
107 template<typename returnType
, typename argType1
, typename argType2
>
108 FunctionPtr(returnType(*value
)(argType1
, argType2
))
109 : m_value((void*)value
)
111 ASSERT_VALID_CODE_POINTER(m_value
);
114 template<typename returnType
, typename argType1
, typename argType2
, typename argType3
>
115 FunctionPtr(returnType(*value
)(argType1
, argType2
, argType3
))
116 : m_value((void*)value
)
118 ASSERT_VALID_CODE_POINTER(m_value
);
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
)
125 ASSERT_VALID_CODE_POINTER(m_value
);
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
)
132 ASSERT_VALID_CODE_POINTER(m_value
);
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)
139 template<typename returnType
>
140 FunctionPtr(returnType (CDECL
*value
)())
141 : m_value((void*)value
)
143 ASSERT_VALID_CODE_POINTER(m_value
);
146 template<typename returnType
, typename argType1
>
147 FunctionPtr(returnType (CDECL
*value
)(argType1
))
148 : m_value((void*)value
)
150 ASSERT_VALID_CODE_POINTER(m_value
);
153 template<typename returnType
, typename argType1
, typename argType2
>
154 FunctionPtr(returnType (CDECL
*value
)(argType1
, argType2
))
155 : m_value((void*)value
)
157 ASSERT_VALID_CODE_POINTER(m_value
);
160 template<typename returnType
, typename argType1
, typename argType2
, typename argType3
>
161 FunctionPtr(returnType (CDECL
*value
)(argType1
, argType2
, argType3
))
162 : m_value((void*)value
)
164 ASSERT_VALID_CODE_POINTER(m_value
);
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
)
171 ASSERT_VALID_CODE_POINTER(m_value
);
175 #if HAS_FASTCALL_CALLING_CONVENTION
177 template<typename returnType
>
178 FunctionPtr(returnType (FASTCALL
*value
)())
179 : m_value((void*)value
)
181 ASSERT_VALID_CODE_POINTER(m_value
);
184 template<typename returnType
, typename argType1
>
185 FunctionPtr(returnType (FASTCALL
*value
)(argType1
))
186 : m_value((void*)value
)
188 ASSERT_VALID_CODE_POINTER(m_value
);
191 template<typename returnType
, typename argType1
, typename argType2
>
192 FunctionPtr(returnType (FASTCALL
*value
)(argType1
, argType2
))
193 : m_value((void*)value
)
195 ASSERT_VALID_CODE_POINTER(m_value
);
198 template<typename returnType
, typename argType1
, typename argType2
, typename argType3
>
199 FunctionPtr(returnType (FASTCALL
*value
)(argType1
, argType2
, argType3
))
200 : m_value((void*)value
)
202 ASSERT_VALID_CODE_POINTER(m_value
);
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
)
209 ASSERT_VALID_CODE_POINTER(m_value
);
213 template<typename FunctionType
>
214 explicit FunctionPtr(FunctionType
* value
)
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
)
220 ASSERT_VALID_CODE_POINTER(m_value
);
223 void* value() const { return m_value
; }
224 void* executableAddress() const { return m_value
; }
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
{
244 explicit ReturnAddressPtr(void* value
)
247 ASSERT_VALID_CODE_POINTER(m_value
);
250 explicit ReturnAddressPtr(FunctionPtr function
)
251 : m_value(function
.value())
253 ASSERT_VALID_CODE_POINTER(m_value
);
256 void* value() const { return m_value
; }
258 void dump(PrintStream
& out
) const
260 out
.print(RawPointer(m_value
));
267 // MacroAssemblerCodePtr:
269 // MacroAssemblerCodePtr should be used to wrap pointers to JIT generated code.
270 class MacroAssemblerCodePtr
{
272 MacroAssemblerCodePtr()
277 explicit MacroAssemblerCodePtr(void* value
)
279 // Decorate the pointer as a thumb code pointer.
280 : m_value(reinterpret_cast<char*>(value
) + 1)
285 ASSERT_VALID_CODE_POINTER(m_value
);
288 static MacroAssemblerCodePtr
createFromExecutableAddress(void* value
)
290 ASSERT_VALID_CODE_POINTER(value
);
291 MacroAssemblerCodePtr result
;
292 result
.m_value
= value
;
296 static MacroAssemblerCodePtr
createLLIntCodePtr(OpcodeID codeId
)
298 return createFromExecutableAddress(LLInt::getCodePtr(codeId
));
301 explicit MacroAssemblerCodePtr(ReturnAddressPtr ra
)
302 : m_value(ra
.value())
304 ASSERT_VALID_CODE_POINTER(m_value
);
307 void* executableAddress() const { return m_value
; }
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; }
312 void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value
); return m_value
; }
315 typedef void* (MacroAssemblerCodePtr::*UnspecifiedBoolType
);
316 operator UnspecifiedBoolType
*() const
318 return !!m_value
? reinterpret_cast<UnspecifiedBoolType
*>(1) : 0;
321 bool operator==(const MacroAssemblerCodePtr
& other
) const
323 return m_value
== other
.m_value
;
326 void dumpWithName(const char* name
, PrintStream
& out
) const
328 if (executableAddress() == dataLocation()) {
329 out
.print(name
, "(", RawPointer(executableAddress()), ")");
332 out
.print(name
, "(executable = ", RawPointer(executableAddress()), ", dataLocation = ", RawPointer(dataLocation()), ")");
335 void dump(PrintStream
& out
) const
337 dumpWithName("CodePtr", out
);
340 enum EmptyValueTag
{ EmptyValue
};
341 enum DeletedValueTag
{ DeletedValue
};
343 MacroAssemblerCodePtr(EmptyValueTag
)
344 : m_value(emptyValue())
348 MacroAssemblerCodePtr(DeletedValueTag
)
349 : m_value(deletedValue())
353 bool isEmptyValue() const { return m_value
== emptyValue(); }
354 bool isDeletedValue() const { return m_value
== deletedValue(); }
356 unsigned hash() const { return PtrHash
<void*>::hash(m_value
); }
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)); }
365 struct MacroAssemblerCodePtrHash
{
366 static unsigned hash(const MacroAssemblerCodePtr
& ptr
) { return ptr
.hash(); }
367 static bool equal(const MacroAssemblerCodePtr
& a
, const MacroAssemblerCodePtr
& b
)
371 static const bool safeToCompareToEmptyOrDeleted
= true;
374 // MacroAssemblerCodeRef:
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
379 class MacroAssemblerCodeRef
{
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
)
390 MacroAssemblerCodeRef()
394 MacroAssemblerCodeRef(PassRefPtr
<ExecutableMemoryHandle
> executableMemory
)
395 : m_codePtr(executableMemory
->start())
396 , m_executableMemory(executableMemory
)
398 ASSERT(m_executableMemory
->isManaged());
399 ASSERT(m_executableMemory
->start());
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
)
408 return MacroAssemblerCodeRef(codePtr
);
411 // Helper for creating self-managed code refs from LLInt.
412 static MacroAssemblerCodeRef
createLLIntCodeRef(OpcodeID codeId
)
414 return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(codeId
)));
417 ExecutableMemoryHandle
* executableMemory() const
419 return m_executableMemory
.get();
422 MacroAssemblerCodePtr
code() const
429 if (!m_executableMemory
)
431 return m_executableMemory
->sizeInBytes();
434 bool tryToDisassemble(const char* prefix
) const
436 return JSC::tryToDisassemble(m_codePtr
, size(), prefix
, WTF::dataFile());
439 typedef void* (MacroAssemblerCodeRef::*UnspecifiedBoolType
);
440 operator UnspecifiedBoolType
*() const
442 return !!m_codePtr
? reinterpret_cast<UnspecifiedBoolType
*>(1) : 0;
445 void dump(PrintStream
& out
) const
447 m_codePtr
.dumpWithName("CodeRef", out
);
451 MacroAssemblerCodePtr m_codePtr
;
452 RefPtr
<ExecutableMemoryHandle
> m_executableMemory
;
459 template<typename T
> struct DefaultHash
;
460 template<> struct DefaultHash
<JSC::MacroAssemblerCodePtr
> {
461 typedef JSC::MacroAssemblerCodePtrHash Hash
;
464 template<typename T
> struct HashTraits
;
465 template<> struct HashTraits
<JSC::MacroAssemblerCodePtr
> : public CustomHashTraits
<JSC::MacroAssemblerCodePtr
> { };
469 #endif // MacroAssemblerCodeRef_h