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 template<typename returnType
, typename argType1
, typename argType2
, typename argType3
, typename argType4
, typename argType5
, typename argType6
>
136 FunctionPtr(returnType(*value
)(argType1
, argType2
, argType3
, argType4
, argType5
, argType6
))
137 : m_value((void*)value
)
139 ASSERT_VALID_CODE_POINTER(m_value
);
141 // MSVC doesn't seem to treat functions with different calling conventions as
142 // different types; these methods already defined for fastcall, below.
143 #if CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS)
145 template<typename returnType
>
146 FunctionPtr(returnType (CDECL
*value
)())
147 : m_value((void*)value
)
149 ASSERT_VALID_CODE_POINTER(m_value
);
152 template<typename returnType
, typename argType1
>
153 FunctionPtr(returnType (CDECL
*value
)(argType1
))
154 : m_value((void*)value
)
156 ASSERT_VALID_CODE_POINTER(m_value
);
159 template<typename returnType
, typename argType1
, typename argType2
>
160 FunctionPtr(returnType (CDECL
*value
)(argType1
, argType2
))
161 : m_value((void*)value
)
163 ASSERT_VALID_CODE_POINTER(m_value
);
166 template<typename returnType
, typename argType1
, typename argType2
, typename argType3
>
167 FunctionPtr(returnType (CDECL
*value
)(argType1
, argType2
, argType3
))
168 : m_value((void*)value
)
170 ASSERT_VALID_CODE_POINTER(m_value
);
173 template<typename returnType
, typename argType1
, typename argType2
, typename argType3
, typename argType4
>
174 FunctionPtr(returnType (CDECL
*value
)(argType1
, argType2
, argType3
, argType4
))
175 : m_value((void*)value
)
177 ASSERT_VALID_CODE_POINTER(m_value
);
181 #if HAS_FASTCALL_CALLING_CONVENTION
183 template<typename returnType
>
184 FunctionPtr(returnType (FASTCALL
*value
)())
185 : m_value((void*)value
)
187 ASSERT_VALID_CODE_POINTER(m_value
);
190 template<typename returnType
, typename argType1
>
191 FunctionPtr(returnType (FASTCALL
*value
)(argType1
))
192 : m_value((void*)value
)
194 ASSERT_VALID_CODE_POINTER(m_value
);
197 template<typename returnType
, typename argType1
, typename argType2
>
198 FunctionPtr(returnType (FASTCALL
*value
)(argType1
, argType2
))
199 : m_value((void*)value
)
201 ASSERT_VALID_CODE_POINTER(m_value
);
204 template<typename returnType
, typename argType1
, typename argType2
, typename argType3
>
205 FunctionPtr(returnType (FASTCALL
*value
)(argType1
, argType2
, argType3
))
206 : m_value((void*)value
)
208 ASSERT_VALID_CODE_POINTER(m_value
);
211 template<typename returnType
, typename argType1
, typename argType2
, typename argType3
, typename argType4
>
212 FunctionPtr(returnType (FASTCALL
*value
)(argType1
, argType2
, argType3
, argType4
))
213 : m_value((void*)value
)
215 ASSERT_VALID_CODE_POINTER(m_value
);
219 template<typename FunctionType
>
220 explicit FunctionPtr(FunctionType
* value
)
221 // Using a C-ctyle cast here to avoid compiler error on RVTC:
222 // Error: #694: reinterpret_cast cannot cast away const or other type qualifiers
223 // (I guess on RVTC function pointers have a different constness to GCC/MSVC?)
224 : m_value((void*)value
)
226 ASSERT_VALID_CODE_POINTER(m_value
);
229 void* value() const { return m_value
; }
230 void* executableAddress() const { return m_value
; }
239 // ReturnAddressPtr should be used to wrap return addresses generated by processor
240 // 'call' instructions exectued in JIT code. We use return addresses to look up
241 // exception and optimization information, and to repatch the call instruction
242 // that is the source of the return address.
243 class ReturnAddressPtr
{
250 explicit ReturnAddressPtr(void* value
)
253 ASSERT_VALID_CODE_POINTER(m_value
);
256 explicit ReturnAddressPtr(FunctionPtr function
)
257 : m_value(function
.value())
259 ASSERT_VALID_CODE_POINTER(m_value
);
262 void* value() const { return m_value
; }
264 void dump(PrintStream
& out
) const
266 out
.print(RawPointer(m_value
));
273 // MacroAssemblerCodePtr:
275 // MacroAssemblerCodePtr should be used to wrap pointers to JIT generated code.
276 class MacroAssemblerCodePtr
{
278 MacroAssemblerCodePtr()
283 explicit MacroAssemblerCodePtr(void* value
)
285 // Decorate the pointer as a thumb code pointer.
286 : m_value(reinterpret_cast<char*>(value
) + 1)
291 ASSERT_VALID_CODE_POINTER(m_value
);
294 static MacroAssemblerCodePtr
createFromExecutableAddress(void* value
)
296 ASSERT_VALID_CODE_POINTER(value
);
297 MacroAssemblerCodePtr result
;
298 result
.m_value
= value
;
302 static MacroAssemblerCodePtr
createLLIntCodePtr(OpcodeID codeId
)
304 return createFromExecutableAddress(LLInt::getCodePtr(codeId
));
307 explicit MacroAssemblerCodePtr(ReturnAddressPtr ra
)
308 : m_value(ra
.value())
310 ASSERT_VALID_CODE_POINTER(m_value
);
313 void* executableAddress() const { return m_value
; }
315 // To use this pointer as a data address remove the decoration.
316 void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value
); return reinterpret_cast<char*>(m_value
) - 1; }
318 void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value
); return m_value
; }
321 explicit operator bool() const { return m_value
; }
323 bool operator==(const MacroAssemblerCodePtr
& other
) const
325 return m_value
== other
.m_value
;
328 void dumpWithName(const char* name
, PrintStream
& out
) const
330 if (executableAddress() == dataLocation()) {
331 out
.print(name
, "(", RawPointer(executableAddress()), ")");
334 out
.print(name
, "(executable = ", RawPointer(executableAddress()), ", dataLocation = ", RawPointer(dataLocation()), ")");
337 void dump(PrintStream
& out
) const
339 dumpWithName("CodePtr", out
);
342 enum EmptyValueTag
{ EmptyValue
};
343 enum DeletedValueTag
{ DeletedValue
};
345 MacroAssemblerCodePtr(EmptyValueTag
)
346 : m_value(emptyValue())
350 MacroAssemblerCodePtr(DeletedValueTag
)
351 : m_value(deletedValue())
355 bool isEmptyValue() const { return m_value
== emptyValue(); }
356 bool isDeletedValue() const { return m_value
== deletedValue(); }
358 unsigned hash() const { return PtrHash
<void*>::hash(m_value
); }
361 static void* emptyValue() { return bitwise_cast
<void*>(static_cast<intptr_t>(1)); }
362 static void* deletedValue() { return bitwise_cast
<void*>(static_cast<intptr_t>(2)); }
367 struct MacroAssemblerCodePtrHash
{
368 static unsigned hash(const MacroAssemblerCodePtr
& ptr
) { return ptr
.hash(); }
369 static bool equal(const MacroAssemblerCodePtr
& a
, const MacroAssemblerCodePtr
& b
)
373 static const bool safeToCompareToEmptyOrDeleted
= true;
376 // MacroAssemblerCodeRef:
378 // A reference to a section of JIT generated code. A CodeRef consists of a
379 // pointer to the code, and a ref pointer to the pool from within which it
381 class MacroAssemblerCodeRef
{
383 // This is private because it's dangerous enough that we want uses of it
384 // to be easy to find - hence the static create method below.
385 explicit MacroAssemblerCodeRef(MacroAssemblerCodePtr codePtr
)
392 MacroAssemblerCodeRef()
396 MacroAssemblerCodeRef(PassRefPtr
<ExecutableMemoryHandle
> executableMemory
)
397 : m_codePtr(executableMemory
->start())
398 , m_executableMemory(executableMemory
)
400 ASSERT(m_executableMemory
->isManaged());
401 ASSERT(m_executableMemory
->start());
405 // Use this only when you know that the codePtr refers to code that is
406 // already being kept alive through some other means. Typically this means
407 // that codePtr is immortal.
408 static MacroAssemblerCodeRef
createSelfManagedCodeRef(MacroAssemblerCodePtr codePtr
)
410 return MacroAssemblerCodeRef(codePtr
);
413 // Helper for creating self-managed code refs from LLInt.
414 static MacroAssemblerCodeRef
createLLIntCodeRef(OpcodeID codeId
)
416 return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(codeId
)));
419 ExecutableMemoryHandle
* executableMemory() const
421 return m_executableMemory
.get();
424 MacroAssemblerCodePtr
code() const
431 if (!m_executableMemory
)
433 return m_executableMemory
->sizeInBytes();
436 bool tryToDisassemble(const char* prefix
) const
438 return JSC::tryToDisassemble(m_codePtr
, size(), prefix
, WTF::dataFile());
441 explicit operator bool() const { return !!m_codePtr
; }
443 void dump(PrintStream
& out
) const
445 m_codePtr
.dumpWithName("CodeRef", out
);
449 MacroAssemblerCodePtr m_codePtr
;
450 RefPtr
<ExecutableMemoryHandle
> m_executableMemory
;
457 template<typename T
> struct DefaultHash
;
458 template<> struct DefaultHash
<JSC::MacroAssemblerCodePtr
> {
459 typedef JSC::MacroAssemblerCodePtrHash Hash
;
462 template<typename T
> struct HashTraits
;
463 template<> struct HashTraits
<JSC::MacroAssemblerCodePtr
> : public CustomHashTraits
<JSC::MacroAssemblerCodePtr
> { };
467 #endif // MacroAssemblerCodeRef_h