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