source: webkit/trunk/JavaScriptCore/wtf/PageAllocation.h@ 65104

Last change on this file since 65104 was 64782, checked in by [email protected], 15 years ago

Bug 43185 - Switch RegisterFile over to use PageAllocation

Reviewed by Sam Weinig.

Remove platform-specific memory allocation code.

  • interpreter/RegisterFile.cpp:

(JSC::RegisterFile::~RegisterFile):
(JSC::RegisterFile::releaseExcessCapacity):

  • interpreter/RegisterFile.h:

(JSC::RegisterFile::RegisterFile):
(JSC::RegisterFile::grow):
(JSC::RegisterFile::checkAllocatedOkay):

  • wtf/PageAllocation.cpp:

(WTF::PageAllocation::lastError):

  • wtf/PageAllocation.h:

(WTF::PageAllocation::allocate):
(WTF::PageAllocation::allocateAt):
(WTF::PageAllocation::allocateAligned):
(WTF::PageAllocation::pageSize):
(WTF::PageAllocation::isPageAligned):
(WTF::PageAllocation::isPowerOfTwo):

  • wtf/PageReservation.h:

(WTF::PageReservation::commit):
(WTF::PageReservation::decommit):
(WTF::PageReservation::reserve):
(WTF::PageReservation::reserveAt):

File size: 10.2 KB
Line 
1/*
2 * Copyright (C) 2010 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 PageAllocation_h
27#define PageAllocation_h
28
29#include <wtf/Assertions.h>
30#include <wtf/UnusedParam.h>
31#include <wtf/VMTags.h>
32
33#if OS(DARWIN)
34#include <mach/mach_init.h>
35#include <mach/vm_map.h>
36#endif
37
38#if OS(HAIKU)
39#include <OS.h>
40#endif
41
42#if OS(WINDOWS)
43#include <malloc.h>
44#include <windows.h>
45#endif
46
47#if OS(SYMBIAN)
48#include <e32hal.h>
49#include <e32std.h>
50#endif
51
52#if HAVE(ERRNO_H)
53#include <errno.h>
54#endif
55
56#if HAVE(MMAP)
57#include <sys/mman.h>
58#include <unistd.h>
59#endif
60
61namespace WTF {
62
63/*
64 PageAllocation
65
66 The PageAllocation class provides a cross-platform memory allocation interface
67 with similar capabilities to posix mmap/munmap. Memory is allocated by calling
68 PageAllocation::allocate, and deallocated by calling deallocate on the
69 PageAllocation object. The PageAllocation holds the allocation's base pointer
70 and size.
71
72 The allocate method is passed the size required (which must be a multiple of
73 the system page size, which can be accessed using PageAllocation::pageSize).
74 Callers may also optinally provide a flag indicating the usage (for use by
75 system memory usage tracking tools, where implemented), and boolean values
76 specifying the required protection (defaulting to writable, non-executable).
77
78 Where HAVE(PAGE_ALLOCATE_AT) and HAVE(PAGE_ALLOCATE_ALIGNED) are available
79 memory may also be allocated at a specified address, or with a specified
80 alignment respectively. PageAllocation::allocateAt take an address to try
81 to allocate at, and a boolean indicating whether this behaviour is strictly
82 required (if this address is unavailable, should memory at another address
83 be allocated instead). PageAllocation::allocateAligned requires that the
84 size is a power of two that is >= system page size.
85*/
86class PageAllocation {
87public:
88 enum Usage {
89 UnknownUsage = -1,
90 FastMallocPages = VM_TAG_FOR_TCMALLOC_MEMORY,
91 JSGCHeapPages = VM_TAG_FOR_COLLECTOR_MEMORY,
92 JSVMStackPages = VM_TAG_FOR_REGISTERFILE_MEMORY,
93 JSJITCodePages = VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY,
94 };
95
96 PageAllocation()
97 : m_base(0)
98 , m_size(0)
99#if OS(SYMBIAN)
100 , m_chunk(0)
101#endif
102 {
103 }
104
105 bool operator!() const { return !m_base; }
106 void* base() const { return m_base; }
107 size_t size() const { return m_size; }
108
109 static PageAllocation allocate(size_t size, Usage usage = UnknownUsage, bool writable = true, bool executable = false)
110 {
111 ASSERT(isPageAligned(size));
112 return systemAllocate(size, usage, writable, executable);
113 }
114
115#if HAVE(PAGE_ALLOCATE_AT)
116 static PageAllocation allocateAt(void* address, bool fixed, size_t size, Usage usage = UnknownUsage, bool writable = true, bool executable = false)
117 {
118 ASSERT(isPageAligned(address));
119 ASSERT(isPageAligned(size));
120 return systemAllocateAt(address, fixed, size, usage, writable, executable);
121 }
122#endif
123
124#if HAVE(PAGE_ALLOCATE_ALIGNED)
125 static PageAllocation allocateAligned(size_t size, Usage usage = UnknownUsage)
126 {
127 ASSERT(isPageAligned(size));
128 ASSERT(isPowerOfTwo(size));
129 return systemAllocateAligned(size, usage);
130 }
131#endif
132
133 void deallocate()
134 {
135 ASSERT(m_base);
136 systemDeallocate(true);
137 }
138
139 static size_t pageSize()
140 {
141 if (!s_pageSize)
142 s_pageSize = systemPageSize();
143 ASSERT(isPowerOfTwo(s_pageSize));
144 return s_pageSize;
145 }
146
147#ifndef NDEBUG
148 static bool isPageAligned(void* address) { return !(reinterpret_cast<intptr_t>(address) & (pageSize() - 1)); }
149 static bool isPageAligned(size_t size) { return !(size & (pageSize() - 1)); }
150 static bool isPowerOfTwo(size_t size) { return !(size & (size - 1)); }
151 static int lastError();
152#endif
153
154protected:
155#if OS(SYMBIAN)
156 PageAllocation(void* base, size_t size, RChunk* chunk)
157 : m_base(base)
158 , m_size(size)
159 , m_chunk(chunk)
160 {
161 }
162#else
163 PageAllocation(void* base, size_t size)
164 : m_base(base)
165 , m_size(size)
166 {
167 }
168#endif
169
170 static PageAllocation systemAllocate(size_t, Usage, bool, bool);
171#if HAVE(PAGE_ALLOCATE_AT)
172 static PageAllocation systemAllocateAt(void*, bool, size_t, Usage, bool, bool);
173#endif
174#if HAVE(PAGE_ALLOCATE_ALIGNED)
175 static PageAllocation systemAllocateAligned(size_t, Usage);
176#endif
177 // systemDeallocate takes a parameter indicating whether memory is currently committed
178 // (this should always be true for PageAllocation, false for PageReservation).
179 void systemDeallocate(bool committed);
180 static size_t systemPageSize();
181
182 void* m_base;
183 size_t m_size;
184#if OS(SYMBIAN)
185 RChunk* m_chunk;
186#endif
187
188 static JS_EXPORTDATA size_t s_pageSize;
189};
190
191
192#if HAVE(MMAP)
193
194
195inline PageAllocation PageAllocation::systemAllocate(size_t size, Usage usage, bool writable, bool executable)
196{
197 return systemAllocateAt(0, false, size, usage, writable, executable);
198}
199
200inline PageAllocation PageAllocation::systemAllocateAt(void* address, bool fixed, size_t size, Usage usage, bool writable, bool executable)
201{
202 int protection = PROT_READ;
203 if (writable)
204 protection |= PROT_WRITE;
205 if (executable)
206 protection |= PROT_EXEC;
207
208 int flags = MAP_PRIVATE | MAP_ANON;
209 if (fixed)
210 flags |= MAP_FIXED;
211
212#if OS(DARWIN) && !defined(BUILDING_ON_TIGER)
213 int fd = usage;
214#else
215 int fd = -1;
216#endif
217
218 void* base = mmap(address, size, protection, flags, fd, 0);
219 if (base == MAP_FAILED)
220 base = 0;
221 return PageAllocation(base, size);
222}
223
224inline PageAllocation PageAllocation::systemAllocateAligned(size_t size, Usage usage)
225{
226#if OS(DARWIN)
227 vm_address_t address = 0;
228 int flags = VM_FLAGS_ANYWHERE;
229 if (usage != -1)
230 flags |= usage;
231 vm_map(current_task(), &address, size, (size - 1), flags, MEMORY_OBJECT_NULL, 0, FALSE, PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE | PROT_EXEC, VM_INHERIT_DEFAULT);
232 return PageAllocation(reinterpret_cast<void*>(address), size);
233#elif HAVE(POSIX_MEMALIGN)
234 void* address;
235 posix_memalign(&address, size, size);
236 return PageAllocation(address, size);
237#else
238 size_t extra = size - pageSize();
239
240 // Check for overflow.
241 if ((size + extra) < size)
242 return PageAllocation(0, size);
243
244#if OS(DARWIN) && !defined(BUILDING_ON_TIGER)
245 int fd = usage;
246#else
247 int fd = -1;
248#endif
249 void* mmapResult = mmap(0, size + extra, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, fd, 0);
250 if (mmapResult == MAP_FAILED)
251 return PageAllocation(0, size);
252 uintptr_t address = reinterpret_cast<uintptr_t>(mmapResult);
253
254 size_t adjust = 0;
255 if ((address & (size - 1)))
256 adjust = size - (address & (size - 1));
257 if (adjust > 0)
258 munmap(reinterpret_cast<char*>(address), adjust);
259 if (adjust < extra)
260 munmap(reinterpret_cast<char*>(address + adjust + size), extra - adjust);
261 address += adjust;
262
263 return PageAllocation(reinterpret_cast<void*>(address), size);
264#endif
265}
266
267inline void PageAllocation::systemDeallocate(bool)
268{
269 int result = munmap(m_base, m_size);
270 ASSERT_UNUSED(result, !result);
271 m_base = 0;
272}
273
274inline size_t PageAllocation::systemPageSize()
275{
276 return getpagesize();
277}
278
279
280#elif HAVE(VIRTUALALLOC)
281
282
283inline PageAllocation PageAllocation::systemAllocate(size_t size, Usage, bool writable, bool executable)
284{
285 DWORD protection = executable ?
286 (writable ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ) :
287 (writable ? PAGE_READWRITE : PAGE_READONLY);
288 return PageAllocation(VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, protection), size);
289}
290
291#if HAVE(ALIGNED_MALLOC)
292inline PageAllocation PageAllocation::systemAllocateAligned(size_t size, Usage usage)
293{
294#if COMPILER(MINGW) && !COMPILER(MINGW64)
295 void* address = __mingw_aligned_malloc(size, size);
296#else
297 void* address = _aligned_malloc(size, size);
298#endif
299 memset(address, 0, size);
300 return PageAllocation(address, size);
301}
302#endif
303
304inline void PageAllocation::systemDeallocate(bool committed)
305{
306#if OS(WINCE)
307 if (committed)
308 VirtualFree(m_base, m_size, MEM_DECOMMIT);
309#else
310 UNUSED_PARAM(committed);
311#endif
312 VirtualFree(m_base, 0, MEM_RELEASE);
313 m_base = 0;
314}
315
316inline size_t PageAllocation::systemPageSize()
317{
318 static size_t size = 0;
319 SYSTEM_INFO system_info;
320 GetSystemInfo(&system_info);
321 size = system_info.dwPageSize;
322 return size;
323}
324
325
326#elif OS(SYMBIAN)
327
328
329inline PageAllocation PageAllocation::systemAllocate(size_t size, Usage usage, bool writable, bool executable)
330{
331 RChunk* rchunk = new RChunk();
332 if (executable)
333 rchunk->CreateLocalCode(size, size);
334 else
335 rchunk->CreateLocal(size, size);
336 return PageAllocation(rchunk->Base(), size, rchunk);
337}
338
339inline void PageAllocation::systemDeallocate(bool)
340{
341 m_chunk->Close();
342 delete m_chunk;
343 m_base = 0;
344}
345
346inline size_t PageAllocation::systemPageSize()
347{
348 static TInt page_size = 0;
349 UserHal::PageSizeInBytes(page_size);
350 return page_size;
351}
352
353
354#endif
355
356
357}
358
359using WTF::PageAllocation;
360
361#endif // PageAllocation_h
Note: See TracBrowser for help on using the repository browser.