From 2bf60c2af7d2952be4698d812a04b8a127e5dd68 Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Thu, 10 Nov 2016 19:55:45 +0100 Subject: [PATCH 1/5] Add an implementation of Default for Heap<*mut T>. We should be able to create a default value for any Heap<*mut T> where *mut T implements GCMethods<*mut T> and Copy, not just for Heap<*mut JSObject>. --- src/rust.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rust.rs b/src/rust.rs index 20b4a3b7b..00aa51acd 100644 --- a/src/rust.rs +++ b/src/rust.rs @@ -556,8 +556,10 @@ impl + Copy> Heap { } } -impl Default for Heap<*mut JSObject> { - fn default() -> Heap<*mut JSObject> { +impl Default for Heap<*mut T> + where *mut T: GCMethods<*mut T> + Copy +{ + fn default() -> Heap<*mut T> { Heap { ptr: UnsafeCell::new(ptr::null_mut()) } From e96ee0b2d6a2e12881c617e88ebf651b2e556dfb Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Thu, 10 Nov 2016 20:02:22 +0100 Subject: [PATCH 2/5] Add a method to create a Heap. Currently, to create a Heap, one first has to create a Heap::default, and then call Heap::set. This is a common pattern and therefore should be abstracted behind a method. --- src/rust.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rust.rs b/src/rust.rs index 00aa51acd..4b09f420d 100644 --- a/src/rust.rs +++ b/src/rust.rs @@ -532,6 +532,14 @@ impl GCMethods for Value { } impl + Copy> Heap { + pub fn new(v: T) -> Heap + where Heap: Default + { + let mut ptr = Heap::default(); + ptr.set(v); + ptr + } + pub fn set(&mut self, v: T) { unsafe { let ptr = self.ptr.get(); From 330aa0822f9ddf2948b0fde37806ddfcd107a199 Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Thu, 10 Nov 2016 20:08:06 +0100 Subject: [PATCH 3/5] Add an implementation of Clone for Heap. --- src/rust.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rust.rs b/src/rust.rs index 4b09f420d..e732feb7b 100644 --- a/src/rust.rs +++ b/src/rust.rs @@ -564,6 +564,14 @@ impl + Copy> Heap { } } +impl + Copy> Clone for Heap + where Heap: Default +{ + fn clone(&self) -> Self { + Heap::new(self.get()) + } +} + impl Default for Heap<*mut T> where *mut T: GCMethods<*mut T> + Copy { From 07661517904ab3bd8fd5a8e5e3193c022f931d2b Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Thu, 10 Nov 2016 20:10:37 +0100 Subject: [PATCH 4/5] Add an implementation of PartialEq for Heap. --- src/rust.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rust.rs b/src/rust.rs index e732feb7b..30878376a 100644 --- a/src/rust.rs +++ b/src/rust.rs @@ -599,6 +599,11 @@ impl + Copy> Drop for Heap { } } +impl + Copy + PartialEq> PartialEq for Heap { + fn eq(&self, other: &Self) -> bool { + self.get() == other.get() + } +} // ___________________________________________________________________________ // Implementations for various things in jsapi.rs From 2e6d70bbdaa731d95c4537f4421a43e93caa6c4c Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Thu, 10 Nov 2016 20:29:54 +0100 Subject: [PATCH 5/5] Implement a Trace trait for types that can be traced. We expose several JSAPI functions that are used for tracing. By abstracting these functions behind a trait we can overload them on the type to be traced. --- src/rust.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/rust.rs b/src/rust.rs index 30878376a..50d141733 100644 --- a/src/rust.rs +++ b/src/rust.rs @@ -51,6 +51,8 @@ use jsapi::AutoIdVector; use jsapi::JS_MayResolveStandardClass; use jsapi::JS_EnumerateStandardClasses; use jsapi::JS_ResolveStandardClass; +use jsapi::JSTracer; +use glue::{CallFunctionTracer, CallObjectTracer, CallScriptTracer, CallStringTracer, CallValueTracer, CallIdTracer}; use glue::{CreateAutoIdVector, SliceAutoIdVector, DestroyAutoIdVector}; use glue::{CreateAutoObjectVector, CreateCallArgsFromVp, AppendToAutoObjectVector, DeleteAutoObjectVector}; use glue::{NewCompileOptions, DeleteCompileOptions}; @@ -280,6 +282,57 @@ impl RootKind for Value { fn rootKind() -> jsapi::RootKind { jsapi::RootKind::Value } } +// Creates a C string literal `$str`. +macro_rules! c_str { + ($str:expr) => { + concat!($str, "\0").as_ptr() as *const ::std::os::raw::c_char + } +} + +/// Types that can be traced. +/// +/// This trait is unsafe; if it is implemented incorrectly, the GC may end up collecting objects +/// that are still reachable. +pub unsafe trait Trace { + unsafe fn trace(&self, trc: *mut JSTracer); +} + +unsafe impl Trace for Heap<*mut JSFunction> { + unsafe fn trace(&self, trc: *mut JSTracer) { + CallFunctionTracer(trc, self as *const _ as *mut Self, c_str!("function")); + } +} + +unsafe impl Trace for Heap<*mut JSObject> { + unsafe fn trace(&self, trc: *mut JSTracer) { + CallObjectTracer(trc, self as *const _ as *mut Self, c_str!("object")); + } +} + +unsafe impl Trace for Heap<*mut JSScript> { + unsafe fn trace(&self, trc: *mut JSTracer) { + CallScriptTracer(trc, self as *const _ as *mut Self, c_str!("script")); + } +} + +unsafe impl Trace for Heap<*mut JSString> { + unsafe fn trace(&self, trc: *mut JSTracer) { + CallStringTracer(trc, self as *const _ as *mut Self, c_str!("string")); + } +} + +unsafe impl Trace for Heap { + unsafe fn trace(&self, trc: *mut JSTracer) { + CallValueTracer(trc, self as *const _ as *mut Self, c_str!("value")); + } +} + +unsafe impl Trace for Heap { + unsafe fn trace(&self, trc: *mut JSTracer) { + CallIdTracer(trc, self as *const _ as *mut Self, c_str!("id")); + } +} + impl Rooted { pub fn new_unrooted(initial: T) -> Rooted { Rooted {