Hash :
93b659f9
Author :
Date :
2025-07-04T12:35:29
Remove PoolAllocator push/pop feature PoolAllocator would manage a stack of memory pools upon client calling push() and pop(). This made the code unnecessarily complicated. The feature was only used with nesting of one, to mark the memory unused after a shader compile. Fix by removing the push/pop feature. Instantiate PoolAllocator in places the previous push() was and uninstantiating instead of previous pop(). This removes the feature where the PoolAllocator would hold on to the allocated memory in order to reuse it. This is seen as a progression: the allocator is held by the compiler, the compiler is held by the shader and each shader typically see only one compile. Thus the free pages were just leaking unused until the shader was destroyed. Instead, destructing the PoolAllocator instead of pop() will donate the memory back to platform/OS, where it is likely more useful. To preserve existing Vulkan behavior, add PoolAllocator::reset() which would mark the memory unused but leave them reserved for the PoolAllocator. Removes UB where PageHeader::nextPage would be accessed after ~PageHeader. Bug: angleproject:429513168 Change-Id: I21e58b46e0887380db3a2cab5ce22f0042cfae9e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6701153 Reviewed-by: Geoff Lang <geofflang@chromium.org> Auto-Submit: Kimmo Kinnunen <kkinnunen@apple.com> Commit-Queue: Kimmo Kinnunen <kkinnunen@apple.com> 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
//
// Copyright 2002 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.
//
#ifndef COMPILER_TRANSLATOR_POOLALLOC_H_
#define COMPILER_TRANSLATOR_POOLALLOC_H_
//
// This header defines the pool_allocator class that allows STL containers
// to use the angle::PoolAllocator class by using the pool_allocator
// class as the allocator (second) template argument.
//
// It also defines functions for managing the GlobalPoolAllocator used by the compiler.
//
#include <stddef.h>
#include <string.h>
#include <vector>
#include "common/PoolAlloc.h"
//
// There could potentially be many pools with pops happening at
// different times. But a simple use is to have a global pop
// with everyone using the same global allocator.
//
extern angle::PoolAllocator *GetGlobalPoolAllocator();
extern void SetGlobalPoolAllocator(angle::PoolAllocator *poolAllocator);
class [[nodiscard]] TScopedPoolAllocator
{
public:
TScopedPoolAllocator() { SetGlobalPoolAllocator(&mAllocator); }
~TScopedPoolAllocator() { SetGlobalPoolAllocator(nullptr); }
private:
angle::PoolAllocator mAllocator;
};
//
// This STL compatible allocator is intended to be used as the allocator
// parameter to templatized STL containers, like vector and map.
//
// It will use the pools for allocation, and not
// do any deallocation, but will still do destruction.
//
template <class T>
class pool_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T *pointer;
typedef const T *const_pointer;
typedef T &reference;
typedef const T &const_reference;
typedef T value_type;
template <class Other>
struct rebind
{
typedef pool_allocator<Other> other;
};
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
pool_allocator() {}
template <class Other>
pool_allocator(const pool_allocator<Other> &p)
{}
template <class Other>
pool_allocator<T> &operator=(const pool_allocator<Other> &p)
{
return *this;
}
#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR)
// libCStd on some platforms have a different allocate/deallocate interface.
// Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be
// allocated, not the number of elements.
void *allocate(size_type n) { return getAllocator().allocate(n); }
void *allocate(size_type n, const void *) { return getAllocator().allocate(n); }
void deallocate(void *, size_type) {}
#else
pointer allocate(size_type n)
{
return static_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
}
pointer allocate(size_type n, const void *)
{
return static_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
}
void deallocate(pointer, size_type) {}
#endif // _RWSTD_ALLOCATOR
void construct(pointer p, const T &val) { new ((void *)p) T(val); }
void destroy(pointer p) { p->T::~T(); }
bool operator==(const pool_allocator &rhs) const { return true; }
bool operator!=(const pool_allocator &rhs) const { return false; }
size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
angle::PoolAllocator &getAllocator() const { return *GetGlobalPoolAllocator(); }
};
#endif // COMPILER_TRANSLATOR_POOLALLOC_H_