Skip to content

Commit

Permalink
Auto merge of #352 - Redfire75369:gc/root-infrastructure, r=jdm
Browse files Browse the repository at this point in the history
Added GC Tracing Infrastructure

Fixes #346
Moved `mozjs::rust::Trace` to `mozjs::gc::trace::Traceable`, and added more implementations for smart pointers, wrappers, and collections.
Added `mozjs::gc::trace::RootedTraceableSet`, `mozjs::gc::collections::RootableVec` and `mozjs::gc::collections::RootedVec`.
Added `rooted_vec!` macro.
Reorganised GC-related code in `mozjs`.

I'm not too sure about the file structure change, but I think it's fine.
If there's any more high-level rooted structures I can add, please do inform me.
  • Loading branch information
bors-servo authored Jun 20, 2023
2 parents 98b6782 + c216686 commit c200e36
Show file tree
Hide file tree
Showing 16 changed files with 1,005 additions and 549 deletions.
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

0 comments on commit c200e36

Please sign in to comment.