Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
4.3 KiB

  1. //==- llvm/Support/Recycler.h - Recycling Allocator --------------*- C++ -*-==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the Recycler class template. See the doxygen comment for
  11. // Recycler for more details.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_SUPPORT_RECYCLER_H
  15. #define LLVM_SUPPORT_RECYCLER_H
  16. #include "llvm/ADT/ilist.h"
  17. #include "llvm/Support/AlignOf.h"
  18. #include "llvm/Support/ErrorHandling.h"
  19. #include <cassert>
  20. namespace llvm {
  21. class BumpPtrAllocator;
  22. /// PrintRecyclingAllocatorStats - Helper for RecyclingAllocator for
  23. /// printing statistics.
  24. ///
  25. void PrintRecyclerStats(size_t Size, size_t Align, size_t FreeListSize);
  26. /// RecyclerStruct - Implementation detail for Recycler. This is a
  27. /// class that the recycler imposes on free'd memory to carve out
  28. /// next/prev pointers.
  29. struct RecyclerStruct {
  30. RecyclerStruct *Prev, *Next;
  31. };
  32. template<>
  33. struct ilist_traits<RecyclerStruct> :
  34. public ilist_default_traits<RecyclerStruct> {
  35. static RecyclerStruct *getPrev(const RecyclerStruct *t) { return t->Prev; }
  36. static RecyclerStruct *getNext(const RecyclerStruct *t) { return t->Next; }
  37. static void setPrev(RecyclerStruct *t, RecyclerStruct *p) { t->Prev = p; }
  38. static void setNext(RecyclerStruct *t, RecyclerStruct *n) { t->Next = n; }
  39. mutable RecyclerStruct Sentinel;
  40. RecyclerStruct *createSentinel() const {
  41. return &Sentinel;
  42. }
  43. static void destroySentinel(RecyclerStruct *) {}
  44. RecyclerStruct *provideInitialHead() const { return createSentinel(); }
  45. RecyclerStruct *ensureHead(RecyclerStruct*) const { return createSentinel(); }
  46. static void noteHead(RecyclerStruct*, RecyclerStruct*) {}
  47. static void deleteNode(RecyclerStruct *) {
  48. llvm_unreachable("Recycler's ilist_traits shouldn't see a deleteNode call!");
  49. }
  50. };
  51. /// Recycler - This class manages a linked-list of deallocated nodes
  52. /// and facilitates reusing deallocated memory in place of allocating
  53. /// new memory.
  54. ///
  55. template<class T, size_t Size = sizeof(T), size_t Align = AlignOf<T>::Alignment>
  56. class Recycler {
  57. /// FreeList - Doubly-linked list of nodes that have deleted contents and
  58. /// are not in active use.
  59. ///
  60. iplist<RecyclerStruct> FreeList;
  61. public:
  62. ~Recycler() {
  63. // If this fails, either the callee has lost track of some allocation,
  64. // or the callee isn't tracking allocations and should just call
  65. // clear() before deleting the Recycler.
  66. assert(FreeList.empty() && "Non-empty recycler deleted!");
  67. }
  68. /// clear - Release all the tracked allocations to the allocator. The
  69. /// recycler must be free of any tracked allocations before being
  70. /// deleted; calling clear is one way to ensure this.
  71. template<class AllocatorType>
  72. void clear(AllocatorType &Allocator) {
  73. while (!FreeList.empty()) {
  74. T *t = reinterpret_cast<T *>(FreeList.remove(FreeList.begin()));
  75. Allocator.Deallocate(t);
  76. }
  77. }
  78. /// Special case for BumpPtrAllocator which has an empty Deallocate()
  79. /// function.
  80. ///
  81. /// There is no need to traverse the free list, pulling all the objects into
  82. /// cache.
  83. void clear(BumpPtrAllocator&) {
  84. FreeList.clearAndLeakNodesUnsafely();
  85. }
  86. template<class SubClass, class AllocatorType>
  87. SubClass *Allocate(AllocatorType &Allocator) {
  88. assert(sizeof(SubClass) <= Size &&
  89. "Recycler allocation size is less than object size!");
  90. assert(AlignOf<SubClass>::Alignment <= Align &&
  91. "Recycler allocation alignment is less than object alignment!");
  92. return !FreeList.empty() ?
  93. reinterpret_cast<SubClass *>(FreeList.remove(FreeList.begin())) :
  94. static_cast<SubClass *>(Allocator.Allocate(Size, Align));
  95. }
  96. template<class AllocatorType>
  97. T *Allocate(AllocatorType &Allocator) {
  98. return Allocate<T>(Allocator);
  99. }
  100. template<class SubClass, class AllocatorType>
  101. void Deallocate(AllocatorType & /*Allocator*/, SubClass* Element) {
  102. FreeList.push_front(reinterpret_cast<RecyclerStruct *>(Element));
  103. }
  104. void PrintStats() {
  105. PrintRecyclerStats(Size, Align, FreeList.size());
  106. }
  107. };
  108. }
  109. #endif