initial import
[vuplus_webkit] / Source / JavaScriptCore / jit / ExecutableAllocator.h
1 /*
2  * Copyright (C) 2008 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 ExecutableAllocator_h
27 #define ExecutableAllocator_h
28 #include <stddef.h> // for ptrdiff_t
29 #include <limits>
30 #include <wtf/Assertions.h>
31 #include <wtf/MetaAllocatorHandle.h>
32 #include <wtf/PageAllocation.h>
33 #include <wtf/PassRefPtr.h>
34 #include <wtf/RefCounted.h>
35 #include <wtf/UnusedParam.h>
36 #include <wtf/Vector.h>
37
38 #if OS(IOS)
39 #include <libkern/OSCacheControl.h>
40 #endif
41
42 #if OS(IOS) || OS(QNX)
43 #include <sys/mman.h>
44 #endif
45
46 #if OS(SYMBIAN)
47 #include <e32std.h>
48 #endif
49
50 #if CPU(MIPS) && OS(LINUX)
51 #include <sys/cachectl.h>
52 #endif
53
54 #if CPU(SH4) && OS(LINUX)
55 #include <asm/cachectl.h>
56 #include <asm/unistd.h>
57 #include <sys/syscall.h>
58 #include <unistd.h>
59 #endif
60
61 #if OS(WINCE)
62 // From pkfuncs.h (private header file from the Platform Builder)
63 #define CACHE_SYNC_ALL 0x07F
64 extern "C" __declspec(dllimport) void CacheRangeFlush(LPVOID pAddr, DWORD dwLength, DWORD dwFlags);
65 #endif
66
67 #if PLATFORM(BREWMP)
68 #include <AEEIMemCache1.h>
69 #include <AEEMemCache1.bid>
70 #include <wtf/brew/RefPtrBrew.h>
71 #endif
72
73 #define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (pageSize() * 4)
74
75 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
76 #define PROTECTION_FLAGS_RW (PROT_READ | PROT_WRITE)
77 #define PROTECTION_FLAGS_RX (PROT_READ | PROT_EXEC)
78 #define EXECUTABLE_POOL_WRITABLE false
79 #else
80 #define EXECUTABLE_POOL_WRITABLE true
81 #endif
82
83 namespace JSC {
84
85 class JSGlobalData;
86 void releaseExecutableMemory(JSGlobalData&);
87
88 inline size_t roundUpAllocationSize(size_t request, size_t granularity)
89 {
90     if ((std::numeric_limits<size_t>::max() - granularity) <= request)
91         CRASH(); // Allocation is too large
92     
93     // Round up to next page boundary
94     size_t size = request + (granularity - 1);
95     size = size & ~(granularity - 1);
96     ASSERT(size >= request);
97     return size;
98 }
99
100 }
101
102 #if ENABLE(JIT) && ENABLE(ASSEMBLER)
103
104 namespace JSC {
105
106 typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle;
107
108 class ExecutableAllocator {
109     enum ProtectionSetting { Writable, Executable };
110
111 public:
112     ExecutableAllocator(JSGlobalData&);
113     
114     static void initializeAllocator();
115
116     bool isValid() const;
117
118     static bool underMemoryPressure();
119     
120 #if ENABLE(META_ALLOCATOR_PROFILE)
121     static void dumpProfile();
122 #else
123     static void dumpProfile() { }
124 #endif
125
126     PassRefPtr<ExecutableMemoryHandle> allocate(JSGlobalData&, size_t sizeInBytes);
127
128 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
129     static void makeWritable(void* start, size_t size)
130     {
131         reprotectRegion(start, size, Writable);
132     }
133
134     static void makeExecutable(void* start, size_t size)
135     {
136         reprotectRegion(start, size, Executable);
137     }
138 #else
139     static void makeWritable(void*, size_t) {}
140     static void makeExecutable(void*, size_t) {}
141 #endif
142
143
144 #if CPU(X86) || CPU(X86_64)
145     static void cacheFlush(void*, size_t)
146     {
147     }
148 #elif CPU(MIPS)
149     static void cacheFlush(void* code, size_t size)
150     {
151 #if GCC_VERSION_AT_LEAST(4, 3, 0)
152 #if WTF_MIPS_ISA_REV(2) && !GCC_VERSION_AT_LEAST(4, 4, 3)
153         int lineSize;
154         asm("rdhwr %0, $1" : "=r" (lineSize));
155         //
156         // Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in
157         // mips_expand_synci_loop that may execute synci one more time.
158         // "start" points to the fisrt byte of the cache line.
159         // "end" points to the last byte of the line before the last cache line.
160         // Because size is always a multiple of 4, this is safe to set
161         // "end" to the last byte.
162         //
163         intptr_t start = reinterpret_cast<intptr_t>(code) & (-lineSize);
164         intptr_t end = ((reinterpret_cast<intptr_t>(code) + size - 1) & (-lineSize)) - 1;
165         __builtin___clear_cache(reinterpret_cast<char*>(start), reinterpret_cast<char*>(end));
166 #else
167         intptr_t end = reinterpret_cast<intptr_t>(code) + size;
168         __builtin___clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end));
169 #endif
170 #else
171         _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
172 #endif
173     }
174 #elif CPU(ARM_THUMB2) && OS(IOS)
175     static void cacheFlush(void* code, size_t size)
176     {
177         sys_cache_control(kCacheFunctionPrepareForExecution, code, size);
178     }
179 #elif CPU(ARM_THUMB2) && OS(LINUX)
180     static void cacheFlush(void* code, size_t size)
181     {
182         asm volatile (
183             "push    {r7}\n"
184             "mov     r0, %0\n"
185             "mov     r1, %1\n"
186             "movw    r7, #0x2\n"
187             "movt    r7, #0xf\n"
188             "movs    r2, #0x0\n"
189             "svc     0x0\n"
190             "pop     {r7}\n"
191             :
192             : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
193             : "r0", "r1", "r2");
194     }
195 #elif OS(SYMBIAN)
196     static void cacheFlush(void* code, size_t size)
197     {
198         User::IMB_Range(code, static_cast<char*>(code) + size);
199     }
200 #elif CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT)
201     static __asm void cacheFlush(void* code, size_t size);
202 #elif CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(GCC)
203     static void cacheFlush(void* code, size_t size)
204     {
205         asm volatile (
206             "push    {r7}\n"
207             "mov     r0, %0\n"
208             "mov     r1, %1\n"
209             "mov     r7, #0xf0000\n"
210             "add     r7, r7, #0x2\n"
211             "mov     r2, #0x0\n"
212             "svc     0x0\n"
213             "pop     {r7}\n"
214             :
215             : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
216             : "r0", "r1", "r2");
217     }
218 #elif OS(WINCE)
219     static void cacheFlush(void* code, size_t size)
220     {
221         CacheRangeFlush(code, size, CACHE_SYNC_ALL);
222     }
223 #elif PLATFORM(BREWMP)
224     static void cacheFlush(void* code, size_t size)
225     {
226         RefPtr<IMemCache1> memCache = createRefPtrInstance<IMemCache1>(AEECLSID_MemCache1);
227         IMemCache1_ClearCache(memCache.get(), reinterpret_cast<uint32>(code), size, MEMSPACE_CACHE_FLUSH, MEMSPACE_DATACACHE);
228         IMemCache1_ClearCache(memCache.get(), reinterpret_cast<uint32>(code), size, MEMSPACE_CACHE_INVALIDATE, MEMSPACE_INSTCACHE);
229     }
230 #elif CPU(SH4) && OS(LINUX)
231     static void cacheFlush(void* code, size_t size)
232     {
233 #ifdef CACHEFLUSH_D_L2
234         syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I | CACHEFLUSH_D_L2);
235 #else
236         syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I);
237 #endif
238     }
239 #elif OS(QNX)
240     static void cacheFlush(void* code, size_t size)
241     {
242 #if !ENABLE(ASSEMBLER_WX_EXCLUSIVE)
243         msync(code, size, MS_INVALIDATE_ICACHE);
244 #else
245         UNUSED_PARAM(code);
246         UNUSED_PARAM(size);
247 #endif
248     }
249 #else
250     #error "The cacheFlush support is missing on this platform."
251 #endif
252     static size_t committedByteCount();
253
254 private:
255
256 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
257     static void reprotectRegion(void*, size_t, ProtectionSetting);
258 #endif
259 };
260
261 } // namespace JSC
262
263 #endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
264
265 #endif // !defined(ExecutableAllocator)