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