248 lines
6.4 KiB
C++
248 lines
6.4 KiB
C++
/*
|
|
* Copyright (C) 2013 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef ART_COMPILER_UTILS_GROWABLE_ARRAY_H_
|
|
#define ART_COMPILER_UTILS_GROWABLE_ARRAY_H_
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include "arena_allocator.h"
|
|
|
|
namespace art {
|
|
|
|
// Type of growable list for memory tuning.
|
|
enum OatListKind {
|
|
kGrowableArrayMisc = 0,
|
|
kGrowableArrayBlockList,
|
|
kGrowableArraySSAtoDalvikMap,
|
|
kGrowableArrayDfsOrder,
|
|
kGrowableArrayDfsPostOrder,
|
|
kGrowableArrayDomPostOrderTraversal,
|
|
kGrowableArraySwitchTables,
|
|
kGrowableArrayFillArrayData,
|
|
kGrowableArraySuccessorBlocks,
|
|
kGrowableArrayPredecessors,
|
|
kGrowableArraySlowPaths,
|
|
kGNumListKinds
|
|
};
|
|
|
|
template<typename T>
|
|
class GrowableArray {
|
|
public:
|
|
class Iterator {
|
|
public:
|
|
explicit Iterator(GrowableArray* g_list, size_t idx)
|
|
: idx_(idx),
|
|
g_list_(g_list) {}
|
|
|
|
explicit Iterator(GrowableArray* g_list)
|
|
: idx_(0),
|
|
g_list_(g_list) {}
|
|
|
|
explicit Iterator()
|
|
: idx_(0),
|
|
g_list_(nullptr) {}
|
|
|
|
// NOTE: returns 0/NULL when no next.
|
|
// TODO: redo to make usage consistent with other iterators.
|
|
T Next() {
|
|
DCHECK(g_list_ != nullptr);
|
|
if (idx_ >= g_list_->Size()) {
|
|
return 0;
|
|
} else {
|
|
return g_list_->Get(idx_++);
|
|
}
|
|
}
|
|
|
|
void Reset() {
|
|
idx_ = 0;
|
|
}
|
|
|
|
void Reset(GrowableArray* g_list) {
|
|
idx_ = 0;
|
|
g_list_ = g_list;
|
|
}
|
|
|
|
size_t GetIndex() const {
|
|
return idx_;
|
|
}
|
|
|
|
T operator*() {
|
|
DCHECK(g_list_ != nullptr);
|
|
if (idx_ >= g_list_->Size()) {
|
|
return 0;
|
|
} else {
|
|
return g_list_->Get(idx_);
|
|
}
|
|
}
|
|
|
|
bool operator!= (const Iterator& other) const {
|
|
return idx_ != other.idx_;
|
|
}
|
|
|
|
const Iterator& operator++ () {
|
|
Next();
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
size_t idx_;
|
|
GrowableArray* g_list_;
|
|
};
|
|
|
|
GrowableArray(ArenaAllocator* arena, size_t init_length, OatListKind kind = kGrowableArrayMisc)
|
|
: arena_(arena),
|
|
num_allocated_(init_length),
|
|
num_used_(0),
|
|
kind_(kind) {
|
|
elem_list_ = static_cast<T*>(arena_->Alloc(sizeof(T) * init_length,
|
|
kArenaAllocGrowableArray));
|
|
};
|
|
|
|
|
|
// Expand the list size to at least new length.
|
|
void Resize(size_t new_length) {
|
|
if (new_length <= num_allocated_) return;
|
|
// If it's a small list double the size, else grow 1.5x.
|
|
size_t target_length =
|
|
(num_allocated_ < 128) ? num_allocated_ << 1 : num_allocated_ + (num_allocated_ >> 1);
|
|
if (new_length > target_length) {
|
|
target_length = new_length;
|
|
}
|
|
T* new_array = static_cast<T*>(arena_->Alloc(sizeof(T) * target_length,
|
|
kArenaAllocGrowableArray));
|
|
memcpy(new_array, elem_list_, sizeof(T) * num_allocated_);
|
|
num_allocated_ = target_length;
|
|
elem_list_ = new_array;
|
|
};
|
|
|
|
// NOTE: does not return storage, just resets use count.
|
|
void Reset() {
|
|
num_used_ = 0;
|
|
}
|
|
|
|
// Insert an element to the end of a list, resizing if necessary.
|
|
void Insert(T elem) {
|
|
if (num_used_ == num_allocated_) {
|
|
Resize(num_used_ + 1);
|
|
}
|
|
elem_list_[num_used_++] = elem;
|
|
}
|
|
|
|
void InsertAt(size_t index, T elem) {
|
|
DCHECK(index <= Size());
|
|
Insert(elem);
|
|
for (size_t i = Size() - 1; i > index; --i) {
|
|
elem_list_[i] = elem_list_[i - 1];
|
|
}
|
|
elem_list_[index] = elem;
|
|
}
|
|
|
|
void Add(T elem) {
|
|
Insert(elem);
|
|
}
|
|
|
|
T Get(size_t index) const {
|
|
DCHECK_LT(index, num_used_);
|
|
return elem_list_[index];
|
|
};
|
|
|
|
// Overwrite existing element at position index. List must be large enough.
|
|
void Put(size_t index, T elem) {
|
|
DCHECK_LT(index, num_used_);
|
|
elem_list_[index] = elem;
|
|
}
|
|
|
|
void Increment(size_t index) {
|
|
DCHECK_LT(index, num_used_);
|
|
elem_list_[index]++;
|
|
}
|
|
|
|
/*
|
|
* Remove an existing element from list. If there are more than one copy
|
|
* of the element, only the first one encountered will be deleted.
|
|
*/
|
|
// TODO: consider renaming this.
|
|
void Delete(T element) {
|
|
bool found = false;
|
|
for (size_t i = 0; i < num_used_ - 1; i++) {
|
|
if (!found && elem_list_[i] == element) {
|
|
found = true;
|
|
}
|
|
if (found) {
|
|
elem_list_[i] = elem_list_[i+1];
|
|
}
|
|
}
|
|
// We should either have found the element, or it was the last (unscanned) element.
|
|
DCHECK(found || (element == elem_list_[num_used_ - 1]));
|
|
num_used_--;
|
|
};
|
|
|
|
void DeleteAt(size_t index) {
|
|
for (size_t i = index; i < num_used_ - 1; i++) {
|
|
elem_list_[i] = elem_list_[i + 1];
|
|
}
|
|
num_used_--;
|
|
};
|
|
|
|
size_t GetNumAllocated() const { return num_allocated_; }
|
|
|
|
size_t Size() const { return num_used_; }
|
|
|
|
bool IsEmpty() const { return num_used_ == 0; }
|
|
|
|
T Pop() {
|
|
DCHECK_GE(num_used_, (size_t)0);
|
|
return elem_list_[--num_used_];
|
|
}
|
|
|
|
T Peek() const {
|
|
DCHECK_GE(num_used_, (size_t)0);
|
|
return elem_list_[num_used_ - 1];
|
|
}
|
|
|
|
void SetSize(size_t new_size) {
|
|
Resize(new_size);
|
|
num_used_ = new_size;
|
|
}
|
|
|
|
T* GetRawStorage() const { return elem_list_; }
|
|
|
|
static void* operator new(size_t size, ArenaAllocator* arena) {
|
|
return arena->Alloc(sizeof(GrowableArray<T>), kArenaAllocGrowableArray);
|
|
};
|
|
static void operator delete(void* p) {} // Nop.
|
|
|
|
Iterator begin() {
|
|
return Iterator(this);
|
|
}
|
|
|
|
Iterator end() {
|
|
return Iterator(this, Size());
|
|
}
|
|
|
|
private:
|
|
ArenaAllocator* const arena_;
|
|
size_t num_allocated_;
|
|
size_t num_used_;
|
|
OatListKind kind_;
|
|
T* elem_list_;
|
|
};
|
|
|
|
} // namespace art
|
|
|
|
#endif // ART_COMPILER_UTILS_GROWABLE_ARRAY_H_
|