]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/MarkedAllocator.cpp
JavaScriptCore-1218.0.1.tar.gz
[apple/javascriptcore.git] / heap / MarkedAllocator.cpp
1 #include "config.h"
2 #include "MarkedAllocator.h"
3
4 #include "GCActivityCallback.h"
5 #include "Heap.h"
6 #include "IncrementalSweeper.h"
7 #include "VM.h"
8 #include <wtf/CurrentTime.h>
9
10 namespace JSC {
11
12 bool MarkedAllocator::isPagedOut(double deadline)
13 {
14 unsigned itersSinceLastTimeCheck = 0;
15 MarkedBlock* block = m_blockList.head();
16 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
30 inline void* MarkedAllocator::tryAllocateHelper(size_t bytes)
31 {
32 if (!m_freeList.head) {
33 for (MarkedBlock*& block = m_blocksToSweep; block; block = block->next()) {
34 MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
35 if (!freeList.head) {
36 block->didConsumeFreeList();
37 continue;
38 }
39
40 if (bytes > block->cellSize()) {
41 block->canonicalizeCellLivenessData(freeList);
42 continue;
43 }
44
45 m_currentBlock = block;
46 m_freeList = freeList;
47 break;
48 }
49
50 if (!m_freeList.head) {
51 m_currentBlock = 0;
52 return 0;
53 }
54 }
55
56 MarkedBlock::FreeCell* head = m_freeList.head;
57 m_freeList.head = head->next;
58 ASSERT(head);
59 return head;
60 }
61
62 inline void* MarkedAllocator::tryAllocate(size_t bytes)
63 {
64 ASSERT(!m_heap->isBusy());
65 m_heap->m_operationInProgress = Allocation;
66 void* result = tryAllocateHelper(bytes);
67 m_heap->m_operationInProgress = NoOperation;
68 return result;
69 }
70
71 void* MarkedAllocator::allocateSlowCase(size_t bytes)
72 {
73 ASSERT(m_heap->vm()->apiLock().currentThreadIsHoldingLock());
74 #if COLLECT_ON_EVERY_ALLOCATION
75 m_heap->collectAllGarbage();
76 ASSERT(m_heap->m_operationInProgress == NoOperation);
77 #endif
78
79 ASSERT(!m_freeList.head);
80 m_heap->didAllocate(m_freeList.bytes);
81
82 void* result = tryAllocate(bytes);
83
84 if (LIKELY(result != 0))
85 return result;
86
87 if (m_heap->shouldCollect()) {
88 m_heap->collect(Heap::DoNotSweep);
89
90 result = tryAllocate(bytes);
91 if (result)
92 return result;
93 }
94
95 ASSERT(!m_heap->shouldCollect());
96
97 MarkedBlock* block = allocateBlock(bytes);
98 ASSERT(block);
99 addBlock(block);
100
101 result = tryAllocate(bytes);
102 ASSERT(result);
103 return result;
104 }
105
106 MarkedBlock* MarkedAllocator::allocateBlock(size_t bytes)
107 {
108 size_t minBlockSize = MarkedBlock::blockSize;
109 size_t minAllocationSize = WTF::roundUpToMultipleOf(WTF::pageSize(), sizeof(MarkedBlock) + bytes);
110 size_t blockSize = std::max(minBlockSize, minAllocationSize);
111
112 size_t cellSize = m_cellSize ? m_cellSize : WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(bytes);
113
114 if (blockSize == MarkedBlock::blockSize)
115 return MarkedBlock::create(m_heap->blockAllocator().allocate<MarkedBlock>(), this, cellSize, m_destructorType);
116 return MarkedBlock::create(m_heap->blockAllocator().allocateCustomSize(blockSize, MarkedBlock::blockSize), this, cellSize, m_destructorType);
117 }
118
119 void MarkedAllocator::addBlock(MarkedBlock* block)
120 {
121 ASSERT(!m_currentBlock);
122 ASSERT(!m_freeList.head);
123
124 m_blockList.append(block);
125 m_blocksToSweep = m_currentBlock = block;
126 m_freeList = block->sweep(MarkedBlock::SweepToFreeList);
127 m_markedSpace->didAddBlock(block);
128 }
129
130 void MarkedAllocator::removeBlock(MarkedBlock* block)
131 {
132 if (m_currentBlock == block) {
133 m_currentBlock = m_currentBlock->next();
134 m_freeList = MarkedBlock::FreeList();
135 }
136 if (m_blocksToSweep == block)
137 m_blocksToSweep = m_blocksToSweep->next();
138 m_blockList.remove(block);
139 }
140
141 } // namespace JSC