26
26
#include < iostream>
27
27
#endif
28
28
29
+ irept nil_rep_storage;
30
+
31
+ #ifdef SHARING
32
+ irept::dt irept::empty_d;
33
+ #endif
34
+
29
35
#ifdef SUB_IS_LIST
30
36
static inline bool named_subt_order (
31
37
const std::pair<irep_namet, irept> &a,
@@ -49,20 +55,157 @@ static inline irept::named_subt::iterator named_subt_lower_bound(
49
55
50
56
const irept &get_nil_irep ()
51
57
{
52
- static irept nil_rep_storage;
53
58
if (nil_rep_storage.id ().empty ()) // initialized?
54
59
nil_rep_storage.id (ID_nil);
55
60
return nil_rep_storage;
56
61
}
57
62
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
+
58
195
void irept::move_to_named_sub (const irep_namet &name, irept &irep)
59
196
{
197
+ #ifdef SHARING
198
+ detach ();
199
+ #endif
60
200
add (name).swap (irep);
61
201
irep.clear ();
62
202
}
63
203
64
204
void irept::move_to_sub (irept &irep)
65
205
{
206
+ #ifdef SHARING
207
+ detach ();
208
+ #endif
66
209
get_sub ().push_back (get_nil_irep ());
67
210
get_sub ().back ().swap (irep);
68
211
}
0 commit comments