blob: 4f513707bb0f0afd46ec9108a9b66b7ee8510638 [file] [log] [blame]
Vladimir Marko83cc7ae2014-02-12 18:02:05 +00001/*
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
Mathieu Chartierb666f482015-02-18 14:33:14 -080017#ifndef ART_RUNTIME_BASE_SCOPED_ARENA_ALLOCATOR_H_
18#define ART_RUNTIME_BASE_SCOPED_ARENA_ALLOCATOR_H_
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000019
Mathieu Chartierb666f482015-02-18 14:33:14 -080020#include "arena_allocator.h"
21#include "debug_stack.h"
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000022#include "globals.h"
Mathieu Chartierb666f482015-02-18 14:33:14 -080023#include "logging.h"
24#include "macros.h"
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000025
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.
Vladimir Marko2a408a32015-09-18 14:11:00 +010035class ArenaStack : private DebugStackRefCounter, private ArenaAllocatorMemoryTool {
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000036 public:
37 explicit ArenaStack(ArenaPool* arena_pool);
38 ~ArenaStack();
39
Vladimir Marko2a408a32015-09-18 14:11:00 +010040 using ArenaAllocatorMemoryTool::IsRunningOnMemoryTool;
41 using ArenaAllocatorMemoryTool::MakeDefined;
42 using ArenaAllocatorMemoryTool::MakeUndefined;
43 using ArenaAllocatorMemoryTool::MakeInaccessible;
44
Vladimir Marko53b6afc2014-03-21 14:21:20 +000045 void Reset();
46
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000047 size_t PeakBytesAllocated() {
48 return PeakStats()->BytesAllocated();
49 }
50
51 MemStats GetPeakStats() const;
52
53 private:
54 struct Peak;
55 struct Current;
56 template <typename Tag> struct TaggedStats : ArenaAllocatorStats { };
57 struct StatsAndPool : TaggedStats<Peak>, TaggedStats<Current> {
58 explicit StatsAndPool(ArenaPool* arena_pool) : pool(arena_pool) { }
59 ArenaPool* const pool;
60 };
61
62 ArenaAllocatorStats* PeakStats() {
63 return static_cast<TaggedStats<Peak>*>(&stats_and_pool_);
64 }
65
66 ArenaAllocatorStats* CurrentStats() {
67 return static_cast<TaggedStats<Current>*>(&stats_and_pool_);
68 }
69
70 // Private - access via ScopedArenaAllocator or ScopedArenaAllocatorAdapter.
71 void* Alloc(size_t bytes, ArenaAllocKind kind) ALWAYS_INLINE {
Vladimir Marko2a408a32015-09-18 14:11:00 +010072 if (UNLIKELY(IsRunningOnMemoryTool())) {
73 return AllocWithMemoryTool(bytes, kind);
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000074 }
Vladimir Marko22a0ef82014-06-10 14:47:51 +010075 size_t rounded_bytes = RoundUp(bytes, 8);
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000076 uint8_t* ptr = top_ptr_;
77 if (UNLIKELY(static_cast<size_t>(top_end_ - ptr) < rounded_bytes)) {
78 ptr = AllocateFromNextArena(rounded_bytes);
79 }
80 CurrentStats()->RecordAlloc(bytes, kind);
81 top_ptr_ = ptr + rounded_bytes;
82 return ptr;
83 }
84
85 uint8_t* AllocateFromNextArena(size_t rounded_bytes);
86 void UpdatePeakStatsAndRestore(const ArenaAllocatorStats& restore_stats);
87 void UpdateBytesAllocated();
Vladimir Marko2a408a32015-09-18 14:11:00 +010088 void* AllocWithMemoryTool(size_t bytes, ArenaAllocKind kind);
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000089
90 StatsAndPool stats_and_pool_;
91 Arena* bottom_arena_;
92 Arena* top_arena_;
93 uint8_t* top_ptr_;
94 uint8_t* top_end_;
95
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000096 friend class ScopedArenaAllocator;
97 template <typename T>
98 friend class ScopedArenaAllocatorAdapter;
99
100 DISALLOW_COPY_AND_ASSIGN(ArenaStack);
101};
102
103class ScopedArenaAllocator
104 : private DebugStackReference, private DebugStackRefCounter, private ArenaAllocatorStats {
105 public:
106 // Create a ScopedArenaAllocator directly on the ArenaStack when the scope of
107 // the allocator is not exactly a C++ block scope. For example, an optimization
108 // pass can create the scoped allocator in Start() and destroy it in End().
109 static ScopedArenaAllocator* Create(ArenaStack* arena_stack) {
110 void* addr = arena_stack->Alloc(sizeof(ScopedArenaAllocator), kArenaAllocMisc);
111 ScopedArenaAllocator* allocator = new(addr) ScopedArenaAllocator(arena_stack);
112 allocator->mark_ptr_ = reinterpret_cast<uint8_t*>(addr);
113 return allocator;
114 }
115
116 explicit ScopedArenaAllocator(ArenaStack* arena_stack);
117 ~ScopedArenaAllocator();
118
119 void Reset();
120
Vladimir Markoe4fcc5b2015-02-13 10:28:29 +0000121 void* Alloc(size_t bytes, ArenaAllocKind kind = kArenaAllocMisc) ALWAYS_INLINE {
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000122 DebugStackReference::CheckTop();
123 return arena_stack_->Alloc(bytes, kind);
124 }
125
Vladimir Markoe4fcc5b2015-02-13 10:28:29 +0000126 template <typename T>
127 T* AllocArray(size_t length, ArenaAllocKind kind = kArenaAllocMisc) {
128 return static_cast<T*>(Alloc(length * sizeof(T), kind));
129 }
130
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100131 // Get adapter for use in STL containers. See scoped_arena_containers.h .
132 ScopedArenaAllocatorAdapter<void> Adapter(ArenaAllocKind kind = kArenaAllocSTL);
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000133
134 // Allow a delete-expression to destroy but not deallocate allocators created by Create().
135 static void operator delete(void* ptr) { UNUSED(ptr); }
136
137 private:
138 ArenaStack* const arena_stack_;
139 Arena* mark_arena_;
140 uint8_t* mark_ptr_;
141 uint8_t* mark_end_;
142
Vladimir Marko3d2ec352014-10-10 15:39:11 +0100143 void DoReset();
144
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000145 template <typename T>
146 friend class ScopedArenaAllocatorAdapter;
147
148 DISALLOW_COPY_AND_ASSIGN(ScopedArenaAllocator);
149};
150
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000151} // namespace art
152
Mathieu Chartierb666f482015-02-18 14:33:14 -0800153#endif // ART_RUNTIME_BASE_SCOPED_ARENA_ALLOCATOR_H_