diff options
Diffstat (limited to 'ops/optimizer.rs')
-rw-r--r-- | ops/optimizer.rs | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/ops/optimizer.rs b/ops/optimizer.rs index 115011008..5a2be7a01 100644 --- a/ops/optimizer.rs +++ b/ops/optimizer.rs @@ -38,12 +38,20 @@ pub(crate) enum BailoutReason { } #[derive(Debug, PartialEq)] +enum StringType { + Cow, + Ref, + Owned, +} + +#[derive(Debug, PartialEq)] enum TransformKind { // serde_v8::Value V8Value, SliceU32(bool), SliceU8(bool), SliceF64(bool), + SeqOneByteString(StringType), PtrU8, PtrVoid, WasmMemory, @@ -78,6 +86,13 @@ impl Transform { } } + fn seq_one_byte_string(index: usize, is_ref: StringType) -> Self { + Transform { + kind: TransformKind::SeqOneByteString(is_ref), + index, + } + } + fn wasm_memory(index: usize) -> Self { Transform { kind: TransformKind::WasmMemory, @@ -180,6 +195,21 @@ impl Transform { }; }) } + // &str + TransformKind::SeqOneByteString(str_ty) => { + *ty = parse_quote! { *const #core::v8::fast_api::FastApiOneByteString }; + match str_ty { + StringType::Ref => q!(Vars { var: &ident }, { + let var = unsafe { &*var }.as_str(); + }), + StringType::Cow => q!(Vars { var: &ident }, { + let var = ::std::borrow::Cow::Borrowed(unsafe { &*var }.as_str()); + }), + StringType::Owned => q!(Vars { var: &ident }, { + let var = unsafe { &*var }.as_str().to_owned(); + }), + } + } TransformKind::WasmMemory => { // Note: `ty` is correctly set to __opts by the fast call tier. // U8 slice is always byte-aligned. @@ -252,6 +282,7 @@ pub(crate) enum FastValue { Uint8Array, Uint32Array, Float64Array, + SeqOneByteString, } impl FastValue { @@ -388,6 +419,13 @@ impl Optimizer { self.analyze_param_type(index, param)?; } + // TODO(@littledivy): https://github.com/denoland/deno/issues/17159 + if self.returns_result + && self.fast_parameters.contains(&FastValue::SeqOneByteString) + { + self.fast_compatible = false; + } + Ok(()) } @@ -661,10 +699,58 @@ impl Optimizer { } } } + // Cow<'_, str> + PathSegment { + ident, arguments, .. + } if ident == "Cow" => { + if let PathArguments::AngleBracketed( + AngleBracketedGenericArguments { args, .. }, + ) = arguments + { + assert_eq!(args.len(), 2); + + let ty = &args[1]; + match ty { + GenericArgument::Type(Type::Path(TypePath { + path: Path { segments, .. }, + .. + })) => { + let segment = single_segment(segments)?; + match segment { + PathSegment { ident, .. } if ident == "str" => { + self.fast_parameters.push(FastValue::SeqOneByteString); + assert!(self + .transforms + .insert( + index, + Transform::seq_one_byte_string( + index, + StringType::Cow + ) + ) + .is_none()); + } + _ => return Err(BailoutReason::FastUnsupportedParamType), + } + } + _ => return Err(BailoutReason::FastUnsupportedParamType), + } + } + } // Is `T` a fast scalar? PathSegment { ident, .. } => { if let Some(val) = get_fast_scalar(ident.to_string().as_str()) { self.fast_parameters.push(val); + } else if ident == "String" { + // Is `T` an owned String? + self.fast_parameters.push(FastValue::SeqOneByteString); + assert!(self + .transforms + .insert( + index, + Transform::seq_one_byte_string(index, StringType::Owned) + ) + .is_none()); } else { return Err(BailoutReason::FastUnsupportedParamType); } @@ -687,6 +773,17 @@ impl Optimizer { { self.has_ref_opstate = true; } + // Is `T` a str? + PathSegment { ident, .. } if ident == "str" => { + self.fast_parameters.push(FastValue::SeqOneByteString); + assert!(self + .transforms + .insert( + index, + Transform::seq_one_byte_string(index, StringType::Ref) + ) + .is_none()); + } _ => return Err(BailoutReason::FastUnsupportedParamType), } } |