blob: 61e420c222eeaa2ae824d0ac5b2f4806c02b62b5 [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,
buzbee862a7602013-04-05 10:58:54 -070029 kGNumListKinds
30};
31
Vladimir Markoe39c54e2014-09-22 14:50:02 +010032// Deprecated
33// TODO: Replace all uses with ArenaVector<T>.
buzbee862a7602013-04-05 10:58:54 -070034template<typename T>
35class GrowableArray {
36 public:
buzbee862a7602013-04-05 10:58:54 -070037 GrowableArray(ArenaAllocator* arena, size_t init_length, OatListKind kind = kGrowableArrayMisc)
38 : arena_(arena),
buzbeea5abf702013-04-12 14:39:29 -070039 num_allocated_(init_length),
buzbee862a7602013-04-05 10:58:54 -070040 num_used_(0),
41 kind_(kind) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070042 elem_list_ = static_cast<T*>(arena_->Alloc(sizeof(T) * init_length,
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000043 kArenaAllocGrowableArray));
Andreas Gampec8ccf682014-09-29 20:07:43 -070044 }
buzbee862a7602013-04-05 10:58:54 -070045
46
47 // Expand the list size to at least new length.
48 void Resize(size_t new_length) {
49 if (new_length <= num_allocated_) return;
buzbeea5abf702013-04-12 14:39:29 -070050 // If it's a small list double the size, else grow 1.5x.
51 size_t target_length =
52 (num_allocated_ < 128) ? num_allocated_ << 1 : num_allocated_ + (num_allocated_ >> 1);
buzbee862a7602013-04-05 10:58:54 -070053 if (new_length > target_length) {
54 target_length = new_length;
55 }
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070056 T* new_array = static_cast<T*>(arena_->Alloc(sizeof(T) * target_length,
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000057 kArenaAllocGrowableArray));
buzbee862a7602013-04-05 10:58:54 -070058 memcpy(new_array, elem_list_, sizeof(T) * num_allocated_);
buzbee862a7602013-04-05 10:58:54 -070059 num_allocated_ = target_length;
60 elem_list_ = new_array;
Andreas Gampec8ccf682014-09-29 20:07:43 -070061 }
buzbee862a7602013-04-05 10:58:54 -070062
63 // NOTE: does not return storage, just resets use count.
64 void Reset() {
65 num_used_ = 0;
66 }
67
68 // Insert an element to the end of a list, resizing if necessary.
69 void Insert(T elem) {
70 if (num_used_ == num_allocated_) {
71 Resize(num_used_ + 1);
72 }
73 elem_list_[num_used_++] = elem;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000074 }
75
76 void InsertAt(size_t index, T elem) {
77 DCHECK(index <= Size());
78 Insert(elem);
79 for (size_t i = Size() - 1; i > index; --i) {
80 elem_list_[i] = elem_list_[i - 1];
81 }
82 elem_list_[index] = elem;
83 }
84
85 void Add(T elem) {
86 Insert(elem);
87 }
buzbee862a7602013-04-05 10:58:54 -070088
89 T Get(size_t index) const {
90 DCHECK_LT(index, num_used_);
91 return elem_list_[index];
Andreas Gampec8ccf682014-09-29 20:07:43 -070092 }
buzbee862a7602013-04-05 10:58:54 -070093
94 // Overwrite existing element at position index. List must be large enough.
95 void Put(size_t index, T elem) {
96 DCHECK_LT(index, num_used_);
97 elem_list_[index] = elem;
98 }
99
100 void Increment(size_t index) {
101 DCHECK_LT(index, num_used_);
102 elem_list_[index]++;
103 }
104
buzbeebd663de2013-09-10 15:41:31 -0700105 /*
106 * Remove an existing element from list. If there are more than one copy
107 * of the element, only the first one encountered will be deleted.
108 */
109 // TODO: consider renaming this.
buzbee862a7602013-04-05 10:58:54 -0700110 void Delete(T element) {
111 bool found = false;
112 for (size_t i = 0; i < num_used_ - 1; i++) {
113 if (!found && elem_list_[i] == element) {
114 found = true;
115 }
116 if (found) {
117 elem_list_[i] = elem_list_[i+1];
118 }
119 }
120 // We should either have found the element, or it was the last (unscanned) element.
121 DCHECK(found || (element == elem_list_[num_used_ - 1]));
122 num_used_--;
Andreas Gampec8ccf682014-09-29 20:07:43 -0700123 }
buzbee862a7602013-04-05 10:58:54 -0700124
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100125 void DeleteAt(size_t index) {
126 for (size_t i = index; i < num_used_ - 1; i++) {
127 elem_list_[i] = elem_list_[i + 1];
128 }
129 num_used_--;
Andreas Gampec8ccf682014-09-29 20:07:43 -0700130 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100131
buzbee862a7602013-04-05 10:58:54 -0700132 size_t GetNumAllocated() const { return num_allocated_; }
133
134 size_t Size() const { return num_used_; }
135
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000136 bool IsEmpty() const { return num_used_ == 0; }
137
138 T Pop() {
139 DCHECK_GE(num_used_, (size_t)0);
140 return elem_list_[--num_used_];
141 }
142
143 T Peek() const {
144 DCHECK_GE(num_used_, (size_t)0);
145 return elem_list_[num_used_ - 1];
146 }
147
buzbeebd663de2013-09-10 15:41:31 -0700148 void SetSize(size_t new_size) {
149 Resize(new_size);
150 num_used_ = new_size;
151 }
152
buzbee862a7602013-04-05 10:58:54 -0700153 T* GetRawStorage() const { return elem_list_; }
154
155 static void* operator new(size_t size, ArenaAllocator* arena) {
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000156 return arena->Alloc(sizeof(GrowableArray<T>), kArenaAllocGrowableArray);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700157 }
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700158 static void operator delete(void* p) {} // Nop.
buzbee862a7602013-04-05 10:58:54 -0700159
160 private:
161 ArenaAllocator* const arena_;
162 size_t num_allocated_;
163 size_t num_used_;
164 OatListKind kind_;
165 T* elem_list_;
166};
167
168} // namespace art
169
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000170#endif // ART_COMPILER_UTILS_GROWABLE_ARRAY_H_