]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 A |
1 | #include "config.h" |
2 | #include "MarkedAllocator.h" | |
3 | ||
4 | #include "GCActivityCallback.h" | |
5 | #include "Heap.h" | |
93a37866 A |
6 | #include "IncrementalSweeper.h" |
7 | #include "VM.h" | |
6fe7ccc8 A |
8 | #include <wtf/CurrentTime.h> |
9 | ||
10 | namespace JSC { | |
11 | ||
12 | bool MarkedAllocator::isPagedOut(double deadline) | |
13 | { | |
14 | unsigned itersSinceLastTimeCheck = 0; | |
93a37866 | 15 | MarkedBlock* block = m_blockList.head(); |
6fe7ccc8 A |
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 | ||
93a37866 | 30 | inline void* MarkedAllocator::tryAllocateHelper(size_t bytes) |
6fe7ccc8 A |
31 | { |
32 | if (!m_freeList.head) { | |
93a37866 A |
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; | |
6fe7ccc8 A |
48 | } |
49 | ||
93a37866 A |
50 | if (!m_freeList.head) { |
51 | m_currentBlock = 0; | |
6fe7ccc8 | 52 | return 0; |
93a37866 | 53 | } |
6fe7ccc8 A |
54 | } |
55 | ||
56 | MarkedBlock::FreeCell* head = m_freeList.head; | |
57 | m_freeList.head = head->next; | |
58 | ASSERT(head); | |
59 | return head; | |
60 | } | |
61 | ||
93a37866 | 62 | inline void* MarkedAllocator::tryAllocate(size_t bytes) |
6fe7ccc8 A |
63 | { |
64 | ASSERT(!m_heap->isBusy()); | |
65 | m_heap->m_operationInProgress = Allocation; | |
93a37866 | 66 | void* result = tryAllocateHelper(bytes); |
6fe7ccc8 A |
67 | m_heap->m_operationInProgress = NoOperation; |
68 | return result; | |
69 | } | |
70 | ||
93a37866 | 71 | void* MarkedAllocator::allocateSlowCase(size_t bytes) |
6fe7ccc8 | 72 | { |
93a37866 | 73 | ASSERT(m_heap->vm()->apiLock().currentThreadIsHoldingLock()); |
6fe7ccc8 A |
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 | ||
93a37866 | 82 | void* result = tryAllocate(bytes); |
6fe7ccc8 A |
83 | |
84 | if (LIKELY(result != 0)) | |
85 | return result; | |
86 | ||
87 | if (m_heap->shouldCollect()) { | |
88 | m_heap->collect(Heap::DoNotSweep); | |
89 | ||
93a37866 | 90 | result = tryAllocate(bytes); |
6fe7ccc8 A |
91 | if (result) |
92 | return result; | |
93 | } | |
94 | ||
95 | ASSERT(!m_heap->shouldCollect()); | |
96 | ||
93a37866 | 97 | MarkedBlock* block = allocateBlock(bytes); |
6fe7ccc8 A |
98 | ASSERT(block); |
99 | addBlock(block); | |
100 | ||
93a37866 | 101 | result = tryAllocate(bytes); |
6fe7ccc8 A |
102 | ASSERT(result); |
103 | return result; | |
104 | } | |
93a37866 A |
105 | |
106 | MarkedBlock* MarkedAllocator::allocateBlock(size_t bytes) | |
6fe7ccc8 | 107 | { |
93a37866 A |
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); | |
6fe7ccc8 A |
117 | } |
118 | ||
119 | void MarkedAllocator::addBlock(MarkedBlock* block) | |
120 | { | |
121 | ASSERT(!m_currentBlock); | |
122 | ASSERT(!m_freeList.head); | |
123 | ||
124 | m_blockList.append(block); | |
93a37866 | 125 | m_blocksToSweep = m_currentBlock = block; |
6fe7ccc8 | 126 | m_freeList = block->sweep(MarkedBlock::SweepToFreeList); |
93a37866 | 127 | m_markedSpace->didAddBlock(block); |
6fe7ccc8 A |
128 | } |
129 | ||
130 | void MarkedAllocator::removeBlock(MarkedBlock* block) | |
131 | { | |
93a37866 A |
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(); | |
6fe7ccc8 A |
138 | m_blockList.remove(block); |
139 | } | |
140 | ||
141 | } // namespace JSC |