Line data Source code
1 : #ifdef __PLUMED_HAS_ASMJIT 2 : // This file is part of AsmJit project <https://asmjit.com> 3 : // 4 : // See asmjit.h or LICENSE.md for license and copyright information 5 : // SPDX-License-Identifier: Zlib 6 : 7 : #ifndef ASMJIT_CORE_ZONESTACK_H_INCLUDED 8 : #define ASMJIT_CORE_ZONESTACK_H_INCLUDED 9 : 10 : #include "zone.h" 11 : 12 : ASMJIT_BEGIN_NAMESPACE 13 : 14 : //! \addtogroup asmjit_zone 15 : //! \{ 16 : 17 : //! Base class used by \ref ZoneStack. 18 : class ZoneStackBase { 19 : public: 20 : ASMJIT_NONCOPYABLE(ZoneStackBase) 21 : 22 : //! \name Constants 23 : //! \{ 24 : 25 : enum : size_t { 26 : kBlockIndexPrev = 0, 27 : kBlockIndexNext = 1, 28 : 29 : kBlockIndexFirst = 0, 30 : kBlockIndexLast = 1, 31 : 32 : kBlockSize = ZoneAllocator::kHiMaxSize 33 : }; 34 : 35 : //! \} 36 : 37 : //! \name Types 38 : //! \{ 39 : 40 : struct Block { 41 : //! Next and previous blocks. 42 : Block* _link[2]; 43 : //! Pointer to the start of the array. 44 : void* _start; 45 : //! Pointer to the end of the array. 46 : void* _end; 47 : 48 82476 : inline bool empty() const noexcept { return _start == _end; } 49 : inline Block* prev() const noexcept { return _link[kBlockIndexPrev]; } 50 54984 : inline Block* next() const noexcept { return _link[kBlockIndexNext]; } 51 : 52 : inline void setPrev(Block* block) noexcept { _link[kBlockIndexPrev] = block; } 53 : inline void setNext(Block* block) noexcept { _link[kBlockIndexNext] = block; } 54 : 55 : template<typename T> 56 192444 : inline T* start() const noexcept { return static_cast<T*>(_start); } 57 : template<typename T> 58 54984 : inline void setStart(T* start) noexcept { _start = static_cast<void*>(start); } 59 : 60 : template<typename T> 61 247428 : inline T* end() const noexcept { return (T*)_end; } 62 : template<typename T> 63 109968 : inline void setEnd(T* end) noexcept { _end = (void*)end; } 64 : 65 : template<typename T> 66 : inline T* data() const noexcept { return (T*)((uint8_t*)(this) + sizeof(Block)); } 67 : 68 : template<typename T> 69 : inline bool canPrepend() const noexcept { return _start > data<void>(); } 70 : 71 : template<typename T> 72 : inline bool canAppend() const noexcept { 73 : size_t kNumBlockItems = (kBlockSize - sizeof(Block)) / sizeof(T); 74 : size_t kStartBlockIndex = sizeof(Block); 75 : size_t kEndBlockIndex = kStartBlockIndex + kNumBlockItems * sizeof(T); 76 : 77 82476 : return (uintptr_t)_end <= ((uintptr_t)this + kEndBlockIndex - sizeof(T)); 78 : } 79 : }; 80 : 81 : //! \} 82 : 83 : //! \name Members 84 : //! \{ 85 : 86 : //! Allocator used to allocate data. 87 : ZoneAllocator* _allocator; 88 : //! First and last blocks. 89 : Block* _block[2]; 90 : 91 : //! \} 92 : 93 : //! \name Construction & Destruction 94 : //! \{ 95 : 96 54984 : inline ZoneStackBase() noexcept { 97 54984 : _allocator = nullptr; 98 54984 : _block[0] = nullptr; 99 27492 : _block[1] = nullptr; 100 : } 101 : inline ~ZoneStackBase() noexcept { reset(); } 102 : 103 : inline bool isInitialized() const noexcept { return _allocator != nullptr; } 104 : ASMJIT_API Error _init(ZoneAllocator* allocator, size_t middleIndex) noexcept; 105 82476 : inline Error reset() noexcept { return _init(nullptr, 0); } 106 : 107 : //! \} 108 : 109 : //! \name Accessors 110 : //! \{ 111 : 112 : //! Returns `ZoneAllocator` attached to this container. 113 : inline ZoneAllocator* allocator() const noexcept { return _allocator; } 114 : 115 : inline bool empty() const noexcept { 116 : ASMJIT_ASSERT(isInitialized()); 117 137460 : return _block[0]->start<void>() == _block[1]->end<void>(); 118 : } 119 : 120 : //! \} 121 : 122 : //! \cond INTERNAL 123 : //! \name Internal 124 : //! \{ 125 : 126 : ASMJIT_API Error _prepareBlock(uint32_t side, size_t initialIndex) noexcept; 127 : ASMJIT_API void _cleanupBlock(uint32_t side, size_t middleIndex) noexcept; 128 : 129 : //! \} 130 : //! \endcond 131 : }; 132 : 133 : //! Zone allocated stack container. 134 : template<typename T> 135 : class ZoneStack : public ZoneStackBase { 136 : public: 137 : ASMJIT_NONCOPYABLE(ZoneStack) 138 : 139 : //! \name Constants 140 : //! \{ 141 : 142 : enum : uint32_t { 143 : kNumBlockItems = uint32_t((kBlockSize - sizeof(Block)) / sizeof(T)), 144 : kStartBlockIndex = uint32_t(sizeof(Block)), 145 : kMidBlockIndex = uint32_t(kStartBlockIndex + (kNumBlockItems / 2) * sizeof(T)), 146 : kEndBlockIndex = uint32_t(kStartBlockIndex + (kNumBlockItems ) * sizeof(T)) 147 : }; 148 : 149 : //! \} 150 : 151 : //! \name Construction & Destruction 152 : //! \{ 153 : 154 : inline ZoneStack() noexcept {} 155 54984 : inline ~ZoneStack() noexcept {} 156 : 157 54984 : inline Error init(ZoneAllocator* allocator) noexcept { return _init(allocator, kMidBlockIndex); } 158 : 159 : //! \} 160 : 161 : //! \name Utilities 162 : //! \{ 163 : 164 : inline Error prepend(T item) noexcept { 165 : ASMJIT_ASSERT(isInitialized()); 166 : Block* block = _block[kBlockIndexFirst]; 167 : 168 : if (!block->canPrepend<T>()) { 169 : ASMJIT_PROPAGATE(_prepareBlock(kBlockIndexFirst, kEndBlockIndex)); 170 : block = _block[kBlockIndexFirst]; 171 : } 172 : 173 : T* ptr = block->start<T>() - 1; 174 : ASMJIT_ASSERT(ptr >= block->data<T>() && ptr <= block->data<T>() + (kNumBlockItems - 1)); 175 : *ptr = item; 176 : block->setStart<T>(ptr); 177 : return kErrorOk; 178 : } 179 : 180 82476 : inline Error append(T item) noexcept { 181 : ASMJIT_ASSERT(isInitialized()); 182 82476 : Block* block = _block[kBlockIndexLast]; 183 : 184 82476 : if (!block->canAppend<T>()) { 185 0 : ASMJIT_PROPAGATE(_prepareBlock(kBlockIndexLast, kStartBlockIndex)); 186 0 : block = _block[kBlockIndexLast]; 187 : } 188 : 189 : T* ptr = block->end<T>(); 190 : ASMJIT_ASSERT(ptr >= block->data<T>() && ptr <= block->data<T>() + (kNumBlockItems - 1)); 191 : 192 82476 : *ptr++ = item; 193 : block->setEnd(ptr); 194 82476 : return kErrorOk; 195 : } 196 : 197 54984 : inline T popFirst() noexcept { 198 : ASMJIT_ASSERT(isInitialized()); 199 : ASMJIT_ASSERT(!empty()); 200 : 201 54984 : Block* block = _block[kBlockIndexFirst]; 202 : ASMJIT_ASSERT(!block->empty()); 203 : 204 : T* ptr = block->start<T>(); 205 54984 : T item = *ptr++; 206 : 207 : block->setStart(ptr); 208 54984 : if (block->empty()) 209 27492 : _cleanupBlock(kBlockIndexFirst, kMidBlockIndex); 210 : 211 54984 : return item; 212 : } 213 : 214 27492 : inline T pop() noexcept { 215 : ASMJIT_ASSERT(isInitialized()); 216 : ASMJIT_ASSERT(!empty()); 217 : 218 27492 : Block* block = _block[kBlockIndexLast]; 219 : ASMJIT_ASSERT(!block->empty()); 220 : 221 : T* ptr = block->end<T>(); 222 27492 : T item = *--ptr; 223 : ASMJIT_ASSERT(ptr >= block->data<T>()); 224 : ASMJIT_ASSERT(ptr >= block->start<T>()); 225 : 226 : block->setEnd(ptr); 227 27492 : if (block->empty()) 228 27492 : _cleanupBlock(kBlockIndexLast, kMidBlockIndex); 229 : 230 27492 : return item; 231 : } 232 : 233 : //! \} 234 : }; 235 : 236 : //! \} 237 : 238 : ASMJIT_END_NAMESPACE 239 : 240 : #endif // ASMJIT_CORE_ZONESTACK_H_INCLUDED 241 : 242 : #endif // __PLUMED_HAS_ASMJIT