@@ -111,45 +111,102 @@ struct Task {
111111 * This runs at task death to free all boxes.
112112 */
113113
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+
114153/// Destroys all managed memory (i.e. @ boxes) held by the current task.
115154#[ cfg( notest) ]
116155#[ lang="annihilate" ]
117156pub unsafe fn annihilate ( ) {
118157 use rt:: rt_free;
119158 use io:: WriterUtil ;
159+ use io;
160+ use libc;
161+ use sys;
162+ use managed;
120163
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+ } ;
122169
123170 // 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+ }
130178 }
131179
132180 // 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+ }
142187 }
143188
144189 // 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 " ) ;
153210 }
154211}
155212
0 commit comments