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