@@ -26,6 +26,12 @@ Author: Daniel Kroening, kroening@kroening.com
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
3036static 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
5056const 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+
58195void 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
64204void 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