1
+ use crate :: set_data_ptr;
1
2
use crate :: trace:: Trace ;
3
+ use std:: alloc:: { alloc, dealloc, Layout } ;
2
4
use std:: cell:: { Cell , RefCell } ;
3
5
use std:: mem;
4
6
use std:: ptr:: { self , NonNull } ;
5
7
8
+ #[ cfg( feature = "nightly" ) ]
9
+ use std:: marker:: Unsize ;
10
+
6
11
struct GcState {
7
12
stats : GcStats ,
8
13
config : GcConfig ,
@@ -103,7 +108,7 @@ impl GcBoxHeader {
103
108
}
104
109
}
105
110
106
- #[ repr( C ) ] // to justify the layout computation in Gc::from_raw
111
+ #[ repr( C ) ] // to justify the layout computations in GcBox::from_box, Gc::from_raw
107
112
pub ( crate ) struct GcBox < T : Trace + ?Sized + ' static > {
108
113
header : GcBoxHeader ,
109
114
data : T ,
@@ -124,6 +129,37 @@ impl<T: Trace> GcBox<T> {
124
129
}
125
130
}
126
131
132
+ impl <
133
+ #[ cfg( not( feature = "nightly" ) ) ] T : Trace ,
134
+ #[ cfg( feature = "nightly" ) ] T : Trace + Unsize < dyn Trace > + ?Sized ,
135
+ > GcBox < T >
136
+ {
137
+ pub ( crate ) fn from_box ( value : Box < T > ) -> NonNull < Self > {
138
+ let header_layout = Layout :: new :: < GcBoxHeader > ( ) ;
139
+ let value_layout = Layout :: for_value :: < T > ( & * value) ;
140
+ let gcbox_layout = header_layout. extend ( value_layout) . unwrap ( ) . 0 . pad_to_align ( ) ;
141
+
142
+ unsafe {
143
+ let gcbox_addr = alloc ( gcbox_layout) ;
144
+ let value = Box :: into_raw ( value) ;
145
+ let gcbox = set_data_ptr ( value as * mut GcBox < T > , gcbox_addr) ;
146
+ ptr:: addr_of_mut!( ( * gcbox) . header) . write ( GcBoxHeader :: new ( ) ) ;
147
+ ptr:: addr_of_mut!( ( * gcbox) . data)
148
+ . cast :: < u8 > ( )
149
+ . copy_from_nonoverlapping ( value. cast :: < u8 > ( ) , value_layout. size ( ) ) ;
150
+ let gcbox = NonNull :: new_unchecked ( gcbox) ;
151
+ insert_gcbox ( gcbox) ;
152
+
153
+ // Box only allocates for size != 0
154
+ if value_layout. size ( ) != 0 {
155
+ dealloc ( value. cast :: < u8 > ( ) , value_layout) ;
156
+ }
157
+
158
+ gcbox
159
+ }
160
+ }
161
+ }
162
+
127
163
unsafe fn insert_gcbox ( gcbox : NonNull < GcBox < dyn Trace > > ) {
128
164
GC_STATE . with ( |st| {
129
165
let mut st = st. borrow_mut ( ) ;
0 commit comments