diff --git a/graph/Graph.cc b/graph/Graph.cc index 3ce7aec6..cf9b0438 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -657,7 +657,7 @@ Graph::makePrevPaths(Vertex *vertex, } PathVertexRep * -Graph::prevPaths(Vertex *vertex) const +Graph::prevPaths(Vertex *vertex) { return prev_paths_.pointer(vertex->prevPaths()); } diff --git a/include/sta/ArrayTable.hh b/include/sta/ArrayTable.hh index 16fdafce..67fb78da 100644 --- a/include/sta/ArrayTable.hh +++ b/include/sta/ArrayTable.hh @@ -47,8 +47,8 @@ public: uint32_t count); // Grow as necessary and return pointer for id. TYPE *ensureId(ObjectId id); - TYPE *pointer(ObjectId id) const; - TYPE &ref(ObjectId id) const; + TYPE *pointer(ObjectId id); + TYPE &ref(ObjectId id); size_t size() const { return size_; } void clear(); @@ -58,7 +58,7 @@ public: private: ArrayBlock *makeBlock(uint32_t size); - void pushBlock(ArrayBlock *block); + void pushBlock(size_t size); void deleteBlocks(); size_t size_; @@ -66,11 +66,8 @@ private: BlockIdx free_block_idx_; // Index of next free object in free_block_idx_. ObjectIdx free_idx_; - // Don't use std::vector so growing blocks_ can be thread safe. - size_t blocks_size_; - size_t blocks_capacity_; - ArrayBlock* *blocks_; - ArrayBlock* *prev_blocks_; + std::vector> blocks_; + std::vector> prev_blocks_; // Linked list of free arrays indexed by array size. std::vector free_list_; static constexpr ObjectId idx_mask_ = block_size - 1; @@ -80,28 +77,24 @@ template ArrayTable::ArrayTable() : size_(0), free_block_idx_(block_idx_null), - free_idx_(object_idx_null), - blocks_size_(0), - blocks_capacity_(1024), - blocks_(new ArrayBlock*[blocks_capacity_]), - prev_blocks_(nullptr) + free_idx_(object_idx_null) { + blocks_.reserve(1024); } template ArrayTable::~ArrayTable() { deleteBlocks(); - delete [] blocks_; - delete [] prev_blocks_; } template void ArrayTable::deleteBlocks() { - for (size_t i = 0; i < blocks_size_; i++) - delete blocks_[i]; + for (size_t i = 0; i < blocks_.size(); i++) + blocks_[i].free(); + blocks_.clear(); } template @@ -120,12 +113,12 @@ ArrayTable::make(uint32_t count, free_list_[count] = *head; } else { - ArrayBlock *block = blocks_size_ ? blocks_[free_block_idx_] : nullptr; + 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 = block_size; - if (blocks_size_ == 0 + if (blocks_.size() == 0 // First block starts at idx 1. && count > block_size - 1) size = count + 1; @@ -145,32 +138,36 @@ template ArrayBlock * ArrayTable::makeBlock(uint32_t size) { - BlockIdx block_idx = blocks_size_; - ArrayBlock *block = new ArrayBlock(size); - pushBlock(block); + BlockIdx block_idx = blocks_.size(); + pushBlock(size); free_block_idx_ = block_idx; // ObjectId zero is reserved for object_id_null. free_idx_ = (block_idx > 0) ? 0 : 1; - return block; + return &blocks_[block_idx]; } template void -ArrayTable::pushBlock(ArrayBlock *block) +ArrayTable::pushBlock(size_t size) { - blocks_[blocks_size_++] = block; - if (blocks_size_ >= block_id_max) + blocks_.push_back(ArrayBlock(size)); + + if (blocks_.size() >= block_id_max) criticalError(223, "max array table block count exceeded."); - if (blocks_size_ == blocks_capacity_) { - size_t new_capacity = blocks_capacity_ * 1.5; - ArrayBlock** new_blocks = new ArrayBlock*[new_capacity]; - memcpy(new_blocks, blocks_, blocks_capacity_ * sizeof(ArrayBlock*)); - if (prev_blocks_) - delete [] prev_blocks_; + if (blocks_.size() == blocks_.capacity()) { + prev_blocks_.reserve(blocks_.capacity() * 1.5); + const auto blocks_mid = blocks_.begin() + prev_blocks_.size(); + std::copy(blocks_.begin(), blocks_mid, prev_blocks_.begin()); + prev_blocks_.insert(prev_blocks_.end(), blocks_mid, blocks_.end()); // Preserve block array for other threads to reference. - prev_blocks_ = blocks_; - blocks_ = new_blocks; - blocks_capacity_ = new_capacity; + // Swap the vectors while keeping blocks_ valid. + // vector::swap is usually basically the same, + // but a naive implementation might temporarily set blocks_ to null. + const size_t vec_size = sizeof(blocks_); + std::uint8_t tmp[vec_size]; + std::memcpy(&tmp, static_cast(&blocks_), vec_size); + std::memcpy(static_cast(&blocks_), static_cast(&prev_blocks_), vec_size); + std::memcpy(static_cast(&prev_blocks_), &tmp, vec_size); } } @@ -191,14 +188,14 @@ ArrayTable::destroy(ObjectId id, template TYPE * -ArrayTable::pointer(ObjectId id) const +ArrayTable::pointer(ObjectId id) { if (id == object_id_null) return nullptr; else { BlockIdx blk_idx = id >> idx_bits; ObjectIdx obj_idx = id & idx_mask_; - return blocks_[blk_idx]->pointer(obj_idx); + return blocks_[blk_idx].pointer(obj_idx); } } @@ -209,23 +206,22 @@ ArrayTable::ensureId(ObjectId id) BlockIdx blk_idx = id >> idx_bits; ObjectIdx obj_idx = id & idx_mask_; // Make enough blocks for blk_idx to be valid. - for (BlockIdx i = blocks_size_; i <= blk_idx; i++) { - ArrayBlock *block = new ArrayBlock(block_size); - pushBlock(block); + for (BlockIdx i = blocks_.size(); i <= blk_idx; i++) { + pushBlock(block_size); } - return blocks_[blk_idx]->pointer(obj_idx); + return blocks_[blk_idx].pointer(obj_idx); } template TYPE & -ArrayTable::ref(ObjectId id) const +ArrayTable::ref(ObjectId id) { if (id == object_id_null) criticalError(222, "null ObjectId reference is undefined."); BlockIdx blk_idx = id >> idx_bits; ObjectIdx obj_idx = id & idx_mask_; - return blocks_[blk_idx]->ref(obj_idx); + return blocks_[blk_idx].ref(obj_idx); } template @@ -233,7 +229,6 @@ void ArrayTable::clear() { deleteBlocks(); - blocks_size_ = 0; size_ = 0; free_block_idx_ = block_idx_null; free_idx_ = object_idx_null; @@ -246,11 +241,12 @@ template class ArrayBlock { public: + ArrayBlock() = default; ArrayBlock(uint32_t size); - ~ArrayBlock(); uint32_t size() const { return size_; } TYPE &ref(ObjectIdx idx) { return objects_[idx]; } TYPE *pointer(ObjectIdx idx) { return &objects_[idx]; } + void free() { delete[] objects_; } private: uint32_t size_; @@ -264,10 +260,4 @@ ArrayBlock::ArrayBlock(uint32_t size) : { } -template -ArrayBlock::~ArrayBlock() -{ - delete [] objects_; -} - } // Namespace diff --git a/include/sta/Graph.hh b/include/sta/Graph.hh index 593e0f2f..d025470c 100644 --- a/include/sta/Graph.hh +++ b/include/sta/Graph.hh @@ -113,7 +113,7 @@ public: size_t requiredCount() const { return requireds_.size(); } PathVertexRep *makePrevPaths(Vertex *vertex, uint32_t count); - PathVertexRep *prevPaths(Vertex *vertex) const; + PathVertexRep *prevPaths(Vertex *vertex); void clearPrevPaths(); // Reported slew are the same as those in the liberty tables. // reported_slews = measured_slews / slew_derate_from_library