// Copyright 2014 the V8 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 V8_ZONE_ZONE_ALLOCATOR_H_ #define V8_ZONE_ZONE_ALLOCATOR_H_ #include #include "src/zone/zone.h" namespace v8 { namespace internal { template class ZoneAllocator { public: typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef T value_type; typedef size_t size_type; typedef ptrdiff_t difference_type; template struct rebind { typedef ZoneAllocator other; }; #ifdef V8_CC_MSVC // MSVS unfortunately requires the default constructor to be defined. ZoneAllocator() : ZoneAllocator(nullptr) { UNREACHABLE(); } #endif explicit ZoneAllocator(Zone* zone) throw() : zone_(zone) {} explicit ZoneAllocator(const ZoneAllocator& other) throw() : ZoneAllocator(other.zone_) {} template ZoneAllocator(const ZoneAllocator& other) throw() : ZoneAllocator(other.zone_) {} template friend class ZoneAllocator; T* address(T& x) const { return &x; } const T* address(const T& x) const { return &x; } T* allocate(size_t n, const void* hint = nullptr) { return static_cast(zone_->NewArray(static_cast(n))); } void deallocate(T* p, size_t) { /* noop for Zones */ } size_t max_size() const throw() { return std::numeric_limits::max() / sizeof(T); } template void construct(U* p, Args&&... args) { void* v_p = const_cast(static_cast(p)); new (v_p) U(std::forward(args)...); } template void destroy(U* p) { p->~U(); } bool operator==(ZoneAllocator const& other) const { return zone_ == other.zone_; } bool operator!=(ZoneAllocator const& other) const { return zone_ != other.zone_; } Zone* zone() { return zone_; } private: Zone* zone_; }; // A recycling zone allocator maintains a free list of deallocated chunks // to reuse on subsiquent allocations. The free list management is purposely // very simple and works best for data-structures which regularly allocate and // free blocks of similar sized memory (such as std::deque). template class RecyclingZoneAllocator : public ZoneAllocator { public: template struct rebind { typedef RecyclingZoneAllocator other; }; #ifdef V8_CC_MSVC // MSVS unfortunately requires the default constructor to be defined. RecyclingZoneAllocator() : ZoneAllocator(nullptr, nullptr), free_list_(nullptr) { UNREACHABLE(); } #endif explicit RecyclingZoneAllocator(Zone* zone) throw() : ZoneAllocator(zone), free_list_(nullptr) {} explicit RecyclingZoneAllocator(const RecyclingZoneAllocator& other) throw() : ZoneAllocator(other), free_list_(nullptr) {} template RecyclingZoneAllocator(const RecyclingZoneAllocator& other) throw() : ZoneAllocator(other), free_list_(nullptr) {} template friend class RecyclingZoneAllocator; T* allocate(size_t n, const void* hint = nullptr) { // Only check top block in free list, since this will be equal to or larger // than the other blocks in the free list. if (free_list_ && free_list_->size >= n) { T* return_val = reinterpret_cast(free_list_); free_list_ = free_list_->next; return return_val; } else { return ZoneAllocator::allocate(n, hint); } } void deallocate(T* p, size_t n) { if ((sizeof(T) * n < sizeof(FreeBlock))) return; // Only add block to free_list if it is equal or larger than previous block // so that allocation stays O(1) only having to look at the top block. if (!free_list_ || free_list_->size <= n) { // Store the free-list within the block being deallocated. DCHECK((sizeof(T) * n >= sizeof(FreeBlock))); FreeBlock* new_free_block = reinterpret_cast(p); new_free_block->size = n; new_free_block->next = free_list_; free_list_ = new_free_block; } } private: struct FreeBlock { FreeBlock* next; size_t size; }; FreeBlock* free_list_; }; typedef ZoneAllocator ZoneBoolAllocator; typedef ZoneAllocator ZoneIntAllocator; } // namespace internal } // namespace v8 #endif // V8_ZONE_ZONE_ALLOCATOR_H_