Skip to content

Commit 3d64070

Browse files
committed
Partially revert "Use small intrusive pointer in irep"
This partially reverts commit b741d4b. While safer to use, these changes prevented sharing on irept's where non-const references had been taken to any irept stored in their sub/named_sub collections. The newly introduced cow.h and small_shared_ptr.h are kept in place, but all modifications to irept are reverted.
1 parent 118f41f commit 3d64070

File tree

3 files changed

+300
-45
lines changed

3 files changed

+300
-45
lines changed

src/util/fresh_symbol.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Chris Smowton, [email protected]
1111

1212
#include "fresh_symbol.h"
1313

14+
#include "invariant.h"
1415
#include "namespace.h"
1516
#include "rename.h"
1617
#include "symbol.h"

src/util/irep.cpp

+144-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ Author: Daniel Kroening, [email protected]
2626
#include <iostream>
2727
#endif
2828

29+
irept nil_rep_storage;
30+
31+
#ifdef SHARING
32+
irept::dt irept::empty_d;
33+
#endif
34+
2935
#ifdef SUB_IS_LIST
3036
static inline bool named_subt_order(
3137
const std::pair<irep_namet, irept> &a,
@@ -49,20 +55,157 @@ static inline irept::named_subt::iterator named_subt_lower_bound(
4955

5056
const irept &get_nil_irep()
5157
{
52-
static irept nil_rep_storage;
5358
if(nil_rep_storage.id().empty()) // initialized?
5459
nil_rep_storage.id(ID_nil);
5560
return nil_rep_storage;
5661
}
5762

63+
#ifdef SHARING
64+
void irept::detach()
65+
{
66+
#ifdef IREP_DEBUG
67+
std::cout << "DETACH1: " << data << '\n';
68+
#endif
69+
70+
if(data==&empty_d)
71+
{
72+
data=new dt;
73+
74+
#ifdef IREP_DEBUG
75+
std::cout << "ALLOCATED " << data << '\n';
76+
#endif
77+
}
78+
else if(data->ref_count>1)
79+
{
80+
dt *old_data(data);
81+
data=new dt(*old_data);
82+
83+
#ifdef IREP_DEBUG
84+
std::cout << "ALLOCATED " << data << '\n';
85+
#endif
86+
87+
data->ref_count=1;
88+
remove_ref(old_data);
89+
}
90+
91+
POSTCONDITION(data->ref_count==1);
92+
93+
#ifdef IREP_DEBUG
94+
std::cout << "DETACH2: " << data << '\n';
95+
#endif
96+
}
97+
#endif
98+
99+
#ifdef SHARING
100+
void irept::remove_ref(dt *old_data)
101+
{
102+
if(old_data==&empty_d)
103+
return;
104+
105+
#if 0
106+
nonrecursive_destructor(old_data);
107+
#else
108+
109+
PRECONDITION(old_data->ref_count!=0);
110+
111+
#ifdef IREP_DEBUG
112+
std::cout << "R: " << old_data << " " << old_data->ref_count << '\n';
113+
#endif
114+
115+
old_data->ref_count--;
116+
if(old_data->ref_count==0)
117+
{
118+
#ifdef IREP_DEBUG
119+
std::cout << "D: " << pretty() << '\n';
120+
std::cout << "DELETING " << old_data->data
121+
<< " " << old_data << '\n';
122+
old_data->clear();
123+
std::cout << "DEALLOCATING " << old_data << "\n";
124+
#endif
125+
126+
// may cause recursive call
127+
delete old_data;
128+
129+
#ifdef IREP_DEBUG
130+
std::cout << "DONE\n";
131+
#endif
132+
}
133+
#endif
134+
}
135+
#endif
136+
137+
/// Does the same as remove_ref, but using an explicit stack instead of
138+
/// recursion.
139+
#ifdef SHARING
140+
void irept::nonrecursive_destructor(dt *old_data)
141+
{
142+
std::vector<dt *> stack(1, old_data);
143+
144+
while(!stack.empty())
145+
{
146+
dt *d=stack.back();
147+
stack.erase(--stack.end());
148+
if(d==&empty_d)
149+
continue;
150+
151+
INVARIANT(d->ref_count!=0, "All contents of the stack must be in use");
152+
d->ref_count--;
153+
154+
if(d->ref_count==0)
155+
{
156+
stack.reserve(stack.size()+
157+
d->named_sub.size()+
158+
d->comments.size()+
159+
d->sub.size());
160+
161+
for(named_subt::iterator
162+
it=d->named_sub.begin();
163+
it!=d->named_sub.end();
164+
it++)
165+
{
166+
stack.push_back(it->second.data);
167+
it->second.data=&empty_d;
168+
}
169+
170+
for(named_subt::iterator
171+
it=d->comments.begin();
172+
it!=d->comments.end();
173+
it++)
174+
{
175+
stack.push_back(it->second.data);
176+
it->second.data=&empty_d;
177+
}
178+
179+
for(subt::iterator
180+
it=d->sub.begin();
181+
it!=d->sub.end();
182+
it++)
183+
{
184+
stack.push_back(it->data);
185+
it->data=&empty_d;
186+
}
187+
188+
// now delete, won't do recursion
189+
delete d;
190+
}
191+
}
192+
}
193+
#endif
194+
58195
void irept::move_to_named_sub(const irep_namet &name, irept &irep)
59196
{
197+
#ifdef SHARING
198+
detach();
199+
#endif
60200
add(name).swap(irep);
61201
irep.clear();
62202
}
63203

64204
void irept::move_to_sub(irept &irep)
65205
{
206+
#ifdef SHARING
207+
detach();
208+
#endif
66209
get_sub().push_back(get_nil_irep());
67210
get_sub().back().swap(irep);
68211
}

0 commit comments

Comments
 (0)