Skip to content

Commit

Permalink
Merge pull request #324 from dherman/module-reorg
Browse files Browse the repository at this point in the history
Module reorganization
  • Loading branch information
dherman authored Jul 10, 2018
2 parents ec13762 + 6769fd8 commit 064d442
Show file tree
Hide file tree
Showing 27 changed files with 881 additions and 878 deletions.
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ rust:
- beta
- nightly

matrix:
exclude:
- env: TRAVIS_NODE_VERSION="8"
rust: beta
- env: TRAVIS_NODE_VERSION="8"
rust: nightly
- env: TRAVIS_NODE_VERSION="6"
rust: beta
- env: TRAVIS_NODE_VERSION="6"
rust: nightly

env:
matrix:
- TRAVIS_NODE_VERSION="10"
Expand Down
12 changes: 0 additions & 12 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,9 @@ environment:
- PLATFORM: x64
NODEJS_VERSION: "10"
RUST_TOOLCHAIN: stable-x86_64-pc-windows-msvc
- PLATFORM: x64
NODEJS_VERSION: "6"
RUST_TOOLCHAIN: beta-x86_64-pc-windows-msvc
- PLATFORM: x64
NODEJS_VERSION: "8"
RUST_TOOLCHAIN: beta-x86_64-pc-windows-msvc
- PLATFORM: x64
NODEJS_VERSION: "10"
RUST_TOOLCHAIN: beta-x86_64-pc-windows-msvc
- PLATFORM: x64
NODEJS_VERSION: "6"
RUST_TOOLCHAIN: nightly-x86_64-pc-windows-msvc
- PLATFORM: x64
NODEJS_VERSION: "8"
RUST_TOOLCHAIN: nightly-x86_64-pc-windows-msvc
- PLATFORM: x64
NODEJS_VERSION: "10"
RUST_TOOLCHAIN: nightly-x86_64-pc-windows-msvc
Expand Down
74 changes: 74 additions & 0 deletions src/borrow/internal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use std;
use std::os::raw::c_void;
use std::collections::HashSet;
use borrow::LoanError;

pub unsafe trait Pointer {
unsafe fn as_ptr(&self) -> *const c_void;
unsafe fn as_mut(&mut self) -> *mut c_void;
}

unsafe impl<T> Pointer for *mut T {
unsafe fn as_ptr(&self) -> *const c_void {
*self as *const c_void
}

unsafe fn as_mut(&mut self) -> *mut c_void {
*self as *mut c_void
}
}
unsafe impl<'a, T> Pointer for &'a mut T {
unsafe fn as_ptr(&self) -> *const c_void {
let r: &T = &**self;
std::mem::transmute(r)
}

unsafe fn as_mut(&mut self) -> *mut c_void {
let r: &mut T = &mut **self;
std::mem::transmute(r)
}
}

pub struct Ledger {
immutable_loans: HashSet<*const c_void>,
mutable_loans: HashSet<*const c_void>
}

impl Ledger {
pub fn new() -> Self {
Ledger {
immutable_loans: HashSet::new(),
mutable_loans: HashSet::new()
}
}

pub fn try_borrow<T>(&mut self, p: *const T) -> Result<(), LoanError> {
let p = p as *const c_void;
if self.mutable_loans.contains(&p) {
return Err(LoanError::Mutating(p));
}
self.immutable_loans.insert(p);
Ok(())
}

pub fn settle<T>(&mut self, p: *const T) {
let p = p as *const c_void;
self.immutable_loans.remove(&p);
}

pub fn try_borrow_mut<T>(&mut self, p: *mut T) -> Result<(), LoanError> {
let p = p as *const c_void;
if self.mutable_loans.contains(&p) {
return Err(LoanError::Mutating(p));
} else if self.immutable_loans.contains(&p) {
return Err(LoanError::Frozen(p));
}
self.mutable_loans.insert(p);
Ok(())
}

pub fn settle_mut<T>(&mut self, p: *mut T) {
let p = p as *const c_void;
self.mutable_loans.remove(&p);
}
}
141 changes: 141 additions & 0 deletions src/borrow/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//! Types and traits for obtaining temporary access to the internals of JavaScript values.
pub(crate) mod internal;

use std::ops::{Deref, DerefMut, Drop};
use std::fmt;
use std::os::raw::c_void;

use context::Lock;
use self::internal::Pointer;

/// A trait for JS values whose internal contents can be borrowed immutably by Rust while the JS engine is locked.
pub trait Borrow: Sized {

/// The type of the value's internal contents.
type Target: Pointer;

/// Borrow the contents of this value immutably.
///
/// If there is already an outstanding mutable loan for this value, this method panics.
fn borrow<'a>(self, lock: &'a Lock<'a>) -> Ref<'a, Self::Target> {
match self.try_borrow(lock) {
Ok(r) => r,
Err(e) => panic!("{}", e)
}
}

/// Borrow the contents of this value immutably.
///
/// If there is already an outstanding mutable loan for this value, this method fails with a `LoanError`.
fn try_borrow<'a>(self, lock: &'a Lock<'a>) -> Result<Ref<'a, Self::Target>, LoanError>;

}

/// A trait for JS values whose internal contents can be borrowed mutably by Rust while the JS engine is locked.
pub trait BorrowMut: Borrow {

/// Borrow the contents of this value mutably.
///
/// If there is already an outstanding loan for this value, this method panics.
fn borrow_mut<'a>(self, lock: &'a Lock<'a>) -> RefMut<'a, Self::Target> {
match self.try_borrow_mut(lock) {
Ok(r) => r,
Err(e) => panic!("{}", e)
}
}

/// Borrow the contents of this value mutably.
///
/// If there is already an outstanding loan for this value, this method panics.
fn try_borrow_mut<'a>(self, lock: &'a Lock<'a>) -> Result<RefMut<'a, Self::Target>, LoanError>;

}

/// An error produced by a failed loan in the `Borrow` or `BorrowMut` traits.
pub enum LoanError {

/// Indicates that there is already an outstanding mutable loan for the object at this address.
Mutating(*const c_void),

/// Indicates that there is already an outstanding immutable loan for the object at this address.
Frozen(*const c_void)

}

impl fmt::Display for LoanError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
LoanError::Mutating(p) => {
write!(f, "outstanding mutable loan exists for object at {:?}", p)
}
LoanError::Frozen(p) => {
write!(f, "object at {:?} is frozen", p)
}
}
}
}

/// An immutable reference to the contents of a borrowed JS value.
pub struct Ref<'a, T: Pointer> {
pointer: T,
lock: &'a Lock<'a>
}

impl<'a, T: Pointer> Ref<'a, T> {
pub(crate) unsafe fn new(lock: &'a Lock<'a>, pointer: T) -> Result<Self, LoanError> {
let mut ledger = lock.ledger.borrow_mut();
ledger.try_borrow(pointer.as_ptr())?;
Ok(Ref { pointer, lock })
}
}

impl<'a, T: Pointer> Drop for Ref<'a, T> {
fn drop(&mut self) {
let mut ledger = self.lock.ledger.borrow_mut();
ledger.settle(unsafe { self.pointer.as_ptr() });
}
}

impl<'a, T: Pointer> Deref for Ref<'a, T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.pointer
}
}

/// A mutable reference to the contents of a borrowed JS value.
pub struct RefMut<'a, T: Pointer> {
pointer: T,
lock: &'a Lock<'a>
}

impl<'a, T: Pointer> RefMut<'a, T> {
pub(crate) unsafe fn new(lock: &'a Lock<'a>, mut pointer: T) -> Result<Self, LoanError> {
let mut ledger = lock.ledger.borrow_mut();
ledger.try_borrow_mut(pointer.as_mut())?;
Ok(RefMut { pointer, lock })
}
}

impl<'a, T: Pointer> Drop for RefMut<'a, T> {
fn drop(&mut self) {
let mut ledger = self.lock.ledger.borrow_mut();
ledger.settle_mut(unsafe { self.pointer.as_mut() });
}
}

impl<'a, T: Pointer> Deref for RefMut<'a, T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.pointer
}
}

impl<'a, T: Pointer> DerefMut for RefMut<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.pointer
}
}
107 changes: 107 additions & 0 deletions src/context/internal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use std;
use std::cell::Cell;
use std::os::raw::c_void;
use neon_runtime;
use neon_runtime::raw;
use neon_runtime::scope::Root;
use value::JsObject;
use value::mem::Handle;
use object::class::ClassMap;
use result::NeonResult;
use super::ModuleContext;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct Isolate(*mut raw::Isolate);

extern "C" fn drop_class_map(map: Box<ClassMap>) {
std::mem::drop(map);
}

impl Isolate {
pub(crate) fn to_raw(self) -> *mut raw::Isolate {
let Isolate(ptr) = self;
ptr
}

pub(crate) fn class_map(&mut self) -> &mut ClassMap {
let mut ptr: *mut c_void = unsafe { neon_runtime::class::get_class_map(self.to_raw()) };
if ptr.is_null() {
let b: Box<ClassMap> = Box::new(ClassMap::new());
let raw = Box::into_raw(b);
ptr = unsafe { std::mem::transmute(raw) };
let free_map: *mut c_void = unsafe { std::mem::transmute(drop_class_map as usize) };
unsafe {
neon_runtime::class::set_class_map(self.to_raw(), ptr, free_map);
}
}
unsafe { std::mem::transmute(ptr) }
}

pub(crate) fn current() -> Isolate {
unsafe {
std::mem::transmute(neon_runtime::call::current_isolate())
}
}
}

pub struct ScopeMetadata {
isolate: Isolate,
active: Cell<bool>
}

pub struct Scope<'a, R: Root + 'static> {
pub metadata: ScopeMetadata,
pub handle_scope: &'a mut R
}

impl<'a, R: Root + 'static> Scope<'a, R> {
pub fn with<T, F: for<'b> FnOnce(Scope<'b, R>) -> T>(f: F) -> T {
let mut handle_scope: R = unsafe { R::allocate() };
let isolate = Isolate::current();
unsafe {
handle_scope.enter(isolate.to_raw());
}
let result = {
let scope = Scope {
metadata: ScopeMetadata {
isolate,
active: Cell::new(true)
},
handle_scope: &mut handle_scope
};
f(scope)
};
unsafe {
handle_scope.exit();
}
result
}
}

pub trait ContextInternal<'a>: Sized {
fn scope_metadata(&self) -> &ScopeMetadata;

fn isolate(&self) -> Isolate {
self.scope_metadata().isolate
}

fn is_active(&self) -> bool {
self.scope_metadata().active.get()
}

fn check_active(&self) {
if !self.is_active() {
panic!("execution context is inactive");
}
}

fn activate(&self) { self.scope_metadata().active.set(true); }
fn deactivate(&self) { self.scope_metadata().active.set(false); }
}

pub fn initialize_module(exports: Handle<JsObject>, init: fn(ModuleContext) -> NeonResult<()>) {
ModuleContext::with(exports, |cx| {
let _ = init(cx);
});
}
Loading

0 comments on commit 064d442

Please sign in to comment.