2
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
4
5
- use crate :: glue:: CallPropertyDescriptorTracer ;
6
- use crate :: jsapi:: js:: TraceValueArray ;
7
5
use crate :: jsapi:: JS ;
8
6
use crate :: jsapi:: { jsid, JSFunction , JSObject , JSScript , JSString , JSTracer } ;
9
-
10
7
use crate :: jsid:: VoidId ;
11
8
use std:: cell:: UnsafeCell ;
12
9
use std:: ffi:: { c_char, c_void} ;
@@ -68,9 +65,9 @@ impl RootKind for JS::Value {
68
65
const KIND : JS :: RootKind = JS :: RootKind :: Value ;
69
66
}
70
67
71
- impl < T : TraceableTrace > RootKind for T {
68
+ impl < T : Rootable > RootKind for T {
72
69
type Vtable = * const RootedVFTable ;
73
- const VTABLE : Self :: Vtable = & <Self as TraceableTrace >:: VTABLE ;
70
+ const VTABLE : Self :: Vtable = & <Self as Rootable >:: VTABLE ;
74
71
const KIND : JS :: RootKind = JS :: RootKind :: Traceable ;
75
72
}
76
73
@@ -93,32 +90,25 @@ impl RootedVFTable {
93
90
pub const PADDING : [ usize ; 2 ] = [ 0 , 0 ] ;
94
91
}
95
92
96
- /// `Rooted<T>` with a T that uses the Traceable RootKind uses dynamic dispatch on the C++ side
97
- /// for custom tracing. This trait provides trace logic via a vtable when creating a Rust instance
98
- /// of the object.
99
- pub unsafe trait TraceableTrace : Sized {
93
+ /// Marker trait that allows any type that implements the [trace::Traceable] trait to be used
94
+ /// with the [Rooted] type.
95
+ ///
96
+ /// `Rooted<T>` relies on dynamic dispatch in C++ when T uses the Traceable RootKind.
97
+ /// This trait initializes the vtable when creating a Rust instance of the Rooted object.
98
+ pub trait Rootable : crate :: trace:: Traceable + Sized {
100
99
const VTABLE : RootedVFTable = RootedVFTable {
101
100
padding : RootedVFTable :: PADDING ,
102
- trace : Self :: trace,
101
+ trace : < Self as Rootable > :: trace,
103
102
} ;
104
103
105
104
unsafe extern "C" fn trace ( this : * mut c_void , trc : * mut JSTracer , _name : * const c_char ) {
106
105
let rooted = this as * mut Rooted < Self > ;
107
106
let rooted = rooted. as_mut ( ) . unwrap ( ) ;
108
- Self :: do_trace ( & mut rooted. ptr , trc) ;
107
+ < Self as crate :: trace :: Traceable > :: trace ( & mut rooted. ptr , trc) ;
109
108
}
110
-
111
- /// Used by `TraceableTrace` implementer to trace its contents.
112
- /// Corresponds to virtual `trace` call in a `Rooted` that inherits from
113
- /// StackRootedTraceableBase (C++).
114
- unsafe fn do_trace ( & mut self , trc : * mut JSTracer ) ;
115
109
}
116
110
117
- unsafe impl TraceableTrace for JS :: PropertyDescriptor {
118
- unsafe fn do_trace ( & mut self , trc : * mut JSTracer ) {
119
- CallPropertyDescriptorTracer ( trc, self ) ;
120
- }
121
- }
111
+ impl < T : Rootable > Rootable for Option < T > { }
122
112
123
113
// The C++ representation of Rooted<T> inherits from StackRootedBase, which
124
114
// contains the actual pointers that get manipulated. The Rust representation
@@ -135,37 +125,63 @@ pub struct RootedBase {
135
125
136
126
// Annoyingly, bindgen can't cope with SM's use of templates, so we have to roll our own.
137
127
#[ repr( C ) ]
138
- #[ derive( Debug ) ]
128
+ #[ cfg_attr(
129
+ feature = "crown" ,
130
+ crown:: unrooted_must_root_lint:: allow_unrooted_interior
131
+ ) ]
139
132
pub struct Rooted < T : RootKind > {
140
133
pub vtable : T :: Vtable ,
141
134
pub base : RootedBase ,
142
135
pub ptr : T ,
143
136
}
144
137
138
+ /// Trait that provides a GC-safe default value for the given type, if one exists.
139
+ pub trait Initialize : Sized {
140
+ /// Create a default value. If there is no meaningful default possible, returns None.
141
+ /// SAFETY:
142
+ /// The default must not be a value that can be meaningfully garbage collected.
143
+ unsafe fn initial ( ) -> Option < Self > ;
144
+ }
145
+
146
+ impl < T > Initialize for Option < T > {
147
+ unsafe fn initial ( ) -> Option < Self > {
148
+ Some ( None )
149
+ }
150
+ }
151
+
145
152
/// A trait for types which can place appropriate GC barriers.
146
153
/// * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/Garbage_collection#Incremental_marking
147
154
/// * https://dxr.mozilla.org/mozilla-central/source/js/src/gc/Barrier.h
148
- pub trait GCMethods {
155
+ pub trait GCMethods : Initialize {
149
156
/// Create a default value
150
- unsafe fn initial ( ) -> Self ;
157
+ unsafe fn initial ( ) -> Self {
158
+ <Self as Initialize >:: initial ( )
159
+ . expect ( "Types used with heap GC methods must have a valid default" )
160
+ }
151
161
152
162
/// Place a post-write barrier
153
163
unsafe fn post_barrier ( v : * mut Self , prev : Self , next : Self ) ;
154
164
}
155
165
156
- impl GCMethods for * mut JSObject {
157
- unsafe fn initial ( ) -> * mut JSObject {
158
- ptr:: null_mut ( )
166
+ impl Initialize for * mut JSObject {
167
+ unsafe fn initial ( ) -> Option < * mut JSObject > {
168
+ Some ( ptr:: null_mut ( ) )
159
169
}
170
+ }
171
+
172
+ impl GCMethods for * mut JSObject {
160
173
unsafe fn post_barrier ( v : * mut * mut JSObject , prev : * mut JSObject , next : * mut JSObject ) {
161
174
JS :: HeapObjectWriteBarriers ( v, prev, next) ;
162
175
}
163
176
}
164
177
165
- impl GCMethods for * mut JSFunction {
166
- unsafe fn initial ( ) -> * mut JSFunction {
167
- ptr:: null_mut ( )
178
+ impl Initialize for * mut JSFunction {
179
+ unsafe fn initial ( ) -> Option < * mut JSFunction > {
180
+ Some ( ptr:: null_mut ( ) )
168
181
}
182
+ }
183
+
184
+ impl GCMethods for * mut JSFunction {
169
185
unsafe fn post_barrier ( v : * mut * mut JSFunction , prev : * mut JSFunction , next : * mut JSFunction ) {
170
186
JS :: HeapObjectWriteBarriers (
171
187
mem:: transmute ( v) ,
@@ -175,60 +191,83 @@ impl GCMethods for *mut JSFunction {
175
191
}
176
192
}
177
193
178
- impl GCMethods for * mut JSString {
179
- unsafe fn initial ( ) -> * mut JSString {
180
- ptr:: null_mut ( )
194
+ impl Initialize for * mut JSString {
195
+ unsafe fn initial ( ) -> Option < * mut JSString > {
196
+ Some ( ptr:: null_mut ( ) )
181
197
}
198
+ }
199
+
200
+ impl GCMethods for * mut JSString {
182
201
unsafe fn post_barrier ( v : * mut * mut JSString , prev : * mut JSString , next : * mut JSString ) {
183
202
JS :: HeapStringWriteBarriers ( v, prev, next) ;
184
203
}
185
204
}
186
205
187
- impl GCMethods for * mut JS :: Symbol {
188
- unsafe fn initial ( ) -> * mut JS :: Symbol {
189
- ptr:: null_mut ( )
206
+ impl Initialize for * mut JS :: Symbol {
207
+ unsafe fn initial ( ) -> Option < * mut JS :: Symbol > {
208
+ Some ( ptr:: null_mut ( ) )
190
209
}
210
+ }
211
+
212
+ impl GCMethods for * mut JS :: Symbol {
191
213
unsafe fn post_barrier ( _: * mut * mut JS :: Symbol , _: * mut JS :: Symbol , _: * mut JS :: Symbol ) { }
192
214
}
193
215
194
- impl GCMethods for * mut JS :: BigInt {
195
- unsafe fn initial ( ) -> * mut JS :: BigInt {
196
- ptr:: null_mut ( )
216
+ impl Initialize for * mut JS :: BigInt {
217
+ unsafe fn initial ( ) -> Option < * mut JS :: BigInt > {
218
+ Some ( ptr:: null_mut ( ) )
197
219
}
220
+ }
221
+
222
+ impl GCMethods for * mut JS :: BigInt {
198
223
unsafe fn post_barrier ( v : * mut * mut JS :: BigInt , prev : * mut JS :: BigInt , next : * mut JS :: BigInt ) {
199
224
JS :: HeapBigIntWriteBarriers ( v, prev, next) ;
200
225
}
201
226
}
202
227
203
- impl GCMethods for * mut JSScript {
204
- unsafe fn initial ( ) -> * mut JSScript {
205
- ptr:: null_mut ( )
228
+ impl Initialize for * mut JSScript {
229
+ unsafe fn initial ( ) -> Option < * mut JSScript > {
230
+ Some ( ptr:: null_mut ( ) )
206
231
}
232
+ }
233
+
234
+ impl GCMethods for * mut JSScript {
207
235
unsafe fn post_barrier ( v : * mut * mut JSScript , prev : * mut JSScript , next : * mut JSScript ) {
208
236
JS :: HeapScriptWriteBarriers ( v, prev, next) ;
209
237
}
210
238
}
211
239
212
- impl GCMethods for jsid {
213
- unsafe fn initial ( ) -> jsid {
214
- VoidId ( )
240
+ impl Initialize for jsid {
241
+ unsafe fn initial ( ) -> Option < jsid > {
242
+ Some ( VoidId ( ) )
215
243
}
244
+ }
245
+
246
+ impl GCMethods for jsid {
216
247
unsafe fn post_barrier ( _: * mut jsid , _: jsid , _: jsid ) { }
217
248
}
218
249
219
- impl GCMethods for JS :: Value {
220
- unsafe fn initial ( ) -> JS :: Value {
221
- JS :: Value :: default ( )
250
+ impl Initialize for JS :: Value {
251
+ unsafe fn initial ( ) -> Option < JS :: Value > {
252
+ Some ( JS :: Value :: default ( ) )
222
253
}
254
+ }
255
+
256
+ impl GCMethods for JS :: Value {
223
257
unsafe fn post_barrier ( v : * mut JS :: Value , prev : JS :: Value , next : JS :: Value ) {
224
258
JS :: HeapValueWriteBarriers ( v, & prev, & next) ;
225
259
}
226
260
}
227
261
228
- impl GCMethods for JS :: PropertyDescriptor {
229
- unsafe fn initial ( ) -> JS :: PropertyDescriptor {
230
- JS :: PropertyDescriptor :: default ( )
262
+ impl Rootable for JS :: PropertyDescriptor { }
263
+
264
+ impl Initialize for JS :: PropertyDescriptor {
265
+ unsafe fn initial ( ) -> Option < JS :: PropertyDescriptor > {
266
+ Some ( JS :: PropertyDescriptor :: default ( ) )
231
267
}
268
+ }
269
+
270
+ impl GCMethods for JS :: PropertyDescriptor {
232
271
unsafe fn post_barrier (
233
272
_: * mut JS :: PropertyDescriptor ,
234
273
_: JS :: PropertyDescriptor ,
@@ -258,19 +297,14 @@ impl<const N: usize> ValueArray<N> {
258
297
}
259
298
}
260
299
261
- unsafe impl < const N : usize > TraceableTrace for ValueArray < N > {
262
- unsafe fn do_trace ( & mut self , trc : * mut JSTracer ) {
263
- TraceValueArray ( trc, N , self . get_mut_ptr ( ) ) ;
264
- }
265
- }
300
+ impl < const N : usize > Rootable for ValueArray < N > { }
266
301
267
- impl < const N : usize > GCMethods for ValueArray < N > {
268
- unsafe fn initial ( ) -> Self {
269
- Self {
270
- elements : [ JS :: Value :: initial ( ) ; N ] ,
271
- }
302
+ impl < const N : usize > Initialize for ValueArray < N > {
303
+ unsafe fn initial ( ) -> Option < Self > {
304
+ Some ( Self {
305
+ elements : [ < JS :: Value as GCMethods > :: initial ( ) ; N ] ,
306
+ } )
272
307
}
273
- unsafe fn post_barrier ( _: * mut Self , _: Self , _: Self ) { }
274
308
}
275
309
276
310
/// RootedValueArray roots an internal fixed-size array of Values
@@ -371,7 +405,7 @@ impl<T: GCMethods + Copy> Drop for Heap<T> {
371
405
fn drop ( & mut self ) {
372
406
unsafe {
373
407
let ptr = self . ptr . get ( ) ;
374
- T :: post_barrier ( ptr, * ptr, T :: initial ( ) ) ;
408
+ T :: post_barrier ( ptr, * ptr, < T as GCMethods > :: initial ( ) ) ;
375
409
}
376
410
}
377
411
}
0 commit comments