initial import
[vuplus_webkit] / Source / JavaScriptCore / jit / ExecutableAllocator.cpp
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 #include "config.h"
27
28 #include "ExecutableAllocator.h"
29
30 #if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
31 #include <wtf/MetaAllocator.h>
32 #include <wtf/PageReservation.h>
33 #include <wtf/VMTags.h>
34 #endif
35
36 #if ENABLE(ASSEMBLER)
37
38 using namespace WTF;
39
40 namespace JSC {
41
42 #if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
43
44 class DemandExecutableAllocator: public MetaAllocator {
45 public:
46     DemandExecutableAllocator()
47         : MetaAllocator(32) // round up all allocations to 32 bytes
48     {
49         // Don't preallocate any memory here.
50     }
51     
52     virtual ~DemandExecutableAllocator()
53     {
54         for (unsigned i = 0; i < reservations.size(); ++i)
55             reservations.at(i).deallocate();
56     }
57
58 protected:
59     virtual void* allocateNewSpace(size_t& numPages)
60     {
61         size_t newNumPages = (((numPages * pageSize() + JIT_ALLOCATOR_LARGE_ALLOC_SIZE - 1) / JIT_ALLOCATOR_LARGE_ALLOC_SIZE * JIT_ALLOCATOR_LARGE_ALLOC_SIZE) + pageSize() - 1) / pageSize();
62         
63         ASSERT(newNumPages >= numPages);
64         
65         numPages = newNumPages;
66         
67         PageReservation reservation = PageReservation::reserve(numPages * pageSize(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
68         if (!reservation)
69             CRASH();
70         
71         reservations.append(reservation);
72         
73         return reservation.base();
74     }
75     
76     virtual void notifyNeedPage(void* page)
77     {
78         OSAllocator::commit(page, pageSize(), EXECUTABLE_POOL_WRITABLE, true);
79     }
80     
81     virtual void notifyPageIsFree(void* page)
82     {
83         OSAllocator::decommit(page, pageSize());
84     }
85
86 private:
87     Vector<PageReservation, 16> reservations;
88 };
89
90 static DemandExecutableAllocator* allocator;
91
92 void ExecutableAllocator::initializeAllocator()
93 {
94     ASSERT(!allocator);
95     allocator = new DemandExecutableAllocator();
96 }
97
98 ExecutableAllocator::ExecutableAllocator(JSGlobalData&)
99 {
100     ASSERT(allocator);
101 }
102
103 bool ExecutableAllocator::isValid() const
104 {
105     return true;
106 }
107
108 bool ExecutableAllocator::underMemoryPressure()
109 {
110     return false;
111 }
112
113 PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData&, size_t sizeInBytes)
114 {
115     RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes);
116     if (!result)
117         CRASH();
118     return result.release();
119 }
120
121 size_t ExecutableAllocator::committedByteCount()
122 {
123     return allocator->bytesCommitted();
124 }
125
126 #if ENABLE(META_ALLOCATOR_PROFILE)
127 void ExecutableAllocator::dumpProfile()
128 {
129     allocator->dumpProfile();
130 }
131 #endif
132
133 #endif // ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
134
135 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
136
137 #if OS(WINDOWS) || OS(SYMBIAN)
138 #error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform."
139 #endif
140
141 void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSetting setting)
142 {
143     size_t pageSize = WTF::pageSize();
144
145     // Calculate the start of the page containing this region,
146     // and account for this extra memory within size.
147     intptr_t startPtr = reinterpret_cast<intptr_t>(start);
148     intptr_t pageStartPtr = startPtr & ~(pageSize - 1);
149     void* pageStart = reinterpret_cast<void*>(pageStartPtr);
150     size += (startPtr - pageStartPtr);
151
152     // Round size up
153     size += (pageSize - 1);
154     size &= ~(pageSize - 1);
155
156     mprotect(pageStart, size, (setting == Writable) ? PROTECTION_FLAGS_RW : PROTECTION_FLAGS_RX);
157 }
158
159 #endif
160
161 #if CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT)
162
163 __asm void ExecutableAllocator::cacheFlush(void* code, size_t size)
164 {
165     ARM
166     push {r7}
167     add r1, r1, r0
168     mov r7, #0xf0000
169     add r7, r7, #0x2
170     mov r2, #0x0
171     svc #0x0
172     pop {r7}
173     bx lr
174 }
175
176 #endif
177
178 }
179
180 #endif // HAVE(ASSEMBLER)