Skip to content

Commit 861c091

Browse files
authored
Refactor Rooted<T> (#576)
* Factor out MaybeUninit from Rooted Signed-off-by: Greg Morenz <greg-morenz@droid.cafe> * Rename ptr to data Signed-off-by: Greg Morenz <greg-morenz@droid.cafe> --------- Signed-off-by: Greg Morenz <greg-morenz@droid.cafe>
1 parent 2b94daa commit 861c091

File tree

5 files changed

+25
-35
lines changed

5 files changed

+25
-35
lines changed

mozjs-sys/src/jsgc.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ pub trait Rootable: crate::trace::Traceable + Sized {
104104
unsafe extern "C" fn trace(this: *mut c_void, trc: *mut JSTracer, _name: *const c_char) {
105105
let rooted = this as *mut Rooted<Self>;
106106
let rooted = rooted.as_mut().unwrap();
107-
<Self as crate::trace::Traceable>::trace(rooted.ptr.assume_init_mut(), trc);
107+
<Self as crate::trace::Traceable>::trace(&mut rooted.data, trc);
108108
}
109109
}
110110

@@ -132,11 +132,7 @@ pub struct RootedBase {
132132
pub struct Rooted<T: RootKind> {
133133
pub vtable: T::Vtable,
134134
pub base: RootedBase,
135-
136-
/// The rooted value
137-
///
138-
/// This will be initialied iff there is a `RootedGuard` for this `Rooted`
139-
pub ptr: mem::MaybeUninit<T>,
135+
pub data: T,
140136
}
141137

142138
/// Trait that provides a GC-safe default value for the given type, if one exists.
@@ -292,7 +288,7 @@ impl<const N: usize> ValueArray<N> {
292288
Self { elements }
293289
}
294290

295-
pub unsafe fn get_ptr(&self) -> *const JS::Value {
291+
pub fn get_ptr(&self) -> *const JS::Value {
296292
self.elements.as_ptr()
297293
}
298294

mozjs-sys/src/jsimpls.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use crate::jsid::VoidId;
2525
use crate::jsval::{JSVal, UndefinedValue};
2626

2727
use std::marker::PhantomData;
28-
use std::mem;
2928
use std::ops::Deref;
3029
use std::ptr;
3130

@@ -144,7 +143,7 @@ impl<const N: usize> From<&Rooted<ValueArray<N>>> for JS::HandleValueArray {
144143
fn from(array: &Rooted<ValueArray<N>>) -> JS::HandleValueArray {
145144
JS::HandleValueArray {
146145
length_: N,
147-
elements_: unsafe { array.ptr.assume_init_ref().get_ptr() },
146+
elements_: array.data.get_ptr(),
148147
}
149148
}
150149
}
@@ -429,14 +428,14 @@ impl RootedBase {
429428
}
430429

431430
impl<T: RootKind> JS::Rooted<T> {
432-
pub fn new_unrooted() -> JS::Rooted<T> {
431+
pub fn new_unrooted(initial: T) -> JS::Rooted<T> {
433432
JS::Rooted {
434433
vtable: T::VTABLE,
435434
base: RootedBase {
436435
stack: ptr::null_mut(),
437436
prev: ptr::null_mut(),
438437
},
439-
ptr: mem::MaybeUninit::zeroed(),
438+
data: initial,
440439
}
441440
}
442441

mozjs/src/conversions.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,8 @@ impl<C: Clone, T: FromJSValConvertible<Config = C>> FromJSValConvertible for Vec
722722
let zero = mem::zeroed();
723723
let mut iterator = ForOfIterator {
724724
cx_: cx,
725-
iterator: RootedObject::new_unrooted(),
726-
nextMethod: RootedValue::new_unrooted(),
725+
iterator: RootedObject::new_unrooted(ptr::null_mut()),
726+
nextMethod: RootedValue::new_unrooted(JSVal { asBits_: 0 }),
727727
index: ::std::u32::MAX, // NOT_ARRAY
728728
..zero
729729
};
@@ -737,7 +737,7 @@ impl<C: Clone, T: FromJSValConvertible<Config = C>> FromJSValConvertible for Vec
737737
return Err(());
738738
}
739739

740-
if iterator.iterator.ptr.assume_init_ref().is_null() {
740+
if iterator.iterator.data.is_null() {
741741
return Ok(ConversionResult::Failure("Value is not iterable".into()));
742742
}
743743

mozjs/src/gc/macros.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#[macro_export]
22
macro_rules! rooted {
33
(in($cx:expr) let $($var:ident)+ = $init:expr) => {
4-
let mut __root = $crate::jsapi::Rooted::new_unrooted();
4+
let mut __root = ::std::mem::MaybeUninit::uninit();
55
let $($var)+ = $crate::gc::RootedGuard::new($cx, &mut __root, $init);
66
};
77
(in($cx:expr) let $($var:ident)+: $type:ty = $init:expr) => {
8-
let mut __root = $crate::jsapi::Rooted::new_unrooted();
8+
let mut __root = ::std::mem::MaybeUninit::uninit();
99
let $($var)+: $crate::gc::RootedGuard<$type> = $crate::gc::RootedGuard::new($cx, &mut __root, $init);
1010
};
1111
(in($cx:expr) let $($var:ident)+: $type:ty) => {
12-
let mut __root = $crate::jsapi::Rooted::new_unrooted();
12+
let mut __root = ::std::mem::MaybeUninit::uninit();
1313
// SAFETY:
1414
// We're immediately storing the initial value in a rooted location.
1515
let $($var)+: $crate::gc::RootedGuard<$type> = $crate::gc::RootedGuard::new(

mozjs/src/gc/root.rs

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ pub struct RootedGuard<'a, T: 'a + RootKind> {
2626
}
2727

2828
impl<'a, T: 'a + RootKind> RootedGuard<'a, T> {
29-
pub fn new(cx: *mut JSContext, root: &'a mut Rooted<T>, initial: T) -> Self {
30-
root.ptr.write(initial);
29+
pub fn new(cx: *mut JSContext, root: &'a mut MaybeUninit<Rooted<T>>, initial: T) -> Self {
30+
let root: *mut Rooted<T> = root.write(Rooted::new_unrooted(initial));
31+
3132
unsafe {
32-
let root: *mut Rooted<T> = root;
3333
Rooted::add_to_root_stack(root, cx);
3434
RootedGuard {
3535
root,
@@ -48,7 +48,7 @@ impl<'a, T: 'a + RootKind> RootedGuard<'a, T> {
4848

4949
pub fn as_ptr(&self) -> *mut T {
5050
// SAFETY: self.root points to an inbounds allocation
51-
unsafe { (&raw mut (*self.root).ptr).cast() }
51+
unsafe { (&raw mut (*self.root).data) }
5252
}
5353

5454
/// Safety: GC must not run during the lifetime of the returned reference.
@@ -63,17 +63,12 @@ impl<'a, T: 'a + RootKind> RootedGuard<'a, T> {
6363
where
6464
T: Copy,
6565
{
66-
// SAFETY: The rooted value is initialized as long as we exist
67-
unsafe { (*self.root).ptr.assume_init() }
66+
*self.deref()
6867
}
6968

7069
pub fn set(&mut self, v: T) {
71-
// SAFETY: The rooted value is initialized as long as we exist
72-
unsafe {
73-
// Make sure the drop impl for T is called
74-
(*self.root).ptr.assume_init_drop();
75-
(*self.root).ptr.write(v);
76-
}
70+
// SAFETY: GC does not run during this block
71+
unsafe { *self.as_mut() = v };
7772
}
7873
}
7974

@@ -90,18 +85,18 @@ where
9085
impl<'a, T: 'a + RootKind> Deref for RootedGuard<'a, T> {
9186
type Target = T;
9287
fn deref(&self) -> &T {
93-
// SAFETY: The rooted value is initialized as long as we exist
94-
unsafe { (*self.root).ptr.assume_init_ref() }
88+
unsafe { &(*self.root).data }
9589
}
9690
}
9791

9892
impl<'a, T: 'a + RootKind> Drop for RootedGuard<'a, T> {
9993
fn drop(&mut self) {
100-
// SAFETY: The rooted value is initialized as long as we exist
94+
// SAFETY: The `drop_in_place` invariants are upheld:
95+
// https://doc.rust-lang.org/std/ptr/fn.drop_in_place.html#safety
10196
unsafe {
102-
// Make sure the drop impl for T is called
103-
(*self.root).ptr.assume_init_drop();
104-
(*self.root).ptr = MaybeUninit::zeroed();
97+
let ptr = self.as_ptr();
98+
ptr::drop_in_place(ptr);
99+
ptr.write_bytes(0, 1);
105100
}
106101

107102
unsafe {

0 commit comments

Comments
 (0)