1413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom/* 2413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * Copyright (C) 2013 The Android Open Source Project 3413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * 4413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * you may not use this file except in compliance with the License. 6413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * You may obtain a copy of the License at 7413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * 8413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * 10413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 11413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * See the License for the specific language governing permissions and 14413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom * limitations under the License. 15413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom */ 16413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom 17ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#ifndef ART_RUNTIME_BASE_ALLOCATOR_H_ 18ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#define ART_RUNTIME_BASE_ALLOCATOR_H_ 19413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom 20bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier#include <map> 21627f917e66a273e7cbc2805e49f53cf1b9ca0c77Dan Albert#include <set> 22bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 23bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier#include "atomic.h" 24413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom#include "base/macros.h" 25bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier#include "base/mutex.h" 267e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers#include "base/type_static_if.h" 27413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom 28413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstromnamespace art { 29413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom 30bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierstatic constexpr bool kEnableTrackingAllocator = false; 31bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 32413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstromclass Allocator { 33413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom public: 34413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom static Allocator* GetMallocAllocator(); 35413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom static Allocator* GetNoopAllocator(); 36413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom 37413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom Allocator() {} 38413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom virtual ~Allocator() {} 39413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom 40413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom virtual void* Alloc(size_t) = 0; 41413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom virtual void Free(void*) = 0; 42413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom 43413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom private: 44413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom DISALLOW_COPY_AND_ASSIGN(Allocator); 45413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom}; 46413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom 47bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier// Used by TrackedAllocators. 48bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierenum AllocatorTag { 49bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagHeap, 50bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagMonitorList, 51bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagClassTable, 52bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagInternTable, 53bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagMaps, 54bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagLOS, 55bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagSafeMap, 56bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagLOSMaps, 57bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagReferenceTable, 58bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagHeapBitmap, 59bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagHeapBitmapLOS, 60bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagMonitorPool, 61bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagLOSFreeList, 62bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagVerifier, 63bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagRememberedSet, 64bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagModUnionCardSet, 65bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagModUnionReferenceArray, 660a7993ee8796e75ea7f251b7cb9e32f2f4335333Andreas Gampe kAllocatorTagJNILibraries, 67bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagCompileTimeClassPath, 68bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagOatFile, 69bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagDexFileVerifier, 7058553c7fd89ce69857017322444265469bb6af62Mathieu Chartier kAllocatorTagRosAlloc, 71bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier kAllocatorTagCount, // Must always be last element. 72bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier}; 73bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierstd::ostream& operator<<(std::ostream& os, const AllocatorTag& tag); 74bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 757e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersnamespace TrackedAllocators { 767e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers 777e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// Running count of number of bytes used for this kind of allocation. Increased by allocations, 787e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// decreased by deallocations. 797e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersextern Atomic<size_t> g_bytes_used[kAllocatorTagCount]; 807e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers 817e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// Largest value of bytes used seen. 827e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersextern volatile size_t g_max_bytes_used[kAllocatorTagCount]; 837e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers 847e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// Total number of bytes allocated of this kind. 857e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersextern Atomic<uint64_t> g_total_bytes_used[kAllocatorTagCount]; 867e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers 877e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersvoid Dump(std::ostream& os); 887e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers 897e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersinline void RegisterAllocation(AllocatorTag tag, size_t bytes) { 907e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers g_total_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes); 917e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers size_t new_bytes = g_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes) + bytes; 927e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers if (g_max_bytes_used[tag] < new_bytes) { 937e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers g_max_bytes_used[tag] = new_bytes; 94bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier } 957e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers} 96bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 977e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersinline void RegisterFree(AllocatorTag tag, size_t bytes) { 987e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers g_bytes_used[tag].FetchAndSubSequentiallyConsistent(bytes); 997e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers} 1007e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers 1017e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers} // namespace TrackedAllocators 102bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 1037e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// Tracking allocator for use with STL types, tracks how much memory is used. 104bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartiertemplate<class T, AllocatorTag kTag> 105c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartierclass TrackingAllocatorImpl : public std::allocator<T> { 106bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier public: 107bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier typedef typename std::allocator<T>::value_type value_type; 108bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier typedef typename std::allocator<T>::size_type size_type; 109bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier typedef typename std::allocator<T>::difference_type difference_type; 110bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier typedef typename std::allocator<T>::pointer pointer; 111bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier typedef typename std::allocator<T>::const_pointer const_pointer; 112bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier typedef typename std::allocator<T>::reference reference; 113bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier typedef typename std::allocator<T>::const_reference const_reference; 114bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 115bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier // Used internally by STL data structures. 116bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier template <class U> 117758a801b66c134361a7b43f7e83f85d1fb800c4cAndreas Gampe TrackingAllocatorImpl(const TrackingAllocatorImpl<U, kTag>& alloc) noexcept { 1186a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(alloc); 119bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier } 120bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 121bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier // Used internally by STL data structures. 122758a801b66c134361a7b43f7e83f85d1fb800c4cAndreas Gampe TrackingAllocatorImpl() noexcept { 123575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe static_assert(kTag < kAllocatorTagCount, "kTag must be less than kAllocatorTagCount"); 124bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier } 125bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 126bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier // Enables an allocator for objects of one type to allocate storage for objects of another type. 127bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier // Used internally by STL data structures. 128bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier template <class U> 129bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier struct rebind { 130bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier typedef TrackingAllocatorImpl<U, kTag> other; 131bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier }; 132bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 133bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier pointer allocate(size_type n, const_pointer hint = 0) { 1346a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(hint); 135bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier const size_t size = n * sizeof(T); 136bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier TrackedAllocators::RegisterAllocation(GetTag(), size); 137bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier return reinterpret_cast<pointer>(malloc(size)); 138bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier } 139bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 140bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier template <typename PT> 141bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier void deallocate(PT p, size_type n) { 142bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier const size_t size = n * sizeof(T); 143bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier TrackedAllocators::RegisterFree(GetTag(), size); 144bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier free(p); 145bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier } 146bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 1477e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers static constexpr AllocatorTag GetTag() { 148bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier return kTag; 149bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier } 150bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier}; 151bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 152bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartiertemplate<class T, AllocatorTag kTag> 153bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier// C++ doesn't allow template typedefs. This is a workaround template typedef which is 154bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier// TrackingAllocatorImpl<T> if kEnableTrackingAllocator is true, std::allocator<T> otherwise. 155bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierclass TrackingAllocator : public TypeStaticIf<kEnableTrackingAllocator, 156bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier TrackingAllocatorImpl<T, kTag>, 157bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier std::allocator<T>>::type { 158bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier}; 159bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 160bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartiertemplate<class Key, class T, AllocatorTag kTag, class Compare = std::less<Key>> 161bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierclass AllocationTrackingMultiMap : public std::multimap< 162bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier Key, T, Compare, TrackingAllocator<std::pair<Key, T>, kTag>> { 163bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier}; 164bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 16558553c7fd89ce69857017322444265469bb6af62Mathieu Chartiertemplate<class Key, AllocatorTag kTag, class Compare = std::less<Key>> 16658553c7fd89ce69857017322444265469bb6af62Mathieu Chartierclass AllocationTrackingSet : public std::set<Key, Compare, TrackingAllocator<Key, kTag>> { 16758553c7fd89ce69857017322444265469bb6af62Mathieu Chartier}; 16858553c7fd89ce69857017322444265469bb6af62Mathieu Chartier 169413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom} // namespace art 170413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom 171ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#endif // ART_RUNTIME_BASE_ALLOCATOR_H_ 172