Hash :
a02670d6
Author :
Date :
2025-08-26T20:41:16
Move unsafe buffers inside header guard macros While this is exactly opposite of what Chromium has chosen to do, there is an issue with clang-format trying to indent preprocessor directives four spaces relative to include guard. This is because Angle's .clang-format file specifies IndentPPDirectives: AfterHash but Chromium's does not. The current placement is sufficient to throw off clang-format's guard detection since the guard macro no longer covers the entire file. Bug: b/436880895 Change-Id: Ic6b99c8cef6213939cdf9b42af8730e1eb423065 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6885892 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org> Auto-Submit: Tom Sepez <tsepez@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// PoolAlloc.h:
// Defines the class interface for PoolAllocator.
//
#ifndef COMMON_POOLALLOC_H_
#define COMMON_POOLALLOC_H_
#ifdef UNSAFE_BUFFERS_BUILD
# pragma allow_unsafe_buffers
#endif
#if !defined(NDEBUG)
# define ANGLE_POOL_ALLOC_GUARD_BLOCKS // define to enable guard block checking
#endif
//
// This header defines an allocator that can be used to efficiently
// allocate a large number of small requests for heap memory, with the
// intention that they are not individually deallocated, but rather
// collectively deallocated at one time.
//
// This simultaneously
//
// * Makes each individual allocation much more efficient; the
// typical allocation is trivial.
// * Completely avoids the cost of doing individual deallocation.
// * Saves the trouble of tracking down and plugging a large class of leaks.
//
// Individual classes can use this allocator by supplying their own
// new and delete methods.
//
#include <stdint.h>
#include "common/angleutils.h"
#include "common/log_utils.h"
#if defined(ANGLE_DISABLE_POOL_ALLOC)
# include <memory>
# include <vector>
#endif
namespace angle
{
class PageHeader;
// Pages are linked together with a simple header at the beginning
// of each allocation obtained from the underlying OS.
// The "page size" used is not, nor must it match, the underlying OS
// page size. But, having it be about that size or equal to a set of
// pages is likely most optimal.
//
class PoolAllocator : angle::NonCopyable
{
public:
static const int kDefaultAlignment = sizeof(void *);
//
// Create PoolAllocator. If alignment is set to 1 byte then fastAllocate()
// function can be used to make allocations with less overhead.
//
PoolAllocator(int growthIncrement = 8 * 1024, int allocationAlignment = kDefaultAlignment);
~PoolAllocator();
// Marks all allocated memory as unused. The memory will be reused.
void reset();
// Call allocate() to actually acquire memory. Returns 0 if no memory
// available, otherwise a properly aligned pointer to 'numBytes' of memory.
//
void *allocate(size_t numBytes);
//
// Call fastAllocate() for a faster allocate function that does minimal bookkeeping
// preCondition: Allocator must have been created w/ alignment of 1
ANGLE_INLINE uint8_t *fastAllocate(size_t numBytes)
{
#if defined(ANGLE_DISABLE_POOL_ALLOC)
return reinterpret_cast<uint8_t *>(allocate(numBytes));
#else
ASSERT(mAlignment == 1);
// No multi-page allocations
ASSERT(numBytes <= (mPageSize - mPageHeaderSkip));
//
// Do the allocation, most likely case inline first, for efficiency.
//
if (numBytes <= mPageSize - mCurrentPageOffset)
{
//
// Safe to allocate from mCurrentPageOffset.
//
uint8_t *memory = reinterpret_cast<uint8_t *>(mInUseList) + mCurrentPageOffset;
mCurrentPageOffset += numBytes;
return memory;
}
return allocateNewPage(numBytes);
#endif
}
// There is no deallocate. The point of this class is that deallocation can be skipped by the
// user of it, as the model of use is to simultaneously deallocate everything at once by
// destroying the instance or reset().
// Catch unwanted allocations.
// TODO(jmadill): Remove this when we remove the global allocator.
void lock();
void unlock();
private:
size_t mAlignment; // all returned allocations will be aligned at
// this granularity, which will be a power of 2
#if !defined(ANGLE_DISABLE_POOL_ALLOC)
// Slow path of allocation when we have to get a new page.
uint8_t *allocateNewPage(size_t numBytes);
// Track allocations if and only if we're using guard blocks
void *initializeAllocation(uint8_t *memory, size_t numBytes);
// Granularity of allocation from the OS
size_t mPageSize;
// Amount of memory to skip to make room for the page header (which is the size of the page
// header, or PageHeader in PoolAlloc.cpp)
size_t mPageHeaderSkip;
// Next offset in top of inUseList to allocate from. This offset is not necessarily aligned to
// anything. When an allocation is made, the data is aligned to mAlignment, and the header (if
// any) will align to pointer size by extension (since mAlignment is made aligned to at least
// pointer size).
size_t mCurrentPageOffset;
// List of unused memory.
PageHeader *mFreeList;
// List of all memory currently being used. The head of this list is where allocations are
// currently being made from.
PageHeader *mInUseList;
int mNumCalls; // just an interesting statistic
size_t mTotalBytes; // just an interesting statistic
#else // !defined(ANGLE_DISABLE_POOL_ALLOC)
std::vector<std::unique_ptr<uint8_t[]>> mStack;
#endif
bool mLocked;
};
} // namespace angle
#endif // COMMON_POOLALLOC_H_