7680380c2572bc16ac7a5d4e3eba8c358c90b374
[WebKit-https.git] / JavaScriptCore / wtf / PageAllocation.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "PageAllocation.h"
29
30 #if HAVE(ERRNO_H)
31 #include <errno.h>
32 #endif
33
34 #if HAVE(MMAP)
35 #include <sys/mman.h>
36 #endif
37
38 #if OS(WINDOWS)
39 #include "windows.h"
40 #endif
41
42 #if OS(SYMBIAN)
43 #include <e32hal.h>
44 #endif
45
46 namespace WTF {
47
48 #if HAVE(MMAP)
49
50 #if HAVE(MADV_FREE_REUSE)
51 bool PageAllocation::commit(void* start, size_t size, bool writable, bool executable) const
52 {
53     UNUSED_PARAM(writable);
54     UNUSED_PARAM(executable);
55     while (madvise(start, size, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
56     return true;
57 }
58
59 void PageAllocation::decommit(void* start, size_t size) const
60 {
61     while (madvise(start, size, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
62 }
63 #elif HAVE(MADV_DONTNEED)
64 bool PageAllocation::commit(void* start, size_t size, bool writable, bool executable) const
65 {
66     UNUSED_PARAM(writable);
67     UNUSED_PARAM(executable);
68     return true;
69 }
70
71 void PageAllocation::decommit(void*, size_t) const
72 {
73     while (madvise(start, size, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
74 }
75 #else
76 bool PageAllocation::commit(void*, size_t, bool writable, bool executable) const
77 {
78     UNUSED_PARAM(writable);
79     UNUSED_PARAM(executable);
80     return true;
81 }
82
83 void PageAllocation::decommit(void*, size_t) const
84 {
85 }
86 #endif
87
88 PageAllocation PageAllocation::allocate(size_t size, Usage usage, bool writable, bool executable)
89 {
90     return allocateAt(0, false, size, usage, writable, executable);
91 }
92
93 PageAllocation PageAllocation::reserve(size_t size, Usage usage, bool writable, bool executable)
94 {
95     return reserveAt(0, false, size, usage, writable, executable);
96 }
97
98 PageAllocation PageAllocation::allocateAt(void* address, bool fixed, size_t size, Usage usage, bool writable, bool executable)
99 {
100     int flags = MAP_PRIVATE | MAP_ANON;
101     if (fixed)
102         flags |= MAP_FIXED;
103
104     int protection = PROT_READ;
105     if (writable)
106         protection |= PROT_WRITE;
107     if (executable)
108         protection |= PROT_EXEC;
109
110     void* base = mmap(address, size, protection, flags, usage, 0);
111     if (base == MAP_FAILED)
112         base = 0;
113
114     return PageAllocation(base, size);
115 }
116
117 PageAllocation PageAllocation::reserveAt(void* address, bool fixed, size_t size, Usage usage, bool writable, bool executable)
118 {
119     PageAllocation result = allocateAt(address, fixed, size, usage, writable, executable);
120     if (!!result)
121         result.decommit(result.base(), size);
122     return result;
123 }
124
125 void PageAllocation::deallocate()
126 {
127     int result = munmap(m_base, m_size);
128     ASSERT_UNUSED(result, !result);
129 }
130
131 size_t PageAllocation::pagesize()
132 {
133     static size_t size = 0;
134     if (!size)
135         size = getpagesize();
136     return size;
137 }
138
139 #elif HAVE(VIRTUALALLOC)
140
141 static DWORD protection(bool writable, bool executable)
142 {
143     if (executable)
144         return writable ?PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
145     return writable ?PAGE_READWRITE : PAGE_READONLY;
146 }
147
148 bool PageAllocation::commit(void* start, size_t size, bool writable, bool executable) const
149 {
150     return VirtualAlloc(start, size, MEM_COMMIT, protection(writable, executable)) == start;
151 }
152
153 void PageAllocation::decommit(void* start, size_t size) const
154 {
155     VirtualFree(start, size, MEM_DECOMMIT);
156 }
157
158 PageAllocation PageAllocation::allocate(size_t size, Usage, bool writable, bool executable)
159 {
160     return PageAllocation(VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, protection(writable, executable)), size);
161 }
162
163 PageAllocation PageAllocation::reserve(size_t size, Usage usage, bool writable, bool executable)
164 {
165     return PageAllocation(VirtualAlloc(0, size, MEM_RESERVE, protection(writable, executable)), size);
166 }
167
168 void PageAllocation::deallocate()
169 {
170     VirtualFree(m_base, 0, MEM_RELEASE); 
171 }
172
173 size_t PageAllocation::pagesize()
174 {
175     static size_t size = 0;
176     if (!size) {
177         SYSTEM_INFO system_info;
178         GetSystemInfo(&system_info);
179         size = system_info.dwPageSize;
180     }
181     return size;
182 }
183
184 #elif OS(SYMBIAN)
185
186 bool PageAllocation::commit(void* start, size_t size, bool writable, bool executable) const
187 {
188     if (m_chunk) {
189         intptr_t offset = static_cast<intptr_t>(base()) - static_cast<intptr_t>(start);
190         m_chunk->Commit(offset, size);
191     }
192     return true;
193 }
194
195 void PageAllocation::decommit(void* start, size_t size) const
196 {
197     if (m_chunk) {
198         intptr_t offset = static_cast<intptr_t>(base()) - static_cast<intptr_t>(start);
199         m_chunk->Decommit(offset, size);
200     }
201 }
202
203 PageAllocation PageAllocation::allocate(size_t size, Usage usage, bool writable, bool executable)
204 {
205     if (!executable)
206         return PageAllocation(fastMalloc(size), size, 0);
207     RChunk* rchunk = new RChunk();
208     TInt errorCode = rchunk->CreateLocalCode(size, size);
209     return PageAllocation(rchunk->Base(), size, rchunk);
210 }
211
212 PageAllocation PageAllocation::reserve(size_t size, Usage usage, bool writable, bool executable)
213 {
214     if (!executable)
215         return PageAllocation(fastMalloc(size), size, 0);
216     RChunk* rchunk = new RChunk();
217     TInt errorCode = rchunk->CreateLocalCode(0, size);
218     return PageAllocation(rchunk, rchunk->Base(), size);
219 }
220
221 void PageAllocation::deallocate()
222 {
223     if (m_chunk) {
224         m_chunk->Close();
225         delete m_chunk;
226     } else
227         fastFree(m_base);
228 }
229
230 size_t PageAllocation::pagesize()
231 {
232     static TInt page_size = 0;
233     if (!page_size)
234         UserHal::PageSizeInBytes(page_size);
235     return page_size;
236 }
237
238 #endif
239
240 }