03a86ea13d4b5596d5f09348bd3141b5a597be50
[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 setMarked() { m_isMarked.store(true); }
123     void clearMarked() { m_isMarked.store(false); }
124     
125     void noteMarked() { }
126     
127     void sweep();
128     
129     void destroy();
130     
131     void dump(PrintStream&) const;
132     
133 private:
134     LargeAllocation(Heap&, size_t, const AllocatorAttributes&);
135     
136     static const unsigned alignment = MarkedBlock::atomSize;
137     static const unsigned halfAlignment = alignment / 2;
138
139     static unsigned headerSize();
140     
141     size_t m_cellSize;
142     bool m_isNewlyAllocated;
143     bool m_hasValidCell;
144     Atomic<bool> m_isMarked;
145     AllocatorAttributes m_attributes;
146     WeakSet m_weakSet;
147 };
148
149 inline unsigned LargeAllocation::headerSize()
150 {
151     return ((sizeof(LargeAllocation) + halfAlignment - 1) & ~(halfAlignment - 1)) | halfAlignment;
152 }
153
154 } // namespace JSC
155