29
29
test( no_crate_inject, attr( deny( warnings) ) ) ) ]
30
30
31
31
#![ feature( alloc) ]
32
- #![ feature( box_syntax) ]
33
32
#![ feature( core_intrinsics) ]
34
33
#![ feature( drop_in_place) ]
35
- #![ feature( raw) ]
36
34
#![ feature( heap_api) ]
37
- #![ feature( oom) ]
38
35
#![ feature( raw) ]
36
+ #![ feature( heap_api) ]
39
37
#![ feature( staged_api) ]
40
38
#![ feature( dropck_parametricity) ]
41
39
#![ cfg_attr( test, feature( test) ) ]
@@ -48,31 +46,34 @@ use std::intrinsics;
48
46
use std:: marker:: { PhantomData , Send } ;
49
47
use std:: mem;
50
48
use std:: ptr;
51
- use std:: raw;
52
- use std:: raw:: Repr ;
53
- use std:: rc:: Rc ;
54
- use std:: slice;
55
49
56
50
use alloc:: heap;
57
51
use alloc:: raw_vec:: RawVec ;
58
52
59
53
// The way arena uses arrays is really deeply awful. The arrays are
60
54
// allocated, and have capacities reserved, but the fill for the array
61
55
// will always stay at 0.
62
- #[ derive( Clone , PartialEq ) ]
63
56
struct Chunk {
64
- data : Rc < RefCell < Vec < u8 > > > ,
57
+ data : RawVec < u8 > ,
65
58
fill : Cell < usize > ,
66
59
is_copy : Cell < bool > ,
67
60
}
68
61
69
62
impl Chunk {
63
+ fn new ( size : usize , is_copy : bool ) -> Chunk {
64
+ Chunk {
65
+ data : RawVec :: with_capacity ( size) ,
66
+ fill : Cell :: new ( 0 ) ,
67
+ is_copy : Cell :: new ( is_copy) ,
68
+ }
69
+ }
70
+
70
71
fn capacity ( & self ) -> usize {
71
- self . data . borrow ( ) . capacity ( )
72
+ self . data . cap ( )
72
73
}
73
74
74
75
unsafe fn as_ptr ( & self ) -> * const u8 {
75
- self . data . borrow ( ) . as_ptr ( )
76
+ self . data . ptr ( )
76
77
}
77
78
}
78
79
@@ -115,22 +116,14 @@ impl<'a> Arena<'a> {
115
116
/// Allocates a new Arena with `initial_size` bytes preallocated.
116
117
pub fn new_with_size ( initial_size : usize ) -> Arena < ' a > {
117
118
Arena {
118
- head : RefCell :: new ( chunk ( initial_size, false ) ) ,
119
- copy_head : RefCell :: new ( chunk ( initial_size, true ) ) ,
119
+ head : RefCell :: new ( Chunk :: new ( initial_size, false ) ) ,
120
+ copy_head : RefCell :: new ( Chunk :: new ( initial_size, true ) ) ,
120
121
chunks : RefCell :: new ( Vec :: new ( ) ) ,
121
122
_marker : PhantomData ,
122
123
}
123
124
}
124
125
}
125
126
126
- fn chunk ( size : usize , is_copy : bool ) -> Chunk {
127
- Chunk {
128
- data : Rc :: new ( RefCell :: new ( Vec :: with_capacity ( size) ) ) ,
129
- fill : Cell :: new ( 0 ) ,
130
- is_copy : Cell :: new ( is_copy) ,
131
- }
132
- }
133
-
134
127
impl < ' longer_than_self > Drop for Arena < ' longer_than_self > {
135
128
fn drop ( & mut self ) {
136
129
unsafe {
@@ -165,8 +158,6 @@ unsafe fn destroy_chunk(chunk: &Chunk) {
165
158
166
159
let start = round_up ( after_tydesc, align) ;
167
160
168
- // debug!("freeing object: idx = {}, size = {}, align = {}, done = {}",
169
- // start, size, align, is_done);
170
161
if is_done {
171
162
( ( * tydesc) . drop_glue ) ( buf. offset ( start as isize ) as * const i8 ) ;
172
163
}
@@ -215,28 +206,34 @@ unsafe fn get_tydesc<T>() -> *const TyDesc {
215
206
}
216
207
217
208
impl < ' longer_than_self > Arena < ' longer_than_self > {
209
+ #[ inline]
218
210
fn chunk_size ( & self ) -> usize {
219
211
self . copy_head . borrow ( ) . capacity ( )
220
212
}
221
213
222
214
// Functions for the POD part of the arena
215
+ #[ cold]
223
216
fn alloc_copy_grow ( & self , n_bytes : usize , align : usize ) -> * const u8 {
224
217
// Allocate a new chunk.
225
218
let new_min_chunk_size = cmp:: max ( n_bytes, self . chunk_size ( ) ) ;
226
- self . chunks . borrow_mut ( ) . push ( self . copy_head . borrow ( ) . clone ( ) ) ;
227
-
228
- * self . copy_head . borrow_mut ( ) = chunk ( ( new_min_chunk_size + 1 ) . next_power_of_two ( ) , true ) ;
219
+ let new_chunk = Chunk :: new ( ( new_min_chunk_size + 1 ) . next_power_of_two ( ) , true ) ;
220
+ let mut copy_head = self . copy_head . borrow_mut ( ) ;
221
+ let old_chunk = mem:: replace ( & mut * copy_head, new_chunk) ;
222
+ self . chunks . borrow_mut ( ) . push ( old_chunk) ;
229
223
230
224
self . alloc_copy_inner ( n_bytes, align)
231
225
}
232
226
233
227
#[ inline]
234
228
fn alloc_copy_inner ( & self , n_bytes : usize , align : usize ) -> * const u8 {
235
229
let start = round_up ( self . copy_head . borrow ( ) . fill . get ( ) , align) ;
230
+ let chunk_size = self . chunk_size ( ) ;
236
231
237
232
let end = start + n_bytes;
238
- if end > self . chunk_size ( ) {
239
- return self . alloc_copy_grow ( n_bytes, align) ;
233
+ if end > chunk_size {
234
+ if !self . copy_head . borrow_mut ( ) . data . reserve_in_place ( start, n_bytes) {
235
+ return self . alloc_copy_grow ( n_bytes, align) ;
236
+ }
240
237
}
241
238
242
239
let copy_head = self . copy_head . borrow ( ) ;
@@ -261,9 +258,10 @@ impl<'longer_than_self> Arena<'longer_than_self> {
261
258
fn alloc_noncopy_grow ( & self , n_bytes : usize , align : usize ) -> ( * const u8 , * const u8 ) {
262
259
// Allocate a new chunk.
263
260
let new_min_chunk_size = cmp:: max ( n_bytes, self . chunk_size ( ) ) ;
264
- self . chunks . borrow_mut ( ) . push ( self . head . borrow ( ) . clone ( ) ) ;
265
-
266
- * self . head . borrow_mut ( ) = chunk ( ( new_min_chunk_size + 1 ) . next_power_of_two ( ) , false ) ;
261
+ let new_chunk = Chunk :: new ( ( new_min_chunk_size + 1 ) . next_power_of_two ( ) , false ) ;
262
+ let mut head = self . head . borrow_mut ( ) ;
263
+ let old_chunk = mem:: replace ( & mut * head, new_chunk) ;
264
+ self . chunks . borrow_mut ( ) . push ( old_chunk) ;
267
265
268
266
self . alloc_noncopy_inner ( n_bytes, align)
269
267
}
@@ -606,7 +604,11 @@ mod tests {
606
604
#[ bench]
607
605
pub fn bench_copy_nonarena ( b : & mut Bencher ) {
608
606
b. iter ( || {
609
- let _: Box < _ > = box Point { x : 1 , y : 2 , z : 3 } ;
607
+ let _: Box < _ > = Box :: new ( Point {
608
+ x : 1 ,
609
+ y : 2 ,
610
+ z : 3
611
+ } ) ;
610
612
} )
611
613
}
612
614
@@ -647,10 +649,10 @@ mod tests {
647
649
#[ bench]
648
650
pub fn bench_noncopy_nonarena ( b : & mut Bencher ) {
649
651
b. iter ( || {
650
- let _: Box < _ > = box Noncopy {
652
+ let _: Box < _ > = Box :: new ( Noncopy {
651
653
string : "hello world" . to_string ( ) ,
652
654
array : vec ! [ 1 , 2 , 3 , 4 , 5 ] ,
653
- } ;
655
+ } ) ;
654
656
} )
655
657
}
656
658
0 commit comments