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>
21627f917e66a273e7cbc2805e49f53cf1b9ca0c77Dan Albert#include <set>
22bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
23bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier#include "atomic.h"
24413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom#include "base/macros.h"
25bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier#include "base/mutex.h"
267e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers#include "base/type_static_if.h"
27413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom
28413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstromnamespace art {
29413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom
30bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierstatic constexpr bool kEnableTrackingAllocator = false;
31bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
32413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstromclass Allocator {
33413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom public:
34413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom  static Allocator* GetMallocAllocator();
35413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom  static Allocator* GetNoopAllocator();
36413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom
37413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom  Allocator() {}
38413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom  virtual ~Allocator() {}
39413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom
40413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom  virtual void* Alloc(size_t) = 0;
41413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom  virtual void Free(void*) = 0;
42413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom
43413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom private:
44413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom  DISALLOW_COPY_AND_ASSIGN(Allocator);
45413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom};
46413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom
47bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier// Used by TrackedAllocators.
48bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierenum AllocatorTag {
49bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagHeap,
50bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagMonitorList,
51bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagClassTable,
52bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagInternTable,
53bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagMaps,
54bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagLOS,
55bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagSafeMap,
56bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagLOSMaps,
57bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagReferenceTable,
58bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagHeapBitmap,
59bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagHeapBitmapLOS,
60bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagMonitorPool,
61bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagLOSFreeList,
62bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagVerifier,
63bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagRememberedSet,
64bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagModUnionCardSet,
65bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagModUnionReferenceArray,
660a7993ee8796e75ea7f251b7cb9e32f2f4335333Andreas Gampe  kAllocatorTagJNILibraries,
67bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagCompileTimeClassPath,
68bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagOatFile,
69bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagDexFileVerifier,
7058553c7fd89ce69857017322444265469bb6af62Mathieu Chartier  kAllocatorTagRosAlloc,
71bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  kAllocatorTagCount,  // Must always be last element.
72bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier};
73bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierstd::ostream& operator<<(std::ostream& os, const AllocatorTag& tag);
74bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
757e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersnamespace TrackedAllocators {
767e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers
777e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// Running count of number of bytes used for this kind of allocation. Increased by allocations,
787e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// decreased by deallocations.
797e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersextern Atomic<size_t> g_bytes_used[kAllocatorTagCount];
807e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers
817e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// Largest value of bytes used seen.
827e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersextern volatile size_t g_max_bytes_used[kAllocatorTagCount];
837e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers
847e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// Total number of bytes allocated of this kind.
857e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersextern Atomic<uint64_t> g_total_bytes_used[kAllocatorTagCount];
867e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers
877e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersvoid Dump(std::ostream& os);
887e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers
897e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersinline void RegisterAllocation(AllocatorTag tag, size_t bytes) {
907e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers  g_total_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes);
917e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers  size_t new_bytes = g_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes) + bytes;
927e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers  if (g_max_bytes_used[tag] < new_bytes) {
937e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers    g_max_bytes_used[tag] = new_bytes;
94bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  }
957e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers}
96bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
977e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogersinline void RegisterFree(AllocatorTag tag, size_t bytes) {
987e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers  g_bytes_used[tag].FetchAndSubSequentiallyConsistent(bytes);
997e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers}
1007e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers
1017e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers}  // namespace TrackedAllocators
102bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
1037e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers// Tracking allocator for use with STL types, tracks how much memory is used.
104bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartiertemplate<class T, AllocatorTag kTag>
105c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartierclass TrackingAllocatorImpl : public std::allocator<T> {
106bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier public:
107bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  typedef typename std::allocator<T>::value_type value_type;
108bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  typedef typename std::allocator<T>::size_type size_type;
109bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  typedef typename std::allocator<T>::difference_type difference_type;
110bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  typedef typename std::allocator<T>::pointer pointer;
111bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  typedef typename std::allocator<T>::const_pointer const_pointer;
112bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  typedef typename std::allocator<T>::reference reference;
113bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  typedef typename std::allocator<T>::const_reference const_reference;
114bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
115bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  // Used internally by STL data structures.
116bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  template <class U>
117758a801b66c134361a7b43f7e83f85d1fb800c4cAndreas Gampe  TrackingAllocatorImpl(const TrackingAllocatorImpl<U, kTag>& alloc) noexcept {
1186a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    UNUSED(alloc);
119bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  }
120bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
121bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  // Used internally by STL data structures.
122758a801b66c134361a7b43f7e83f85d1fb800c4cAndreas Gampe  TrackingAllocatorImpl() noexcept {
123575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe    static_assert(kTag < kAllocatorTagCount, "kTag must be less than kAllocatorTagCount");
124bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  }
125bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
126bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  // Enables an allocator for objects of one type to allocate storage for objects of another type.
127bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  // Used internally by STL data structures.
128bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  template <class U>
129bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  struct rebind {
130bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier    typedef TrackingAllocatorImpl<U, kTag> other;
131bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  };
132bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
133bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  pointer allocate(size_type n, const_pointer hint = 0) {
1346a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    UNUSED(hint);
135bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier    const size_t size = n * sizeof(T);
136bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier    TrackedAllocators::RegisterAllocation(GetTag(), size);
137bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier    return reinterpret_cast<pointer>(malloc(size));
138bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  }
139bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
140bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  template <typename PT>
141bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  void deallocate(PT p, size_type n) {
142bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier    const size_t size = n * sizeof(T);
143bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier    TrackedAllocators::RegisterFree(GetTag(), size);
144bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier    free(p);
145bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  }
146bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
1477e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers  static constexpr AllocatorTag GetTag() {
148bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier    return kTag;
149bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  }
150bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier};
151bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
152bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartiertemplate<class T, AllocatorTag kTag>
153bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier// C++ doesn't allow template typedefs. This is a workaround template typedef which is
154bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier// TrackingAllocatorImpl<T> if kEnableTrackingAllocator is true, std::allocator<T> otherwise.
155bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierclass TrackingAllocator : public TypeStaticIf<kEnableTrackingAllocator,
156bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier                                              TrackingAllocatorImpl<T, kTag>,
157bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier                                              std::allocator<T>>::type {
158bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier};
159bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
160bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartiertemplate<class Key, class T, AllocatorTag kTag, class Compare = std::less<Key>>
161bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartierclass AllocationTrackingMultiMap : public std::multimap<
162bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier    Key, T, Compare, TrackingAllocator<std::pair<Key, T>, kTag>> {
163bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier};
164bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
16558553c7fd89ce69857017322444265469bb6af62Mathieu Chartiertemplate<class Key, AllocatorTag kTag, class Compare = std::less<Key>>
16658553c7fd89ce69857017322444265469bb6af62Mathieu Chartierclass AllocationTrackingSet : public std::set<Key, Compare, TrackingAllocator<Key, kTag>> {
16758553c7fd89ce69857017322444265469bb6af62Mathieu Chartier};
16858553c7fd89ce69857017322444265469bb6af62Mathieu Chartier
169413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom}  // namespace art
170413e89f277ec6ba1bdf2040f5b5611f29a27a447Brian Carlstrom
171ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#endif  // ART_RUNTIME_BASE_ALLOCATOR_H_
172