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