1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_BASE_ALLOCATOR_H_ 18 #define ART_RUNTIME_BASE_ALLOCATOR_H_ 19 20 #include <map> 21 #include <set> 22 #include <unordered_map> 23 24 #include "atomic.h" 25 #include "base/hash_map.h" 26 #include "base/macros.h" 27 #include "base/mutex.h" 28 #include "base/type_static_if.h" 29 30 namespace art { 31 32 static constexpr bool kEnableTrackingAllocator = false; 33 34 class Allocator { 35 public: 36 static Allocator* GetMallocAllocator(); 37 static Allocator* GetNoopAllocator(); 38 39 Allocator() {} 40 virtual ~Allocator() {} 41 42 virtual void* Alloc(size_t) = 0; 43 virtual void Free(void*) = 0; 44 45 private: 46 DISALLOW_COPY_AND_ASSIGN(Allocator); 47 }; 48 49 // Used by TrackedAllocators. 50 enum AllocatorTag { 51 kAllocatorTagHeap, 52 kAllocatorTagMonitorList, 53 kAllocatorTagClassTable, 54 kAllocatorTagInternTable, 55 kAllocatorTagMaps, 56 kAllocatorTagLOS, 57 kAllocatorTagSafeMap, 58 kAllocatorTagLOSMaps, 59 kAllocatorTagReferenceTable, 60 kAllocatorTagHeapBitmap, 61 kAllocatorTagHeapBitmapLOS, 62 kAllocatorTagMonitorPool, 63 kAllocatorTagLOSFreeList, 64 kAllocatorTagVerifier, 65 kAllocatorTagRememberedSet, 66 kAllocatorTagModUnionCardSet, 67 kAllocatorTagModUnionReferenceArray, 68 kAllocatorTagJNILibraries, 69 kAllocatorTagCompileTimeClassPath, 70 kAllocatorTagOatFile, 71 kAllocatorTagDexFileVerifier, 72 kAllocatorTagRosAlloc, 73 kAllocatorTagCount, // Must always be last element. 74 }; 75 std::ostream& operator<<(std::ostream& os, const AllocatorTag& tag); 76 77 namespace TrackedAllocators { 78 79 // Running count of number of bytes used for this kind of allocation. Increased by allocations, 80 // decreased by deallocations. 81 extern Atomic<size_t> g_bytes_used[kAllocatorTagCount]; 82 83 // Largest value of bytes used seen. 84 extern volatile size_t g_max_bytes_used[kAllocatorTagCount]; 85 86 // Total number of bytes allocated of this kind. 87 extern Atomic<uint64_t> g_total_bytes_used[kAllocatorTagCount]; 88 89 void Dump(std::ostream& os); 90 91 inline void RegisterAllocation(AllocatorTag tag, size_t bytes) { 92 g_total_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes); 93 size_t new_bytes = g_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes) + bytes; 94 if (g_max_bytes_used[tag] < new_bytes) { 95 g_max_bytes_used[tag] = new_bytes; 96 } 97 } 98 99 inline void RegisterFree(AllocatorTag tag, size_t bytes) { 100 g_bytes_used[tag].FetchAndSubSequentiallyConsistent(bytes); 101 } 102 103 } // namespace TrackedAllocators 104 105 // Tracking allocator for use with STL types, tracks how much memory is used. 106 template<class T, AllocatorTag kTag> 107 class TrackingAllocatorImpl : public std::allocator<T> { 108 public: 109 typedef typename std::allocator<T>::value_type value_type; 110 typedef typename std::allocator<T>::size_type size_type; 111 typedef typename std::allocator<T>::difference_type difference_type; 112 typedef typename std::allocator<T>::pointer pointer; 113 typedef typename std::allocator<T>::const_pointer const_pointer; 114 typedef typename std::allocator<T>::reference reference; 115 typedef typename std::allocator<T>::const_reference const_reference; 116 117 // Used internally by STL data structures. 118 template <class U> 119 TrackingAllocatorImpl( // NOLINT, implicit 120 const TrackingAllocatorImpl<U, kTag>& alloc ATTRIBUTE_UNUSED) noexcept {} 121 122 // Used internally by STL data structures. 123 TrackingAllocatorImpl() noexcept { 124 static_assert(kTag < kAllocatorTagCount, "kTag must be less than kAllocatorTagCount"); 125 } 126 127 // Enables an allocator for objects of one type to allocate storage for objects of another type. 128 // Used internally by STL data structures. 129 template <class U> 130 struct rebind { 131 typedef TrackingAllocatorImpl<U, kTag> other; 132 }; 133 134 pointer allocate(size_type n, const_pointer hint ATTRIBUTE_UNUSED = 0) { 135 const size_t size = n * sizeof(T); 136 TrackedAllocators::RegisterAllocation(GetTag(), size); 137 return reinterpret_cast<pointer>(malloc(size)); 138 } 139 140 template <typename PT> 141 void deallocate(PT p, size_type n) { 142 const size_t size = n * sizeof(T); 143 TrackedAllocators::RegisterFree(GetTag(), size); 144 free(p); 145 } 146 147 static constexpr AllocatorTag GetTag() { 148 return kTag; 149 } 150 }; 151 152 template<class T, AllocatorTag kTag> 153 // C++ doesn't allow template typedefs. This is a workaround template typedef which is 154 // TrackingAllocatorImpl<T> if kEnableTrackingAllocator is true, std::allocator<T> otherwise. 155 using TrackingAllocator = typename TypeStaticIf<kEnableTrackingAllocator, 156 TrackingAllocatorImpl<T, kTag>, 157 std::allocator<T>>::type; 158 159 template<class Key, class T, AllocatorTag kTag, class Compare = std::less<Key>> 160 using AllocationTrackingMultiMap = std::multimap< 161 Key, T, Compare, TrackingAllocator<std::pair<const Key, T>, kTag>>; 162 163 template<class Key, AllocatorTag kTag, class Compare = std::less<Key>> 164 using AllocationTrackingSet = std::set<Key, Compare, TrackingAllocator<Key, kTag>>; 165 166 template<class Key, 167 class T, 168 AllocatorTag kTag, 169 class Hash = std::hash<Key>, 170 class Pred = std::equal_to<Key>> 171 using AllocationTrackingUnorderedMap = std::unordered_map< 172 Key, T, Hash, Pred, TrackingAllocator<std::pair<const Key, T>, kTag>>; 173 174 template<class Key, 175 class T, 176 class EmptyFn, 177 AllocatorTag kTag, 178 class Hash = std::hash<Key>, 179 class Pred = std::equal_to<Key>> 180 using AllocationTrackingHashMap = HashMap< 181 Key, T, EmptyFn, Hash, Pred, TrackingAllocator<std::pair<Key, T>, kTag>>; 182 } // namespace art 183 184 #endif // ART_RUNTIME_BASE_ALLOCATOR_H_ 185