bmalloc: Refactored SegregatedFreeList and BoundaryTag::init
[WebKit-https.git] / Source / bmalloc / bmalloc / LargeChunk.h
1 /*
2  * Copyright (C) 2014 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 LargeChunk_h
27 #define LargeChunk_h
28
29 #include "BeginTag.h"
30 #include "EndTag.h"
31 #include "ObjectType.h"
32 #include "Sizes.h"
33 #include "VMAllocate.h"
34
35 namespace bmalloc {
36
37 class LargeChunk {
38 public:
39     static LargeChunk* create();
40     static LargeChunk* get(void*);
41
42     static BeginTag* beginTag(void*);
43     static EndTag* endTag(void*, size_t);
44
45     char* begin() { return m_memory; }
46     char* end() { return reinterpret_cast<char*>(this) + largeChunkSize; }
47
48 private:
49      // Round up to ensure 2 dummy boundary tags -- for the left and right sentinels.
50      static const size_t boundaryTagCount = max(2 * largeMin / sizeof(BoundaryTag), largeChunkSize / largeMin); 
51
52     // Our metadata layout includes a left and right edge sentinel.
53     // Metadata takes up enough space to leave at least the first two
54     // boundary tag slots unused.
55     //
56     //      So, boundary tag space looks like this:
57     //
58     //          [OOXXXXX...]
59     //
60     //      And BoundaryTag::get subtracts one, producing:
61     //
62     //          [OXXXXX...O].
63     //
64     // We use the X's for boundary tags and the O's for edge sentinels.
65
66     BoundaryTag m_boundaryTags[boundaryTagCount];
67
68     // Align to vmPageSize to avoid sharing physical pages with metadata.
69     // Otherwise, we'll confuse the scavenger into trying to scavenge metadata.
70     // FIXME: Below #ifdef workaround fix should be removed after all linux based ports bump
71     // own gcc version. See https://bugs.webkit.org/show_bug.cgi?id=140162#c87
72 #if BPLATFORM(IOS)
73     char m_memory[] __attribute__((aligned(16384)));
74     static_assert(vmPageSize == 16384, "vmPageSize and alignment must be same");
75 #else
76     char m_memory[] __attribute__((aligned(4096)));
77     static_assert(vmPageSize == 4096, "vmPageSize and alignment must be same");
78 #endif
79 };
80
81 inline LargeChunk* LargeChunk::get(void* object)
82 {
83     BASSERT(!isSmallOrMedium(object));
84     return static_cast<LargeChunk*>(mask(object, largeChunkMask));
85 }
86
87 inline BeginTag* LargeChunk::beginTag(void* object)
88 {
89     LargeChunk* chunk = get(object);
90     size_t boundaryTagNumber = (static_cast<char*>(object) - reinterpret_cast<char*>(chunk)) / largeMin - 1; // - 1 to offset from the right sentinel.
91     return static_cast<BeginTag*>(&chunk->m_boundaryTags[boundaryTagNumber]);
92 }
93
94 inline EndTag* LargeChunk::endTag(void* object, size_t size)
95 {
96     BASSERT(!isSmallOrMedium(object));
97
98     LargeChunk* chunk = get(object);
99     char* end = static_cast<char*>(object) + size;
100
101     // We subtract largeMin before computing the end pointer's boundary tag. An
102     // object's size need not be an even multiple of largeMin. Subtracting
103     // largeMin rounds down to the last boundary tag prior to our neighbor.
104
105     size_t boundaryTagNumber = (end - largeMin - reinterpret_cast<char*>(chunk)) / largeMin - 1; // - 1 to offset from the right sentinel.
106     return static_cast<EndTag*>(&chunk->m_boundaryTags[boundaryTagNumber]);
107 }
108
109 }; // namespace bmalloc
110
111 #endif // LargeChunk