2 * Copyright (C) 2009 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.
28 #include "ExecutableAllocator.h"
30 #if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
32 #include "CodeProfiling.h"
36 #include <wtf/MetaAllocator.h>
37 #include <wtf/PageReservation.h>
38 #include <wtf/VMTags.h>
44 #define MMAP_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_JIT)
51 static const size_t fixedPoolSize
= 16 * 1024 * 1024;
53 static const size_t fixedPoolSize
= 1024 * 1024 * 1024;
55 static const size_t fixedPoolSize
= 32 * 1024 * 1024;
58 class FixedVMPoolExecutableAllocator
: public MetaAllocator
{
60 FixedVMPoolExecutableAllocator()
61 : MetaAllocator(32) // round up all allocations to 32 bytes
63 m_reservation
= PageReservation::reserveWithGuardPages(fixedPoolSize
, OSAllocator::JSJITCodePages
, EXECUTABLE_POOL_WRITABLE
, true);
64 #if !(ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
69 ASSERT(m_reservation
.size() == fixedPoolSize
);
70 addFreshFreeSpace(m_reservation
.base(), m_reservation
.size());
75 virtual void* allocateNewSpace(size_t&)
77 // We're operating in a fixed pool, so new allocation is always prohibited.
81 virtual void notifyNeedPage(void* page
)
86 m_reservation
.commit(page
, pageSize());
90 virtual void notifyPageIsFree(void* page
)
94 int result
= madvise(page
, pageSize(), MADV_FREE
);
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.
104 m_reservation
.decommit(page
, pageSize());
109 PageReservation m_reservation
;
112 static FixedVMPoolExecutableAllocator
* allocator
;
114 void ExecutableAllocator::initializeAllocator()
117 allocator
= new FixedVMPoolExecutableAllocator();
118 CodeProfiling::notifyAllocator(allocator
);
121 ExecutableAllocator::ExecutableAllocator(JSGlobalData
&)
126 ExecutableAllocator::~ExecutableAllocator()
130 bool ExecutableAllocator::isValid() const
132 return !!allocator
->bytesReserved();
135 bool ExecutableAllocator::underMemoryPressure()
137 MetaAllocator::Statistics statistics
= allocator
->currentStatistics();
138 return statistics
.bytesAllocated
> statistics
.bytesReserved
/ 2;
141 double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage
)
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
;
149 size_t divisor
= statistics
.bytesReserved
- bytesAllocated
;
151 result
= static_cast<double>(statistics
.bytesReserved
) / divisor
;
157 PassRefPtr
<ExecutableMemoryHandle
> ExecutableAllocator::allocate(JSGlobalData
& globalData
, size_t sizeInBytes
, void* ownerUID
, JITCompilationEffort effort
)
159 RefPtr
<ExecutableMemoryHandle
> result
= allocator
->allocate(sizeInBytes
, ownerUID
);
161 if (effort
== JITCompilationCanFail
)
163 releaseExecutableMemory(globalData
);
164 result
= allocator
->allocate(sizeInBytes
, ownerUID
);
168 return result
.release();
171 size_t ExecutableAllocator::committedByteCount()
173 return allocator
->bytesCommitted();
176 #if ENABLE(META_ALLOCATOR_PROFILE)
177 void ExecutableAllocator::dumpProfile()
179 allocator
->dumpProfile();
186 #endif // ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
188 #if !ENABLE(ASSEMBLER)
189 // FIXME: Needed to satisfy JavaScriptCore.exp requirements when building only the interpreter.
191 size_t ExecutableAllocator::committedByteCount()
196 #endif // !ENABLE(JIT)