scoped_arena_allocator.h revision 8081d2b8d7a743729557051d0294e040e61c747a
1/*
2 * Copyright (C) 2014 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_COMPILER_UTILS_SCOPED_ARENA_ALLOCATOR_H_
18#define ART_COMPILER_UTILS_SCOPED_ARENA_ALLOCATOR_H_
19
20#include "base/logging.h"
21#include "base/macros.h"
22#include "utils/arena_allocator.h"
23#include "utils/debug_stack.h"
24#include "globals.h"
25
26namespace art {
27
28class ArenaStack;
29class ScopedArenaAllocator;
30
31template <typename T>
32class ScopedArenaAllocatorAdapter;
33
34// Holds a list of Arenas for use by ScopedArenaAllocator stack.
35class ArenaStack : private DebugStackRefCounter {
36 public:
37  explicit ArenaStack(ArenaPool* arena_pool);
38  ~ArenaStack();
39
40  void Reset();
41
42  size_t PeakBytesAllocated() {
43    return PeakStats()->BytesAllocated();
44  }
45
46  MemStats GetPeakStats() const;
47
48 private:
49  struct Peak;
50  struct Current;
51  template <typename Tag> struct TaggedStats : ArenaAllocatorStats { };
52  struct StatsAndPool : TaggedStats<Peak>, TaggedStats<Current> {
53    explicit StatsAndPool(ArenaPool* arena_pool) : pool(arena_pool) { }
54    ArenaPool* const pool;
55  };
56
57  ArenaAllocatorStats* PeakStats() {
58    return static_cast<TaggedStats<Peak>*>(&stats_and_pool_);
59  }
60
61  ArenaAllocatorStats* CurrentStats() {
62    return static_cast<TaggedStats<Current>*>(&stats_and_pool_);
63  }
64
65  // Private - access via ScopedArenaAllocator or ScopedArenaAllocatorAdapter.
66  void* Alloc(size_t bytes, ArenaAllocKind kind) ALWAYS_INLINE {
67    if (UNLIKELY(running_on_valgrind_)) {
68      return AllocValgrind(bytes, kind);
69    }
70    size_t rounded_bytes = RoundUp(bytes, 8);
71    uint8_t* ptr = top_ptr_;
72    if (UNLIKELY(static_cast<size_t>(top_end_ - ptr) < rounded_bytes)) {
73      ptr = AllocateFromNextArena(rounded_bytes);
74    }
75    CurrentStats()->RecordAlloc(bytes, kind);
76    top_ptr_ = ptr + rounded_bytes;
77    return ptr;
78  }
79
80  uint8_t* AllocateFromNextArena(size_t rounded_bytes);
81  void UpdatePeakStatsAndRestore(const ArenaAllocatorStats& restore_stats);
82  void UpdateBytesAllocated();
83  void* AllocValgrind(size_t bytes, ArenaAllocKind kind);
84
85  StatsAndPool stats_and_pool_;
86  Arena* bottom_arena_;
87  Arena* top_arena_;
88  uint8_t* top_ptr_;
89  uint8_t* top_end_;
90
91  const bool running_on_valgrind_;
92
93  friend class ScopedArenaAllocator;
94  template <typename T>
95  friend class ScopedArenaAllocatorAdapter;
96
97  DISALLOW_COPY_AND_ASSIGN(ArenaStack);
98};
99
100class ScopedArenaAllocator
101    : private DebugStackReference, private DebugStackRefCounter, private ArenaAllocatorStats {
102 public:
103  // Create a ScopedArenaAllocator directly on the ArenaStack when the scope of
104  // the allocator is not exactly a C++ block scope. For example, an optimization
105  // pass can create the scoped allocator in Start() and destroy it in End().
106  static ScopedArenaAllocator* Create(ArenaStack* arena_stack) {
107    void* addr = arena_stack->Alloc(sizeof(ScopedArenaAllocator), kArenaAllocMisc);
108    ScopedArenaAllocator* allocator = new(addr) ScopedArenaAllocator(arena_stack);
109    allocator->mark_ptr_ = reinterpret_cast<uint8_t*>(addr);
110    return allocator;
111  }
112
113  explicit ScopedArenaAllocator(ArenaStack* arena_stack);
114  ~ScopedArenaAllocator();
115
116  void Reset();
117
118  void* Alloc(size_t bytes, ArenaAllocKind kind) ALWAYS_INLINE {
119    DebugStackReference::CheckTop();
120    return arena_stack_->Alloc(bytes, kind);
121  }
122
123  // Get adapter for use in STL containers. See scoped_arena_containers.h .
124  ScopedArenaAllocatorAdapter<void> Adapter(ArenaAllocKind kind = kArenaAllocSTL);
125
126  // Allow a delete-expression to destroy but not deallocate allocators created by Create().
127  static void operator delete(void* ptr) { UNUSED(ptr); }
128
129 private:
130  ArenaStack* const arena_stack_;
131  Arena* mark_arena_;
132  uint8_t* mark_ptr_;
133  uint8_t* mark_end_;
134
135  template <typename T>
136  friend class ScopedArenaAllocatorAdapter;
137
138  DISALLOW_COPY_AND_ASSIGN(ScopedArenaAllocator);
139};
140
141}  // namespace art
142
143#endif  // ART_COMPILER_UTILS_SCOPED_ARENA_ALLOCATOR_H_
144