4
4
//! as it is difficult to depend on crates from within `proc_macro`, due to it
5
5
//! being built at the same time as `std`.
6
6
7
- use std:: cell:: { Cell , RefCell } ;
8
7
use std:: mem:: MaybeUninit ;
9
8
use std:: ops:: Range ;
10
9
use std:: { cmp, ptr, slice} ;
@@ -26,27 +25,22 @@ const HUGE_PAGE: usize = 2 * 1024 * 1024;
26
25
/// This arena doesn't have support for allocating anything other than byte
27
26
/// slices, as that is all that is necessary.
28
27
pub ( crate ) struct Arena {
29
- start : Cell < * mut MaybeUninit < u8 > > ,
30
- end : Cell < * mut MaybeUninit < u8 > > ,
31
- chunks : RefCell < Vec < Box < [ MaybeUninit < u8 > ] > > > ,
28
+ start : * mut MaybeUninit < u8 > ,
29
+ end : * mut MaybeUninit < u8 > ,
30
+ chunks : Vec < Box < [ MaybeUninit < u8 > ] > > ,
32
31
}
33
32
34
33
impl Arena {
35
34
pub ( crate ) fn new ( ) -> Self {
36
- Arena {
37
- start : Cell :: new ( ptr:: null_mut ( ) ) ,
38
- end : Cell :: new ( ptr:: null_mut ( ) ) ,
39
- chunks : RefCell :: new ( Vec :: new ( ) ) ,
40
- }
35
+ Arena { start : ptr:: null_mut ( ) , end : ptr:: null_mut ( ) , chunks : Vec :: new ( ) }
41
36
}
42
37
43
38
/// Add a new chunk with at least `additional` free bytes.
44
39
#[ inline( never) ]
45
40
#[ cold]
46
- fn grow ( & self , additional : usize ) {
47
- let mut chunks = self . chunks . borrow_mut ( ) ;
41
+ fn grow ( & mut self , additional : usize ) {
48
42
let mut new_cap;
49
- if let Some ( last_chunk) = chunks. last_mut ( ) {
43
+ if let Some ( last_chunk) = self . chunks . last_mut ( ) {
50
44
// If the previous chunk's len is less than HUGE_PAGE
51
45
// bytes, then this chunk will be least double the previous
52
46
// chunk's size.
@@ -60,48 +54,46 @@ impl Arena {
60
54
61
55
let mut chunk = Box :: new_uninit_slice ( new_cap) ;
62
56
let Range { start, end } = chunk. as_mut_ptr_range ( ) ;
63
- self . start . set ( start) ;
64
- self . end . set ( end) ;
65
- chunks. push ( chunk) ;
57
+ self . start = start;
58
+ self . end = end;
59
+ self . chunks . push ( chunk) ;
66
60
}
67
61
68
62
/// Allocates a byte slice with specified size from the current memory
69
63
/// chunk. Returns `None` if there is no free space left to satisfy the
70
64
/// request.
71
- #[ allow( clippy:: mut_from_ref) ]
72
- fn alloc_raw_without_grow ( & self , bytes : usize ) -> Option < & mut [ MaybeUninit < u8 > ] > {
73
- let start = self . start . get ( ) . addr ( ) ;
74
- let old_end = self . end . get ( ) ;
65
+ fn alloc_raw_without_grow ( & mut self , bytes : usize ) -> Option < & mut [ MaybeUninit < u8 > ] > {
66
+ let start = self . start . addr ( ) ;
67
+ let old_end = self . end ;
75
68
let end = old_end. addr ( ) ;
76
69
77
70
let new_end = end. checked_sub ( bytes) ?;
78
71
if start <= new_end {
79
72
let new_end = old_end. with_addr ( new_end) ;
80
- self . end . set ( new_end) ;
73
+ self . end = new_end;
81
74
// SAFETY: `bytes` bytes starting at `new_end` were just reserved.
82
75
Some ( unsafe { slice:: from_raw_parts_mut ( new_end, bytes) } )
83
76
} else {
84
77
None
85
78
}
86
79
}
87
80
88
- fn alloc_raw ( & self , bytes : usize ) -> & mut [ MaybeUninit < u8 > ] {
81
+ fn alloc_raw ( & mut self , bytes : usize ) -> & mut [ MaybeUninit < u8 > ] {
89
82
if bytes == 0 {
90
83
return & mut [ ] ;
91
84
}
92
85
93
- loop {
94
- if let Some ( a) = self . alloc_raw_without_grow ( bytes) {
95
- break a;
96
- }
97
- // No free space left. Allocate a new chunk to satisfy the request.
98
- // On failure the grow will panic or abort.
99
- self . grow ( bytes) ;
86
+ if let Some ( a) = self . alloc_raw_without_grow ( bytes) {
87
+ // SAFETY: the lifetime is extended here, but then constrained again in `alloc_str`.
88
+ return unsafe { & mut * ( a as * mut _ ) } ;
100
89
}
90
+ // No free space left. Allocate a new chunk to satisfy the request.
91
+ // On failure the grow will panic or abort.
92
+ self . grow ( bytes) ;
93
+ self . alloc_raw_without_grow ( bytes) . unwrap ( )
101
94
}
102
95
103
- #[ allow( clippy:: mut_from_ref) ] // arena allocator
104
- pub ( crate ) fn alloc_str < ' a > ( & ' a self , string : & str ) -> & ' a mut str {
96
+ pub ( crate ) fn alloc_str < ' a > ( & ' a mut self , string : & str ) -> & ' a mut str {
105
97
let alloc = self . alloc_raw ( string. len ( ) ) ;
106
98
let bytes = alloc. write_copy_of_slice ( string. as_bytes ( ) ) ;
107
99
0 commit comments