bmalloc: Pathological madvise churn on the free(malloc(x)) benchmark
[WebKit-https.git] / Source / bmalloc / bmalloc / BoundaryTag.h
1 /*
2  * Copyright (C) 2014, 2015 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 BoundaryTag_h
27 #define BoundaryTag_h
28
29 #include "BAssert.h"
30 #include "Owner.h"
31 #include "Range.h"
32 #include "Sizes.h"
33 #include <cstring>
34
35 namespace bmalloc {
36
37 class BeginTag;
38 class EndTag;
39 class LargeChunk;
40 class Range;
41
42 class BoundaryTag {
43 public:
44     static Range init(LargeChunk*);
45     static unsigned compactBegin(void*);
46
47     bool isFree() { return m_isFree; }
48     void setFree(bool isFree) { m_isFree = isFree; }
49     
50     bool isEnd() { return m_isEnd; }
51     void setEnd(bool isEnd) { m_isEnd = isEnd; }
52
53     Owner owner() { return m_owner; }
54     void setOwner(Owner owner) { m_owner = owner; }
55     
56     bool isMarked() { return m_isMarked; }
57     void setMarked(bool isMarked) { m_isMarked = isMarked; }
58
59     bool isNull() { return !m_size; }
60     void clear() { std::memset(this, 0, sizeof(*this)); }
61     
62     size_t size() { return m_size; }
63     unsigned compactBegin() { return m_compactBegin; }
64
65     void setRange(const Range&);
66     
67     bool isSentinel() { return !m_compactBegin; }
68     void initSentinel();
69     
70     EndTag* prev();
71     BeginTag* next();
72
73 private:
74     static const size_t flagBits = 4;
75     static const size_t compactBeginBits = 4;
76     static const size_t sizeBits = bitCount<unsigned>() - flagBits - compactBeginBits;
77
78     static_assert(
79         (1 << compactBeginBits) - 1 >= (largeMin - 1) / largeAlignment,
80         "compactBegin must be encodable in a BoundaryTag.");
81
82     static_assert(
83         (1 << sizeBits) - 1 >= largeMax,
84         "largeMax must be encodable in a BoundaryTag.");
85
86     bool m_isFree: 1;
87     bool m_isEnd: 1;
88     Owner m_owner: 1;
89     bool m_isMarked: 1;
90     unsigned m_compactBegin: compactBeginBits;
91     unsigned m_size: sizeBits;
92 };
93
94 inline unsigned BoundaryTag::compactBegin(void* object)
95 {
96     return static_cast<unsigned>(
97         reinterpret_cast<uintptr_t>(mask(object, largeMin - 1)) / largeAlignment);
98 }
99
100 inline void BoundaryTag::setRange(const Range& range)
101 {
102     m_compactBegin = compactBegin(range.begin());
103     BASSERT(this->compactBegin() == compactBegin(range.begin()));
104
105     m_size = static_cast<unsigned>(range.size());
106     BASSERT(this->size() == range.size());
107 }
108
109 inline EndTag* BoundaryTag::prev()
110 {
111     BoundaryTag* prev = this - 1;
112     return reinterpret_cast<EndTag*>(prev);
113 }
114
115 inline BeginTag* BoundaryTag::next()
116 {
117     BoundaryTag* next = this + 1;
118     return reinterpret_cast<BeginTag*>(next);
119 }
120
121 inline void BoundaryTag::initSentinel()
122 {
123     setRange(Range(nullptr, largeMin));
124     setFree(false);
125     setOwner(Owner::VMHeap);
126 }
127
128 } // namespace bmalloc
129
130 #endif // BoundaryTag_h