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