Skip to content

Commit 9d4e645

Browse files
committed
remove use of transmute in cppgc
1 parent 4d5b674 commit 9d4e645

File tree

3 files changed

+81
-85
lines changed

3 files changed

+81
-85
lines changed

src/cppgc.rs

Lines changed: 81 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -86,22 +86,6 @@ unsafe extern "C" {
8686
) -> *mut RustObj;
8787
}
8888

89-
unsafe fn get_rust_obj<'s>(obj: *const RustObj) -> &'s dyn GarbageCollected {
90-
unsafe {
91-
&*std::mem::transmute::<[usize; 2], *mut dyn GarbageCollected>((*obj).data)
92-
}
93-
}
94-
95-
unsafe fn get_rust_obj_mut<'s>(
96-
obj: *mut RustObj,
97-
) -> &'s mut dyn GarbageCollected {
98-
unsafe {
99-
&mut *std::mem::transmute::<[usize; 2], *mut dyn GarbageCollected>(
100-
(*obj).data,
101-
)
102-
}
103-
}
104-
10589
#[unsafe(no_mangle)]
10690
unsafe extern "C" fn rusty_v8_RustObj_trace(
10791
obj: *const RustObj,
@@ -129,25 +113,6 @@ unsafe extern "C" fn rusty_v8_RustObj_drop(obj: *mut RustObj) {
129113
}
130114
}
131115

132-
fn object_offset_for_rust_obj<T: GarbageCollected>() -> usize {
133-
#[repr(C)]
134-
struct Calc<T> {
135-
header: RustObj,
136-
data: T,
137-
}
138-
139-
std::mem::offset_of!(Calc<T>, data)
140-
}
141-
142-
/// # Safety
143-
///
144-
/// T must be the correct type for this specific RustObj
145-
unsafe fn get_object_from_rust_obj<T: GarbageCollected>(
146-
rust_obj: *const RustObj,
147-
) -> *mut T {
148-
unsafe { rust_obj.byte_add(object_offset_for_rust_obj::<T>()) as *mut T }
149-
}
150-
151116
/// Process-global initialization of the garbage collector. Must be called before
152117
/// creating a Heap.
153118
///
@@ -357,6 +322,29 @@ pub unsafe trait GarbageCollected {
357322
fn get_name(&self) -> &'static CStr;
358323
}
359324

325+
#[repr(C)]
326+
struct RustObjConcrete<T> {
327+
head: RustObj,
328+
dynamic: *mut dyn GarbageCollected,
329+
value: T,
330+
}
331+
332+
unsafe fn get_rust_obj<'s>(obj: *const RustObj) -> &'s dyn GarbageCollected {
333+
unsafe {
334+
let obj = &*(obj as *const RustObjConcrete<()>);
335+
&*obj.dynamic
336+
}
337+
}
338+
339+
unsafe fn get_rust_obj_mut<'s>(
340+
obj: *mut RustObj,
341+
) -> &'s mut dyn GarbageCollected {
342+
unsafe {
343+
let obj = &mut *(obj as *mut RustObjConcrete<()>);
344+
&mut *obj.dynamic
345+
}
346+
}
347+
360348
/// Constructs an instance of T, which is a garbage collected type.
361349
///
362350
/// The object will be allocated on the heap and managed by cppgc. During
@@ -376,30 +364,30 @@ pub unsafe fn make_garbage_collected<T: GarbageCollected + 'static>(
376364
const {
377365
// max alignment in cppgc is 16
378366
assert!(std::mem::align_of::<T>() <= 16);
367+
assert!(
368+
std::mem::offset_of!(RustObjConcrete<T>, dynamic)
369+
== std::mem::offset_of!(RustObjConcrete<()>, dynamic)
370+
);
379371
}
380372

381-
let additional_bytes = (object_offset_for_rust_obj::<T>()
382-
- std::mem::size_of::<RustObj>())
383-
+ std::mem::size_of::<T>();
373+
let additional_bytes =
374+
std::mem::size_of::<RustObjConcrete<T>>() - std::mem::size_of::<RustObj>();
384375

385376
let pointer = unsafe {
386377
cppgc__make_garbage_collectable(
387378
heap as *const Heap as *mut _,
388379
additional_bytes,
389-
std::mem::align_of::<T>(),
380+
std::mem::align_of::<RustObjConcrete<T>>(),
390381
)
391382
};
392383

393384
assert!(!pointer.is_null());
394385

395386
unsafe {
396-
let inner = get_object_from_rust_obj::<T>(pointer);
397-
inner.write(obj);
398-
399-
let rust_obj = &mut *pointer;
400-
rust_obj.data = std::mem::transmute::<*mut dyn GarbageCollected, [usize; 2]>(
401-
&mut *inner as &mut dyn GarbageCollected as *mut dyn GarbageCollected,
402-
);
387+
let pointer = &mut *(pointer as *mut RustObjConcrete<T>);
388+
let value_ptr = std::ptr::addr_of_mut!(pointer.value);
389+
value_ptr.write(obj);
390+
std::ptr::addr_of_mut!(pointer.dynamic).write(value_ptr as _);
403391
}
404392

405393
UnsafePtr {
@@ -408,6 +396,50 @@ pub unsafe fn make_garbage_collected<T: GarbageCollected + 'static>(
408396
}
409397
}
410398

399+
/// # Safety
400+
///
401+
/// T must be the correct type for this specific RustObj
402+
unsafe fn get_value_from_rust_obj<T: GarbageCollected>(
403+
obj: *mut RustObj,
404+
) -> *const T {
405+
unsafe {
406+
let obj = &mut *(obj as *mut RustObjConcrete<T>);
407+
std::ptr::addr_of_mut!(obj.value)
408+
}
409+
}
410+
411+
/// UnsafePtr is used to refer to an on-heap object from the stack.
412+
#[derive(Clone, Copy)]
413+
pub struct UnsafePtr<T: GarbageCollected> {
414+
pointer: NonNull<RustObj>,
415+
_phantom: PhantomData<T>,
416+
}
417+
418+
impl<T: GarbageCollected> UnsafePtr<T> {
419+
/// Create a new UnsafePtr.
420+
///
421+
/// # Safety
422+
///
423+
/// The caller must ensure that the returned pointer is always stored on
424+
/// the stack, or is safely moved into one of the other cppgc pointer types.
425+
pub unsafe fn new(value: &impl GetRustObj<T>) -> Option<UnsafePtr<T>> {
426+
NonNull::new(value.get_rust_obj()).map(|pointer| UnsafePtr {
427+
pointer,
428+
_phantom: PhantomData,
429+
})
430+
}
431+
432+
pub unsafe fn as_ref(&self) -> &T {
433+
unsafe { &*get_value_from_rust_obj(self.pointer.as_ptr()) }
434+
}
435+
}
436+
437+
impl<T: GarbageCollected> GetRustObj<T> for UnsafePtr<T> {
438+
fn get_rust_obj(&self) -> *mut RustObj {
439+
self.pointer.as_ptr()
440+
}
441+
}
442+
411443
#[doc(hidden)]
412444
pub trait GetRustObj<T: GarbageCollected> {
413445
fn get_rust_obj(&self) -> *mut RustObj;
@@ -501,15 +533,15 @@ macro_rules! member {
501533
#[doc = ""]
502534
#[doc = "The caller must ensure that this pointer is being traced correctly by appearing in the [`trace`](GarbageCollected::trace)"]
503535
#[doc = "implementation of the object that owns the pointer. Between initializing the pointer and calling `get()`, the pointer must be reachable by the garbage collector."]
504-
pub unsafe fn get(&self) -> Option<&T> {
536+
pub unsafe fn get(&self) -> Option<T> {
505537
let ptr = self.inner.get();
506538
if ptr.is_null() {
507539
None
508540
} else {
509541
// SAFETY: Either this is a strong reference and the pointer is valid according
510542
// to the safety contract of this method, or this is a weak reference and the
511543
// ptr will be null if it was collected.
512-
Some(unsafe { &*get_object_from_rust_obj(ptr) })
544+
Some(unsafe { &*get_value_from_rust_obj(ptr) })
513545
}
514546
}
515547
}
@@ -607,7 +639,7 @@ macro_rules! persistent {
607639
} else {
608640
// SAFETY: Either this is a strong reference and the pointer is always valid
609641
// or this is a weak reference and the ptr will be null if it was collected.
610-
Some(unsafe { &*get_object_from_rust_obj(ptr) })
642+
Some(unsafe { &*get_value_from_rust_obj(ptr) })
611643
}
612644
}
613645

@@ -661,40 +693,6 @@ persistent! {
661693
WeakPersistent
662694
}
663695

664-
/// UnsafePtr is used to refer to an on-heap object from the stack.
665-
#[derive(Clone, Copy)]
666-
pub struct UnsafePtr<T: GarbageCollected> {
667-
pointer: NonNull<RustObj>,
668-
_phantom: PhantomData<T>,
669-
}
670-
671-
impl<T: GarbageCollected> UnsafePtr<T> {
672-
/// Create a new UnsafePtr.
673-
///
674-
/// # Safety
675-
///
676-
/// The caller must ensure that the returned pointer is always stored on
677-
/// the stack, or is safely moved into one of the other cppgc pointer types.
678-
pub unsafe fn new(other: &impl GetRustObj<T>) -> Option<Self> {
679-
NonNull::new(other.get_rust_obj()).map(|pointer| Self {
680-
pointer,
681-
_phantom: PhantomData,
682-
})
683-
}
684-
}
685-
686-
impl<T: GarbageCollected> UnsafePtr<T> {
687-
pub unsafe fn as_ref(&self) -> &T {
688-
unsafe { &*get_object_from_rust_obj(self.pointer.as_ptr()) }
689-
}
690-
}
691-
692-
impl<T: GarbageCollected> GetRustObj<T> for UnsafePtr<T> {
693-
fn get_rust_obj(&self) -> *mut RustObj {
694-
self.pointer.as_ptr()
695-
}
696-
}
697-
698696
/// `GcCell` is a zero-overhead memory cell that provides interior mutability
699697
/// for garbage collected types.
700698
///

src/object.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,6 @@ impl Object {
768768
/// # Safety
769769
///
770770
/// The `TAG` must be unique to the caller within the heap.
771-
#[allow(clippy::not_unsafe_ptr_arg_deref)]
772771
#[inline(always)]
773772
pub unsafe fn wrap<const TAG: u16, T: GarbageCollected>(
774773
isolate: &mut Isolate,

src/support.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,5 +185,4 @@ class RustObj : public v8::Object::Wrappable {
185185
~RustObj();
186186
void Trace(cppgc::Visitor* visitor) const;
187187
const char* GetHumanReadableName() const final;
188-
uintptr_t data[2];
189188
};

0 commit comments

Comments
 (0)