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