Index: src/Common/PersistentMap.h
===================================================================
--- src/Common/PersistentMap.h (revision b419abbf67c78a1c8cb7d489fe599026745bad2b)
+++ src/Common/PersistentMap.h (revision fdae91367ec3ec0ae0d11f084e14da4fd527b06c)
@@ -114,4 +114,11 @@
}
+ /// check if this is the only reference to itself
+ /// NOTE: optimizations employing this function are not thread-safe
+ bool is_shared(long local_ptrs = 0) const {
+ // 2 accounts for both the pointer which owns "this" and the one created for its use_count
+ return (this->shared_from_this().use_count() - local_ptrs) > 2;
+ }
+
public:
using size_type = std::size_t;
@@ -144,6 +151,4 @@
// remove map from base
Base base_map = base->take_as();
- base->reset_as_base();
- // xxx -- investigate checking ref-count and omitting re-initialization if 1
// switch base to inverse of self and mutate base map
@@ -153,7 +158,10 @@
auto it = base_map.find( self.key );
- base->init(
- mut_this->shared_from_this(), std::move(self.key), std::move(it->second) );
- base->mode = INS;
+ if ( base->is_shared( 1 ) ) {
+ base->reset_as_base();
+ base->init(
+ mut_this->shared_from_this(), std::move(self.key), std::move(it->second) );
+ base->mode = INS;
+ }
base_map.erase( it );
@@ -163,6 +171,9 @@
Ins& self = mut_this->as();
- base->init( mut_this->shared_from_this(), self.key );
- base->mode = REM;
+ if ( base->is_shared( 1 ) ) {
+ base->reset_as_base();
+ base->init( mut_this->shared_from_this(), self.key );
+ base->mode = REM;
+ }
base_map.emplace( std::move(self.key), std::move(self.val) );
@@ -173,7 +184,10 @@
auto it = base_map.find( self.key );
- base->init(
- mut_this->shared_from_this(), std::move(self.key), std::move(it->second) );
- base->mode = UPD;
+ if ( base->is_shared( 1 ) ) {
+ base->reset_as_base();
+ base->init(
+ mut_this->shared_from_this(), std::move(self.key), std::move(it->second) );
+ base->mode = UPD;
+ }
it->second = std::move(self.val);
@@ -240,5 +254,4 @@
// transfer map to new node
Ptr ret = std::make_shared( take_as() );
- reset_as_base();
Base& base_map = ret->as();
@@ -246,13 +259,19 @@
auto it = base_map.find( k );
if ( it == base_map.end() ) {
- // set self to REM node and insert into base
- init( ret, k );
- mode = REM;
+ if ( is_shared() ) {
+ // set self to REM node and insert into base
+ reset_as_base();
+ init( ret, k );
+ mode = REM;
+ }
base_map.emplace_hint( it, std::forward(k), std::forward(v) );
} else {
- // set self to UPD node and modify base
- init( ret, std::forward(k), std::move(it->second) );
- mode = UPD;
+ if ( is_shared() ) {
+ // set self to UPD node and modify base
+ reset_as_base();
+ init( ret, std::forward(k), std::move(it->second) );
+ mode = UPD;
+ }
it->second = std::forward(v);
@@ -271,10 +290,12 @@
// transfer map to new node
Ptr ret = std::make_shared( take_as() );
- reset_as_base();
Base& base_map = ret->as();
- // set self to INS node and remove from base
- init( ret, k, base_map[k] );
- mode = INS;
+ if ( is_shared() ) {
+ // set self to INS node and remove from base
+ reset_as_base();
+ init( ret, k, base_map[k] );
+ mode = INS;
+ }
base_map.erase( k );
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc (revision b419abbf67c78a1c8cb7d489fe599026745bad2b)
+++ src/SymTab/Indexer.cc (revision fdae91367ec3ec0ae0d11f084e14da4fd527b06c)
@@ -189,5 +189,4 @@
void Indexer::leaveScope() {
if ( repScope == scope ) {
- // replace all maps and scope index with previous scope's versions
Ptr prev = prevScope; // make sure prevScope stays live
*this = std::move(*prevScope); // replace with previous scope