summaryrefslogtreecommitdiff
path: root/ops/optimizer.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-11-27 05:54:28 -0800
committerGitHub <noreply@github.com>2022-11-27 19:24:28 +0530
commitca66978a5aadddf7895b49b44076c574e7e6a0b0 (patch)
tree65d93f524bc5fea23cef4e75b02de275833158e1 /ops/optimizer.rs
parent9ffc6acdbb3326dde74c803332547b0ae33e483a (diff)
feat(ops): fast calls for Wasm (#16776)
This PR introduces Wasm ops. These calls are optimized for entry from Wasm land. The `#[op(wasm)]` attribute is opt-in. Last parameter `Option<&mut [u8]>` is the memory slice of the Wasm module *when entered from a Fast API call*. Otherwise, the user is expected to implement logic to obtain the memory if `None` ```rust #[op(wasm)] pub fn op_args_get( offset: i32, buffer_offset: i32, memory: Option<&mut [u8]>, ) { // ... } ```
Diffstat (limited to 'ops/optimizer.rs')
-rw-r--r--ops/optimizer.rs54
1 files changed, 53 insertions, 1 deletions
diff --git a/ops/optimizer.rs b/ops/optimizer.rs
index 8fa2ab1f5..d25857032 100644
--- a/ops/optimizer.rs
+++ b/ops/optimizer.rs
@@ -26,6 +26,7 @@ enum TransformKind {
SliceU32(bool),
SliceU8(bool),
PtrU8,
+ WasmMemory,
}
impl Transform {
@@ -50,6 +51,13 @@ impl Transform {
}
}
+ fn wasm_memory(index: usize) -> Self {
+ Transform {
+ kind: TransformKind::WasmMemory,
+ index,
+ }
+ }
+
fn u8_ptr(index: usize) -> Self {
Transform {
kind: TransformKind::PtrU8,
@@ -124,6 +132,16 @@ impl Transform {
};
})
}
+ TransformKind::WasmMemory => {
+ // Note: `ty` is correctly set to __opts by the fast call tier.
+ q!(Vars { var: &ident, core }, {
+ let var = unsafe {
+ &*(__opts.wasm_memory
+ as *const core::v8::fast_api::FastApiTypedArray<u8>)
+ }
+ .get_storage_if_aligned();
+ })
+ }
// *const u8
TransformKind::PtrU8 => {
*ty =
@@ -201,6 +219,8 @@ pub(crate) struct Optimizer {
// Do we depend on FastApiCallbackOptions?
pub(crate) needs_fast_callback_option: bool,
+ pub(crate) has_wasm_memory: bool,
+
pub(crate) fast_result: Option<FastValue>,
pub(crate) fast_parameters: Vec<FastValue>,
@@ -262,6 +282,9 @@ impl Optimizer {
self.is_async = op.is_async;
self.fast_compatible = true;
+ // Just assume for now. We will validate later.
+ self.has_wasm_memory = op.attrs.is_wasm;
+
let sig = &op.item.sig;
// Analyze return type
@@ -419,7 +442,32 @@ impl Optimizer {
TypeReference { elem, .. },
))) = args.last()
{
- if let Type::Path(TypePath {
+ if self.has_wasm_memory {
+ // -> Option<&mut [u8]>
+ if let Type::Slice(TypeSlice { elem, .. }) = &**elem {
+ if let Type::Path(TypePath {
+ path: Path { segments, .. },
+ ..
+ }) = &**elem
+ {
+ let segment = single_segment(segments)?;
+
+ match segment {
+ // Is `T` a u8?
+ PathSegment { ident, .. } if ident == "u8" => {
+ self.needs_fast_callback_option = true;
+ assert!(self
+ .transforms
+ .insert(index, Transform::wasm_memory(index))
+ .is_none());
+ }
+ _ => {
+ return Err(BailoutReason::FastUnsupportedParamType)
+ }
+ }
+ }
+ }
+ } else if let Type::Path(TypePath {
path: Path { segments, .. },
..
}) = &**elem
@@ -654,6 +702,10 @@ mod tests {
.expect("Failed to read expected file");
let mut attrs = Attributes::default();
+ if source.contains("// @test-attr:wasm") {
+ attrs.must_be_fast = true;
+ attrs.is_wasm = true;
+ }
if source.contains("// @test-attr:fast") {
attrs.must_be_fast = true;
}