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 23 #include "atomic.h" 24 #include "base/macros.h" 25 #include "base/mutex.h" 26 #include "base/type_static_if.h" 27 28 namespace art { 29 30 static constexpr bool kEnableTrackingAllocator = false; 31 32 class Allocator { 33 public: 34 static Allocator* GetMallocAllocator(); 35 static Allocator* GetNoopAllocator(); 36 37 Allocator() {} 38 virtual ~Allocator() {} 39 40 virtual void* Alloc(size_t) = 0; 41 virtual void Free(void*) = 0; 42 43 private: 44 DISALLOW_COPY_AND_ASSIGN(Allocator); 45 }; 46 47 // Used by TrackedAllocators. 48 enum AllocatorTag { 49 kAllocatorTagHeap, 50 kAllocatorTagMonitorList, 51 kAllocatorTagClassTable, 52 kAllocatorTagInternTable, 53 kAllocatorTagMaps, 54 kAllocatorTagLOS, 55 kAllocatorTagSafeMap, 56 kAllocatorTagLOSMaps, 57 kAllocatorTagReferenceTable, 58 kAllocatorTagHeapBitmap, 59 kAllocatorTagHeapBitmapLOS, 60 kAllocatorTagMonitorPool, 61 kAllocatorTagLOSFreeList, 62 kAllocatorTagVerifier, 63 kAllocatorTagRememberedSet, 64 kAllocatorTagModUnionCardSet, 65 kAllocatorTagModUnionReferenceArray, 66 kAllocatorTagJNILibraries, 67 kAllocatorTagCompileTimeClassPath, 68 kAllocatorTagOatFile, 69 kAllocatorTagDexFileVerifier, 70 kAllocatorTagRosAlloc, 71 kAllocatorTagCount, // Must always be last element. 72 }; 73 std::ostream& operator<<(std::ostream& os, const AllocatorTag& tag); 74 75 namespace TrackedAllocators { 76 77 // Running count of number of bytes used for this kind of allocation. Increased by allocations, 78 // decreased by deallocations. 79 extern Atomic<size_t> g_bytes_used[kAllocatorTagCount]; 80 81 // Largest value of bytes used seen. 82 extern volatile size_t g_max_bytes_used[kAllocatorTagCount]; 83 84 // Total number of bytes allocated of this kind. 85 extern Atomic<uint64_t> g_total_bytes_used[kAllocatorTagCount]; 86 87 void Dump(std::ostream& os); 88 89 inline void RegisterAllocation(AllocatorTag tag, size_t bytes) { 90 g_total_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes); 91 size_t new_bytes = g_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes) + bytes; 92 if (g_max_bytes_used[tag] < new_bytes) { 93 g_max_bytes_used[tag] = new_bytes; 94 } 95 } 96 97 inline void RegisterFree(AllocatorTag tag, size_t bytes) { 98 g_bytes_used[tag].FetchAndSubSequentiallyConsistent(bytes); 99 } 100 101 } // namespace TrackedAllocators 102 103 // Tracking allocator for use with STL types, tracks how much memory is used. 104 template<class T, AllocatorTag kTag> 105 class TrackingAllocatorImpl : public std::allocator<T> { 106 public: 107 typedef typename std::allocator<T>::value_type value_type; 108 typedef typename std::allocator<T>::size_type size_type; 109 typedef typename std::allocator<T>::difference_type difference_type; 110 typedef typename std::allocator<T>::pointer pointer; 111 typedef typename std::allocator<T>::const_pointer const_pointer; 112 typedef typename std::allocator<T>::reference reference; 113 typedef typename std::allocator<T>::const_reference const_reference; 114 115 // Used internally by STL data structures. 116 template <class U> 117 TrackingAllocatorImpl(const TrackingAllocatorImpl<U, kTag>& alloc) noexcept { 118 UNUSED(alloc); 119 } 120 121 // Used internally by STL data structures. 122 TrackingAllocatorImpl() noexcept { 123 static_assert(kTag < kAllocatorTagCount, "kTag must be less than kAllocatorTagCount"); 124 } 125 126 // Enables an allocator for objects of one type to allocate storage for objects of another type. 127 // Used internally by STL data structures. 128 template <class U> 129 struct rebind { 130 typedef TrackingAllocatorImpl<U, kTag> other; 131 }; 132 133 pointer allocate(size_type n, const_pointer hint = 0) { 134 UNUSED(hint); 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 class TrackingAllocator : public TypeStaticIf<kEnableTrackingAllocator, 156 TrackingAllocatorImpl<T, kTag>, 157 std::allocator<T>>::type { 158 }; 159 160 template<class Key, class T, AllocatorTag kTag, class Compare = std::less<Key>> 161 class AllocationTrackingMultiMap : public std::multimap< 162 Key, T, Compare, TrackingAllocator<std::pair<Key, T>, kTag>> { 163 }; 164 165 template<class Key, AllocatorTag kTag, class Compare = std::less<Key>> 166 class AllocationTrackingSet : public std::set<Key, Compare, TrackingAllocator<Key, kTag>> { 167 }; 168 169 } // namespace art 170 171 #endif // ART_RUNTIME_BASE_ALLOCATOR_H_ 172