fpizlo@apple.com | b426f86 | 2014-02-10 02:51:13 +0000 | [diff] [blame] | 1 | /* |
fpizlo@apple.com | aeddff9 | 2016-07-18 21:33:45 +0000 | [diff] [blame^] | 2 | * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved. |
fpizlo@apple.com | b426f86 | 2014-02-10 02:51:13 +0000 | [diff] [blame] | 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 | |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 26 | #include "config.h" |
| 27 | #include "MarkedAllocator.h" |
| 28 | |
mhahnenberg@apple.com | 2b64eec0 | 2012-04-18 16:18:32 +0000 | [diff] [blame] | 29 | #include "GCActivityCallback.h" |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 30 | #include "Heap.h" |
mhahnenberg@apple.com | 59c64f1 | 2012-07-31 23:05:12 +0000 | [diff] [blame] | 31 | #include "IncrementalSweeper.h" |
fpizlo@apple.com | fb7eff2 | 2014-02-11 01:45:50 +0000 | [diff] [blame] | 32 | #include "JSCInlines.h" |
ggaren@apple.com | 9a9a4b5 | 2013-04-18 19:32:17 +0000 | [diff] [blame] | 33 | #include "VM.h" |
mhahnenberg@apple.com | 2e132e4 | 2012-05-03 00:14:05 +0000 | [diff] [blame] | 34 | #include <wtf/CurrentTime.h> |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 35 | |
| 36 | namespace JSC { |
| 37 | |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 38 | static bool isListPagedOut(double deadline, DoublyLinkedList<MarkedBlock>& list) |
mhahnenberg@apple.com | 2e132e4 | 2012-05-03 00:14:05 +0000 | [diff] [blame] | 39 | { |
| 40 | unsigned itersSinceLastTimeCheck = 0; |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 41 | MarkedBlock* block = list.head(); |
mhahnenberg@apple.com | 2e132e4 | 2012-05-03 00:14:05 +0000 | [diff] [blame] | 42 | while (block) { |
| 43 | block = block->next(); |
| 44 | ++itersSinceLastTimeCheck; |
| 45 | if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) { |
| 46 | double currentTime = WTF::monotonicallyIncreasingTime(); |
| 47 | if (currentTime > deadline) |
| 48 | return true; |
| 49 | itersSinceLastTimeCheck = 0; |
| 50 | } |
| 51 | } |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 52 | return false; |
| 53 | } |
mhahnenberg@apple.com | 2e132e4 | 2012-05-03 00:14:05 +0000 | [diff] [blame] | 54 | |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 55 | bool MarkedAllocator::isPagedOut(double deadline) |
| 56 | { |
| 57 | if (isListPagedOut(deadline, m_blockList)) |
| 58 | return true; |
mhahnenberg@apple.com | 2e132e4 | 2012-05-03 00:14:05 +0000 | [diff] [blame] | 59 | return false; |
| 60 | } |
| 61 | |
ggaren@apple.com | 7535d92 | 2016-06-21 23:06:08 +0000 | [diff] [blame] | 62 | void MarkedAllocator::retire(MarkedBlock* block, MarkedBlock::FreeList& freeList) |
| 63 | { |
| 64 | m_blockList.remove(block); |
| 65 | m_retiredBlocks.push(block); |
| 66 | block->didRetireBlock(freeList); |
| 67 | } |
| 68 | |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 69 | inline void* MarkedAllocator::tryAllocateHelper(size_t bytes) |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 70 | { |
msaboff@apple.com | 84946d4 | 2015-02-06 01:12:00 +0000 | [diff] [blame] | 71 | if (m_currentBlock) { |
| 72 | ASSERT(m_currentBlock == m_nextBlockToSweep); |
| 73 | m_currentBlock->didConsumeFreeList(); |
| 74 | m_nextBlockToSweep = m_currentBlock->next(); |
| 75 | } |
mhahnenberg@apple.com | bee96a3 | 2013-09-16 19:48:48 +0000 | [diff] [blame] | 76 | |
msaboff@apple.com | 84946d4 | 2015-02-06 01:12:00 +0000 | [diff] [blame] | 77 | MarkedBlock* next; |
| 78 | for (MarkedBlock*& block = m_nextBlockToSweep; block; block = next) { |
| 79 | next = block->next(); |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 80 | |
msaboff@apple.com | 84946d4 | 2015-02-06 01:12:00 +0000 | [diff] [blame] | 81 | MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 82 | |
msaboff@apple.com | 84946d4 | 2015-02-06 01:12:00 +0000 | [diff] [blame] | 83 | double utilization = ((double)MarkedBlock::blockSize - (double)freeList.bytes) / (double)MarkedBlock::blockSize; |
| 84 | if (utilization >= Options::minMarkedBlockUtilization()) { |
| 85 | ASSERT(freeList.bytes || !freeList.head); |
ggaren@apple.com | 7535d92 | 2016-06-21 23:06:08 +0000 | [diff] [blame] | 86 | retire(block, freeList); |
msaboff@apple.com | 84946d4 | 2015-02-06 01:12:00 +0000 | [diff] [blame] | 87 | continue; |
mhahnenberg@apple.com | 7f5b959 | 2012-07-27 22:59:14 +0000 | [diff] [blame] | 88 | } |
msaboff@apple.com | 84946d4 | 2015-02-06 01:12:00 +0000 | [diff] [blame] | 89 | |
| 90 | if (bytes > block->cellSize()) { |
| 91 | block->stopAllocating(freeList); |
| 92 | continue; |
| 93 | } |
| 94 | |
| 95 | m_currentBlock = block; |
| 96 | m_freeList = freeList; |
| 97 | break; |
| 98 | } |
| 99 | |
| 100 | if (!m_freeList.head) { |
| 101 | m_currentBlock = 0; |
| 102 | return 0; |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 103 | } |
mhahnenberg@apple.com | 3f62e72 | 2013-12-19 04:30:02 +0000 | [diff] [blame] | 104 | |
| 105 | ASSERT(m_freeList.head); |
mhahnenberg@apple.com | fa811df | 2014-02-13 04:24:41 +0000 | [diff] [blame] | 106 | void* head = tryPopFreeList(bytes); |
mhahnenberg@apple.com | 8b5cfd3 | 2012-04-20 00:05:37 +0000 | [diff] [blame] | 107 | ASSERT(head); |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 108 | m_markedSpace->didAllocateInBlock(m_currentBlock); |
mhahnenberg@apple.com | 8b5cfd3 | 2012-04-20 00:05:37 +0000 | [diff] [blame] | 109 | return head; |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 110 | } |
mhahnenberg@apple.com | fa811df | 2014-02-13 04:24:41 +0000 | [diff] [blame] | 111 | |
| 112 | inline void* MarkedAllocator::tryPopFreeList(size_t bytes) |
| 113 | { |
| 114 | ASSERT(m_currentBlock); |
| 115 | if (bytes > m_currentBlock->cellSize()) |
| 116 | return 0; |
| 117 | |
| 118 | MarkedBlock::FreeCell* head = m_freeList.head; |
| 119 | m_freeList.head = head->next; |
| 120 | return head; |
| 121 | } |
| 122 | |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 123 | inline void* MarkedAllocator::tryAllocate(size_t bytes) |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 124 | { |
mhahnenberg@apple.com | 47c9c53 | 2012-06-05 20:38:21 +0000 | [diff] [blame] | 125 | ASSERT(!m_heap->isBusy()); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 126 | m_heap->m_operationInProgress = Allocation; |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 127 | void* result = tryAllocateHelper(bytes); |
mhahnenberg@apple.com | fa811df | 2014-02-13 04:24:41 +0000 | [diff] [blame] | 128 | |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 129 | m_heap->m_operationInProgress = NoOperation; |
mhahnenberg@apple.com | fa811df | 2014-02-13 04:24:41 +0000 | [diff] [blame] | 130 | ASSERT(result || !m_currentBlock); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 131 | return result; |
| 132 | } |
mark.lam@apple.com | a2a9f66 | 2014-04-24 21:12:56 +0000 | [diff] [blame] | 133 | |
| 134 | ALWAYS_INLINE void MarkedAllocator::doTestCollectionsIfNeeded() |
| 135 | { |
| 136 | if (!Options::slowPathAllocsBetweenGCs()) |
| 137 | return; |
| 138 | |
| 139 | static unsigned allocationCount = 0; |
| 140 | if (!allocationCount) { |
| 141 | if (!m_heap->isDeferred()) |
| 142 | m_heap->collectAllGarbage(); |
| 143 | ASSERT(m_heap->m_operationInProgress == NoOperation); |
| 144 | } |
| 145 | if (++allocationCount >= Options::slowPathAllocsBetweenGCs()) |
| 146 | allocationCount = 0; |
| 147 | } |
| 148 | |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 149 | void* MarkedAllocator::allocateSlowCase(size_t bytes) |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 150 | { |
andersca@apple.com | b987aae | 2013-07-26 00:13:13 +0000 | [diff] [blame] | 151 | ASSERT(m_heap->vm()->currentThreadIsHoldingAPILock()); |
mark.lam@apple.com | a2a9f66 | 2014-04-24 21:12:56 +0000 | [diff] [blame] | 152 | doTestCollectionsIfNeeded(); |
| 153 | |
mhahnenberg@apple.com | bee96a3 | 2013-09-16 19:48:48 +0000 | [diff] [blame] | 154 | ASSERT(!m_markedSpace->isIterating()); |
mhahnenberg@apple.com | 8b5cfd3 | 2012-04-20 00:05:37 +0000 | [diff] [blame] | 155 | ASSERT(!m_freeList.head); |
| 156 | m_heap->didAllocate(m_freeList.bytes); |
mhahnenberg@apple.com | 2b64eec0 | 2012-04-18 16:18:32 +0000 | [diff] [blame] | 157 | |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 158 | void* result = tryAllocate(bytes); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 159 | |
| 160 | if (LIKELY(result != 0)) |
| 161 | return result; |
| 162 | |
oliver@apple.com | 284cc3d | 2013-07-25 04:00:33 +0000 | [diff] [blame] | 163 | if (m_heap->collectIfNecessaryOrDefer()) { |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 164 | result = tryAllocate(bytes); |
mhahnenberg@apple.com | 3e7e4e0 | 2012-05-09 02:44:39 +0000 | [diff] [blame] | 165 | if (result) |
| 166 | return result; |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 167 | } |
mhahnenberg@apple.com | 3e7e4e0 | 2012-05-09 02:44:39 +0000 | [diff] [blame] | 168 | |
mhahnenberg@apple.com | 8b5cfd3 | 2012-04-20 00:05:37 +0000 | [diff] [blame] | 169 | ASSERT(!m_heap->shouldCollect()); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 170 | |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 171 | MarkedBlock* block = allocateBlock(bytes); |
mhahnenberg@apple.com | 3e7e4e0 | 2012-05-09 02:44:39 +0000 | [diff] [blame] | 172 | ASSERT(block); |
| 173 | addBlock(block); |
| 174 | |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 175 | result = tryAllocate(bytes); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 176 | ASSERT(result); |
| 177 | return result; |
| 178 | } |
ggaren@apple.com | a68a650 | 2012-05-22 23:59:51 +0000 | [diff] [blame] | 179 | |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 180 | MarkedBlock* MarkedAllocator::allocateBlock(size_t bytes) |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 181 | { |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 182 | size_t minBlockSize = MarkedBlock::blockSize; |
saambarati1@gmail.com | 64bf94c | 2015-08-27 05:54:21 +0000 | [diff] [blame] | 183 | size_t minAllocationSize = WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(sizeof(MarkedBlock)) + WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(bytes); |
| 184 | minAllocationSize = WTF::roundUpToMultipleOf(WTF::pageSize(), minAllocationSize); |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 185 | size_t blockSize = std::max(minBlockSize, minAllocationSize); |
| 186 | |
| 187 | size_t cellSize = m_cellSize ? m_cellSize : WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(bytes); |
| 188 | |
fpizlo@apple.com | aeddff9 | 2016-07-18 21:33:45 +0000 | [diff] [blame^] | 189 | // FIXME: Support allocating storage in marked blocks. This would mean that allocateBlock() |
| 190 | // takes a HeapCell::Kind, or something like that. |
| 191 | // https://bugs.webkit.org/show_bug.cgi?id=159658 |
| 192 | return MarkedBlock::create(*m_heap, this, blockSize, cellSize, m_needsDestruction, HeapCell::JSCell); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 193 | } |
| 194 | |
| 195 | void MarkedAllocator::addBlock(MarkedBlock* block) |
| 196 | { |
| 197 | ASSERT(!m_currentBlock); |
mhahnenberg@apple.com | 8b5cfd3 | 2012-04-20 00:05:37 +0000 | [diff] [blame] | 198 | ASSERT(!m_freeList.head); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 199 | |
| 200 | m_blockList.append(block); |
mhahnenberg@apple.com | fa811df | 2014-02-13 04:24:41 +0000 | [diff] [blame] | 201 | m_nextBlockToSweep = block; |
ggaren@apple.com | 6159e5f | 2012-09-11 03:02:46 +0000 | [diff] [blame] | 202 | m_markedSpace->didAddBlock(block); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 203 | } |
| 204 | |
| 205 | void MarkedAllocator::removeBlock(MarkedBlock* block) |
| 206 | { |
ggaren@apple.com | 4b67d0d | 2012-06-21 02:00:08 +0000 | [diff] [blame] | 207 | if (m_currentBlock == block) { |
ggaren@apple.com | dd7793a | 2012-07-31 21:26:38 +0000 | [diff] [blame] | 208 | m_currentBlock = m_currentBlock->next(); |
ggaren@apple.com | 4b67d0d | 2012-06-21 02:00:08 +0000 | [diff] [blame] | 209 | m_freeList = MarkedBlock::FreeList(); |
| 210 | } |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 211 | if (m_nextBlockToSweep == block) |
| 212 | m_nextBlockToSweep = m_nextBlockToSweep->next(); |
| 213 | |
mhahnenberg@apple.com | b59501b | 2014-03-12 01:45:54 +0000 | [diff] [blame] | 214 | block->willRemoveBlock(); |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 215 | m_blockList.remove(block); |
| 216 | } |
| 217 | |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 218 | void MarkedAllocator::reset() |
| 219 | { |
| 220 | m_lastActiveBlock = 0; |
| 221 | m_currentBlock = 0; |
| 222 | m_freeList = MarkedBlock::FreeList(); |
| 223 | if (m_heap->operationInProgress() == FullCollection) |
mhahnenberg@apple.com | b59501b | 2014-03-12 01:45:54 +0000 | [diff] [blame] | 224 | m_blockList.append(m_retiredBlocks); |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 225 | |
mhahnenberg@apple.com | b59501b | 2014-03-12 01:45:54 +0000 | [diff] [blame] | 226 | m_nextBlockToSweep = m_blockList.head(); |
ggaren@apple.com | 7535d92 | 2016-06-21 23:06:08 +0000 | [diff] [blame] | 227 | |
| 228 | if (UNLIKELY(Options::useImmortalObjects())) { |
| 229 | MarkedBlock* next; |
| 230 | for (MarkedBlock*& block = m_nextBlockToSweep; block; block = next) { |
| 231 | next = block->next(); |
| 232 | |
| 233 | MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList); |
| 234 | retire(block, freeList); |
| 235 | } |
| 236 | } |
mhahnenberg@apple.com | 3ddd7ac | 2014-01-10 02:28:27 +0000 | [diff] [blame] | 237 | } |
| 238 | |
mhahnenberg@apple.com | 96b8cd1 | 2014-03-12 18:17:43 +0000 | [diff] [blame] | 239 | void MarkedAllocator::lastChanceToFinalize() |
| 240 | { |
| 241 | m_blockList.append(m_retiredBlocks); |
fpizlo@apple.com | aeddff9 | 2016-07-18 21:33:45 +0000 | [diff] [blame^] | 242 | forEachBlock( |
| 243 | [&] (MarkedBlock* block) { |
| 244 | block->lastChanceToFinalize(); |
| 245 | }); |
mhahnenberg@apple.com | 96b8cd1 | 2014-03-12 18:17:43 +0000 | [diff] [blame] | 246 | } |
| 247 | |
mhahnenberg@apple.com | ce85b93 | 2012-02-03 19:27:57 +0000 | [diff] [blame] | 248 | } // namespace JSC |