diff --git a/Cargo.lock b/Cargo.lock index 16f3f9497c..cd03c5ac65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -303,7 +303,7 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rusty_v8 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rusty_v8 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1155,7 +1155,7 @@ dependencies = [ [[package]] name = "rusty_v8" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1906,7 +1906,7 @@ dependencies = [ "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" "checksum rustls-native-certs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51ffebdbb48c14f84eba0b715197d673aff1dd22cc1007ca647e28483bbcc307" -"checksum rusty_v8 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0acbe68bf184bc575f1f33294e74d37d5cd6d28e5857cb7b5501c17575decda" +"checksum rusty_v8 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d0a2e0cf49117db64379701eb50d12ab9ec3ca8292047f140c13c5174599441" "checksum rustyline 5.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a23cb19702a8d6afb6edb3c842386e680d4883760e0df74e6848e23c2a87a635" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" diff --git a/core/Cargo.toml b/core/Cargo.toml index 9f05f7528c..e1a8be8139 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -21,7 +21,7 @@ libc = "0.2.66" log = "0.4.8" serde_json = "1.0.44" url = "2.1.0" -rusty_v8 = "=0.1.0" +rusty_v8 = "0.1.1" [[example]] name = "deno_core_http_bench" diff --git a/core/bindings.rs b/core/bindings.rs index 3e3b47a7a3..b7c20c2ee2 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -6,10 +6,8 @@ use crate::isolate::PinnedBuf; use crate::isolate::SHARED_RESPONSE_BUF_SIZE; use rusty_v8 as v8; -use v8::InIsolate; use v8::MapFnTo; -use libc::c_void; use std::convert::TryFrom; use std::option::Option; use std::ptr; @@ -95,16 +93,19 @@ pub fn module_origin<'a>( ) } -pub fn initialize_context<'a>( - scope: &mut impl v8::ToLocal<'a>, - mut context: v8::Local, -) { - context.enter(); +pub fn initialize_context<'s>( + scope: &mut impl v8::ToLocal<'s>, +) -> v8::Local<'s, v8::Context> { + let mut hs = v8::EscapableHandleScope::new(scope); + let scope = hs.enter(); + let context = v8::Context::new(scope); let global = context.global(scope); - let deno_val = v8::Object::new(scope); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); + let deno_val = v8::Object::new(scope); global.set( context, v8::String::new(scope, "Deno").unwrap().into(), @@ -112,7 +113,6 @@ pub fn initialize_context<'a>( ); let mut core_val = v8::Object::new(scope); - deno_val.set( context, v8::String::new(scope, "core").unwrap().into(), @@ -178,7 +178,7 @@ pub fn initialize_context<'a>( queue_microtask_val.into(), ); - context.exit(); + scope.escape(context) } pub unsafe fn slice_to_uint8array<'sc>( @@ -221,7 +221,7 @@ pub extern "C" fn host_import_module_dynamically_callback( referrer: v8::Local, specifier: v8::Local, ) -> *mut v8::Promise { - let mut cbs = v8::CallbackScope::new(context); + let mut cbs = v8::CallbackScope::new_escapable(context); let mut hs = v8::EscapableHandleScope::new(cbs.enter()); let scope = hs.enter(); let isolate = scope.isolate(); @@ -307,7 +307,7 @@ pub extern "C" fn message_callback( // TerminateExecution was called if scope.isolate().is_execution_terminating() { - let u = v8::new_undefined(scope); + let u = v8::undefined(scope); deno_isolate.handle_exception(scope, context, u.into()); return; } @@ -324,8 +324,9 @@ pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) { let deno_isolate: &mut Isolate = unsafe { &mut *(scope.isolate().get_data(0) as *mut Isolate) }; - let mut context = deno_isolate.global_context.get(scope).unwrap(); - context.enter(); + let context = deno_isolate.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); let promise = message.get_promise(); let promise_id = promise.get_identity_hash(); @@ -351,8 +352,6 @@ pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) { // Should not warn. See #1272 } }; - - context.exit(); } fn print( @@ -465,7 +464,7 @@ fn eval_context( Ok(s) => s, Err(_) => { let msg = v8::String::new(scope, "Invalid argument").unwrap(); - let exception = v8::type_error(scope, msg); + let exception = v8::Exception::type_error(scope, msg); scope.isolate().throw_exception(exception); return; } @@ -494,7 +493,7 @@ fn eval_context( output.set( context, v8::Integer::new(scope, 0).into(), - v8::new_null(scope).into(), + v8::null(scope).into(), ); let errinfo_obj = v8::Object::new(scope); @@ -535,7 +534,7 @@ fn eval_context( output.set( context, v8::Integer::new(scope, 0).into(), - v8::new_null(scope).into(), + v8::null(scope).into(), ); let errinfo_obj = v8::Object::new(scope); @@ -577,7 +576,7 @@ fn eval_context( output.set( context, v8::Integer::new(scope, 1).into(), - v8::new_null(scope).into(), + v8::null(scope).into(), ); rv.set(output.into()); } @@ -591,11 +590,7 @@ fn error_to_json( unsafe { &mut *(scope.isolate().get_data(0) as *mut Isolate) }; let context = deno_isolate.global_context.get(scope).unwrap(); - // TODO(piscisaureus): This is transmute necessary because of a bug in - // rusty_v8's implementation of `v8::create_message()`, which needs to be - // fixed. - let exception = unsafe { std::mem::transmute(args.get(0)) }; - let message = v8::create_message(scope, exception); + let message = v8::Exception::create_message(scope, args.get(0)); let json_obj = encode_message_as_object(scope, context, message); let json_string = v8::json::stringify(context, json_obj.into()).unwrap(); @@ -611,7 +606,7 @@ fn queue_microtask( Ok(f) => scope.isolate().enqueue_microtask(f), Err(_) => { let msg = v8::String::new(scope, "Invalid argument").unwrap(); - let exception = v8::type_error(scope, msg); + let exception = v8::Exception::type_error(scope, msg); scope.isolate().throw_exception(exception); } }; @@ -628,15 +623,10 @@ fn shared_getter( // Lazily initialize the persistent external ArrayBuffer. if deno_isolate.shared_ab.is_empty() { - let data_ptr = deno_isolate.shared.bytes.as_ptr(); - let data_len = deno_isolate.shared.bytes.len(); - let ab = unsafe { - v8::SharedArrayBuffer::new_DEPRECATED( - scope, - data_ptr as *mut c_void, - data_len, - ) - }; + let ab = v8::SharedArrayBuffer::new_with_backing_store( + scope, + deno_isolate.shared.get_backing_store(), + ); deno_isolate.shared_ab.set(scope, ab); } @@ -649,7 +639,7 @@ pub fn module_resolve_callback<'s>( specifier: v8::Local<'s, v8::String>, referrer: v8::Local<'s, v8::Module>, ) -> Option> { - let mut scope = v8::CallbackScope::new(context); + let mut scope = v8::CallbackScope::new_escapable(context); let mut scope = v8::EscapableHandleScope::new(scope.enter()); let scope = scope.enter(); diff --git a/core/es_isolate.rs b/core/es_isolate.rs index a3231a90c2..aa20b383bc 100644 --- a/core/es_isolate.rs +++ b/core/es_isolate.rs @@ -87,7 +87,7 @@ impl Drop for EsIsolate { // Clear persistent handles we own. { let mut locker = v8::Locker::new(&isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); for module in self.modules.info.values_mut() { module.handle.reset(scope); @@ -142,11 +142,12 @@ impl EsIsolate { let isolate = self.core_isolate.v8_isolate.as_ref().unwrap(); let mut locker = v8::Locker::new(&isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); assert!(!self.core_isolate.global_context.is_empty()); - let mut context = self.core_isolate.global_context.get(scope).unwrap(); - context.enter(); + let context = self.core_isolate.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); let name_str = v8::String::new(scope, name).unwrap(); let source_str = v8::String::new(scope, source).unwrap(); @@ -166,7 +167,6 @@ impl EsIsolate { context, tc.exception().unwrap(), ); - context.exit(); return 0; } let module = maybe_module.unwrap(); @@ -183,7 +183,6 @@ impl EsIsolate { self .modules .register(id, name, main, handle, import_specifiers); - context.exit(); id } @@ -203,18 +202,17 @@ impl EsIsolate { fn mod_instantiate2(&mut self, id: ModuleId) { let isolate = self.core_isolate.v8_isolate.as_ref().unwrap(); let mut locker = v8::Locker::new(isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); assert!(!self.core_isolate.global_context.is_empty()); - let mut context = self.core_isolate.global_context.get(scope).unwrap(); - context.enter(); - let mut try_catch = v8::TryCatch::new(scope); + let context = self.core_isolate.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let mut try_catch = v8::TryCatch::new(cs.enter()); let tc = try_catch.enter(); let maybe_info = self.modules.get_info(id); if maybe_info.is_none() { - context.exit(); return; } @@ -222,7 +220,6 @@ impl EsIsolate { let mut module = module_handle.get(scope).unwrap(); if module.get_status() == v8::ModuleStatus::Errored { - context.exit(); return; } @@ -237,8 +234,6 @@ impl EsIsolate { tc.exception().unwrap(), ); } - - context.exit(); } /// Instanciates a ES module @@ -254,11 +249,12 @@ impl EsIsolate { fn mod_evaluate2(&mut self, id: ModuleId) { let isolate = self.core_isolate.v8_isolate.as_ref().unwrap(); let mut locker = v8::Locker::new(isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); assert!(!self.core_isolate.global_context.is_empty()); - let mut context = self.core_isolate.global_context.get(scope).unwrap(); - context.enter(); + let context = self.core_isolate.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); let info = self.modules.get_info(id).expect("ModuleInfo not found"); let mut module = info.handle.get(scope).expect("Empty module handle"); @@ -292,8 +288,6 @@ impl EsIsolate { } other => panic!("Unexpected module status {:?}", other), }; - - context.exit(); } /// Evaluates an already instantiated ES module. @@ -353,11 +347,13 @@ impl EsIsolate { ); let isolate = self.core_isolate.v8_isolate.as_ref().unwrap(); let mut locker = v8::Locker::new(isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); assert!(!self.core_isolate.global_context.is_empty()); - let mut context = self.core_isolate.global_context.get(scope).unwrap(); - context.enter(); + let context = self.core_isolate.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); + let mut resolver_handle = self .dyn_import_map .remove(&id) @@ -367,7 +363,7 @@ impl EsIsolate { // Resolution error. if let Some(error_str) = error { let msg = v8::String::new(scope, &error_str).unwrap(); - let e = v8::type_error(scope, msg); + let e = v8::Exception::type_error(scope, msg); resolver.reject(context, e).unwrap(); } else { let e = self.core_isolate.last_exception_handle.get(scope).unwrap(); @@ -375,8 +371,8 @@ impl EsIsolate { self.core_isolate.last_exception.take(); resolver.reject(context, e).unwrap(); } - isolate.run_microtasks(); - context.exit(); + + scope.isolate().run_microtasks(); self.core_isolate.check_last_exception() } @@ -389,11 +385,13 @@ impl EsIsolate { assert!(mod_id != 0); let isolate = self.core_isolate.v8_isolate.as_ref().unwrap(); let mut locker = v8::Locker::new(isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); assert!(!self.core_isolate.global_context.is_empty()); - let mut context = self.core_isolate.global_context.get(scope).unwrap(); - context.enter(); + let context = self.core_isolate.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); + let mut resolver_handle = self .dyn_import_map .remove(&id) @@ -409,8 +407,7 @@ impl EsIsolate { assert_eq!(module.get_status(), v8::ModuleStatus::Evaluated); let module_namespace = module.get_module_namespace(); resolver.resolve(context, module_namespace).unwrap(); - isolate.run_microtasks(); - context.exit(); + scope.isolate().run_microtasks(); self.core_isolate.check_last_exception() } diff --git a/core/isolate.rs b/core/isolate.rs index 0696d5ad48..ebd25b82ad 100644 --- a/core/isolate.rs +++ b/core/isolate.rs @@ -200,7 +200,7 @@ impl Drop for Isolate { // Clear persistent handles we own. { let mut locker = v8::Locker::new(&isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); // self.global_context.reset(scope); @@ -232,7 +232,7 @@ static DENO_INIT: Once = Once::new(); #[allow(clippy::missing_safety_doc)] pub unsafe fn v8_init() { - let platform = v8::platform::new_default_platform(); + let platform = v8::new_default_platform(); v8::V8::initialize_platform(platform); v8::V8::initialize(); // TODO(ry) This makes WASM compile synchronously. Eventually we should @@ -282,16 +282,14 @@ impl Isolate { let isolate = Isolate::setup_isolate(isolate); let mut locker = v8::Locker::new(&isolate); - { - let mut hs = v8::HandleScope::new(&mut locker); - let scope = hs.enter(); - let context = v8::Context::new(scope); - // context.enter(); - global_context.set(scope, context); - creator.set_default_context(context); - bindings::initialize_context(scope, context); - // context.exit(); - } + let scope = locker.enter(); + + let mut hs = v8::HandleScope::new(scope); + let scope = hs.enter(); + + let context = bindings::initialize_context(scope); + global_context.set(scope, context); + creator.set_default_context(context); (isolate, Some(creator)) } else { @@ -302,23 +300,25 @@ impl Isolate { params.set_snapshot_blob(snapshot); } - let load_snapshot_is_null = load_snapshot.is_none(); let isolate = v8::Isolate::new(params); let isolate = Isolate::setup_isolate(isolate); - { - let mut locker = v8::Locker::new(&isolate); - let mut hs = v8::HandleScope::new(&mut locker); - let scope = hs.enter(); - let context = v8::Context::new(scope); + let mut locker = v8::Locker::new(&isolate); + let scope = locker.enter(); - if load_snapshot_is_null { + let mut hs = v8::HandleScope::new(scope); + let scope = hs.enter(); + + let context = match load_snapshot { + Some(_) => v8::Context::new(scope), + None => { // If no snapshot is provided, we initialize the context with empty // main source code and source maps. - bindings::initialize_context(scope, context); + bindings::initialize_context(scope) } - global_context.set(scope, context); - } + }; + global_context.set(scope, context); + (isolate, None) }; @@ -374,7 +374,7 @@ impl Isolate { pub fn clear_exception(&mut self) { let isolate = self.v8_isolate.as_ref().unwrap(); let mut locker = v8::Locker::new(isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); self.last_exception_handle.reset(scope); self.last_exception.take(); @@ -395,7 +395,7 @@ impl Isolate { let exception = if exception.is_null_or_undefined() { let exception_str = v8::String::new(scope, "execution terminated").unwrap(); - v8::error(scope, exception_str) + v8::Exception::error(scope, exception_str) } else { exception }; @@ -419,7 +419,7 @@ impl Isolate { context: v8::Local<'a, v8::Context>, exception: v8::Local<'a, v8::Value>, ) -> String { - let message = v8::create_message(scope, exception); + let message = v8::Exception::create_message(scope, exception); self.encode_message_as_json(scope, context, message) } @@ -434,15 +434,6 @@ impl Isolate { json_string.to_rust_string_lossy(s) } - #[allow(dead_code)] - pub fn run_microtasks(&mut self) { - let isolate = self.v8_isolate.as_mut().unwrap(); - let _locker = v8::Locker::new(isolate); - isolate.enter(); - isolate.run_microtasks(); - isolate.exit(); - } - // TODO(bartlomieju): `error_handler` should be removed #[allow(dead_code)] pub fn set_error_handler(&mut self, handler: Box) { @@ -545,24 +536,25 @@ impl Isolate { let isolate = self.v8_isolate.as_ref().unwrap(); let mut locker = v8::Locker::new(isolate); assert!(!self.global_context.is_empty()); - let mut hs = v8::HandleScope::new(&mut locker); - let s = hs.enter(); - let mut context = self.global_context.get(s).unwrap(); - context.enter(); - let source = v8::String::new(s, js_source).unwrap(); - let name = v8::String::new(s, js_filename).unwrap(); - let mut try_catch = v8::TryCatch::new(s); + let mut hs = v8::HandleScope::new(locker.enter()); + let scope = hs.enter(); + let context = self.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); + + let source = v8::String::new(scope, js_source).unwrap(); + let name = v8::String::new(scope, js_filename).unwrap(); + let mut try_catch = v8::TryCatch::new(scope); let tc = try_catch.enter(); - let origin = bindings::script_origin(s, name); + let origin = bindings::script_origin(scope, name); let mut script = - v8::Script::compile(s, context, source, Some(&origin)).unwrap(); - let result = script.run(s, context); + v8::Script::compile(scope, context, source, Some(&origin)).unwrap(); + let result = script.run(scope, context); if result.is_none() { assert!(tc.has_caught()); let exception = tc.exception().unwrap(); - self.handle_exception(s, context, exception); + self.handle_exception(scope, context, exception); } - context.exit(); self.check_last_exception() } @@ -596,10 +588,11 @@ impl Isolate { let mut locker = v8::Locker::new(isolate); assert!(!self.global_context.is_empty()); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); - let mut context = self.global_context.get(scope).unwrap(); - context.enter(); + let context = self.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); let pending_promises: Vec<(i32, v8::Global)> = self.pending_promise_map.drain().collect(); @@ -608,17 +601,15 @@ impl Isolate { self.handle_exception(scope, context, error); handle.reset(scope); } - - context.exit(); } fn throw_exception(&mut self, text: &str) { let isolate = self.v8_isolate.as_ref().unwrap(); let mut locker = v8::Locker::new(isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); let msg = v8::String::new(scope, text).unwrap(); - isolate.throw_exception(msg.into()); + scope.isolate().throw_exception(msg.into()); } fn async_op_response2(&mut self, op_id: OpId, buf: Box<[u8]>) { @@ -626,10 +617,11 @@ impl Isolate { // println!("deno_execute -> Isolate ptr {:?}", isolate); let mut locker = v8::Locker::new(isolate); assert!(!self.global_context.is_empty()); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); - let mut context = self.global_context.get(scope).unwrap(); - context.enter(); + let context = self.global_context.get(scope).unwrap(); + let mut cs = v8::ContextScope::new(scope, context); + let scope = cs.enter(); let mut try_catch = v8::TryCatch::new(scope); let tc = try_catch.enter(); @@ -642,28 +634,24 @@ impl Isolate { return; } - let mut argc = 0; - let mut args: Vec> = vec![]; + let global: v8::Local = context.global(scope).into(); - if !buf.is_empty() { - argc = 2; - let op_id = v8::Integer::new(scope, op_id as i32); - args.push(op_id.into()); - let buf = unsafe { bindings::slice_to_uint8array(self, scope, &buf) }; - args.push(buf.into()); - } - - let global = context.global(scope); - let maybe_value = + let maybe_value = if !buf.is_empty() { + let op_id: v8::Local = + v8::Integer::new(scope, op_id as i32).into(); + let buf: v8::Local = + unsafe { bindings::slice_to_uint8array(self, scope, &buf) }.into(); js_recv_cb .unwrap() - .call(scope, context, global.into(), argc, args); + .call(scope, context, global, &[op_id, buf]) + } else { + js_recv_cb.unwrap().call(scope, context, global, &[]) + }; if tc.has_caught() { assert!(maybe_value.is_none()); self.handle_exception(scope, context, tc.exception().unwrap()); } - context.exit(); } fn async_op_response( @@ -689,7 +677,7 @@ impl Isolate { let isolate = self.v8_isolate.as_ref().unwrap(); let mut locker = v8::Locker::new(isolate); - let mut hs = v8::HandleScope::new(&mut locker); + let mut hs = v8::HandleScope::new(locker.enter()); let scope = hs.enter(); self.global_context.reset(scope); diff --git a/core/shared_queue.rs b/core/shared_queue.rs index f449eb6b86..cd18568136 100644 --- a/core/shared_queue.rs +++ b/core/shared_queue.rs @@ -17,6 +17,7 @@ SharedQueue Binary Layout */ use crate::ops::OpId; +use rusty_v8 as v8; const MAX_RECORDS: usize = 100; /// Total number of records added. @@ -34,18 +35,39 @@ const HEAD_INIT: usize = 4 * INDEX_RECORDS; pub const RECOMMENDED_SIZE: usize = 128 * MAX_RECORDS; pub struct SharedQueue { - pub bytes: Vec, + buf: v8::SharedRef, } impl SharedQueue { pub fn new(len: usize) -> Self { - let mut bytes = Vec::new(); - bytes.resize(HEAD_INIT + len, 0); - let mut q = Self { bytes }; + let mut buf = Vec::new(); + buf.resize(HEAD_INIT + len, 0); + let buf = buf.into_boxed_slice(); + let buf = + unsafe { v8::SharedArrayBuffer::new_backing_store_from_boxed_slice(buf) }; + let mut q = Self { buf }; q.reset(); q } + pub fn get_backing_store(&mut self) -> &mut v8::SharedRef { + &mut self.buf + } + + pub fn bytes(&self) -> &[u8] { + unsafe { + // This is quite bad. The rusty_v8 issue that makes it necessitates it + // just barely missed the rusty_v8 v0.1.1 release cutoff. + #[allow(clippy::cast_ref_to_mut)] + let self_mut = &mut *(self as *const _ as *mut Self); + self_mut.bytes_mut() + } + } + + pub fn bytes_mut(&mut self) -> &mut [u8] { + self.buf.data_bytes() + } + fn reset(&mut self) { debug!("rust:shared_queue:reset"); let s: &mut [u32] = self.as_u32_slice_mut(); @@ -55,21 +77,21 @@ impl SharedQueue { } fn as_u32_slice(&self) -> &[u32] { - let p = self.bytes.as_ptr(); + let p = self.bytes().as_ptr(); // Assert pointer is 32 bit aligned before casting. assert_eq!((p as usize) % std::mem::align_of::(), 0); #[allow(clippy::cast_ptr_alignment)] let p32 = p as *const u32; - unsafe { std::slice::from_raw_parts(p32, self.bytes.len() / 4) } + unsafe { std::slice::from_raw_parts(p32, self.bytes().len() / 4) } } fn as_u32_slice_mut(&mut self) -> &mut [u32] { - let p = self.bytes.as_mut_ptr(); + let p = self.bytes_mut().as_mut_ptr(); // Assert pointer is 32 bit aligned before casting. assert_eq!((p as usize) % std::mem::align_of::(), 0); #[allow(clippy::cast_ptr_alignment)] let p32 = p as *mut u32; - unsafe { std::slice::from_raw_parts_mut(p32, self.bytes.len() / 4) } + unsafe { std::slice::from_raw_parts_mut(p32, self.bytes().len() / 4) } } pub fn size(&self) -> usize { @@ -149,7 +171,7 @@ impl SharedQueue { self.num_shifted_off(), self.head() ); - Some((op_id, &self.bytes[off..end])) + Some((op_id, &self.bytes()[off..end])) } /// Because JS-side may cast `record` to Int32Array it is required @@ -166,13 +188,13 @@ impl SharedQueue { ); assert_eq!(record.len() % 4, 0); let index = self.num_records(); - if end > self.bytes.len() || index >= MAX_RECORDS { + if end > self.bytes().len() || index >= MAX_RECORDS { debug!("WARNING the sharedQueue overflowed"); return false; } self.set_meta(index, end, op_id); assert_eq!(end - off, record.len()); - self.bytes[off..end].copy_from_slice(record); + self.bytes_mut()[off..end].copy_from_slice(record); let u32_slice = self.as_u32_slice_mut(); u32_slice[INDEX_NUM_RECORDS] += 1; u32_slice[INDEX_HEAD] = end as u32;