blob: 5be7ab29bc2c7473823cf446a1ad04eef8b3662c [file] [log] [blame]
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +00001#include "config.h"
2#include "MarkedAllocator.h"
3
mhahnenberg@apple.com2b64eec02012-04-18 16:18:32 +00004#include "GCActivityCallback.h"
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +00005#include "Heap.h"
mhahnenberg@apple.com59c64f12012-07-31 23:05:12 +00006#include "IncrementalSweeper.h"
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00007#include "VM.h"
mhahnenberg@apple.com2e132e42012-05-03 00:14:05 +00008#include <wtf/CurrentTime.h>
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +00009
10namespace JSC {
11
mhahnenberg@apple.com2e132e42012-05-03 00:14:05 +000012bool MarkedAllocator::isPagedOut(double deadline)
13{
14 unsigned itersSinceLastTimeCheck = 0;
ggaren@apple.comdd7793a2012-07-31 21:26:38 +000015 MarkedBlock* block = m_blockList.head();
mhahnenberg@apple.com2e132e42012-05-03 00:14:05 +000016 while (block) {
17 block = block->next();
18 ++itersSinceLastTimeCheck;
19 if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) {
20 double currentTime = WTF::monotonicallyIncreasingTime();
21 if (currentTime > deadline)
22 return true;
23 itersSinceLastTimeCheck = 0;
24 }
25 }
26
27 return false;
28}
29
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000030inline void* MarkedAllocator::tryAllocateHelper(size_t bytes)
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000031{
mhahnenberg@apple.com8b5cfd32012-04-20 00:05:37 +000032 if (!m_freeList.head) {
ggaren@apple.comdd7793a2012-07-31 21:26:38 +000033 for (MarkedBlock*& block = m_blocksToSweep; block; block = block->next()) {
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000034 MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
35 if (!freeList.head) {
36 block->didConsumeFreeList();
37 continue;
mhahnenberg@apple.com7f5b9592012-07-27 22:59:14 +000038 }
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000039
40 if (bytes > block->cellSize()) {
mhahnenberg@apple.com76e50b12012-09-14 07:06:23 +000041 block->canonicalizeCellLivenessData(freeList);
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000042 continue;
43 }
44
45 m_currentBlock = block;
46 m_freeList = freeList;
47 break;
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000048 }
49
mhahnenberg@apple.com7f5b9592012-07-27 22:59:14 +000050 if (!m_freeList.head) {
51 m_currentBlock = 0;
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000052 return 0;
mhahnenberg@apple.com7f5b9592012-07-27 22:59:14 +000053 }
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000054 }
55
mhahnenberg@apple.com8b5cfd32012-04-20 00:05:37 +000056 MarkedBlock::FreeCell* head = m_freeList.head;
57 m_freeList.head = head->next;
58 ASSERT(head);
59 return head;
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000060}
61
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000062inline void* MarkedAllocator::tryAllocate(size_t bytes)
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000063{
mhahnenberg@apple.com47c9c532012-06-05 20:38:21 +000064 ASSERT(!m_heap->isBusy());
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000065 m_heap->m_operationInProgress = Allocation;
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000066 void* result = tryAllocateHelper(bytes);
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000067 m_heap->m_operationInProgress = NoOperation;
68 return result;
69}
70
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000071void* MarkedAllocator::allocateSlowCase(size_t bytes)
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000072{
andersca@apple.comb987aae2013-07-26 00:13:13 +000073 ASSERT(m_heap->vm()->currentThreadIsHoldingAPILock());
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000074#if COLLECT_ON_EVERY_ALLOCATION
75 m_heap->collectAllGarbage();
76 ASSERT(m_heap->m_operationInProgress == NoOperation);
77#endif
78
mhahnenberg@apple.com8b5cfd32012-04-20 00:05:37 +000079 ASSERT(!m_freeList.head);
80 m_heap->didAllocate(m_freeList.bytes);
mhahnenberg@apple.com2b64eec02012-04-18 16:18:32 +000081
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000082 void* result = tryAllocate(bytes);
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000083
84 if (LIKELY(result != 0))
85 return result;
86
oliver@apple.com284cc3d2013-07-25 04:00:33 +000087 if (m_heap->collectIfNecessaryOrDefer()) {
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000088 result = tryAllocate(bytes);
mhahnenberg@apple.com3e7e4e02012-05-09 02:44:39 +000089 if (result)
90 return result;
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000091 }
mhahnenberg@apple.com3e7e4e02012-05-09 02:44:39 +000092
mhahnenberg@apple.com8b5cfd32012-04-20 00:05:37 +000093 ASSERT(!m_heap->shouldCollect());
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000094
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000095 MarkedBlock* block = allocateBlock(bytes);
mhahnenberg@apple.com3e7e4e02012-05-09 02:44:39 +000096 ASSERT(block);
97 addBlock(block);
98
ggaren@apple.com6159e5f2012-09-11 03:02:46 +000099 result = tryAllocate(bytes);
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000100 ASSERT(result);
101 return result;
102}
ggaren@apple.coma68a6502012-05-22 23:59:51 +0000103
ggaren@apple.com6159e5f2012-09-11 03:02:46 +0000104MarkedBlock* MarkedAllocator::allocateBlock(size_t bytes)
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000105{
ggaren@apple.com6159e5f2012-09-11 03:02:46 +0000106 size_t minBlockSize = MarkedBlock::blockSize;
107 size_t minAllocationSize = WTF::roundUpToMultipleOf(WTF::pageSize(), sizeof(MarkedBlock) + bytes);
108 size_t blockSize = std::max(minBlockSize, minAllocationSize);
109
110 size_t cellSize = m_cellSize ? m_cellSize : WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(bytes);
111
mhahnenberg@apple.com5c018e72012-10-12 03:10:30 +0000112 if (blockSize == MarkedBlock::blockSize)
113 return MarkedBlock::create(m_heap->blockAllocator().allocate<MarkedBlock>(), this, cellSize, m_destructorType);
114 return MarkedBlock::create(m_heap->blockAllocator().allocateCustomSize(blockSize, MarkedBlock::blockSize), this, cellSize, m_destructorType);
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000115}
116
117void MarkedAllocator::addBlock(MarkedBlock* block)
118{
119 ASSERT(!m_currentBlock);
mhahnenberg@apple.com8b5cfd32012-04-20 00:05:37 +0000120 ASSERT(!m_freeList.head);
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000121
122 m_blockList.append(block);
mhahnenberg@apple.com7f5b9592012-07-27 22:59:14 +0000123 m_blocksToSweep = m_currentBlock = block;
mhahnenberg@apple.com8b5cfd32012-04-20 00:05:37 +0000124 m_freeList = block->sweep(MarkedBlock::SweepToFreeList);
ggaren@apple.com6159e5f2012-09-11 03:02:46 +0000125 m_markedSpace->didAddBlock(block);
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000126}
127
128void MarkedAllocator::removeBlock(MarkedBlock* block)
129{
ggaren@apple.com4b67d0d2012-06-21 02:00:08 +0000130 if (m_currentBlock == block) {
ggaren@apple.comdd7793a2012-07-31 21:26:38 +0000131 m_currentBlock = m_currentBlock->next();
ggaren@apple.com4b67d0d2012-06-21 02:00:08 +0000132 m_freeList = MarkedBlock::FreeList();
133 }
mhahnenberg@apple.com7f5b9592012-07-27 22:59:14 +0000134 if (m_blocksToSweep == block)
ggaren@apple.comdd7793a2012-07-31 21:26:38 +0000135 m_blocksToSweep = m_blocksToSweep->next();
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000136 m_blockList.remove(block);
137}
138
139} // namespace JSC