mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-21 15:04:33 -05:00
feat: v8::ArrayBuffer::new_backing_store_from_vec (#946)
So we can avoid `.into_boxed_slice()` calls which may require a (costly) memmove when instantiating from a Vec
This commit is contained in:
parent
7a5d1cd10c
commit
7772779210
3 changed files with 96 additions and 4 deletions
|
@ -232,7 +232,7 @@ pub type BackingStoreDeleterCallback = unsafe extern "C" fn(
|
|||
deleter_data: *mut c_void,
|
||||
);
|
||||
|
||||
pub unsafe extern "C" fn backing_store_deleter_callback(
|
||||
pub unsafe extern "C" fn boxed_slice_deleter_callback(
|
||||
data: *mut c_void,
|
||||
byte_length: usize,
|
||||
_deleter_data: *mut c_void,
|
||||
|
@ -242,6 +242,15 @@ pub unsafe extern "C" fn backing_store_deleter_callback(
|
|||
drop(b);
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn vec_deleter_callback(
|
||||
data: *mut c_void,
|
||||
byte_length: usize,
|
||||
deleter_data: *mut c_void,
|
||||
) {
|
||||
let capacity = deleter_data as usize;
|
||||
drop(Vec::from_raw_parts(data as *mut u8, byte_length, capacity))
|
||||
}
|
||||
|
||||
/// A wrapper around the backing store (i.e. the raw memory) of an array buffer.
|
||||
/// See a document linked in http://crbug.com/v8/9908 for more information.
|
||||
///
|
||||
|
@ -425,12 +434,36 @@ impl ArrayBuffer {
|
|||
UniqueRef::from_raw(v8__ArrayBuffer__NewBackingStore__with_data(
|
||||
data_ptr,
|
||||
byte_length,
|
||||
backing_store_deleter_callback,
|
||||
boxed_slice_deleter_callback,
|
||||
null_mut(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new standalone BackingStore that takes over the ownership of
|
||||
/// the given buffer.
|
||||
///
|
||||
/// The destructor of the BackingStore frees owned buffer memory.
|
||||
///
|
||||
/// The result can be later passed to ArrayBuffer::New. The raw pointer
|
||||
/// to the buffer must not be passed again to any V8 API function.
|
||||
pub fn new_backing_store_from_vec(
|
||||
mut data: Vec<u8>,
|
||||
) -> UniqueRef<BackingStore> {
|
||||
let byte_length = data.len();
|
||||
let capacity = data.capacity();
|
||||
let data_ptr = data.as_mut_ptr() as *mut c_void;
|
||||
std::mem::forget(data);
|
||||
unsafe {
|
||||
UniqueRef::from_raw(v8__ArrayBuffer__NewBackingStore__with_data(
|
||||
data_ptr,
|
||||
byte_length,
|
||||
vec_deleter_callback,
|
||||
capacity as *mut c_void,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new standalone BackingStore backed by given ptr.
|
||||
///
|
||||
/// SAFETY: This API consumes raw pointers so is inherently
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
use std::ffi::c_void;
|
||||
use std::ptr::null_mut;
|
||||
|
||||
use crate::array_buffer::backing_store_deleter_callback;
|
||||
use crate::array_buffer::boxed_slice_deleter_callback;
|
||||
use crate::array_buffer::vec_deleter_callback;
|
||||
use crate::support::SharedRef;
|
||||
use crate::support::UniqueRef;
|
||||
use crate::BackingStore;
|
||||
|
@ -123,7 +124,30 @@ impl SharedArrayBuffer {
|
|||
UniqueRef::from_raw(v8__SharedArrayBuffer__NewBackingStore__with_data(
|
||||
data_ptr,
|
||||
byte_length,
|
||||
backing_store_deleter_callback,
|
||||
boxed_slice_deleter_callback,
|
||||
null_mut(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new standalone BackingStore that takes over the ownership of
|
||||
/// the given buffer.
|
||||
///
|
||||
/// The destructor of the BackingStore frees owned buffer memory.
|
||||
///
|
||||
/// The result can be later passed to SharedArrayBuffer::New. The raw pointer
|
||||
/// to the buffer must not be passed again to any V8 API function.
|
||||
pub fn new_backing_store_from_vec(
|
||||
mut data: Vec<u8>,
|
||||
) -> UniqueRef<BackingStore> {
|
||||
let byte_length = data.len();
|
||||
let data_ptr = data.as_mut_ptr() as *mut c_void;
|
||||
std::mem::forget(data);
|
||||
unsafe {
|
||||
UniqueRef::from_raw(v8__SharedArrayBuffer__NewBackingStore__with_data(
|
||||
data_ptr,
|
||||
byte_length,
|
||||
vec_deleter_callback,
|
||||
null_mut(),
|
||||
))
|
||||
}
|
||||
|
|
|
@ -570,6 +570,7 @@ fn array_buffer() {
|
|||
assert_eq!(unique_bs[0].get(), 0);
|
||||
assert_eq!(unique_bs[9].get(), 9);
|
||||
|
||||
// From Box<[u8]>
|
||||
let data: Box<[u8]> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9].into_boxed_slice();
|
||||
let unique_bs = v8::ArrayBuffer::new_backing_store_from_boxed_slice(data);
|
||||
assert_eq!(10, unique_bs.byte_length());
|
||||
|
@ -588,6 +589,26 @@ fn array_buffer() {
|
|||
assert_eq!(10, shared_bs_2.byte_length());
|
||||
assert_eq!(shared_bs_2[0].get(), 0);
|
||||
assert_eq!(shared_bs_2[9].get(), 9);
|
||||
|
||||
// From Vec<u8>
|
||||
let data = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
let unique_bs = v8::ArrayBuffer::new_backing_store_from_vec(data);
|
||||
assert_eq!(10, unique_bs.byte_length());
|
||||
assert!(!unique_bs.is_shared());
|
||||
assert_eq!(unique_bs[0].get(), 0);
|
||||
assert_eq!(unique_bs[9].get(), 9);
|
||||
|
||||
let shared_bs_1 = unique_bs.make_shared();
|
||||
assert_eq!(10, shared_bs_1.byte_length());
|
||||
assert!(!shared_bs_1.is_shared());
|
||||
assert_eq!(shared_bs_1[0].get(), 0);
|
||||
assert_eq!(shared_bs_1[9].get(), 9);
|
||||
|
||||
let ab = v8::ArrayBuffer::with_backing_store(scope, &shared_bs_1);
|
||||
let shared_bs_2 = ab.get_backing_store();
|
||||
assert_eq!(10, shared_bs_2.byte_length());
|
||||
assert_eq!(shared_bs_2[0].get(), 0);
|
||||
assert_eq!(shared_bs_2[9].get(), 9);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6078,6 +6099,20 @@ fn backing_store_from_empty_boxed_slice() {
|
|||
let _ = v8::ArrayBuffer::with_backing_store(&mut scope, &store);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn backing_store_from_empty_vec() {
|
||||
let _setup_guard = setup();
|
||||
|
||||
let mut isolate = v8::Isolate::new(Default::default());
|
||||
let mut scope = v8::HandleScope::new(&mut isolate);
|
||||
let context = v8::Context::new(&mut scope);
|
||||
let mut scope = v8::ContextScope::new(&mut scope, context);
|
||||
|
||||
let store =
|
||||
v8::ArrayBuffer::new_backing_store_from_vec(Vec::new()).make_shared();
|
||||
let _ = v8::ArrayBuffer::with_backing_store(&mut scope, &store);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn current_stack_trace() {
|
||||
// Setup isolate
|
||||
|
|
Loading…
Reference in a new issue