32
32
// overhead when initializing plain-old-data and means we don't need
33
33
// to waste time running the destructors of POD.
34
34
35
+ use list:: { MutList , MutCons , MutNil } ;
35
36
use list;
36
- use list:: { List , Cons , Nil } ;
37
37
38
38
use core:: at_vec;
39
- use core:: cast:: transmute;
39
+ use core:: cast:: { transmute, transmute_mut_region } ;
40
40
use core:: cast;
41
41
use core:: libc:: size_t;
42
42
use core:: ptr;
@@ -74,26 +74,28 @@ static tydesc_drop_glue_index: size_t = 3 as size_t;
74
74
// will always stay at 0.
75
75
struct Chunk {
76
76
data : @[ u8 ] ,
77
- mut fill : uint ,
77
+ fill : uint ,
78
78
is_pod : bool ,
79
79
}
80
80
81
81
pub struct Arena {
82
82
// The head is seperated out from the list as a unbenchmarked
83
83
// microoptimization, to avoid needing to case on the list to
84
84
// access the head.
85
- priv mut head : Chunk ,
86
- priv mut pod_head : Chunk ,
87
- priv mut chunks : @List < Chunk > ,
85
+ priv head : Chunk ,
86
+ priv pod_head : Chunk ,
87
+ priv chunks : @mut MutList < Chunk > ,
88
88
}
89
89
90
90
#[ unsafe_destructor]
91
91
impl Drop for Arena {
92
92
fn finalize ( & self ) {
93
93
unsafe {
94
94
destroy_chunk ( & self . head ) ;
95
- for list:: each( self . chunks) |chunk| {
96
- if !chunk. is_pod { destroy_chunk ( chunk) ; }
95
+ for self . chunks. each |chunk| {
96
+ if !chunk. is_pod {
97
+ destroy_chunk ( chunk) ;
98
+ }
97
99
}
98
100
}
99
101
}
@@ -113,7 +115,7 @@ pub fn arena_with_size(initial_size: uint) -> Arena {
113
115
Arena {
114
116
head : chunk ( initial_size, false ) ,
115
117
pod_head : chunk ( initial_size, true ) ,
116
- chunks : @Nil ,
118
+ chunks : @mut MutNil ,
117
119
}
118
120
}
119
121
@@ -170,39 +172,40 @@ unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) {
170
172
171
173
pub impl Arena {
172
174
// Functions for the POD part of the arena
173
- priv fn alloc_pod_grow ( & self , n_bytes : uint , align : uint ) -> * u8 {
175
+ priv fn alloc_pod_grow ( & mut self , n_bytes : uint , align : uint ) -> * u8 {
174
176
// Allocate a new chunk.
175
177
let chunk_size = at_vec:: capacity ( self . pod_head . data ) ;
176
178
let new_min_chunk_size = uint:: max ( n_bytes, chunk_size) ;
177
- self . chunks = @Cons ( copy self . pod_head , self . chunks ) ;
179
+ self . chunks = @mut MutCons ( copy self . pod_head , self . chunks ) ;
178
180
self . pod_head =
179
181
chunk ( uint:: next_power_of_two ( new_min_chunk_size + 1 u) , true ) ;
180
182
181
183
return self . alloc_pod_inner ( n_bytes, align) ;
182
184
}
183
185
184
186
#[ inline( always) ]
185
- priv fn alloc_pod_inner ( & self , n_bytes : uint , align : uint ) -> * u8 {
186
- let head = & mut self . pod_head ;
187
+ priv fn alloc_pod_inner ( & mut self , n_bytes : uint , align : uint ) -> * u8 {
188
+ unsafe {
189
+ // XXX: Borrow check
190
+ let head = transmute_mut_region ( & mut self . pod_head ) ;
187
191
188
- let start = round_up_to ( head. fill , align) ;
189
- let end = start + n_bytes;
190
- if end > at_vec:: capacity ( head. data ) {
191
- return self . alloc_pod_grow ( n_bytes, align) ;
192
- }
193
- head. fill = end;
192
+ let start = round_up_to ( head. fill , align) ;
193
+ let end = start + n_bytes;
194
+ if end > at_vec:: capacity ( head. data ) {
195
+ return self . alloc_pod_grow ( n_bytes, align) ;
196
+ }
197
+ head. fill = end;
194
198
195
- //debug!("idx = %u, size = %u, align = %u, fill = %u",
196
- // start, n_bytes, align, head.fill);
199
+ //debug!("idx = %u, size = %u, align = %u, fill = %u",
200
+ // start, n_bytes, align, head.fill);
197
201
198
- unsafe {
199
202
ptr:: offset ( vec:: raw:: to_ptr ( head. data ) , start)
200
203
}
201
204
}
202
205
203
206
#[ inline( always) ]
204
207
#[ cfg( stage0) ]
205
- priv fn alloc_pod < T > ( & self , op : & fn ( ) -> T ) -> & ' self T {
208
+ priv fn alloc_pod < T > ( & mut self , op : & fn ( ) -> T ) -> & ' self T {
206
209
unsafe {
207
210
let tydesc = sys:: get_type_desc :: < T > ( ) ;
208
211
let ptr = self . alloc_pod_inner ( ( * tydesc) . size , ( * tydesc) . align ) ;
@@ -216,7 +219,7 @@ pub impl Arena {
216
219
#[ cfg( stage1) ]
217
220
#[ cfg( stage2) ]
218
221
#[ cfg( stage3) ]
219
- priv fn alloc_pod < ' a , T > ( & ' a self , op : & fn ( ) -> T ) -> & ' a T {
222
+ priv fn alloc_pod < ' a , T > ( & ' a mut self , op : & fn ( ) -> T ) -> & ' a T {
220
223
unsafe {
221
224
let tydesc = sys:: get_type_desc :: < T > ( ) ;
222
225
let ptr = self . alloc_pod_inner ( ( * tydesc) . size , ( * tydesc) . align ) ;
@@ -227,42 +230,44 @@ pub impl Arena {
227
230
}
228
231
229
232
// Functions for the non-POD part of the arena
230
- priv fn alloc_nonpod_grow ( & self , n_bytes : uint , align : uint ) -> ( * u8 , * u8 ) {
233
+ priv fn alloc_nonpod_grow ( & mut self , n_bytes : uint , align : uint )
234
+ -> ( * u8 , * u8 ) {
231
235
// Allocate a new chunk.
232
236
let chunk_size = at_vec:: capacity ( self . head . data ) ;
233
237
let new_min_chunk_size = uint:: max ( n_bytes, chunk_size) ;
234
- self . chunks = @Cons ( copy self . head , self . chunks ) ;
238
+ self . chunks = @mut MutCons ( copy self . head , self . chunks ) ;
235
239
self . head =
236
240
chunk ( uint:: next_power_of_two ( new_min_chunk_size + 1 u) , false ) ;
237
241
238
242
return self . alloc_nonpod_inner ( n_bytes, align) ;
239
243
}
240
244
241
245
#[ inline( always) ]
242
- priv fn alloc_nonpod_inner ( & self , n_bytes : uint , align : uint ) -> ( * u8 , * u8 ) {
243
- let head = & mut self . head ;
244
-
245
- let tydesc_start = head. fill ;
246
- let after_tydesc = head. fill + sys:: size_of :: < * TypeDesc > ( ) ;
247
- let start = round_up_to ( after_tydesc, align) ;
248
- let end = start + n_bytes;
249
- if end > at_vec:: capacity ( head. data ) {
250
- return self . alloc_nonpod_grow ( n_bytes, align) ;
251
- }
252
- head. fill = round_up_to ( end, sys:: pref_align_of :: < * TypeDesc > ( ) ) ;
246
+ priv fn alloc_nonpod_inner ( & mut self , n_bytes : uint , align : uint )
247
+ -> ( * u8 , * u8 ) {
248
+ unsafe {
249
+ let head = transmute_mut_region ( & mut self . head ) ;
250
+
251
+ let tydesc_start = head. fill ;
252
+ let after_tydesc = head. fill + sys:: size_of :: < * TypeDesc > ( ) ;
253
+ let start = round_up_to ( after_tydesc, align) ;
254
+ let end = start + n_bytes;
255
+ if end > at_vec:: capacity ( head. data ) {
256
+ return self . alloc_nonpod_grow ( n_bytes, align) ;
257
+ }
258
+ head. fill = round_up_to ( end, sys:: pref_align_of :: < * TypeDesc > ( ) ) ;
253
259
254
- //debug!("idx = %u, size = %u, align = %u, fill = %u",
255
- // start, n_bytes, align, head.fill);
260
+ //debug!("idx = %u, size = %u, align = %u, fill = %u",
261
+ // start, n_bytes, align, head.fill);
256
262
257
- unsafe {
258
263
let buf = vec:: raw:: to_ptr ( head. data ) ;
259
264
return ( ptr:: offset ( buf, tydesc_start) , ptr:: offset ( buf, start) ) ;
260
265
}
261
266
}
262
267
263
268
#[ inline( always) ]
264
269
#[ cfg( stage0) ]
265
- priv fn alloc_nonpod < T > ( & self , op : & fn ( ) -> T ) -> & ' self T {
270
+ priv fn alloc_nonpod < T > ( & mut self , op : & fn ( ) -> T ) -> & ' self T {
266
271
unsafe {
267
272
let tydesc = sys:: get_type_desc :: < T > ( ) ;
268
273
let ( ty_ptr, ptr) =
@@ -286,7 +291,7 @@ pub impl Arena {
286
291
#[ cfg( stage1) ]
287
292
#[ cfg( stage2) ]
288
293
#[ cfg( stage3) ]
289
- priv fn alloc_nonpod < ' a , T > ( & ' a self , op : & fn ( ) -> T ) -> & ' a T {
294
+ priv fn alloc_nonpod < ' a , T > ( & ' a mut self , op : & fn ( ) -> T ) -> & ' a T {
290
295
unsafe {
291
296
let tydesc = sys:: get_type_desc :: < T > ( ) ;
292
297
let ( ty_ptr, ptr) =
@@ -309,13 +314,16 @@ pub impl Arena {
309
314
// The external interface
310
315
#[ inline( always) ]
311
316
#[ cfg( stage0) ]
312
- fn alloc < T > ( & self , op : & fn ( ) -> T ) -> & ' self T {
317
+ fn alloc < T > ( & mut self , op : & fn ( ) -> T ) -> & ' self T {
313
318
unsafe {
319
+ // XXX: Borrow check
320
+ let this = transmute_mut_region ( self ) ;
314
321
if !rusti:: needs_drop :: < T > ( ) {
315
- self . alloc_pod ( op)
316
- } else {
317
- self . alloc_nonpod ( op)
322
+ return this. alloc_pod ( op) ;
318
323
}
324
+ // XXX: Borrow check
325
+ let this = transmute_mut_region ( self ) ;
326
+ this. alloc_nonpod ( op)
319
327
}
320
328
}
321
329
@@ -324,13 +332,16 @@ pub impl Arena {
324
332
#[ cfg( stage1) ]
325
333
#[ cfg( stage2) ]
326
334
#[ cfg( stage3) ]
327
- fn alloc < ' a , T > ( & ' a self , op : & fn ( ) -> T ) -> & ' a T {
335
+ fn alloc < ' a , T > ( & ' a mut self , op : & fn ( ) -> T ) -> & ' a T {
328
336
unsafe {
337
+ // XXX: Borrow check
338
+ let this = transmute_mut_region ( self ) ;
329
339
if !rusti:: needs_drop :: < T > ( ) {
330
- self . alloc_pod ( op)
331
- } else {
332
- self . alloc_nonpod ( op)
340
+ return this. alloc_pod ( op) ;
333
341
}
342
+ // XXX: Borrow check
343
+ let this = transmute_mut_region ( self ) ;
344
+ this. alloc_nonpod ( op)
334
345
}
335
346
}
336
347
}
@@ -348,7 +359,9 @@ fn test_arena_destructors() {
348
359
}
349
360
}
350
361
351
- #[ test] #[ should_fail] #[ ignore( cfg( windows) ) ]
362
+ #[ test]
363
+ #[ should_fail]
364
+ #[ ignore( cfg( windows) ) ]
352
365
fn test_arena_destructors_fail( ) {
353
366
let arena = Arena ( ) ;
354
367
// Put some stuff in the arena.
0 commit comments