@@ -111,45 +111,102 @@ struct Task {
111
111
* This runs at task death to free all boxes.
112
112
*/
113
113
114
+ struct AnnihilateStats {
115
+ n_total_boxes : uint ,
116
+ n_unique_boxes : uint ,
117
+ n_bytes_freed : uint
118
+ }
119
+
120
+ unsafe fn each_live_alloc ( f : fn ( box : * mut BoxRepr , uniq : bool ) -> bool ) {
121
+ use managed;
122
+
123
+ let task: * Task = transmute ( rustrt:: rust_get_task ( ) ) ;
124
+ let box = ( * task) . boxed_region . live_allocs ;
125
+ let mut box: * mut BoxRepr = transmute ( copy box) ;
126
+ while box != mut_null ( ) {
127
+ let next = transmute ( copy ( * box) . header . next ) ;
128
+ let uniq =
129
+ ( * box) . header . ref_count == managed:: raw:: RC_MANAGED_UNIQUE ;
130
+
131
+ if ! f ( box, uniq) {
132
+ break
133
+ }
134
+
135
+ box = next
136
+ }
137
+ }
138
+
139
+ #[ cfg( unix) ]
140
+ fn debug_mem ( ) -> bool {
141
+ use os;
142
+ use libc;
143
+ do os:: as_c_charp ( "RUST_DEBUG_MEM" ) |p| {
144
+ unsafe { libc:: getenv ( p) != null ( ) }
145
+ }
146
+ }
147
+
148
+ #[ cfg( windows) ]
149
+ fn debug_mem ( ) -> bool {
150
+ false
151
+ }
152
+
114
153
/// Destroys all managed memory (i.e. @ boxes) held by the current task.
115
154
#[ cfg( notest) ]
116
155
#[ lang="annihilate" ]
117
156
pub unsafe fn annihilate ( ) {
118
157
use rt:: rt_free;
119
158
use io:: WriterUtil ;
159
+ use io;
160
+ use libc;
161
+ use sys;
162
+ use managed;
120
163
121
- let task: * Task = transmute ( rustrt:: rust_get_task ( ) ) ;
164
+ let mut stats = AnnihilateStats {
165
+ n_total_boxes : 0 ,
166
+ n_unique_boxes : 0 ,
167
+ n_bytes_freed : 0
168
+ } ;
122
169
123
170
// Pass 1: Make all boxes immortal.
124
- let box = ( * task) . boxed_region . live_allocs ;
125
- let mut box: * mut BoxRepr = transmute ( copy box) ;
126
- while box != mut_null ( ) {
127
- debug ! ( "making box immortal: %x" , box as uint) ;
128
- ( * box) . header . ref_count = 0x77777777 ;
129
- box = transmute ( copy ( * box) . header . next ) ;
171
+ for each_live_alloc |box, uniq| {
172
+ stats. n_total_boxes += 1 ;
173
+ if uniq {
174
+ stats. n_unique_boxes += 1 ;
175
+ } else {
176
+ ( * box) . header . ref_count = managed:: raw:: RC_IMMORTAL ;
177
+ }
130
178
}
131
179
132
180
// Pass 2: Drop all boxes.
133
- let box = ( * task) . boxed_region . live_allocs ;
134
- let mut box: * mut BoxRepr = transmute ( copy box) ;
135
- while box != mut_null ( ) {
136
- debug ! ( "calling drop glue for box: %x" , box as uint) ;
137
- let tydesc: * TypeDesc = transmute ( copy ( * box) . header . type_desc ) ;
138
- let drop_glue: DropGlue = transmute ( ( ( * tydesc) . drop_glue , 0 ) ) ;
139
- drop_glue ( to_unsafe_ptr ( & tydesc) , transmute ( & ( * box) . data ) ) ;
140
-
141
- box = transmute ( copy ( * box) . header . next ) ;
181
+ for each_live_alloc |box, uniq| {
182
+ if !uniq {
183
+ let tydesc: * TypeDesc = transmute ( copy ( * box) . header . type_desc ) ;
184
+ let drop_glue: DropGlue = transmute ( ( ( * tydesc) . drop_glue , 0 ) ) ;
185
+ drop_glue ( to_unsafe_ptr ( & tydesc) , transmute ( & ( * box) . data ) ) ;
186
+ }
142
187
}
143
188
144
189
// Pass 3: Free all boxes.
145
- loop {
146
- let box = ( * task) . boxed_region . live_allocs ;
147
- if box == null ( ) { break ; }
148
- let mut box: * mut BoxRepr = transmute ( copy box) ;
149
- assert ( * box) . header . prev == null ( ) ;
150
-
151
- debug ! ( "freeing box: %x" , box as uint) ;
152
- rt_free ( transmute ( box) ) ;
190
+ for each_live_alloc |box, uniq| {
191
+ if !uniq {
192
+ stats. n_bytes_freed +=
193
+ ( * ( ( * box) . header . type_desc ) ) . size
194
+ + sys:: size_of :: < BoxRepr > ( ) ;
195
+ rt_free ( transmute ( box) ) ;
196
+ }
197
+ }
198
+
199
+ if debug_mem ( ) {
200
+ // We do logging here w/o allocation.
201
+ let dbg = libc:: STDERR_FILENO as io:: fd_t ;
202
+ dbg. write_str ( "annihilator stats:" ) ;
203
+ dbg. write_str ( "\n total_boxes: " ) ;
204
+ dbg. write_uint ( stats. n_total_boxes ) ;
205
+ dbg. write_str ( "\n unique_boxes: " ) ;
206
+ dbg. write_uint ( stats. n_unique_boxes ) ;
207
+ dbg. write_str ( "\n bytes_freed: " ) ;
208
+ dbg. write_uint ( stats. n_bytes_freed ) ;
209
+ dbg. write_str ( "\n " ) ;
153
210
}
154
211
}
155
212
0 commit comments