1/*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
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
29#include "ExecutableAllocator.h"
30#include "PassRefPtr.h"
31#include "RefPtr.h"
32#include "UnusedParam.h"
33
34#if ENABLE(ASSEMBLER)
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).
38#if CPU(ARM_THUMB2)
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
55namespace JSC {
56
57// FunctionPtr:
58//
59// FunctionPtr should be used to wrap pointers to C/C++ functions in JSC
60// (particularly, the stub functions).
61class FunctionPtr {
62public:
63    FunctionPtr()
64        : m_value(0)
65    {
66    }
67
68    template<typename returnType>
69    FunctionPtr(returnType(*value)())
70        : m_value((void*)value)
71    {
72        ASSERT_VALID_CODE_POINTER(m_value);
73    }
74
75    template<typename returnType, typename argType1>
76    FunctionPtr(returnType(*value)(argType1))
77        : m_value((void*)value)
78    {
79        ASSERT_VALID_CODE_POINTER(m_value);
80    }
81
82    template<typename returnType, typename argType1, typename argType2>
83    FunctionPtr(returnType(*value)(argType1, argType2))
84        : m_value((void*)value)
85    {
86        ASSERT_VALID_CODE_POINTER(m_value);
87    }
88
89    template<typename returnType, typename argType1, typename argType2, typename argType3>
90    FunctionPtr(returnType(*value)(argType1, argType2, argType3))
91        : m_value((void*)value)
92    {
93        ASSERT_VALID_CODE_POINTER(m_value);
94    }
95
96    template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4>
97    FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4))
98        : m_value((void*)value)
99    {
100        ASSERT_VALID_CODE_POINTER(m_value);
101    }
102
103    template<typename FunctionType>
104    explicit FunctionPtr(FunctionType* value)
105        // Using a C-ctyle cast here to avoid compiler error on RVTC:
106        // Error:  #694: reinterpret_cast cannot cast away const or other type qualifiers
107        // (I guess on RVTC function pointers have a different constness to GCC/MSVC?)
108        : m_value((void*)value)
109    {
110        ASSERT_VALID_CODE_POINTER(m_value);
111    }
112
113    void* value() const { return m_value; }
114    void* executableAddress() const { return m_value; }
115
116
117private:
118    void* m_value;
119};
120
121// ReturnAddressPtr:
122//
123// ReturnAddressPtr should be used to wrap return addresses generated by processor
124// 'call' instructions exectued in JIT code.  We use return addresses to look up
125// exception and optimization information, and to repatch the call instruction
126// that is the source of the return address.
127class ReturnAddressPtr {
128public:
129    ReturnAddressPtr()
130        : m_value(0)
131    {
132    }
133
134    explicit ReturnAddressPtr(void* value)
135        : m_value(value)
136    {
137        ASSERT_VALID_CODE_POINTER(m_value);
138    }
139
140    explicit ReturnAddressPtr(FunctionPtr function)
141        : m_value(function.value())
142    {
143        ASSERT_VALID_CODE_POINTER(m_value);
144    }
145
146    void* value() const { return m_value; }
147
148private:
149    void* m_value;
150};
151
152// MacroAssemblerCodePtr:
153//
154// MacroAssemblerCodePtr should be used to wrap pointers to JIT generated code.
155class MacroAssemblerCodePtr {
156public:
157    MacroAssemblerCodePtr()
158        : m_value(0)
159    {
160    }
161
162    explicit MacroAssemblerCodePtr(void* value)
163#if CPU(ARM_THUMB2)
164        // Decorate the pointer as a thumb code pointer.
165        : m_value(reinterpret_cast<char*>(value) + 1)
166#else
167        : m_value(value)
168#endif
169    {
170        ASSERT_VALID_CODE_POINTER(m_value);
171    }
172
173    explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
174        : m_value(ra.value())
175    {
176        ASSERT_VALID_CODE_POINTER(m_value);
177    }
178
179    void* executableAddress() const { return m_value; }
180#if CPU(ARM_THUMB2)
181    // To use this pointer as a data address remove the decoration.
182    void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast<char*>(m_value) - 1; }
183#else
184    void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
185#endif
186
187    bool operator!()
188    {
189        return !m_value;
190    }
191
192private:
193    void* m_value;
194};
195
196// MacroAssemblerCodeRef:
197//
198// A reference to a section of JIT generated code.  A CodeRef consists of a
199// pointer to the code, and a ref pointer to the pool from within which it
200// was allocated.
201class MacroAssemblerCodeRef {
202public:
203    MacroAssemblerCodeRef()
204        : m_size(0)
205    {
206    }
207
208    MacroAssemblerCodeRef(void* code, PassRefPtr<ExecutablePool> executablePool, size_t size)
209        : m_code(code)
210        , m_executablePool(executablePool)
211        , m_size(size)
212    {
213    }
214
215    MacroAssemblerCodePtr m_code;
216    RefPtr<ExecutablePool> m_executablePool;
217    size_t m_size;
218};
219
220} // namespace JSC
221
222#endif // ENABLE(ASSEMBLER)
223
224#endif // MacroAssemblerCodeRef_h
225