From 2e89d12078a400e7b673ac013ecfce3f7edd4ca2 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 17 Sep 2021 15:42:07 -0700 Subject: [PATCH] reclaim destroyed arrival arrays Signed-off-by: James Cherry --- graph/Graph.cc | 4 ++-- include/sta/ArrayTable.hh | 49 +++++++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/graph/Graph.cc b/graph/Graph.cc index 5e03e275..c8815b25 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -527,7 +527,7 @@ void Graph::deleteArrivals(Vertex *vertex, uint32_t count) { - arrivals_.deleteArray(count); + arrivals_.destroy(vertex->arrivals(), count); vertex->setArrivals(arrival_null); } @@ -557,7 +557,7 @@ void Graph::deleteRequireds(Vertex *vertex, uint32_t count) { - arrivals_.deleteArray(count); + arrivals_.destroy(vertex->requireds(), count); vertex->setRequireds(arrival_null); } diff --git a/include/sta/ArrayTable.hh b/include/sta/ArrayTable.hh index 7ffec6fb..16a53370 100644 --- a/include/sta/ArrayTable.hh +++ b/include/sta/ArrayTable.hh @@ -9,6 +9,7 @@ #pragma once #include // memcpy +#include #include "ObjectId.hh" #include "Error.hh" @@ -34,7 +35,8 @@ public: void make(uint32_t count, TYPE *&array, ObjectId &id); - void deleteArray(uint32_t count); + void destroy(ObjectId id, + uint32_t count); // Grow as necessary and return pointer for id. TYPE *ensureId(ObjectId id); TYPE *pointer(ObjectId id) const; @@ -61,6 +63,8 @@ private: size_t blocks_capacity_; ArrayBlock* *blocks_; ArrayBlock* *prev_blocks_; + // Linked list of free arrays indexed by array size. + std::vector free_list_; static constexpr ObjectId idx_mask_ = block_size - 1; }; @@ -98,17 +102,28 @@ ArrayTable::make(uint32_t count, TYPE *&array, ObjectId &id) { - ArrayBlock *block = blocks_size_ ? blocks_[free_block_idx_] : nullptr; - if ((free_idx_ == object_idx_null - && free_block_idx_ == block_idx_null) - || free_idx_ + count >= block->size()) { - uint32_t size = (count > block_size) ? count : block_size; - block = makeBlock(size); + // Check the free list for a previously destroyed array with the right size. + if (count < free_list_.size() + && free_list_[count] != object_id_null) { + id = free_list_[count]; + array = pointer(id); + + ObjectId *head = reinterpret_cast(array); + free_list_[count] = *head; + } + else { + ArrayBlock *block = blocks_size_ ? blocks_[free_block_idx_] : nullptr; + if ((free_idx_ == object_idx_null + && free_block_idx_ == block_idx_null) + || free_idx_ + count >= block->size()) { + uint32_t size = (count > block_size) ? count : block_size; + block = makeBlock(size); + } + // makeId(free_block_idx_, idx_bits) + id = (free_block_idx_ << idx_bits) + free_idx_; + array = block->pointer(free_idx_); + free_idx_ += count; } - // makeId(free_block_idx_, idx_bits) - id = (free_block_idx_ << idx_bits) + free_idx_; - array = block->pointer(free_idx_); - free_idx_ += count; size_ += count; } @@ -147,8 +162,17 @@ ArrayTable::pushBlock(ArrayBlock *block) template void -ArrayTable::deleteArray(uint32_t) +ArrayTable::destroy(ObjectId id, + uint32_t count) { + if (count >= free_list_.size()) + free_list_.resize(count + 1); + TYPE *array = pointer(id); + // Prepend id to the free list. + ObjectId *head = reinterpret_cast(array); + *head = free_list_[count]; + free_list_[count] = id; + size_ -= count; } template @@ -199,6 +223,7 @@ ArrayTable::clear() size_ = 0; free_block_idx_ = block_idx_null; free_idx_ = object_idx_null; + free_list_.clear(); } ////////////////////////////////////////////////////////////////