Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added GC Tracing Infrastructure #352

Merged
merged 13 commits into from
Jun 20, 2023
9 changes: 2 additions & 7 deletions mozjs/src/jsgc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use jsapi::jsid;
use jsapi::JSFunction;
use jsapi::JSObject;
use jsapi::JSScript;
use jsapi::JSString;
use jsapi::JSTracer;
use jsapi::JS;
use jsapi::{jsid, JSFunction, JSObject, JSScript, JSString, JSTracer};

use jsid::VoidId;
use std::cell::UnsafeCell;
use std::ffi::c_void;
use std::mem;
use std::os::raw::c_void;
use std::ptr;

/// A trait for JS types that can be registered as roots.
Expand Down
2 changes: 1 addition & 1 deletion mozjs/src/jsglue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ JSLinearString* AtomToLinearString(JSAtom* atom) {
return JS::AtomToLinearString(atom);
}

/* These types are using maybe, so we manually unwrap it in these wrappers */
// These types are using maybe so we manually unwrap them in these wrappers

bool FromPropertyDescriptor(JSContext* cx,
JS::Handle<JS::PropertyDescriptor> desc_,
Expand Down
55 changes: 21 additions & 34 deletions mozjs/src/jsglue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,32 +47,39 @@
#include "jsapi.h"
#include "jsfriendapi.h"

// Reexport some functions that are marked inline.

namespace glue {

// Reexport some functions that are marked inline.

bool JS_Init();

JS::RealmOptions* JS_NewRealmOptions();
void DeleteRealmOptions(JS::RealmOptions* options);
JS::OwningCompileOptions* JS_NewOwningCompileOptions(JSContext* cx);
void DeleteOwningCompileOptions(JS::OwningCompileOptions* optiosn);

JS::shadow::Zone* JS_AsShadowZone(JS::Zone* zone);

JS::CallArgs JS_CallArgsFromVp(unsigned argc, JS::Value* vp);

void JS_StackCapture_AllFrames(JS::StackCapture*);
void JS_StackCapture_MaxFrames(uint32_t max, JS::StackCapture*);
void JS_StackCapture_FirstSubsumedFrame(JSContext* cx,
bool ignoreSelfHostedFrames,
JS::StackCapture*);

// Reexport some methods

bool JS_ForOfIteratorInit(
JS::ForOfIterator* iterator, JS::HandleValue iterable,
JS::ForOfIterator::NonIterableBehavior nonIterableBehavior);
bool JS_ForOfIteratorNext(JS::ForOfIterator* iterator,
JS::MutableHandleValue val, bool* done);

JS::shadow::Zone* JS_AsShadowZone(JS::Zone* zone);

JS::CallArgs JS_CallArgsFromVp(unsigned argc, JS::Value* vp);
// These functions are only intended for use in testing,
// to make sure that the Rust implementation of JS::Value
// agrees with the C++ implementation.

void JS_ValueSetBoolean(JS::Value* value, bool x);
bool JS_ValueIsBoolean(const JS::Value* value);
Expand All @@ -98,36 +105,16 @@ size_t GetLinearStringLength(JSLinearString* s);
uint16_t GetLinearStringCharAt(JSLinearString* s, size_t idx);
JSLinearString* AtomToLinearString(JSAtom* atom);

bool FromPropertyDescriptor(JSContext* cx,
JS::Handle<JS::PropertyDescriptor> desc,
JS::MutableHandle<JS::Value> vp);
bool JS_GetOwnPropertyDescriptorById(
JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc, bool* isNone);
bool JS_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj,
const char* name,
JS::MutableHandle<JS::PropertyDescriptor> desc,
bool* isNone);
bool JS_GetOwnUCPropertyDescriptor(
JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::MutableHandle<JS::PropertyDescriptor> desc, bool* isNone);
bool JS_GetPropertyDescriptorById(
JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc,
JS::MutableHandleObject holder, bool* isNone);
bool JS_GetPropertyDescriptor(JSContext* cx, JS::HandleObject obj,
const char* name,
JS::MutableHandle<JS::PropertyDescriptor> desc,
JS::MutableHandleObject holder, bool* isNone);
bool JS_GetUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj,
const char16_t* name, size_t namelen,
JS::MutableHandle<JS::PropertyDescriptor> desc,
JS::MutableHandleObject holder, bool* isNone);
bool SetPropertyIgnoringNamedGetter(JSContext* cx, JS::HandleObject obj,
JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver,
JS::Handle<JS::PropertyDescriptor> ownDesc,
JS::ObjectOpResult& result);
// These types are using maybe so we manually unwrap them in these wrappers

bool FromPropertyDescriptor(JSContext *cx, JS::Handle<JS::PropertyDescriptor> desc, JS::MutableHandle<JS::Value> vp);
bool JS_GetOwnPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandle<JS::PropertyDescriptor> desc, bool* isNone);
bool JS_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandle<JS::PropertyDescriptor> desc, bool* isNone);
bool JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::MutableHandle<JS::PropertyDescriptor> desc, bool* isNone);
bool JS_GetPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandle<JS::PropertyDescriptor> desc, JS::MutableHandleObject holder, bool* isNone);
bool JS_GetPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandle<JS::PropertyDescriptor> desc, JS::MutableHandleObject holder, bool* isNone);
bool JS_GetUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::MutableHandle<JS::PropertyDescriptor> desc, JS::MutableHandleObject holder, bool* isNone);
bool SetPropertyIgnoringNamedGetter(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v, JS::HandleValue receiver, JS::Handle<JS::PropertyDescriptor> ownDesc, JS::ObjectOpResult& result);

bool CreateError(JSContext* cx, JSExnType type, JS::HandleObject stack,
JS::HandleString fileName, uint32_t lineNumber,
Expand Down
2 changes: 1 addition & 1 deletion mozjs/src/jsimpls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ impl<T> JS::Handle<T> {

impl<T> JS::MutableHandle<T> {
pub unsafe fn from_marked_location(ptr: *mut T) -> JS::MutableHandle<T> {
JS::MutableHandle { ptr: ptr, _phantom_0: ::std::marker::PhantomData }
JS::MutableHandle { ptr, _phantom_0: ::std::marker::PhantomData }
}

pub fn handle(&self) -> JS::Handle<T> {
Expand Down
3 changes: 2 additions & 1 deletion rust-mozjs/src/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use jsval::{BooleanValue, Int32Value, NullValue, UInt32Value, UndefinedValue};
use jsval::{JSVal, ObjectOrNullValue, ObjectValue, StringValue, SymbolValue};
use libc;
use num_traits::{Bounded, Zero};
use rooted;
use rust::maybe_wrap_value;
use rust::{maybe_wrap_object_or_null_value, maybe_wrap_object_value, ToString};
use rust::{HandleValue, MutableHandleValue};
Expand Down Expand Up @@ -631,7 +632,7 @@ impl<'a> ForOfIteratorGuard<'a> {
unsafe {
root.iterator.add_to_root_stack(cx);
}
ForOfIteratorGuard { root: root }
ForOfIteratorGuard { root }
}
}

Expand Down
116 changes: 116 additions & 0 deletions rust-mozjs/src/gc/collections.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use gc::{RootedTraceableSet, Traceable};
use jsapi::{Heap, JSTracer};
use mozjs_sys::jsgc::GCMethods;
use rust::Handle;
use std::ops::{Deref, DerefMut};

/// A vector of items to be rooted with `RootedVec`.
/// Guaranteed to be empty when not rooted.
pub struct RootableVec<T: Traceable> {
v: Vec<T>,
}

impl<T: Traceable> RootableVec<T> {
/// Create a vector of items of type T that can be rooted later.
pub fn new_unrooted() -> RootableVec<T> {
RootableVec { v: Vec::new() }
}
}

unsafe impl<T: Traceable> Traceable for RootableVec<T> {
unsafe fn trace(&self, trc: *mut JSTracer) {
self.v.trace(trc);
}
}

/// A vector of items rooted for the lifetime 'a.
pub struct RootedVec<'a, T: Traceable + 'static> {
root: &'a mut RootableVec<T>,
}

impl<'a, T: Traceable + 'static> RootedVec<'a, T> {
pub fn new(root: &'a mut RootableVec<T>) -> RootedVec<'a, T> {
unsafe {
RootedTraceableSet::add(root);
}
RootedVec { root }
}
}

impl<'a, T: Traceable + 'static> Drop for RootedVec<'a, T> {
fn drop(&mut self) {
self.clear();
unsafe {
RootedTraceableSet::remove(self.root);
}
}
}

impl<'a, T: Traceable> Deref for RootedVec<'a, T> {
type Target = Vec<T>;
fn deref(&self) -> &Vec<T> {
&self.root.v
}
}

impl<'a, T: Traceable> DerefMut for RootedVec<'a, T> {
fn deref_mut(&mut self) -> &mut Vec<T> {
&mut self.root.v
}
}

pub struct RootedTraceableBox<T: Traceable + 'static> {
ptr: *mut T,
}

impl<T: Traceable + 'static> RootedTraceableBox<T> {
pub fn new(traceable: T) -> RootedTraceableBox<T> {
Self::from_box(Box::new(traceable))
}

pub fn from_box(boxed_traceable: Box<T>) -> RootedTraceableBox<T> {
let traceable = Box::into_raw(boxed_traceable);
unsafe {
RootedTraceableSet::add(traceable);
}
RootedTraceableBox { ptr: traceable }
}
}

impl<T> RootedTraceableBox<Heap<T>>
where
Heap<T>: Traceable + 'static,
T: GCMethods + Copy,
{
pub fn handle(&self) -> Handle<T> {
unsafe { Handle::from_raw((*self.ptr).handle()) }
}
}

unsafe impl<T: Traceable + 'static> Traceable for RootedTraceableBox<T> {
unsafe fn trace(&self, trc: *mut JSTracer) {
(*self.ptr).trace(trc)
}
}

impl<T: Traceable> Deref for RootedTraceableBox<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.ptr }
}
}

impl<T: Traceable> DerefMut for RootedTraceableBox<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.ptr }
}
}

impl<T: Traceable + 'static> Drop for RootedTraceableBox<T> {
fn drop(&mut self) {
unsafe {
RootedTraceableSet::remove(self.ptr);
let _ = Box::from_raw(self.ptr);
}
}
}
Loading