mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-25 08:39:15 -05:00
feat: cppgc::Ptr (#1523)
This commit is contained in:
parent
2c5db866a2
commit
57fb97a43b
5 changed files with 118 additions and 43 deletions
|
@ -21,7 +21,11 @@ impl std::fmt::Display for Rope {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rope {
|
impl Rope {
|
||||||
pub fn new(part: String, next: v8::cppgc::Member<Rope>) -> Rope {
|
pub fn new(part: String, next: Option<v8::cppgc::Ptr<Rope>>) -> Rope {
|
||||||
|
let next = match next {
|
||||||
|
Some(p) => v8::cppgc::Member::new(&p),
|
||||||
|
None => v8::cppgc::Member::empty(),
|
||||||
|
};
|
||||||
Self { part, next }
|
Self { part, next }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,15 +59,15 @@ fn main() {
|
||||||
&heap,
|
&heap,
|
||||||
Rope::new(
|
Rope::new(
|
||||||
String::from("Hello "),
|
String::from("Hello "),
|
||||||
v8::cppgc::make_garbage_collected(
|
Some(v8::cppgc::make_garbage_collected(
|
||||||
&heap,
|
&heap,
|
||||||
Rope::new(String::from("World!"), v8::cppgc::Member::empty()),
|
Rope::new(String::from("World!"), None),
|
||||||
),
|
)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("{}", rope.borrow().unwrap());
|
println!("{}", rope);
|
||||||
|
|
||||||
// Manually trigger garbage collection.
|
// Manually trigger garbage collection.
|
||||||
heap.enable_detached_garbage_collections_for_testing();
|
heap.enable_detached_garbage_collections_for_testing();
|
||||||
|
@ -76,7 +80,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should still be live here:
|
// Should still be live here:
|
||||||
println!("{}", rope.borrow().unwrap());
|
println!("{}", rope);
|
||||||
|
|
||||||
println!("Collect: NoHeapPointers");
|
println!("Collect: NoHeapPointers");
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -3936,8 +3936,8 @@ void cppgc__WeakMember__Assign(cppgc::WeakMember<RustObj>* member,
|
||||||
member->operator=(other);
|
member->operator=(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
cppgc::Persistent<RustObj>* cppgc__Persistent__CONSTRUCT() {
|
cppgc::Persistent<RustObj>* cppgc__Persistent__CONSTRUCT(RustObj* obj) {
|
||||||
return new cppgc::Persistent<RustObj>(nullptr);
|
return new cppgc::Persistent<RustObj>(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cppgc__Persistent__DESTRUCT(cppgc::Persistent<RustObj>* self) {
|
void cppgc__Persistent__DESTRUCT(cppgc::Persistent<RustObj>* self) {
|
||||||
|
@ -3952,8 +3952,8 @@ RustObj* cppgc__Persistent__Get(cppgc::Persistent<RustObj>* self) {
|
||||||
return self->Get();
|
return self->Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
cppgc::WeakPersistent<RustObj>* cppgc__WeakPersistent__CONSTRUCT() {
|
cppgc::WeakPersistent<RustObj>* cppgc__WeakPersistent__CONSTRUCT(RustObj* obj) {
|
||||||
return new cppgc::WeakPersistent<RustObj>(nullptr);
|
return new cppgc::WeakPersistent<RustObj>(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cppgc__WeakPersistent__DESTRUCT(cppgc::WeakPersistent<RustObj>* self) {
|
void cppgc__WeakPersistent__DESTRUCT(cppgc::WeakPersistent<RustObj>* self) {
|
||||||
|
|
127
src/cppgc.rs
127
src/cppgc.rs
|
@ -8,6 +8,7 @@ use crate::support::UniqueRef;
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
use crate::TracedReference;
|
use crate::TracedReference;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn cppgc__initialize_process(platform: *mut Platform);
|
fn cppgc__initialize_process(platform: *mut Platform);
|
||||||
|
@ -63,12 +64,14 @@ extern "C" {
|
||||||
other: *mut RustObj,
|
other: *mut RustObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn cppgc__Persistent__CONSTRUCT() -> *mut PersistentInner;
|
fn cppgc__Persistent__CONSTRUCT(obj: *mut RustObj) -> *mut PersistentInner;
|
||||||
fn cppgc__Persistent__DESTRUCT(this: *mut PersistentInner);
|
fn cppgc__Persistent__DESTRUCT(this: *mut PersistentInner);
|
||||||
fn cppgc__Persistent__Assign(this: *mut PersistentInner, ptr: *mut RustObj);
|
fn cppgc__Persistent__Assign(this: *mut PersistentInner, ptr: *mut RustObj);
|
||||||
fn cppgc__Persistent__Get(this: *const PersistentInner) -> *mut RustObj;
|
fn cppgc__Persistent__Get(this: *const PersistentInner) -> *mut RustObj;
|
||||||
|
|
||||||
fn cppgc__WeakPersistent__CONSTRUCT() -> *mut WeakPersistentInner;
|
fn cppgc__WeakPersistent__CONSTRUCT(
|
||||||
|
obj: *mut RustObj,
|
||||||
|
) -> *mut WeakPersistentInner;
|
||||||
fn cppgc__WeakPersistent__DESTRUCT(this: *mut WeakPersistentInner);
|
fn cppgc__WeakPersistent__DESTRUCT(this: *mut WeakPersistentInner);
|
||||||
fn cppgc__WeakPersistent__Assign(
|
fn cppgc__WeakPersistent__Assign(
|
||||||
this: *mut WeakPersistentInner,
|
this: *mut WeakPersistentInner,
|
||||||
|
@ -154,18 +157,6 @@ pub trait Traced {
|
||||||
fn trace(&self, visitor: &Visitor);
|
fn trace(&self, visitor: &Visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: GarbageCollected> Traced for Member<T> {
|
|
||||||
fn trace(&self, visitor: &Visitor) {
|
|
||||||
unsafe { cppgc__Visitor__Trace__Member(visitor, &self.inner) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: GarbageCollected> Traced for WeakMember<T> {
|
|
||||||
fn trace(&self, visitor: &Visitor) {
|
|
||||||
unsafe { cppgc__Visitor__Trace__WeakMember(visitor, &self.inner) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Traced for TracedReference<T> {
|
impl<T> Traced for TracedReference<T> {
|
||||||
fn trace(&self, visitor: &Visitor) {
|
fn trace(&self, visitor: &Visitor) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -290,11 +281,11 @@ pub trait GarbageCollected {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller must ensure that the returned pointer is always stored on
|
/// The caller must ensure that the returned pointer is always stored on
|
||||||
/// the stack, or moved into one of the Persistent types.
|
/// the stack, or is safely moved into one of the other cppgc pointer types.
|
||||||
pub unsafe fn make_garbage_collected<T: GarbageCollected>(
|
pub unsafe fn make_garbage_collected<T: GarbageCollected>(
|
||||||
heap: &Heap,
|
heap: &Heap,
|
||||||
obj: T,
|
obj: T,
|
||||||
) -> Member<T> {
|
) -> Ptr<T> {
|
||||||
unsafe extern "C" fn trace<T: GarbageCollected>(
|
unsafe extern "C" fn trace<T: GarbageCollected>(
|
||||||
obj: *const RustObj,
|
obj: *const RustObj,
|
||||||
visitor: *mut Visitor,
|
visitor: *mut Visitor,
|
||||||
|
@ -312,7 +303,7 @@ pub unsafe fn make_garbage_collected<T: GarbageCollected>(
|
||||||
- std::mem::size_of::<RustObj>())
|
- std::mem::size_of::<RustObj>())
|
||||||
+ std::mem::size_of::<T>();
|
+ std::mem::size_of::<T>();
|
||||||
|
|
||||||
let handle = unsafe {
|
let pointer = unsafe {
|
||||||
cppgc__make_garbage_collectable(
|
cppgc__make_garbage_collectable(
|
||||||
heap as *const Heap as *mut _,
|
heap as *const Heap as *mut _,
|
||||||
additional_bytes,
|
additional_bytes,
|
||||||
|
@ -322,10 +313,13 @@ pub unsafe fn make_garbage_collected<T: GarbageCollected>(
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
get_object_from_rust_obj::<T>(handle).write(obj);
|
get_object_from_rust_obj::<T>(pointer).write(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
Member::new(handle)
|
Ptr {
|
||||||
|
pointer: NonNull::new_unchecked(pointer),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -333,6 +327,12 @@ pub trait GetRustObj<T: GarbageCollected> {
|
||||||
fn get_rust_obj(&self) -> *mut RustObj;
|
fn get_rust_obj(&self) -> *mut RustObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: GarbageCollected> GetRustObj<T> for *mut RustObj {
|
||||||
|
fn get_rust_obj(&self) -> *mut RustObj {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! member {
|
macro_rules! member {
|
||||||
($( # $attr:tt )* $name:ident) => {
|
($( # $attr:tt )* $name:ident) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
|
@ -379,18 +379,24 @@ macro_rules! member {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: GarbageCollected> $name<T> {
|
impl<T: GarbageCollected> $name<T> {
|
||||||
pub(crate) fn new(obj: *mut RustObj) -> Self {
|
|
||||||
Self {
|
|
||||||
inner: [< $name Inner >]::new(obj),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = "Create a new empty "]
|
#[doc = "Create a new empty "]
|
||||||
#[doc = stringify!($name)]
|
#[doc = stringify!($name)]
|
||||||
#[doc = " which may be set later."]
|
#[doc = " which may be set later."]
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self::new(std::ptr::null_mut())
|
Self {
|
||||||
|
inner: [< $name Inner >]::new(std::ptr::null_mut()),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = "Create a new "]
|
||||||
|
#[doc = stringify!(name)]
|
||||||
|
#[doc = " and initialize it with an object."]
|
||||||
|
pub fn new(other: &impl GetRustObj<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: [< $name Inner >]::new(other.get_rust_obj()),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Set the object pointed to by this "]
|
#[doc = "Set the object pointed to by this "]
|
||||||
|
@ -422,6 +428,12 @@ macro_rules! member {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: GarbageCollected> Traced for $name<T> {
|
||||||
|
fn trace(&self, visitor: &Visitor) {
|
||||||
|
unsafe { [< cppgc__Visitor__Trace__ $name >](visitor, &self.inner) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: GarbageCollected> std::fmt::Debug for $name<T> {
|
impl<T: GarbageCollected> std::fmt::Debug for $name<T> {
|
||||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
fmt.debug_struct(stringify!($name)).finish()
|
fmt.debug_struct(stringify!($name)).finish()
|
||||||
|
@ -467,7 +479,18 @@ macro_rules! persistent {
|
||||||
#[doc = stringify!($name)]
|
#[doc = stringify!($name)]
|
||||||
#[doc = " which may be set later."]
|
#[doc = " which may be set later."]
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
let this = unsafe { [< cppgc__ $name __CONSTRUCT >]() };
|
let this = unsafe { [< cppgc__ $name __CONSTRUCT >](std::ptr::null_mut()) };
|
||||||
|
Self {
|
||||||
|
inner: this,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = "Create a new "]
|
||||||
|
#[doc = stringify!(name)]
|
||||||
|
#[doc = " and initialize it with an object."]
|
||||||
|
pub fn new(other: &impl GetRustObj<T>) -> Self {
|
||||||
|
let this = unsafe { [< cppgc__ $name __CONSTRUCT >](other.get_rust_obj()) };
|
||||||
Self {
|
Self {
|
||||||
inner: this,
|
inner: this,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
|
@ -551,3 +574,51 @@ persistent! {
|
||||||
/// thread.
|
/// thread.
|
||||||
WeakPersistent
|
WeakPersistent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ptr is used to refer to an on-heap object from the stack.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Ptr<T: GarbageCollected> {
|
||||||
|
pointer: NonNull<RustObj>,
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GarbageCollected> Ptr<T> {
|
||||||
|
/// Create a new Ptr.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The caller must ensure that the returned pointer is always stored on
|
||||||
|
/// the stack, or is safely moved into one of the other cppgc pointer types.
|
||||||
|
pub unsafe fn new(other: &impl GetRustObj<T>) -> Option<Self> {
|
||||||
|
NonNull::new(other.get_rust_obj()).map(|pointer| Self {
|
||||||
|
pointer,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GarbageCollected> std::ops::Deref for Ptr<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
unsafe { &*get_object_from_rust_obj(self.pointer.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GarbageCollected> GetRustObj<T> for Ptr<T> {
|
||||||
|
fn get_rust_obj(&self) -> *mut RustObj {
|
||||||
|
self.pointer.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GarbageCollected + std::fmt::Debug> std::fmt::Debug for Ptr<T> {
|
||||||
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
std::fmt::Debug::fmt(&**self, fmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GarbageCollected + std::fmt::Display> std::fmt::Display for Ptr<T> {
|
||||||
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(&**self, fmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::cppgc::GarbageCollected;
|
use crate::cppgc::GarbageCollected;
|
||||||
use crate::cppgc::GetRustObj;
|
use crate::cppgc::GetRustObj;
|
||||||
use crate::cppgc::Member;
|
use crate::cppgc::Ptr;
|
||||||
use crate::cppgc::RustObj;
|
use crate::cppgc::RustObj;
|
||||||
use crate::isolate::Isolate;
|
use crate::isolate::Isolate;
|
||||||
use crate::support::int;
|
use crate::support::int;
|
||||||
|
@ -721,16 +721,16 @@ impl Object {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller must ensure that the returned pointer is always stored on
|
/// The caller must ensure that the returned pointer is always stored on
|
||||||
/// the stack, or moved into one of the Persistent types.
|
/// the stack, or is safely moved into one of the other cppgc pointer types.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn unwrap<const TAG: u16, T: GarbageCollected>(
|
pub unsafe fn unwrap<const TAG: u16, T: GarbageCollected>(
|
||||||
isolate: &mut Isolate,
|
isolate: &mut Isolate,
|
||||||
wrapper: Local<Object>,
|
wrapper: Local<Object>,
|
||||||
) -> Member<T> {
|
) -> Option<Ptr<T>> {
|
||||||
// TODO: use a const assert once const expressions are stable
|
// TODO: use a const assert once const expressions are stable
|
||||||
assert!(TAG < LAST_TAG);
|
assert!(TAG < LAST_TAG);
|
||||||
let ptr = unsafe { v8__Object__Unwrap(isolate as *mut _, &*wrapper, TAG) };
|
let ptr = unsafe { v8__Object__Unwrap(isolate as *mut _, &*wrapper, TAG) };
|
||||||
Member::new(ptr)
|
Ptr::new(&ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this object can be generally used to wrap object objects.
|
/// Returns true if this object can be generally used to wrap object objects.
|
||||||
|
|
|
@ -89,7 +89,7 @@ fn cppgc_object_wrap() {
|
||||||
) {
|
) {
|
||||||
let obj = args.get(0).try_into().unwrap();
|
let obj = args.get(0).try_into().unwrap();
|
||||||
let member = unsafe { v8::Object::unwrap::<TAG, Wrap>(scope, obj) };
|
let member = unsafe { v8::Object::unwrap::<TAG, Wrap>(scope, obj) };
|
||||||
rv.set(member.borrow().unwrap().value.get(scope).unwrap());
|
rv.set(member.unwrap().value.get(scope).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue