183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko/* 283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * Copyright (C) 2014 The Android Open Source Project 383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * 483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * you may not use this file except in compliance with the License. 683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * You may obtain a copy of the License at 783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * 883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * 1083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * Unless required by applicable law or agreed to in writing, software 1183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 1283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * See the License for the specific language governing permissions and 1483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko * limitations under the License. 1583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko */ 1683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 1783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#ifndef ART_COMPILER_UTILS_SCOPED_ARENA_ALLOCATOR_H_ 1883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#define ART_COMPILER_UTILS_SCOPED_ARENA_ALLOCATOR_H_ 1983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 2083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#include "base/logging.h" 2183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#include "base/macros.h" 2283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#include "utils/arena_allocator.h" 2383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#include "utils/debug_stack.h" 2483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#include "globals.h" 2583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 2683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markonamespace art { 2783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 2883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass ArenaStack; 2983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass ScopedArenaAllocator; 3083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 3183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markotemplate <typename T> 3283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass ScopedArenaAllocatorAdapter; 3383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 3483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko// Holds a list of Arenas for use by ScopedArenaAllocator stack. 3583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass ArenaStack : private DebugStackRefCounter { 3683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko public: 3783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko explicit ArenaStack(ArenaPool* arena_pool); 3883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ~ArenaStack(); 3983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 4053b6afc93d91f9a48660682082dafcd81a652d6cVladimir Marko void Reset(); 4153b6afc93d91f9a48660682082dafcd81a652d6cVladimir Marko 4283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko size_t PeakBytesAllocated() { 4383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko return PeakStats()->BytesAllocated(); 4483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 4583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 4683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko MemStats GetPeakStats() const; 4783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 4883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko private: 4983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko struct Peak; 5083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko struct Current; 5183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko template <typename Tag> struct TaggedStats : ArenaAllocatorStats { }; 5283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko struct StatsAndPool : TaggedStats<Peak>, TaggedStats<Current> { 5383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko explicit StatsAndPool(ArenaPool* arena_pool) : pool(arena_pool) { } 5483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ArenaPool* const pool; 5583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko }; 5683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 5783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ArenaAllocatorStats* PeakStats() { 5883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko return static_cast<TaggedStats<Peak>*>(&stats_and_pool_); 5983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 6083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 6183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ArenaAllocatorStats* CurrentStats() { 6283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko return static_cast<TaggedStats<Current>*>(&stats_and_pool_); 6383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 6483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 6583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko // Private - access via ScopedArenaAllocator or ScopedArenaAllocatorAdapter. 6683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void* Alloc(size_t bytes, ArenaAllocKind kind) ALWAYS_INLINE { 6783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko if (UNLIKELY(running_on_valgrind_)) { 6883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko return AllocValgrind(bytes, kind); 6983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 7022a0ef8fbe78577ad4127e5becf20b3afa797478Vladimir Marko size_t rounded_bytes = RoundUp(bytes, 8); 7183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko uint8_t* ptr = top_ptr_; 7283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko if (UNLIKELY(static_cast<size_t>(top_end_ - ptr) < rounded_bytes)) { 7383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ptr = AllocateFromNextArena(rounded_bytes); 7483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 7583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko CurrentStats()->RecordAlloc(bytes, kind); 7683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko top_ptr_ = ptr + rounded_bytes; 7783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko return ptr; 7883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 7983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 8083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko uint8_t* AllocateFromNextArena(size_t rounded_bytes); 8183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void UpdatePeakStatsAndRestore(const ArenaAllocatorStats& restore_stats); 8283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void UpdateBytesAllocated(); 8383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void* AllocValgrind(size_t bytes, ArenaAllocKind kind); 8483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 8583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko StatsAndPool stats_and_pool_; 8683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko Arena* bottom_arena_; 8783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko Arena* top_arena_; 8883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko uint8_t* top_ptr_; 8983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko uint8_t* top_end_; 9083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 9183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko const bool running_on_valgrind_; 9283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 9383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko friend class ScopedArenaAllocator; 9483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko template <typename T> 9583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko friend class ScopedArenaAllocatorAdapter; 9683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 9783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DISALLOW_COPY_AND_ASSIGN(ArenaStack); 9883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko}; 9983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 10083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Markoclass ScopedArenaAllocator 10183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko : private DebugStackReference, private DebugStackRefCounter, private ArenaAllocatorStats { 10283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko public: 10383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko // Create a ScopedArenaAllocator directly on the ArenaStack when the scope of 10483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko // the allocator is not exactly a C++ block scope. For example, an optimization 10583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko // pass can create the scoped allocator in Start() and destroy it in End(). 10683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko static ScopedArenaAllocator* Create(ArenaStack* arena_stack) { 10783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void* addr = arena_stack->Alloc(sizeof(ScopedArenaAllocator), kArenaAllocMisc); 10883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ScopedArenaAllocator* allocator = new(addr) ScopedArenaAllocator(arena_stack); 10983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko allocator->mark_ptr_ = reinterpret_cast<uint8_t*>(addr); 11083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko return allocator; 11183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 11283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 11383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko explicit ScopedArenaAllocator(ArenaStack* arena_stack); 11483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ~ScopedArenaAllocator(); 11583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 11683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void Reset(); 11783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 11883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko void* Alloc(size_t bytes, ArenaAllocKind kind) ALWAYS_INLINE { 11983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DebugStackReference::CheckTop(); 12083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko return arena_stack_->Alloc(bytes, kind); 12183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko } 12283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 1238081d2b8d7a743729557051d0294e040e61c747aVladimir Marko // Get adapter for use in STL containers. See scoped_arena_containers.h . 1248081d2b8d7a743729557051d0294e040e61c747aVladimir Marko ScopedArenaAllocatorAdapter<void> Adapter(ArenaAllocKind kind = kArenaAllocSTL); 12583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 12683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko // Allow a delete-expression to destroy but not deallocate allocators created by Create(). 12783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko static void operator delete(void* ptr) { UNUSED(ptr); } 12883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 12983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko private: 13083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko ArenaStack* const arena_stack_; 13183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko Arena* mark_arena_; 13283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko uint8_t* mark_ptr_; 13383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko uint8_t* mark_end_; 13483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 13583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko template <typename T> 13683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko friend class ScopedArenaAllocatorAdapter; 13783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 13883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko DISALLOW_COPY_AND_ASSIGN(ScopedArenaAllocator); 13983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko}; 14083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 14183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko} // namespace art 14283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko 14383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko#endif // ART_COMPILER_UTILS_SCOPED_ARENA_ALLOCATOR_H_ 144