Simplify memory usage tracking in CopiedSpace
[WebKit-https.git] / Source / JavaScriptCore / heap / CopiedSpaceInlineMethods.h
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
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
26 #ifndef CopiedSpaceInlineMethods_h
27 #define CopiedSpaceInlineMethods_h
28
29 #include "CopiedBlock.h"
30 #include "CopiedSpace.h"
31 #include "Heap.h"
32 #include "HeapBlock.h"
33 #include "JSGlobalData.h"
34 #include <wtf/CheckedBoolean.h>
35
36 namespace JSC {
37
38 inline bool CopiedSpace::contains(void* ptr, CopiedBlock*& result)
39 {
40     CopiedBlock* block = blockFor(ptr);
41     result = block;
42     return !m_toSpaceFilter.ruleOut(reinterpret_cast<Bits>(block)) && m_toSpaceSet.contains(block);
43 }
44
45 inline void CopiedSpace::pin(CopiedBlock* block)
46 {
47     block->m_isPinned = true;
48 }
49
50 inline void CopiedSpace::startedCopying()
51 {
52     DoublyLinkedList<HeapBlock>* temp = m_fromSpace;
53     m_fromSpace = m_toSpace;
54     m_toSpace = temp;
55
56     m_toSpaceFilter.reset();
57     m_allocator.startedCopying();
58
59     m_waterMark = 0;
60
61     ASSERT(!m_inCopyingPhase);
62     ASSERT(!m_numberOfLoanedBlocks);
63     m_inCopyingPhase = true;
64 }
65
66 inline void CopiedSpace::recycleBlock(CopiedBlock* block)
67 {
68     {
69         MutexLocker locker(m_heap->m_freeBlockLock);
70         m_heap->m_freeBlocks.push(block);
71         m_heap->m_numberOfFreeBlocks++;
72     }
73
74     {
75         MutexLocker locker(m_loanedBlocksLock);
76         ASSERT(m_numberOfLoanedBlocks > 0);
77         m_numberOfLoanedBlocks--;
78         if (!m_numberOfLoanedBlocks)
79             m_loanedBlocksCondition.signal();
80     }
81 }
82
83 inline CheckedBoolean CopiedSpace::borrowBlock(CopiedBlock** outBlock)
84 {
85     CopiedBlock* block = 0;
86     if (!getFreshBlock(AllocationMustSucceed, &block)) {
87         *outBlock = 0;
88         return false;
89     }
90
91     ASSERT(m_inCopyingPhase);
92     MutexLocker locker(m_loanedBlocksLock);
93     m_numberOfLoanedBlocks++;
94
95     ASSERT(block->m_offset == block->payload());
96     *outBlock = block;
97     return true;
98 }
99
100 inline CheckedBoolean CopiedSpace::addNewBlock()
101 {
102     CopiedBlock* block = 0;
103     if (!getFreshBlock(AllocationCanFail, &block))
104         return false;
105         
106     m_toSpace->push(block);
107     m_toSpaceFilter.add(reinterpret_cast<Bits>(block));
108     m_toSpaceSet.add(block);
109     m_allocator.resetCurrentBlock(block);
110     return true;
111 }
112
113 inline CheckedBoolean CopiedSpace::allocateNewBlock(CopiedBlock** outBlock)
114 {
115     PageAllocationAligned allocation = PageAllocationAligned::allocate(HeapBlock::s_blockSize, HeapBlock::s_blockSize, OSAllocator::JSGCHeapPages);
116     if (!static_cast<bool>(allocation)) {
117         *outBlock = 0;
118         return false;
119     }
120
121     *outBlock = new (NotNull, allocation.base()) CopiedBlock(allocation);
122     return true;
123 }
124
125 inline bool CopiedSpace::fitsInBlock(CopiedBlock* block, size_t bytes)
126 {
127     return static_cast<char*>(block->m_offset) + bytes < reinterpret_cast<char*>(block) + block->capacity() && static_cast<char*>(block->m_offset) + bytes > block->m_offset;
128 }
129
130 inline CheckedBoolean CopiedSpace::tryAllocate(size_t bytes, void** outPtr)
131 {
132     ASSERT(!m_heap->globalData()->isInitializingObject());
133
134     if (isOversize(bytes) || !m_allocator.fitsInCurrentBlock(bytes))
135         return tryAllocateSlowCase(bytes, outPtr);
136     
137     *outPtr = m_allocator.allocate(bytes);
138     ASSERT(*outPtr);
139     return true;
140 }
141
142 inline void* CopiedSpace::allocateFromBlock(CopiedBlock* block, size_t bytes)
143 {
144     ASSERT(fitsInBlock(block, bytes));
145     ASSERT(is8ByteAligned(block->m_offset));
146     
147     void* ptr = block->m_offset;
148     ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + block->capacity());
149     block->m_offset = static_cast<void*>((static_cast<char*>(ptr) + bytes));
150     ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + block->capacity());
151
152     ASSERT(is8ByteAligned(ptr));
153     return ptr;
154 }
155
156 inline bool CopiedSpace::isOversize(size_t bytes)
157 {
158     return bytes > s_maxAllocationSize;
159 }
160
161 inline bool CopiedSpace::isPinned(void* ptr)
162 {
163     return blockFor(ptr)->m_isPinned;
164 }
165
166 inline CopiedBlock* CopiedSpace::oversizeBlockFor(void* ptr)
167 {
168     return reinterpret_cast<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & WTF::pageMask());
169 }
170
171 inline CopiedBlock* CopiedSpace::blockFor(void* ptr)
172 {
173     return reinterpret_cast<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & s_blockMask);
174 }
175
176 } // namespace JSC
177
178 #endif