bmalloc
[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     alignas(largeAlignment) char m_memory[];
68 };
69
70 inline LargeChunk* LargeChunk::create()
71 {
72     size_t vmSize = bmalloc::vmSize(largeChunkSize);
73     std::pair<void*, Range> result = vmAllocate(vmSize, superChunkSize, largeChunkOffset);
74     return new (result.first) LargeChunk;
75 }
76
77 inline LargeChunk* LargeChunk::get(void* object)
78 {
79     ASSERT(!isSmallOrMedium(object));
80     return static_cast<LargeChunk*>(mask(object, largeChunkMask));
81 }
82
83 inline BeginTag* LargeChunk::beginTag(void* object)
84 {
85     LargeChunk* chunk = get(object);
86     size_t boundaryTagNumber = (static_cast<char*>(object) - reinterpret_cast<char*>(chunk)) / largeMin - 1; // - 1 to offset from the right sentinel.
87     return static_cast<BeginTag*>(&chunk->m_boundaryTags[boundaryTagNumber]);
88 }
89
90 inline EndTag* LargeChunk::endTag(void* object, size_t size)
91 {
92     ASSERT(!isSmallOrMedium(object));
93
94     LargeChunk* chunk = get(object);
95     char* end = static_cast<char*>(object) + size;
96
97     // We subtract largeMin before computing the end pointer's boundary tag. An
98     // object's size need not be an even multiple of largeMin. Subtracting
99     // largeMin rounds down to the last boundary tag prior to our neighbor.
100
101     size_t boundaryTagNumber = (end - largeMin - reinterpret_cast<char*>(chunk)) / largeMin - 1; // - 1 to offset from the right sentinel.
102     return static_cast<EndTag*>(&chunk->m_boundaryTags[boundaryTagNumber]);
103 }
104
105 }; // namespace bmalloc
106
107 #endif // LargeChunk