summaryrefslogtreecommitdiff
path: root/ops/optimizer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ops/optimizer.rs')
-rw-r--r--ops/optimizer.rs97
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),
}
}