2 * Copyright (C) 2008 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 ExecutableAllocator_h
27 #define ExecutableAllocator_h
28 #include <stddef.h> // for ptrdiff_t
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>
39 #include <libkern/OSCacheControl.h>
42 #if OS(IOS) || OS(QNX)
50 #if CPU(MIPS) && OS(LINUX)
51 #include <sys/cachectl.h>
54 #if CPU(SH4) && OS(LINUX)
55 #include <asm/cachectl.h>
56 #include <asm/unistd.h>
57 #include <sys/syscall.h>
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);
68 #include <AEEIMemCache1.h>
69 #include <AEEMemCache1.bid>
70 #include <wtf/brew/RefPtrBrew.h>
73 #define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (pageSize() * 4)
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
80 #define EXECUTABLE_POOL_WRITABLE true
86 void releaseExecutableMemory(JSGlobalData&);
88 inline size_t roundUpAllocationSize(size_t request, size_t granularity)
90 if ((std::numeric_limits<size_t>::max() - granularity) <= request)
91 CRASH(); // Allocation is too large
93 // Round up to next page boundary
94 size_t size = request + (granularity - 1);
95 size = size & ~(granularity - 1);
96 ASSERT(size >= request);
102 #if ENABLE(JIT) && ENABLE(ASSEMBLER)
106 typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle;
108 class ExecutableAllocator {
109 enum ProtectionSetting { Writable, Executable };
112 ExecutableAllocator(JSGlobalData&);
114 static void initializeAllocator();
116 bool isValid() const;
118 static bool underMemoryPressure();
120 #if ENABLE(META_ALLOCATOR_PROFILE)
121 static void dumpProfile();
123 static void dumpProfile() { }
126 PassRefPtr<ExecutableMemoryHandle> allocate(JSGlobalData&, size_t sizeInBytes);
128 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
129 static void makeWritable(void* start, size_t size)
131 reprotectRegion(start, size, Writable);
134 static void makeExecutable(void* start, size_t size)
136 reprotectRegion(start, size, Executable);
139 static void makeWritable(void*, size_t) {}
140 static void makeExecutable(void*, size_t) {}
144 #if CPU(X86) || CPU(X86_64)
145 static void cacheFlush(void*, size_t)
149 static void cacheFlush(void* code, size_t size)
151 #if GCC_VERSION_AT_LEAST(4, 3, 0)
152 #if WTF_MIPS_ISA_REV(2) && !GCC_VERSION_AT_LEAST(4, 4, 3)
154 asm("rdhwr %0, $1" : "=r" (lineSize));
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.
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));
167 intptr_t end = reinterpret_cast<intptr_t>(code) + size;
168 __builtin___clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end));
171 _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
174 #elif CPU(ARM_THUMB2) && OS(IOS)
175 static void cacheFlush(void* code, size_t size)
177 sys_cache_control(kCacheFunctionPrepareForExecution, code, size);
179 #elif CPU(ARM_THUMB2) && OS(LINUX)
180 static void cacheFlush(void* code, size_t size)
192 : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
196 static void cacheFlush(void* code, size_t size)
198 User::IMB_Range(code, static_cast<char*>(code) + size);
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)
215 : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
219 static void cacheFlush(void* code, size_t size)
221 CacheRangeFlush(code, size, CACHE_SYNC_ALL);
223 #elif PLATFORM(BREWMP)
224 static void cacheFlush(void* code, size_t size)
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);
230 #elif CPU(SH4) && OS(LINUX)
231 static void cacheFlush(void* code, size_t size)
233 #ifdef CACHEFLUSH_D_L2
234 syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I | CACHEFLUSH_D_L2);
236 syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I);
240 static void cacheFlush(void* code, size_t size)
242 #if !ENABLE(ASSEMBLER_WX_EXCLUSIVE)
243 msync(code, size, MS_INVALIDATE_ICACHE);
250 #error "The cacheFlush support is missing on this platform."
252 static size_t committedByteCount();
256 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
257 static void reprotectRegion(void*, size_t, ProtectionSetting);
263 #endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
265 #endif // !defined(ExecutableAllocator)