diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2022-12-12 06:14:20 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-12 14:14:20 +0000 |
commit | a2db70a8d0820722695e9094c8dbc888bde1ffa3 (patch) | |
tree | 6885e2aee424ab0264a8b01df9b0bafbcfe85792 /ext/ffi/static.rs | |
parent | 890b0653104388bfef60ca7ebd0af758caf5f0be (diff) |
refactor(ext/ffi): split into multiple parts (#16950)
- [x] `dlfcn.rs` - `dlopen()`-related code.
- [x] `turbocall.rs` - Call trampoline JIT compiler.
- [x] `repr.rs` - Pointer representation. Home of the UnsafePointerView
ops.
- [x] `symbol.rs` - Function symbol related code.
- [x] `callback.rs` - Home of `Deno.UnsafeCallback` ops.
- [x] `ir.rs` - Intermediate representation for values. Home of the
`NativeValue` type.
- [x] `call.rs` - Generic call ops. Home to everything related to
calling FFI symbols.
- [x] `static.rs` - static symbol support
I find easier to work with this setup, I eventually want to expand
TurboCall to unroll type conversion loop in generic calls, generate code
for individual symbols (lazy function pointers), etc.
Diffstat (limited to 'ext/ffi/static.rs')
-rw-r--r-- | ext/ffi/static.rs | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/ext/ffi/static.rs b/ext/ffi/static.rs new file mode 100644 index 000000000..aa0bb325c --- /dev/null +++ b/ext/ffi/static.rs @@ -0,0 +1,146 @@ +// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. + +use crate::dlfcn::DynamicLibraryResource; +use crate::symbol::NativeType; +use crate::MAX_SAFE_INTEGER; +use crate::MIN_SAFE_INTEGER; +use deno_core::error::type_error; +use deno_core::error::AnyError; +use deno_core::op; +use deno_core::serde_v8; +use deno_core::v8; +use deno_core::ResourceId; +use std::ptr; + +#[op(v8)] +pub fn op_ffi_get_static<'scope>( + scope: &mut v8::HandleScope<'scope>, + state: &mut deno_core::OpState, + rid: ResourceId, + name: String, + static_type: NativeType, +) -> Result<serde_v8::Value<'scope>, AnyError> { + let resource = state.resource_table.get::<DynamicLibraryResource>(rid)?; + + let data_ptr = resource.get_static(name)?; + + Ok(match static_type { + NativeType::Void => { + return Err(type_error("Invalid FFI static type 'void'")); + } + NativeType::Bool => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const bool) }; + let boolean: v8::Local<v8::Value> = + v8::Boolean::new(scope, result).into(); + boolean.into() + } + NativeType::U8 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const u8) }; + let number: v8::Local<v8::Value> = + v8::Integer::new_from_unsigned(scope, result as u32).into(); + number.into() + } + NativeType::I8 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const i8) }; + let number: v8::Local<v8::Value> = + v8::Integer::new(scope, result as i32).into(); + number.into() + } + NativeType::U16 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const u16) }; + let number: v8::Local<v8::Value> = + v8::Integer::new_from_unsigned(scope, result as u32).into(); + number.into() + } + NativeType::I16 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const i16) }; + let number: v8::Local<v8::Value> = + v8::Integer::new(scope, result as i32).into(); + number.into() + } + NativeType::U32 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const u32) }; + let number: v8::Local<v8::Value> = + v8::Integer::new_from_unsigned(scope, result).into(); + number.into() + } + NativeType::I32 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const i32) }; + let number: v8::Local<v8::Value> = v8::Integer::new(scope, result).into(); + number.into() + } + NativeType::U64 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const u64) }; + let integer: v8::Local<v8::Value> = if result > MAX_SAFE_INTEGER as u64 { + v8::BigInt::new_from_u64(scope, result).into() + } else { + v8::Number::new(scope, result as f64).into() + }; + integer.into() + } + NativeType::I64 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const i64) }; + let integer: v8::Local<v8::Value> = if result > MAX_SAFE_INTEGER as i64 + || result < MIN_SAFE_INTEGER as i64 + { + v8::BigInt::new_from_i64(scope, result).into() + } else { + v8::Number::new(scope, result as f64).into() + }; + integer.into() + } + NativeType::USize => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const usize) }; + let integer: v8::Local<v8::Value> = if result > MAX_SAFE_INTEGER as usize + { + v8::BigInt::new_from_u64(scope, result as u64).into() + } else { + v8::Number::new(scope, result as f64).into() + }; + integer.into() + } + NativeType::ISize => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const isize) }; + let integer: v8::Local<v8::Value> = + if !(MIN_SAFE_INTEGER..=MAX_SAFE_INTEGER).contains(&result) { + v8::BigInt::new_from_i64(scope, result as i64).into() + } else { + v8::Number::new(scope, result as f64).into() + }; + integer.into() + } + NativeType::F32 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const f32) }; + let number: v8::Local<v8::Value> = + v8::Number::new(scope, result as f64).into(); + number.into() + } + NativeType::F64 => { + // SAFETY: ptr is user provided + let result = unsafe { ptr::read_unaligned(data_ptr as *const f64) }; + let number: v8::Local<v8::Value> = v8::Number::new(scope, result).into(); + number.into() + } + NativeType::Pointer | NativeType::Function | NativeType::Buffer => { + let result = data_ptr as u64; + let integer: v8::Local<v8::Value> = if result > MAX_SAFE_INTEGER as u64 { + v8::BigInt::new_from_u64(scope, result).into() + } else { + v8::Number::new(scope, result as f64).into() + }; + integer.into() + } + }) +} |