blob: 6ed207c33890a48cda9dbafea91b061674d6bdb4 [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 Geoffray1af0c0b2014-02-19 17:30:16 +000017#ifndef ART_COMPILER_DEX_GROWABLE_ARRAY_H_
18#define ART_COMPILER_DEX_GROWABLE_ARRAY_H_
buzbee862a7602013-04-05 10:58:54 -070019
20#include <stdint.h>
21#include <stddef.h>
Nicolas Geoffray1af0c0b2014-02-19 17:30:16 +000022#include "compiler_enums.h"
buzbee862a7602013-04-05 10:58:54 -070023#include "arena_allocator.h"
24
25namespace art {
26
Nicolas Geoffray1af0c0b2014-02-19 17:30:16 +000027struct CompilationUnit;
28
buzbee862a7602013-04-05 10:58:54 -070029// Type of growable list for memory tuning.
30enum OatListKind {
31 kGrowableArrayMisc = 0,
32 kGrowableArrayBlockList,
33 kGrowableArraySSAtoDalvikMap,
34 kGrowableArrayDfsOrder,
35 kGrowableArrayDfsPostOrder,
36 kGrowableArrayDomPostOrderTraversal,
37 kGrowableArrayThrowLaunchPads,
38 kGrowableArraySuspendLaunchPads,
39 kGrowableArraySwitchTables,
40 kGrowableArrayFillArrayData,
41 kGrowableArraySuccessorBlocks,
42 kGrowableArrayPredecessors,
Dave Allisonbcec6fb2014-01-17 12:52:22 -080043 kGrowableArraySlowPaths,
buzbee862a7602013-04-05 10:58:54 -070044 kGNumListKinds
45};
46
47template<typename T>
48class GrowableArray {
49 public:
buzbee862a7602013-04-05 10:58:54 -070050 class Iterator {
51 public:
Brian Carlstrom93ba8932013-07-17 21:31:49 -070052 explicit Iterator(GrowableArray* g_list)
buzbee862a7602013-04-05 10:58:54 -070053 : idx_(0),
Brian Carlstrom9b7085a2013-07-18 15:15:21 -070054 g_list_(g_list) {}
buzbee862a7602013-04-05 10:58:54 -070055
56 // NOTE: returns 0/NULL when no next.
57 // TODO: redo to make usage consistent with other iterators.
58 T Next() {
59 if (idx_ >= g_list_->Size()) {
60 return 0;
61 } else {
62 return g_list_->Get(idx_++);
63 }
64 }
65
66 void Reset() {
67 idx_ = 0;
68 }
69
buzbee862a7602013-04-05 10:58:54 -070070 private:
71 size_t idx_;
72 GrowableArray* const g_list_;
73 };
74
75 GrowableArray(ArenaAllocator* arena, size_t init_length, OatListKind kind = kGrowableArrayMisc)
76 : arena_(arena),
buzbeea5abf702013-04-12 14:39:29 -070077 num_allocated_(init_length),
buzbee862a7602013-04-05 10:58:54 -070078 num_used_(0),
79 kind_(kind) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070080 elem_list_ = static_cast<T*>(arena_->Alloc(sizeof(T) * init_length,
81 ArenaAllocator::kAllocGrowableArray));
buzbee862a7602013-04-05 10:58:54 -070082 };
83
84
85 // Expand the list size to at least new length.
86 void Resize(size_t new_length) {
87 if (new_length <= num_allocated_) return;
buzbeea5abf702013-04-12 14:39:29 -070088 // If it's a small list double the size, else grow 1.5x.
89 size_t target_length =
90 (num_allocated_ < 128) ? num_allocated_ << 1 : num_allocated_ + (num_allocated_ >> 1);
buzbee862a7602013-04-05 10:58:54 -070091 if (new_length > target_length) {
92 target_length = new_length;
93 }
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070094 T* new_array = static_cast<T*>(arena_->Alloc(sizeof(T) * target_length,
95 ArenaAllocator::kAllocGrowableArray));
buzbee862a7602013-04-05 10:58:54 -070096 memcpy(new_array, elem_list_, sizeof(T) * num_allocated_);
buzbee862a7602013-04-05 10:58:54 -070097 num_allocated_ = target_length;
98 elem_list_ = new_array;
99 };
100
101 // NOTE: does not return storage, just resets use count.
102 void Reset() {
103 num_used_ = 0;
104 }
105
106 // Insert an element to the end of a list, resizing if necessary.
107 void Insert(T elem) {
108 if (num_used_ == num_allocated_) {
109 Resize(num_used_ + 1);
110 }
111 elem_list_[num_used_++] = elem;
Nicolas Geoffray1af0c0b2014-02-19 17:30:16 +0000112 };
buzbee862a7602013-04-05 10:58:54 -0700113
114 T Get(size_t index) const {
115 DCHECK_LT(index, num_used_);
116 return elem_list_[index];
117 };
118
119 // Overwrite existing element at position index. List must be large enough.
120 void Put(size_t index, T elem) {
121 DCHECK_LT(index, num_used_);
122 elem_list_[index] = elem;
123 }
124
125 void Increment(size_t index) {
126 DCHECK_LT(index, num_used_);
127 elem_list_[index]++;
128 }
129
buzbeebd663de2013-09-10 15:41:31 -0700130 /*
131 * Remove an existing element from list. If there are more than one copy
132 * of the element, only the first one encountered will be deleted.
133 */
134 // TODO: consider renaming this.
buzbee862a7602013-04-05 10:58:54 -0700135 void Delete(T element) {
136 bool found = false;
137 for (size_t i = 0; i < num_used_ - 1; i++) {
138 if (!found && elem_list_[i] == element) {
139 found = true;
140 }
141 if (found) {
142 elem_list_[i] = elem_list_[i+1];
143 }
144 }
145 // We should either have found the element, or it was the last (unscanned) element.
146 DCHECK(found || (element == elem_list_[num_used_ - 1]));
147 num_used_--;
148 };
149
150 size_t GetNumAllocated() const { return num_allocated_; }
151
152 size_t Size() const { return num_used_; }
153
buzbeebd663de2013-09-10 15:41:31 -0700154 void SetSize(size_t new_size) {
155 Resize(new_size);
156 num_used_ = new_size;
157 }
158
buzbee862a7602013-04-05 10:58:54 -0700159 T* GetRawStorage() const { return elem_list_; }
160
161 static void* operator new(size_t size, ArenaAllocator* arena) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700162 return arena->Alloc(sizeof(GrowableArray<T>), ArenaAllocator::kAllocGrowableArray);
buzbee862a7602013-04-05 10:58:54 -0700163 };
Brian Carlstrom9b7085a2013-07-18 15:15:21 -0700164 static void operator delete(void* p) {} // Nop.
buzbee862a7602013-04-05 10:58:54 -0700165
166 private:
167 ArenaAllocator* const arena_;
168 size_t num_allocated_;
169 size_t num_used_;
170 OatListKind kind_;
171 T* elem_list_;
172};
173
174} // namespace art
175
Nicolas Geoffray1af0c0b2014-02-19 17:30:16 +0000176#endif // ART_COMPILER_DEX_GROWABLE_ARRAY_H_