@@ -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) ]
10690unsafe 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) ]
412444pub trait GetRustObj < T : GarbageCollected > {
413445 fn get_rust_obj ( & self ) -> * mut RustObj ;
@@ -509,7 +541,7 @@ macro_rules! member {
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///
0 commit comments