blob: 993492da6d7e73cf5db8bfcf76f8346a83cae88c [file] [log] [blame]
buzbee862a7602013-04-05 10:58:54 -07001/*
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
Nicolas Geoffray818f2102014-02-18 16:43:35 +000017#ifndef ART_COMPILER_UTILS_GROWABLE_ARRAY_H_
18#define ART_COMPILER_UTILS_GROWABLE_ARRAY_H_
buzbee862a7602013-04-05 10:58:54 -070019
20#include <stdint.h>
21#include <stddef.h>
buzbee862a7602013-04-05 10:58:54 -070022#include "arena_allocator.h"
23
24namespace art {
25
buzbee862a7602013-04-05 10:58:54 -070026// Type of growable list for memory tuning.
27enum OatListKind {
28 kGrowableArrayMisc = 0,
29 kGrowableArrayBlockList,
30 kGrowableArraySSAtoDalvikMap,
31 kGrowableArrayDfsOrder,
32 kGrowableArrayDfsPostOrder,
33 kGrowableArrayDomPostOrderTraversal,
buzbee862a7602013-04-05 10:58:54 -070034 kGrowableArraySuspendLaunchPads,
35 kGrowableArraySwitchTables,
36 kGrowableArrayFillArrayData,
37 kGrowableArraySuccessorBlocks,
38 kGrowableArrayPredecessors,
Dave Allisonbcec6fb2014-01-17 12:52:22 -080039 kGrowableArraySlowPaths,
buzbee862a7602013-04-05 10:58:54 -070040 kGNumListKinds
41};
42
43template<typename T>
44class GrowableArray {
45 public:
buzbee862a7602013-04-05 10:58:54 -070046 class Iterator {
47 public:
Brian Carlstrom93ba8932013-07-17 21:31:49 -070048 explicit Iterator(GrowableArray* g_list)
buzbee862a7602013-04-05 10:58:54 -070049 : idx_(0),
Brian Carlstrom9b7085a2013-07-18 15:15:21 -070050 g_list_(g_list) {}
buzbee862a7602013-04-05 10:58:54 -070051
Jean Christophe Beyler1ceea7e2014-04-15 16:18:48 -070052 explicit Iterator()
53 : idx_(0),
54 g_list_(nullptr) {}
55
buzbee862a7602013-04-05 10:58:54 -070056 // NOTE: returns 0/NULL when no next.
57 // TODO: redo to make usage consistent with other iterators.
58 T Next() {
Jean Christophe Beyler1ceea7e2014-04-15 16:18:48 -070059 DCHECK(g_list_ != nullptr);
buzbee862a7602013-04-05 10:58:54 -070060 if (idx_ >= g_list_->Size()) {
61 return 0;
62 } else {
63 return g_list_->Get(idx_++);
64 }
65 }
66
67 void Reset() {
68 idx_ = 0;
69 }
70
Jean Christophe Beyler1ceea7e2014-04-15 16:18:48 -070071 void Reset(GrowableArray* g_list) {
72 idx_ = 0;
73 g_list_ = g_list;
74 }
75
76 size_t GetIndex() const {
77 return idx_;
78 }
79
buzbee862a7602013-04-05 10:58:54 -070080 private:
81 size_t idx_;
82 GrowableArray* const g_list_;
83 };
84
85 GrowableArray(ArenaAllocator* arena, size_t init_length, OatListKind kind = kGrowableArrayMisc)
86 : arena_(arena),
buzbeea5abf702013-04-12 14:39:29 -070087 num_allocated_(init_length),
buzbee862a7602013-04-05 10:58:54 -070088 num_used_(0),
89 kind_(kind) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070090 elem_list_ = static_cast<T*>(arena_->Alloc(sizeof(T) * init_length,
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000091 kArenaAllocGrowableArray));
buzbee862a7602013-04-05 10:58:54 -070092 };
93
94
95 // Expand the list size to at least new length.
96 void Resize(size_t new_length) {
97 if (new_length <= num_allocated_) return;
buzbeea5abf702013-04-12 14:39:29 -070098 // If it's a small list double the size, else grow 1.5x.
99 size_t target_length =
100 (num_allocated_ < 128) ? num_allocated_ << 1 : num_allocated_ + (num_allocated_ >> 1);
buzbee862a7602013-04-05 10:58:54 -0700101 if (new_length > target_length) {
102 target_length = new_length;
103 }
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700104 T* new_array = static_cast<T*>(arena_->Alloc(sizeof(T) * target_length,
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000105 kArenaAllocGrowableArray));
buzbee862a7602013-04-05 10:58:54 -0700106 memcpy(new_array, elem_list_, sizeof(T) * num_allocated_);
buzbee862a7602013-04-05 10:58:54 -0700107 num_allocated_ = target_length;
108 elem_list_ = new_array;
109 };
110
111 // NOTE: does not return storage, just resets use count.
112 void Reset() {
113 num_used_ = 0;
114 }
115
116 // Insert an element to the end of a list, resizing if necessary.
117 void Insert(T elem) {
118 if (num_used_ == num_allocated_) {
119 Resize(num_used_ + 1);
120 }
121 elem_list_[num_used_++] = elem;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000122 }
123
124 void InsertAt(size_t index, T elem) {
125 DCHECK(index <= Size());
126 Insert(elem);
127 for (size_t i = Size() - 1; i > index; --i) {
128 elem_list_[i] = elem_list_[i - 1];
129 }
130 elem_list_[index] = elem;
131 }
132
133 void Add(T elem) {
134 Insert(elem);
135 }
buzbee862a7602013-04-05 10:58:54 -0700136
137 T Get(size_t index) const {
138 DCHECK_LT(index, num_used_);
139 return elem_list_[index];
140 };
141
142 // Overwrite existing element at position index. List must be large enough.
143 void Put(size_t index, T elem) {
144 DCHECK_LT(index, num_used_);
145 elem_list_[index] = elem;
146 }
147
148 void Increment(size_t index) {
149 DCHECK_LT(index, num_used_);
150 elem_list_[index]++;
151 }
152
buzbeebd663de2013-09-10 15:41:31 -0700153 /*
154 * Remove an existing element from list. If there are more than one copy
155 * of the element, only the first one encountered will be deleted.
156 */
157 // TODO: consider renaming this.
buzbee862a7602013-04-05 10:58:54 -0700158 void Delete(T element) {
159 bool found = false;
160 for (size_t i = 0; i < num_used_ - 1; i++) {
161 if (!found && elem_list_[i] == element) {
162 found = true;
163 }
164 if (found) {
165 elem_list_[i] = elem_list_[i+1];
166 }
167 }
168 // We should either have found the element, or it was the last (unscanned) element.
169 DCHECK(found || (element == elem_list_[num_used_ - 1]));
170 num_used_--;
171 };
172
173 size_t GetNumAllocated() const { return num_allocated_; }
174
175 size_t Size() const { return num_used_; }
176
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000177 bool IsEmpty() const { return num_used_ == 0; }
178
179 T Pop() {
180 DCHECK_GE(num_used_, (size_t)0);
181 return elem_list_[--num_used_];
182 }
183
184 T Peek() const {
185 DCHECK_GE(num_used_, (size_t)0);
186 return elem_list_[num_used_ - 1];
187 }
188
buzbeebd663de2013-09-10 15:41:31 -0700189 void SetSize(size_t new_size) {
190 Resize(new_size);
191 num_used_ = new_size;
192 }
193
buzbee862a7602013-04-05 10:58:54 -0700194 T* GetRawStorage() const { return elem_list_; }
195
196 static void* operator new(size_t size, ArenaAllocator* arena) {
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000197 return arena->Alloc(sizeof(GrowableArray<T>), kArenaAllocGrowableArray);
buzbee862a7602013-04-05 10:58:54 -0700198 };
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700199 static void operator delete(void* p) {} // Nop.
buzbee862a7602013-04-05 10:58:54 -0700200
201 private:
202 ArenaAllocator* const arena_;
203 size_t num_allocated_;
204 size_t num_used_;
205 OatListKind kind_;
206 T* elem_list_;
207};
208
209} // namespace art
210
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000211#endif // ART_COMPILER_UTILS_GROWABLE_ARRAY_H_