Home | History | Annotate | Download | only in base
      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