@@ -81,8 +81,8 @@ pub struct Arena {
8181 // The head is separated out from the list as a unbenchmarked
8282 // microoptimization, to avoid needing to case on the list to access the
8383 // head.
84- head : Chunk ,
85- copy_head : Chunk ,
84+ head : RefCell < Chunk > ,
85+ copy_head : RefCell < Chunk > ,
8686 chunks : RefCell < Vec < Chunk > > ,
8787}
8888
@@ -95,8 +95,8 @@ impl Arena {
9595 /// Allocate a new Arena with `initial_size` bytes preallocated.
9696 pub fn new_with_size ( initial_size : uint ) -> Arena {
9797 Arena {
98- head : chunk ( initial_size, false ) ,
99- copy_head : chunk ( initial_size, true ) ,
98+ head : RefCell :: new ( chunk ( initial_size, false ) ) ,
99+ copy_head : RefCell :: new ( chunk ( initial_size, true ) ) ,
100100 chunks : RefCell :: new ( Vec :: new ( ) ) ,
101101 }
102102 }
@@ -114,7 +114,7 @@ fn chunk(size: uint, is_copy: bool) -> Chunk {
114114impl Drop for Arena {
115115 fn drop ( & mut self ) {
116116 unsafe {
117- destroy_chunk ( & self . head ) ;
117+ destroy_chunk ( & * self . head . borrow ( ) ) ;
118118 for chunk in self . chunks . borrow ( ) . iter ( ) {
119119 if !chunk. is_copy . get ( ) {
120120 destroy_chunk ( chunk) ;
@@ -171,38 +171,40 @@ fn un_bitpack_tydesc_ptr(p: uint) -> (*TyDesc, bool) {
171171
172172impl Arena {
173173 fn chunk_size ( & self ) -> uint {
174- self . copy_head . capacity ( )
174+ self . copy_head . borrow ( ) . capacity ( )
175175 }
176+
176177 // Functions for the POD part of the arena
177- fn alloc_copy_grow ( & mut self , n_bytes : uint , align : uint ) -> * u8 {
178+ fn alloc_copy_grow ( & self , n_bytes : uint , align : uint ) -> * u8 {
178179 // Allocate a new chunk.
179180 let new_min_chunk_size = cmp:: max ( n_bytes, self . chunk_size ( ) ) ;
180- self . chunks . borrow_mut ( ) . push ( self . copy_head . clone ( ) ) ;
181- self . copy_head =
181+ self . chunks . borrow_mut ( ) . push ( self . copy_head . borrow ( ) . clone ( ) ) ;
182+
183+ * self . copy_head . borrow_mut ( ) =
182184 chunk ( num:: next_power_of_two ( new_min_chunk_size + 1 u) , true ) ;
183185
184186 return self . alloc_copy_inner ( n_bytes, align) ;
185187 }
186188
187189 #[ inline]
188- fn alloc_copy_inner ( & mut self , n_bytes : uint , align : uint ) -> * u8 {
189- unsafe {
190- let start = round_up ( self . copy_head . fill . get ( ) , align) ;
191- let end = start + n_bytes;
192- if end > self . chunk_size ( ) {
193- return self . alloc_copy_grow ( n_bytes, align) ;
194- }
195- self . copy_head . fill . set ( end) ;
190+ fn alloc_copy_inner ( & self , n_bytes : uint , align : uint ) -> * u8 {
191+ let start = round_up ( self . copy_head . borrow ( ) . fill . get ( ) , align) ;
192+
193+ let end = start + n_bytes;
194+ if end > self . chunk_size ( ) {
195+ return self . alloc_copy_grow ( n_bytes, align) ;
196+ }
196197
197- //debug!("idx = {}, size = {}, align = {}, fill = {}",
198- // start, n_bytes, align, head .fill.get() );
198+ let copy_head = self . copy_head . borrow ( ) ;
199+ copy_head . fill . set ( end ) ;
199200
200- self . copy_head . as_ptr ( ) . offset ( start as int )
201+ unsafe {
202+ copy_head. as_ptr ( ) . offset ( start as int )
201203 }
202204 }
203205
204206 #[ inline]
205- fn alloc_copy < ' a , T > ( & ' a mut self , op: || -> T ) -> & ' a T {
207+ fn alloc_copy < ' a , T > ( & ' a self , op: || -> T ) -> & ' a T {
206208 unsafe {
207209 let ptr = self . alloc_copy_inner ( mem:: size_of :: < T > ( ) ,
208210 mem:: min_align_of :: < T > ( ) ) ;
@@ -213,42 +215,48 @@ impl Arena {
213215 }
214216
215217 // Functions for the non-POD part of the arena
216- fn alloc_noncopy_grow ( & mut self , n_bytes : uint , align : uint )
217- -> ( * u8 , * u8 ) {
218+ fn alloc_noncopy_grow ( & self , n_bytes : uint , align : uint ) -> ( * u8 , * u8 ) {
218219 // Allocate a new chunk.
219220 let new_min_chunk_size = cmp:: max ( n_bytes, self . chunk_size ( ) ) ;
220- self . chunks . borrow_mut ( ) . push ( self . head . clone ( ) ) ;
221- self . head =
221+ self . chunks . borrow_mut ( ) . push ( self . head . borrow ( ) . clone ( ) ) ;
222+
223+ * self . head . borrow_mut ( ) =
222224 chunk ( num:: next_power_of_two ( new_min_chunk_size + 1 u) , false ) ;
223225
224226 return self . alloc_noncopy_inner ( n_bytes, align) ;
225227 }
226228
227229 #[ inline]
228- fn alloc_noncopy_inner ( & mut self , n_bytes : uint , align : uint )
229- -> ( * u8 , * u8 ) {
230- unsafe {
231- let tydesc_start = self . head . fill . get ( ) ;
232- let after_tydesc = self . head . fill . get ( ) + mem:: size_of :: < * TyDesc > ( ) ;
230+ fn alloc_noncopy_inner ( & self , n_bytes : uint , align : uint ) -> ( * u8 , * u8 ) {
231+ // Be careful to not maintain any `head` borrows active, because
232+ // `alloc_noncopy_grow` borrows it mutably.
233+ let ( start, end, tydesc_start, head_capacity) = {
234+ let head = self . head . borrow ( ) ;
235+ let fill = head. fill . get ( ) ;
236+
237+ let tydesc_start = fill;
238+ let after_tydesc = fill + mem:: size_of :: < * TyDesc > ( ) ;
233239 let start = round_up ( after_tydesc, align) ;
234240 let end = start + n_bytes;
235241
236- if end > self . head . capacity ( ) {
237- return self . alloc_noncopy_grow ( n_bytes, align) ;
238- }
242+ ( start, end, tydesc_start, head. capacity ( ) )
243+ } ;
239244
240- self . head . fill . set ( round_up ( end, mem:: align_of :: < * TyDesc > ( ) ) ) ;
245+ if end > head_capacity {
246+ return self . alloc_noncopy_grow ( n_bytes, align) ;
247+ }
241248
242- //debug!("idx = {}, size = {}, align = {}, fill = {}",
243- // start, n_bytes, align, head.fill);
249+ let head = self . head . borrow ( ) ;
250+ head. fill . set ( round_up ( end , mem :: align_of :: < * TyDesc > ( ) ) ) ;
244251
245- let buf = self . head . as_ptr ( ) ;
252+ unsafe {
253+ let buf = head. as_ptr ( ) ;
246254 return ( buf. offset ( tydesc_start as int ) , buf. offset ( start as int ) ) ;
247255 }
248256 }
249257
250258 #[ inline]
251- fn alloc_noncopy < ' a , T > ( & ' a mut self , op: || -> T ) -> & ' a T {
259+ fn alloc_noncopy < ' a , T > ( & ' a self , op: || -> T ) -> & ' a T {
252260 unsafe {
253261 let tydesc = get_tydesc :: < T > ( ) ;
254262 let ( ty_ptr, ptr) =
@@ -274,12 +282,10 @@ impl Arena {
274282 #[ inline]
275283 pub fn alloc < ' a , T > ( & ' a self , op: || -> T ) -> & ' a T {
276284 unsafe {
277- // FIXME #13933: Remove/justify all `&T` to `&mut T` transmutes
278- let this: & mut Arena = mem:: transmute :: < & _ , & mut _ > ( self ) ;
279285 if intrinsics:: needs_drop :: < T > ( ) {
280- this . alloc_noncopy ( op)
286+ self . alloc_noncopy ( op)
281287 } else {
282- this . alloc_copy ( op)
288+ self . alloc_copy ( op)
283289 }
284290 }
285291 }
0 commit comments