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