CodeBlocks should be in IsoSubspaces
[WebKit-https.git] / Source / JavaScriptCore / heap / LargeAllocation.h
1 /*
2  * Copyright (C) 2016-2017 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 #pragma once
27
28 #include "MarkedBlock.h"
29 #include "WeakSet.h"
30
31 namespace JSC {
32
33 class SlotVisitor;
34
35 // WebKit has a good malloc that already knows what to do for large allocations. The GC shouldn't
36 // have to think about such things. That's where LargeAllocation comes in. We will allocate large
37 // objects directly using malloc, and put the LargeAllocation header just before them. We can detect
38 // when a HeapCell* is a LargeAllocation because it will have the MarkedBlock::atomSize / 2 bit set.
39
40 class LargeAllocation : public BasicRawSentinelNode<LargeAllocation> {
41 public:
42     static LargeAllocation* tryCreate(Heap&, size_t, Subspace*);
43     
44     ~LargeAllocation();
45     
46     static LargeAllocation* fromCell(const void* cell)
47     {
48         return bitwise_cast<LargeAllocation*>(bitwise_cast<char*>(cell) - headerSize());
49     }
50     
51     HeapCell* cell() const
52     {
53         return bitwise_cast<HeapCell*>(bitwise_cast<char*>(this) + headerSize());
54     }
55     
56     static bool isLargeAllocation(HeapCell* cell)
57     {
58         return bitwise_cast<uintptr_t>(cell) & halfAlignment;
59     }
60     
61     Subspace* subspace() const { return m_subspace; }
62     
63     void lastChanceToFinalize();
64     
65     Heap* heap() const { return m_weakSet.heap(); }
66     VM* vm() const { return m_weakSet.vm(); }
67     WeakSet& weakSet() { return m_weakSet; }
68     
69     void shrink();
70     
71     void visitWeakSet(SlotVisitor&);
72     void reapWeakSet();
73     
74     void clearNewlyAllocated() { m_isNewlyAllocated = false; }
75     void flip();
76     
77     bool isNewlyAllocated() const { return m_isNewlyAllocated; }
78     ALWAYS_INLINE bool isMarked() { return m_isMarked.load(std::memory_order_relaxed); }
79     ALWAYS_INLINE bool isMarked(HeapCell*) { return isMarked(); }
80     ALWAYS_INLINE bool isMarked(HeapCell*, Dependency) { return isMarked(); }
81     ALWAYS_INLINE bool isMarked(HeapVersion, HeapCell*) { return isMarked(); }
82     bool isLive() { return isMarked() || isNewlyAllocated(); }
83     
84     bool hasValidCell() const { return m_hasValidCell; }
85     
86     bool isEmpty();
87     
88     size_t cellSize() const { return m_cellSize; }
89     
90     bool aboveLowerBound(const void* rawPtr)
91     {
92         char* ptr = bitwise_cast<char*>(rawPtr);
93         char* begin = bitwise_cast<char*>(cell());
94         return ptr >= begin;
95     }
96     
97     bool belowUpperBound(const void* rawPtr)
98     {
99         char* ptr = bitwise_cast<char*>(rawPtr);
100         char* begin = bitwise_cast<char*>(cell());
101         char* end = begin + cellSize();
102         // We cannot #include IndexingHeader.h because reasons. The fact that IndexingHeader is 8
103         // bytes is wired deep into our engine, so this isn't so bad.
104         size_t sizeOfIndexingHeader = 8;
105         return ptr <= end + sizeOfIndexingHeader;
106     }
107     
108     bool contains(const void* rawPtr)
109     {
110         return aboveLowerBound(rawPtr) && belowUpperBound(rawPtr);
111     }
112     
113     const AllocatorAttributes& attributes() const { return m_attributes; }
114     
115     Dependency aboutToMark(HeapVersion) { return Dependency(); }
116     
117     ALWAYS_INLINE bool testAndSetMarked()
118     {
119         // This method is usually called when the object is already marked. This avoids us
120         // having to CAS in that case. It's profitable to reduce the total amount of CAS
121         // traffic.
122         if (isMarked())
123             return true;
124         return m_isMarked.compareExchangeStrong(false, true);
125     }
126     ALWAYS_INLINE bool testAndSetMarked(HeapCell*, Dependency) { return testAndSetMarked(); }
127     void clearMarked() { m_isMarked.store(false); }
128     
129     void noteMarked() { }
130     
131 #if ASSERT_DISABLED
132     void assertValidCell(VM&, HeapCell*) const { }
133 #else
134     void assertValidCell(VM&, HeapCell*) const;
135 #endif
136     
137     void sweep();
138     
139     void destroy();
140     
141     void dump(PrintStream&) const;
142     
143 private:
144     LargeAllocation(Heap&, size_t, Subspace*);
145     
146     static const unsigned alignment = MarkedBlock::atomSize;
147     static const unsigned halfAlignment = alignment / 2;
148
149     static unsigned headerSize();
150     
151     size_t m_cellSize;
152     bool m_isNewlyAllocated;
153     bool m_hasValidCell;
154     Atomic<bool> m_isMarked;
155     AllocatorAttributes m_attributes;
156     Subspace* m_subspace;
157     WeakSet m_weakSet;
158 };
159
160 inline unsigned LargeAllocation::headerSize()
161 {
162     return ((sizeof(LargeAllocation) + halfAlignment - 1) & ~(halfAlignment - 1)) | halfAlignment;
163 }
164
165 } // namespace JSC
166