summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/Cargo.toml1
-rw-r--r--core/bindings.rs53
-rw-r--r--core/core_isolate.rs61
-rw-r--r--core/es_isolate.rs8
-rw-r--r--core/examples/http_bench.rs19
-rw-r--r--core/ops.rs18
-rw-r--r--core/plugin_api.rs2
-rw-r--r--core/zero_copy_buf.rs10
8 files changed, 75 insertions, 97 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 6b73cc02a..038b81580 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -21,6 +21,7 @@ libc = "0.2.71"
log = "0.4.8"
rusty_v8 = "0.6.0"
serde_json = "1.0.55"
+smallvec = "1.4.0"
url = "2.1.1"
[[example]]
diff --git a/core/bindings.rs b/core/bindings.rs
index 6407cb555..0d0a633a5 100644
--- a/core/bindings.rs
+++ b/core/bindings.rs
@@ -8,6 +8,7 @@ use crate::ZeroCopyBuf;
use rusty_v8 as v8;
use v8::MapFnTo;
+use smallvec::SmallVec;
use std::cell::Cell;
use std::convert::TryFrom;
use std::option::Option;
@@ -388,24 +389,11 @@ fn send(
}
};
- let control_backing_store: v8::SharedRef<v8::BackingStore>;
- let control = match v8::Local::<v8::ArrayBufferView>::try_from(args.get(1)) {
- Ok(view) => unsafe {
- control_backing_store = view.buffer(scope).unwrap().get_backing_store();
- get_backing_store_slice(
- &control_backing_store,
- view.byte_offset(),
- view.byte_length(),
- )
- },
- Err(_) => &[],
- };
-
let state_rc = CoreIsolate::state(scope);
let mut state = state_rc.borrow_mut();
assert!(!state.global_context.is_empty());
- let mut buf_iter = (2..args.length()).map(|idx| {
+ let buf_iter = (1..args.length()).map(|idx| {
v8::Local::<v8::ArrayBufferView>::try_from(args.get(idx))
.map(|view| ZeroCopyBuf::new(scope, view))
.map_err(|err| {
@@ -415,36 +403,15 @@ fn send(
})
});
- let mut buf_one: ZeroCopyBuf;
- let mut buf_vec: Vec<ZeroCopyBuf>;
-
- // Collect all ArrayBufferView's
- let buf_iter_result = match buf_iter.len() {
- 0 => Ok(&mut [][..]),
- 1 => match buf_iter.next().unwrap() {
- Ok(buf) => {
- buf_one = buf;
- Ok(std::slice::from_mut(&mut buf_one))
+ // If response is empty then it's either async op or exception was thrown.
+ let maybe_response =
+ match buf_iter.collect::<Result<SmallVec<[ZeroCopyBuf; 2]>, _>>() {
+ Ok(mut bufs) => state.dispatch_op(scope, op_id, &mut bufs),
+ Err(exc) => {
+ scope.throw_exception(exc);
+ return;
}
- Err(err) => Err(err),
- },
- _ => match buf_iter.collect::<Result<Vec<_>, _>>() {
- Ok(v) => {
- buf_vec = v;
- Ok(&mut buf_vec[..])
- }
- Err(err) => Err(err),
- },
- };
-
- // If response is empty then it's either async op or exception was thrown
- let maybe_response = match buf_iter_result {
- Ok(bufs) => state.dispatch_op(scope, op_id, control, bufs),
- Err(exc) => {
- scope.throw_exception(exc);
- return;
- }
- };
+ };
if let Some(response) = maybe_response {
// Synchronous response.
diff --git a/core/core_isolate.rs b/core/core_isolate.rs
index bb1807f62..ffe75c00c 100644
--- a/core/core_isolate.rs
+++ b/core/core_isolate.rs
@@ -350,7 +350,7 @@ impl CoreIsolate {
/// Requires runtime to explicitly ask for op ids before using any of the ops.
pub fn register_op<F>(&mut self, name: &str, op: F) -> OpId
where
- F: Fn(&mut CoreIsolateState, &[u8], &mut [ZeroCopyBuf]) -> Op + 'static,
+ F: Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op + 'static,
{
let state_rc = Self::state(self);
let mut state = state_rc.borrow_mut();
@@ -466,7 +466,7 @@ impl CoreIsolateState {
/// Requires runtime to explicitly ask for op ids before using any of the ops.
pub fn register_op<F>(&mut self, name: &str, op: F) -> OpId
where
- F: Fn(&mut CoreIsolateState, &[u8], &mut [ZeroCopyBuf]) -> Op + 'static,
+ F: Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op + 'static,
{
self.op_registry.register(name, op)
}
@@ -485,11 +485,10 @@ impl CoreIsolateState {
&mut self,
scope: &mut v8::HandleScope<'s>,
op_id: OpId,
- control_buf: &[u8],
zero_copy_bufs: &mut [ZeroCopyBuf],
) -> Option<(OpId, Box<[u8]>)> {
let op = if let Some(dispatcher) = self.op_registry.get(op_id) {
- dispatcher(self, control_buf, zero_copy_bufs)
+ dispatcher(self, zero_copy_bufs)
} else {
let message =
v8::String::new(scope, &format!("Unknown op id: {}", op_id)).unwrap();
@@ -704,20 +703,21 @@ pub mod tests {
let mut isolate = CoreIsolate::new(StartupData::None, false);
let dispatcher = move |_state: &mut CoreIsolateState,
- control: &[u8],
zero_copy: &mut [ZeroCopyBuf]|
-> Op {
dispatch_count_.fetch_add(1, Ordering::Relaxed);
match mode {
Mode::Async => {
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
+ assert_eq!(zero_copy.len(), 1);
+ assert_eq!(zero_copy[0].len(), 1);
+ assert_eq!(zero_copy[0][0], 42);
let buf = vec![43u8].into_boxed_slice();
Op::Async(futures::future::ready(buf).boxed())
}
Mode::AsyncUnref => {
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
+ assert_eq!(zero_copy.len(), 1);
+ assert_eq!(zero_copy[0].len(), 1);
+ assert_eq!(zero_copy[0][0], 42);
let fut = async {
// This future never finish.
futures::future::pending::<()>().await;
@@ -726,8 +726,6 @@ pub mod tests {
Op::AsyncUnref(fut.boxed())
}
Mode::AsyncZeroCopy(count) => {
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 24);
assert_eq!(zero_copy.len(), count as usize);
zero_copy.iter().enumerate().for_each(|(idx, buf)| {
assert_eq!(buf.len(), 1);
@@ -738,13 +736,15 @@ pub mod tests {
Op::Async(futures::future::ready(buf).boxed())
}
Mode::OverflowReqSync => {
- assert_eq!(control.len(), 100 * 1024 * 1024);
+ assert_eq!(zero_copy.len(), 1);
+ assert_eq!(zero_copy[0].len(), 100 * 1024 * 1024);
let buf = vec![43u8].into_boxed_slice();
Op::Sync(buf)
}
Mode::OverflowResSync => {
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
+ assert_eq!(zero_copy.len(), 1);
+ assert_eq!(zero_copy[0].len(), 1);
+ assert_eq!(zero_copy[0][0], 42);
let mut vec = Vec::<u8>::new();
vec.resize(100 * 1024 * 1024, 0);
vec[0] = 99;
@@ -752,13 +752,15 @@ pub mod tests {
Op::Sync(buf)
}
Mode::OverflowReqAsync => {
- assert_eq!(control.len(), 100 * 1024 * 1024);
+ assert_eq!(zero_copy.len(), 1);
+ assert_eq!(zero_copy[0].len(), 100 * 1024 * 1024);
let buf = vec![43u8].into_boxed_slice();
Op::Async(futures::future::ready(buf).boxed())
}
Mode::OverflowResAsync => {
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
+ assert_eq!(zero_copy.len(), 1);
+ assert_eq!(zero_copy[0].len(), 1);
+ assert_eq!(zero_copy[0][0], 42);
let mut vec = Vec::<u8>::new();
vec.resize(100 * 1024 * 1024, 0);
vec[0] = 4;
@@ -807,37 +809,38 @@ pub mod tests {
js_check(isolate.execute(
"filename.js",
r#"
- let control = new Uint8Array([24]);
- Deno.core.send(1, control);
+ Deno.core.send(1);
"#,
));
assert_eq!(dispatch_count.load(Ordering::Relaxed), 1);
}
#[test]
- fn test_dispatch_one_zero_copy_buf() {
- let (mut isolate, dispatch_count) = setup(Mode::AsyncZeroCopy(1));
+ fn test_dispatch_stack_zero_copy_bufs() {
+ let (mut isolate, dispatch_count) = setup(Mode::AsyncZeroCopy(2));
js_check(isolate.execute(
"filename.js",
r#"
- let control = new Uint8Array([24]);
- let zero_copy = new Uint8Array([0]);
- Deno.core.send(1, control, zero_copy);
+ let zero_copy_a = new Uint8Array([0]);
+ let zero_copy_b = new Uint8Array([1]);
+ Deno.core.send(1, zero_copy_a, zero_copy_b);
"#,
));
assert_eq!(dispatch_count.load(Ordering::Relaxed), 1);
}
#[test]
- fn test_dispatch_two_zero_copy_bufs() {
- let (mut isolate, dispatch_count) = setup(Mode::AsyncZeroCopy(2));
+ fn test_dispatch_heap_zero_copy_bufs() {
+ let (mut isolate, dispatch_count) = setup(Mode::AsyncZeroCopy(5));
js_check(isolate.execute(
"filename.js",
r#"
- let control = new Uint8Array([24]);
let zero_copy_a = new Uint8Array([0]);
let zero_copy_b = new Uint8Array([1]);
- Deno.core.send(1, control, zero_copy_a, zero_copy_b);
+ let zero_copy_c = new Uint8Array([2]);
+ let zero_copy_d = new Uint8Array([3]);
+ let zero_copy_e = new Uint8Array([4]);
+ Deno.core.send(1, zero_copy_a, zero_copy_b, zero_copy_c, zero_copy_d, zero_copy_e);
"#,
));
assert_eq!(dispatch_count.load(Ordering::Relaxed), 1);
@@ -1120,7 +1123,7 @@ pub mod tests {
r#"
let thrown;
try {
- Deno.core.dispatch(100, []);
+ Deno.core.dispatch(100);
} catch (e) {
thrown = e;
}
diff --git a/core/es_isolate.rs b/core/es_isolate.rs
index 5bb1a55c0..a59ba7e92 100644
--- a/core/es_isolate.rs
+++ b/core/es_isolate.rs
@@ -708,12 +708,12 @@ pub mod tests {
let mut isolate = EsIsolate::new(loader, StartupData::None, false);
let dispatcher = move |_state: &mut CoreIsolateState,
- control: &[u8],
- _zero_copy: &mut [ZeroCopyBuf]|
+ zero_copy: &mut [ZeroCopyBuf]|
-> Op {
dispatch_count_.fetch_add(1, Ordering::Relaxed);
- assert_eq!(control.len(), 1);
- assert_eq!(control[0], 42);
+ assert_eq!(zero_copy.len(), 1);
+ assert_eq!(zero_copy[0].len(), 1);
+ assert_eq!(zero_copy[0][0], 42);
let buf = vec![43u8, 0, 0, 0].into_boxed_slice();
Op::Async(futures::future::ready(buf).boxed())
};
diff --git a/core/examples/http_bench.rs b/core/examples/http_bench.rs
index 233864fac..92e69d215 100644
--- a/core/examples/http_bench.rs
+++ b/core/examples/http_bench.rs
@@ -117,18 +117,19 @@ impl Isolate {
{
let state = self.state.clone();
let core_handler = move |_isolate_state: &mut CoreIsolateState,
- control_buf: &[u8],
zero_copy_bufs: &mut [ZeroCopyBuf]|
-> Op {
+ assert!(!zero_copy_bufs.is_empty());
let state = state.clone();
- let record = Record::from(control_buf);
+ let record = Record::from(zero_copy_bufs[0].as_ref());
let is_sync = record.promise_id == 0;
assert!(is_sync);
- let result: i32 = match handler(state, record.rid, zero_copy_bufs) {
- Ok(r) => r as i32,
- Err(_) => -1,
- };
+ let result: i32 =
+ match handler(state, record.rid, &mut zero_copy_bufs[1..]) {
+ Ok(r) => r as i32,
+ Err(_) => -1,
+ };
let buf = RecordBuf::from(Record { result, ..record })[..].into();
Op::Sync(buf)
};
@@ -147,15 +148,15 @@ impl Isolate {
{
let state = self.state.clone();
let core_handler = move |_isolate_state: &mut CoreIsolateState,
- control_buf: &[u8],
zero_copy_bufs: &mut [ZeroCopyBuf]|
-> Op {
+ assert!(!zero_copy_bufs.is_empty());
let state = state.clone();
- let record = Record::from(control_buf);
+ let record = Record::from(zero_copy_bufs[0].as_ref());
let is_sync = record.promise_id == 0;
assert!(!is_sync);
- let mut zero_copy = zero_copy_bufs.to_vec();
+ let mut zero_copy = zero_copy_bufs[1..].to_vec();
let fut = async move {
let op = handler(state, record.rid, &mut zero_copy);
let result = op
diff --git a/core/ops.rs b/core/ops.rs
index eb995df6e..65a0f325b 100644
--- a/core/ops.rs
+++ b/core/ops.rs
@@ -22,7 +22,7 @@ pub enum Op {
/// Main type describing op
pub type OpDispatcher =
- dyn Fn(&mut CoreIsolateState, &[u8], &mut [ZeroCopyBuf]) -> Op + 'static;
+ dyn Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op + 'static;
#[derive(Default)]
pub struct OpRegistry {
@@ -33,7 +33,7 @@ pub struct OpRegistry {
impl OpRegistry {
pub fn new() -> Self {
let mut registry = Self::default();
- let op_id = registry.register("ops", |state, _, _| {
+ let op_id = registry.register("ops", |state, _| {
let buf = state.op_registry.json_map();
Op::Sync(buf)
});
@@ -43,7 +43,7 @@ impl OpRegistry {
pub fn register<F>(&mut self, name: &str, op: F) -> OpId
where
- F: Fn(&mut CoreIsolateState, &[u8], &mut [ZeroCopyBuf]) -> Op + 'static,
+ F: Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op + 'static,
{
let op_id = self.dispatchers.len() as u32;
@@ -81,7 +81,7 @@ fn test_op_registry() {
let c = Arc::new(atomic::AtomicUsize::new(0));
let c_ = c.clone();
- let test_id = op_registry.register("test", move |_, _, _| {
+ let test_id = op_registry.register("test", move |_, _| {
c_.fetch_add(1, atomic::Ordering::SeqCst);
Op::Sync(Box::new([]))
});
@@ -97,7 +97,7 @@ fn test_op_registry() {
let dispatch = op_registry.get(test_id).unwrap();
let state_rc = CoreIsolate::state(&isolate);
let mut state = state_rc.borrow_mut();
- let res = dispatch(&mut state, &[], &mut []);
+ let res = dispatch(&mut state, &mut []);
if let Op::Sync(buf) = res {
assert_eq!(buf.len(), 0);
} else {
@@ -127,10 +127,10 @@ fn register_op_during_call() {
let test_id = {
let mut g = op_registry.lock().unwrap();
- g.register("dynamic_register_op", move |_, _, _| {
+ g.register("dynamic_register_op", move |_, _| {
let c__ = c_.clone();
let mut g = op_registry_.lock().unwrap();
- g.register("test", move |_, _, _| {
+ g.register("test", move |_, _| {
c__.fetch_add(1, atomic::Ordering::SeqCst);
Op::Sync(Box::new([]))
});
@@ -148,7 +148,7 @@ fn register_op_during_call() {
{
let state_rc = CoreIsolate::state(&isolate);
let mut state = state_rc.borrow_mut();
- dispatcher1(&mut state, &[], &mut []);
+ dispatcher1(&mut state, &mut []);
}
let mut expected = HashMap::new();
@@ -166,7 +166,7 @@ fn register_op_during_call() {
};
let state_rc = CoreIsolate::state(&isolate);
let mut state = state_rc.borrow_mut();
- let res = dispatcher2(&mut state, &[], &mut []);
+ let res = dispatcher2(&mut state, &mut []);
if let Op::Sync(buf) = res {
assert_eq!(buf.len(), 0);
} else {
diff --git a/core/plugin_api.rs b/core/plugin_api.rs
index 16f5d4a36..0cb9acaeb 100644
--- a/core/plugin_api.rs
+++ b/core/plugin_api.rs
@@ -15,7 +15,7 @@ pub use crate::ZeroCopyBuf;
pub type InitFn = fn(&mut dyn Interface);
-pub type DispatchOpFn = fn(&mut dyn Interface, &[u8], &mut [ZeroCopyBuf]) -> Op;
+pub type DispatchOpFn = fn(&mut dyn Interface, &mut [ZeroCopyBuf]) -> Op;
pub trait Interface {
fn register_op(&mut self, name: &str, dispatcher: DispatchOpFn) -> OpId;
diff --git a/core/zero_copy_buf.rs b/core/zero_copy_buf.rs
index a458e12ff..a2625b8aa 100644
--- a/core/zero_copy_buf.rs
+++ b/core/zero_copy_buf.rs
@@ -6,8 +6,14 @@ use std::ops::DerefMut;
/// A ZeroCopyBuf encapsulates a slice that's been borrowed from a JavaScript
/// ArrayBuffer object. JavaScript objects can normally be garbage collected,
/// but the existence of a ZeroCopyBuf inhibits this until it is dropped. It
-/// behaves much like an Arc<[u8]>, although a ZeroCopyBuf currently can't be
-/// cloned.
+/// behaves much like an Arc<[u8]>.
+///
+/// # Cloning
+/// Cloning a ZeroCopyBuf does not clone the contents of the buffer,
+/// it creates a new reference to that buffer.
+///
+/// To actually clone the contents of the buffer do
+/// `let copy = Vec::from(&*zero_copy_buf);`
#[derive(Clone)]
pub struct ZeroCopyBuf {
backing_store: v8::SharedRef<v8::BackingStore>,