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 
     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