]> git.saurik.com Git - apple/javascriptcore.git/blame - jit/ExecutableAllocatorFixedVMPool.cpp
JavaScriptCore-1097.3.tar.gz
[apple/javascriptcore.git] / jit / ExecutableAllocatorFixedVMPool.cpp
CommitLineData
ba379fdc
A
1/*
2 * Copyright (C) 2009 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
4e4e5a6f 30#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
ba379fdc 31
6fe7ccc8 32#include "CodeProfiling.h"
4e4e5a6f 33#include <errno.h>
ba379fdc
A
34#include <sys/mman.h>
35#include <unistd.h>
6fe7ccc8 36#include <wtf/MetaAllocator.h>
14957cd0 37#include <wtf/PageReservation.h>
ba379fdc
A
38#include <wtf/VMTags.h>
39
14957cd0
A
40#if OS(LINUX)
41#include <stdio.h>
42#endif
43
4e4e5a6f
A
44 #define MMAP_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_JIT)
45
ba379fdc
A
46using namespace WTF;
47
48namespace JSC {
14957cd0 49
6fe7ccc8
A
50#if CPU(ARM)
51static const size_t fixedPoolSize = 16 * 1024 * 1024;
52#elif CPU(X86_64)
53static const size_t fixedPoolSize = 1024 * 1024 * 1024;
54#else
55static const size_t fixedPoolSize = 32 * 1024 * 1024;
ba379fdc
A
56#endif
57
6fe7ccc8 58class FixedVMPoolExecutableAllocator : public MetaAllocator {
b80e6193 59public:
6fe7ccc8
A
60 FixedVMPoolExecutableAllocator()
61 : MetaAllocator(32) // round up all allocations to 32 bytes
b80e6193 62 {
6fe7ccc8
A
63 m_reservation = PageReservation::reserveWithGuardPages(fixedPoolSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
64#if !(ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
65 if (!m_reservation)
66 CRASH();
67#endif
68 if (m_reservation) {
69 ASSERT(m_reservation.size() == fixedPoolSize);
70 addFreshFreeSpace(m_reservation.base(), m_reservation.size());
ba379fdc 71 }
b80e6193 72 }
6fe7ccc8
A
73
74protected:
75 virtual void* allocateNewSpace(size_t&)
b80e6193 76 {
6fe7ccc8
A
77 // We're operating in a fixed pool, so new allocation is always prohibited.
78 return 0;
b80e6193 79 }
6fe7ccc8
A
80
81 virtual void notifyNeedPage(void* page)
b80e6193 82 {
6fe7ccc8
A
83#if OS(DARWIN)
84 UNUSED_PARAM(page);
85#else
86 m_reservation.commit(page, pageSize());
b80e6193 87#endif
b80e6193 88 }
6fe7ccc8
A
89
90 virtual void notifyPageIsFree(void* page)
91 {
92#if OS(DARWIN)
93 for (;;) {
94 int result = madvise(page, pageSize(), MADV_FREE);
95 if (!result)
96 return;
97 ASSERT(result == -1);
98 if (errno != EAGAIN) {
99 ASSERT_NOT_REACHED(); // In debug mode, this should be a hard failure.
100 break; // In release mode, we should just ignore the error - not returning memory to the OS is better than crashing, especially since we _will_ be able to reuse the memory internally anyway.
ba379fdc 101 }
b80e6193 102 }
b80e6193 103#else
6fe7ccc8 104 m_reservation.decommit(page, pageSize());
4e4e5a6f 105#endif
ba379fdc 106 }
b80e6193 107
14957cd0 108private:
14957cd0 109 PageReservation m_reservation;
ba379fdc
A
110};
111
6fe7ccc8 112static FixedVMPoolExecutableAllocator* allocator;
14957cd0 113
6fe7ccc8
A
114void ExecutableAllocator::initializeAllocator()
115{
116 ASSERT(!allocator);
117 allocator = new FixedVMPoolExecutableAllocator();
118 CodeProfiling::notifyAllocator(allocator);
119}
14957cd0 120
6fe7ccc8 121ExecutableAllocator::ExecutableAllocator(JSGlobalData&)
14957cd0 122{
6fe7ccc8
A
123 ASSERT(allocator);
124}
14957cd0 125
6fe7ccc8 126ExecutableAllocator::~ExecutableAllocator()
ba379fdc 127{
ba379fdc
A
128}
129
4e4e5a6f
A
130bool ExecutableAllocator::isValid() const
131{
6fe7ccc8 132 return !!allocator->bytesReserved();
4e4e5a6f
A
133}
134
14957cd0 135bool ExecutableAllocator::underMemoryPressure()
ba379fdc 136{
6fe7ccc8
A
137 MetaAllocator::Statistics statistics = allocator->currentStatistics();
138 return statistics.bytesAllocated > statistics.bytesReserved / 2;
ba379fdc
A
139}
140
6fe7ccc8 141double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage)
ba379fdc 142{
6fe7ccc8
A
143 MetaAllocator::Statistics statistics = allocator->currentStatistics();
144 ASSERT(statistics.bytesAllocated <= statistics.bytesReserved);
145 size_t bytesAllocated = statistics.bytesAllocated + addedMemoryUsage;
146 if (bytesAllocated >= statistics.bytesReserved)
147 bytesAllocated = statistics.bytesReserved;
148 double result = 1.0;
149 size_t divisor = statistics.bytesReserved - bytesAllocated;
150 if (divisor)
151 result = static_cast<double>(statistics.bytesReserved) / divisor;
152 if (result < 1.0)
153 result = 1.0;
154 return result;
b80e6193
A
155}
156
6fe7ccc8 157PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData& globalData, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort)
b80e6193 158{
6fe7ccc8
A
159 RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes, ownerUID);
160 if (!result) {
161 if (effort == JITCompilationCanFail)
162 return result;
163 releaseExecutableMemory(globalData);
164 result = allocator->allocate(sizeInBytes, ownerUID);
165 if (!result)
166 CRASH();
167 }
168 return result.release();
ba379fdc
A
169}
170
6fe7ccc8
A
171size_t ExecutableAllocator::committedByteCount()
172{
173 return allocator->bytesCommitted();
174}
175
176#if ENABLE(META_ALLOCATOR_PROFILE)
177void ExecutableAllocator::dumpProfile()
178{
179 allocator->dumpProfile();
180}
181#endif
182
ba379fdc
A
183}
184
14957cd0 185
6fe7ccc8 186#endif // ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
14957cd0 187
6fe7ccc8 188#if !ENABLE(ASSEMBLER)
14957cd0
A
189// FIXME: Needed to satisfy JavaScriptCore.exp requirements when building only the interpreter.
190namespace JSC {
191size_t ExecutableAllocator::committedByteCount()
192{
193 return 0;
194}
195} // namespace JSC
196#endif // !ENABLE(JIT)