Repository: denoland/deno_core
Pull request #870 (2024-08-16 08:27:44)

Add `no_side_effect` attribute for ops
```
test bench_op_string_bytestring                 ... bench:      54,952 ns/iter (+/- 2,375)
test bench_op_string_bytestring_no_side_effects ... bench:      53,643 ns/iter (+/- 5,830)
```


Patch:
diff --git a/core/benches/ops/sync.rs b/core/benches/ops/sync.rs
index 9f483ea..686a65d 100644
--- a/core/benches/ops/sync.rs
+++ b/core/benches/ops/sync.rs
@@ -11,6 +11,8 @@ deno_core::extension!(
   ops = [
     op_void,
     op_void_nofast,
+    op_void_no_side_effects,
+    op_void_nofast_no_side_effects,
     op_void_metrics,
     op_void_nofast_metrics,
     op_u32,
@@ -18,6 +20,7 @@ deno_core::extension!(
     op_string,
     op_string_onebyte,
     op_string_bytestring,
+    op_string_bytestring_no_side_effects,
     op_string_option_u32,
     op_local,
     op_local_scope,
@@ -45,9 +48,15 @@ deno_core::extension!(
 #[op2(fast)]
 pub fn op_void() {}
 
+#[op2(fast, no_side_effects)]
+pub fn op_void_no_side_effects() {}
+
 #[op2(nofast)]
 pub fn op_void_nofast() {}
 
+#[op2(no_side_effects, nofast)]
+pub fn op_void_nofast_no_side_effects() {}
+
 #[op2(fast)]
 pub fn op_void_metrics() {}
 
@@ -79,6 +88,11 @@ pub fn op_string_bytestring(#[serde] s: ByteString) -> u32 {
   s.len() as _
 }
 
+#[op2(no_side_effects)]
+pub fn op_string_bytestring_no_side_effects(#[serde] s: ByteString) -> u32 {
+  s.len() as _
+}
+
 #[op2]
 pub fn op_string_option_u32(#[string] s: &str) -> Option<u32> {
   Some(s.len() as _)
@@ -230,6 +244,26 @@ fn bench_op_void_nofast(b: &mut Bencher) {
   bench_op(b, BENCH_COUNT, "op_void_nofast", 0, "op_void_nofast();");
 }
 
+fn bench_op_void_no_side_effects(b: &mut Bencher) {
+  bench_op(
+    b,
+    BENCH_COUNT,
+    "op_void_no_side_effects",
+    0,
+    "op_void_no_side_effects();",
+  );
+}
+
+fn bench_op_void_nofast_no_side_effects(b: &mut Bencher) {
+  bench_op(
+    b,
+    BENCH_COUNT,
+    "op_void_nofast_no_side_effects",
+    0,
+    "op_void_nofast_no_side_effects();",
+  );
+}
+
 /// A void function with no return value.
 fn bench_op_void_metrics(b: &mut Bencher) {
   bench_op(b, BENCH_COUNT, "op_void_metrics", 0, "op_void_metrics()");
@@ -321,6 +355,16 @@ fn bench_op_string_bytestring(b: &mut Bencher) {
   bench_op(b, BENCH_COUNT, "op_string_bytestring", 1, "accum += op_string_bytestring('this is a reasonably long string that we would like to get the length of!');");
 }
 
+fn bench_op_string_bytestring_no_side_effects(b: &mut Bencher) {
+  bench_op(
+    b,
+    BENCH_COUNT,
+    "op_string_bytestring_no_side_effects",
+    1,
+    "accum += op_string_bytestring_no_side_effects('this is a reasonably long string that we would like to get the length of!');",
+  );
+}
+
 /// A string function with a numeric return value.
 fn bench_op_string_large_utf8_1000(b: &mut Bencher) {
   bench_op(
@@ -457,11 +501,14 @@ benchmark_group!(
   bench_op_void,
   bench_op_void_2x,
   bench_op_void_nofast,
+  bench_op_void_no_side_effects,
+  bench_op_void_nofast_no_side_effects,
   bench_op_void_metrics,
   bench_op_void_nofast_metrics,
   bench_op_u32,
   bench_op_option_u32,
   bench_op_string_bytestring,
+  bench_op_string_bytestring_no_side_effects,
   bench_op_string,
   bench_op_string_large_1000,
   bench_op_string_large_1000000,
diff --git a/core/extensions.rs b/core/extensions.rs
index 40270b4..f7e6ed8 100644
--- a/core/extensions.rs
+++ b/core/extensions.rs
@@ -175,6 +175,7 @@ pub struct OpDecl {
   pub is_async: bool,
   pub is_reentrant: bool,
   pub arg_count: u8,
+  pub no_side_effects: bool,
   /// The slow dispatch call. If metrics are disabled, the `v8::Function` is created with this callback.
   pub(crate) slow_fn: OpFnRef,
   /// The slow dispatch call with metrics enabled. If metrics are enabled, the `v8::Function` is created with this callback.
@@ -196,6 +197,7 @@ impl OpDecl {
     is_async: bool,
     is_reentrant: bool,
     arg_count: u8,
+    no_side_effects: bool,
     slow_fn: OpFnRef,
     slow_fn_with_metrics: OpFnRef,
     fast_fn: Option<FastFunction>,
@@ -209,6 +211,7 @@ impl OpDecl {
       is_async,
       is_reentrant,
       arg_count,
+      no_side_effects,
       slow_fn,
       slow_fn_with_metrics,
       fast_fn,
diff --git a/core/runtime/bindings.rs b/core/runtime/bindings.rs
index 5a520d7..b60e73b 100644
--- a/core/runtime/bindings.rs
+++ b/core/runtime/bindings.rs
@@ -385,6 +385,11 @@ fn op_ctx_function<'s>(
   let builder: v8::FunctionBuilder<v8::FunctionTemplate> =
     v8::FunctionTemplate::builder_raw(slow_fn)
       .data(external.into())
+      .side_effect_type(if op_ctx.decl.no_side_effects {
+        v8::SideEffectType::HasNoSideEffect
+      } else {
+        v8::SideEffectType::HasSideEffect
+      })
       .length(op_ctx.decl.arg_count as i32);
 
   let template = if let Some(fast_function) = &fast_fn {
diff --git a/ops/op2/config.rs b/ops/op2/config.rs
index 87b7b7d..8a52ecb 100644
--- a/ops/op2/config.rs
+++ b/ops/op2/config.rs
@@ -24,6 +24,8 @@ pub(crate) struct MacroConfig {
   pub reentrant: bool,
   /// Marks an op as a method on a wrapped object.
   pub method: Option<String>,
+  /// Marks an op with no side effects.
+  pub no_side_effects: bool,
 }
 
 impl MacroConfig {
@@ -87,6 +89,8 @@ impl MacroConfig {
         config.async_deferred = true;
       } else if flag == "reentrant" {
         config.reentrant = true;
+      } else if flag == "no_side_effects" {
+        config.no_side_effects = true;
       } else if flag.starts_with("method(") {
         let tokens =
           syn::parse_str::<TokenTree>(&flag[6..])?.into_token_stream();
@@ -123,6 +127,20 @@ impl MacroConfig {
     {
       return Err(Op2Error::InvalidAttributeCombination("nofast", "async"));
     }
+    if config.no_side_effects
+      && (config.r#async && !config.async_lazy && !config.async_deferred)
+    {
+      return Err(Op2Error::InvalidAttributeCombination(
+        "no_side_effects",
+        "async",
+      ));
+    }
+    if config.no_side_effects && config.reentrant {
+      return Err(Op2Error::InvalidAttributeCombination(
+        "no_side_effects",
+        "reentrant",
+      ));
+    }
 
     Ok(config)
   }
diff --git a/ops/op2/mod.rs b/ops/op2/mod.rs
index 5638c2d..2e2d4e9 100644
--- a/ops/op2/mod.rs
+++ b/ops/op2/mod.rs
@@ -198,6 +198,7 @@ fn generate_op2(
   };
   let is_async = signature.ret_val.is_async();
   let is_reentrant = config.reentrant;
+  let no_side_effect = config.no_side_effects;
 
   match (is_async, config.r#async) {
     (true, false) => return Err(Op2Error::ShouldBeAsync),
@@ -295,6 +296,7 @@ fn generate_op2(
           /*is_async*/ #is_async,
           /*is_reentrant*/ #is_reentrant,
           /*arg_count*/ #arg_count as u8,
+          /*no_side_effect*/ #no_side_effect,
           /*slow_fn*/ Self::#slow_function as _,
           /*slow_fn_metrics*/ Self::#slow_function_metrics as _,
           /*fast_fn*/ #fast_definition,


Test patch:
diff --git a/ops/op2/test_cases/async/async_arg_return.out b/ops/op2/test_cases/async/async_arg_return.out
index 0214fcb..a671bd2 100644
--- a/ops/op2/test_cases/async/async_arg_return.out
+++ b/ops/op2/test_cases/async/async_arg_return.out
@@ -11,6 +11,7 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_arg_return_result.out b/ops/op2/test_cases/async/async_arg_return_result.out
index 4721cc4..c67b15b 100644
--- a/ops/op2/test_cases/async/async_arg_return_result.out
+++ b/ops/op2/test_cases/async/async_arg_return_result.out
@@ -11,6 +11,7 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_cppgc.out b/ops/op2/test_cases/async/async_cppgc.out
index 1e5fad2..6b544cf 100644
--- a/ops/op2/test_cases/async/async_cppgc.out
+++ b/ops/op2/test_cases/async/async_cppgc.out
@@ -11,6 +11,7 @@ const fn op_make_cppgc_object() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -134,6 +135,7 @@ const fn op_use_cppgc_object() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -257,6 +259,7 @@ const fn op_use_optional_cppgc_object() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_deferred.out b/ops/op2/test_cases/async/async_deferred.out
index 26dc5ab..3b04fbe 100644
--- a/ops/op2/test_cases/async/async_deferred.out
+++ b/ops/op2/test_cases/async/async_deferred.out
@@ -11,6 +11,7 @@ pub const fn op_async_deferred() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/async/async_jsbuffer.out b/ops/op2/test_cases/async/async_jsbuffer.out
index f7f2199..cc86522 100644
--- a/ops/op2/test_cases/async/async_jsbuffer.out
+++ b/ops/op2/test_cases/async/async_jsbuffer.out
@@ -11,6 +11,7 @@ pub const fn op_async_v8_buffer() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_lazy.out b/ops/op2/test_cases/async/async_lazy.out
index dad4d37..c46e0e3 100644
--- a/ops/op2/test_cases/async/async_lazy.out
+++ b/ops/op2/test_cases/async/async_lazy.out
@@ -11,6 +11,7 @@ pub const fn op_async_lazy() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/async/async_op_metadata.out b/ops/op2/test_cases/async/async_op_metadata.out
index 13249ab..f7e5ba9 100644
--- a/ops/op2/test_cases/async/async_op_metadata.out
+++ b/ops/op2/test_cases/async/async_op_metadata.out
@@ -11,6 +11,7 @@ const fn op_blob_read_part() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -117,6 +118,7 @@ const fn op_broadcast_recv() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_opstate.out b/ops/op2/test_cases/async/async_opstate.out
index 188954e..ab3cfb6 100644
--- a/ops/op2/test_cases/async/async_opstate.out
+++ b/ops/op2/test_cases/async/async_opstate.out
@@ -11,6 +11,7 @@ pub const fn op_async_opstate() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_result.out b/ops/op2/test_cases/async/async_result.out
index 927a704..94d4cc4 100644
--- a/ops/op2/test_cases/async/async_result.out
+++ b/ops/op2/test_cases/async/async_result.out
@@ -11,6 +11,7 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_result_impl.out b/ops/op2/test_cases/async/async_result_impl.out
index 7ceecb5..4e7e1ee 100644
--- a/ops/op2/test_cases/async/async_result_impl.out
+++ b/ops/op2/test_cases/async/async_result_impl.out
@@ -11,6 +11,7 @@ pub const fn op_async_result_impl() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_result_smi.out b/ops/op2/test_cases/async/async_result_smi.out
index 0a7a024..f528d99 100644
--- a/ops/op2/test_cases/async/async_result_smi.out
+++ b/ops/op2/test_cases/async/async_result_smi.out
@@ -11,6 +11,7 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_v8_global.out b/ops/op2/test_cases/async/async_v8_global.out
index 0c4d212..27e286b 100644
--- a/ops/op2/test_cases/async/async_v8_global.out
+++ b/ops/op2/test_cases/async/async_v8_global.out
@@ -11,6 +11,7 @@ pub const fn op_async_v8_global() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/async/async_void.out b/ops/op2/test_cases/async/async_void.out
index 8f9f32f..66391d2 100644
--- a/ops/op2/test_cases/async/async_void.out
+++ b/ops/op2/test_cases/async/async_void.out
@@ -11,6 +11,7 @@ pub const fn op_async() -> ::deno_core::_ops::OpDecl {
             true,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/add.out b/ops/op2/test_cases/sync/add.out
index 0cc9397..35dd679 100644
--- a/ops/op2/test_cases/sync/add.out
+++ b/ops/op2/test_cases/sync/add.out
@@ -11,6 +11,7 @@ const fn op_add() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/add_options.out b/ops/op2/test_cases/sync/add_options.out
index 110fd7d..6fe6225 100644
--- a/ops/op2/test_cases/sync/add_options.out
+++ b/ops/op2/test_cases/sync/add_options.out
@@ -11,6 +11,7 @@ pub const fn op_test_add_option() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/bigint.out b/ops/op2/test_cases/sync/bigint.out
index 1030622..07e4bc2 100644
--- a/ops/op2/test_cases/sync/bigint.out
+++ b/ops/op2/test_cases/sync/bigint.out
@@ -11,6 +11,7 @@ pub const fn op_bigint() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/bool.out b/ops/op2/test_cases/sync/bool.out
index 02535c0..1b3cc7b 100644
--- a/ops/op2/test_cases/sync/bool.out
+++ b/ops/op2/test_cases/sync/bool.out
@@ -11,6 +11,7 @@ pub const fn op_bool() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/bool_result.out b/ops/op2/test_cases/sync/bool_result.out
index 75f049a..db3179d 100644
--- a/ops/op2/test_cases/sync/bool_result.out
+++ b/ops/op2/test_cases/sync/bool_result.out
@@ -11,6 +11,7 @@ pub const fn op_bool() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/buffers.out b/ops/op2/test_cases/sync/buffers.out
index 5386a1e..57aa39c 100644
--- a/ops/op2/test_cases/sync/buffers.out
+++ b/ops/op2/test_cases/sync/buffers.out
@@ -11,6 +11,7 @@ const fn op_buffers() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             4usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -298,6 +299,7 @@ const fn op_buffers_32() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             4usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -585,6 +587,7 @@ const fn op_buffers_option() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/buffers_copy.out b/ops/op2/test_cases/sync/buffers_copy.out
index eac0b71..91e9de9 100644
--- a/ops/op2/test_cases/sync/buffers_copy.out
+++ b/ops/op2/test_cases/sync/buffers_copy.out
@@ -11,6 +11,7 @@ const fn op_buffers() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             3usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -251,6 +252,7 @@ const fn op_buffers_32() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/buffers_out.out b/ops/op2/test_cases/sync/buffers_out.out
index b03fb52..aaaba93 100644
--- a/ops/op2/test_cases/sync/buffers_out.out
+++ b/ops/op2/test_cases/sync/buffers_out.out
@@ -11,6 +11,7 @@ const fn op_buffers() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -132,6 +133,7 @@ const fn op_buffers_option() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -263,6 +265,7 @@ const fn op_arraybuffers() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/cfg.out b/ops/op2/test_cases/sync/cfg.out
index c69dba4..788c298 100644
--- a/ops/op2/test_cases/sync/cfg.out
+++ b/ops/op2/test_cases/sync/cfg.out
@@ -13,6 +13,7 @@ pub const fn op_maybe_windows() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -152,6 +153,7 @@ pub const fn op_maybe_windows() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/clippy_allow.out b/ops/op2/test_cases/sync/clippy_allow.out
index 230ff14..1318936 100644
--- a/ops/op2/test_cases/sync/clippy_allow.out
+++ b/ops/op2/test_cases/sync/clippy_allow.out
@@ -13,6 +13,7 @@ pub const fn op_extra_annotation() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -150,6 +151,7 @@ pub const fn op_clippy_internal() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/cppgc_resource.out b/ops/op2/test_cases/sync/cppgc_resource.out
index d965c8e..31c2ba4 100644
--- a/ops/op2/test_cases/sync/cppgc_resource.out
+++ b/ops/op2/test_cases/sync/cppgc_resource.out
@@ -11,6 +11,7 @@ const fn op_cppgc_object() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -191,6 +192,7 @@ const fn op_option_cppgc_object() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -379,6 +381,7 @@ const fn op_make_cppgc_object() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -471,6 +474,7 @@ const fn op_use_cppgc_object() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -651,6 +655,7 @@ const fn op_make_cppgc_object_option() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -746,6 +751,7 @@ const fn op_use_cppgc_object_option() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/doc_comment.out b/ops/op2/test_cases/sync/doc_comment.out
index b221365..d581070 100644
--- a/ops/op2/test_cases/sync/doc_comment.out
+++ b/ops/op2/test_cases/sync/doc_comment.out
@@ -12,6 +12,7 @@ pub const fn op_has_doc_comment() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/fast_alternative.out b/ops/op2/test_cases/sync/fast_alternative.out
index 3ab5da7..f0c0b75 100644
--- a/ops/op2/test_cases/sync/fast_alternative.out
+++ b/ops/op2/test_cases/sync/fast_alternative.out
@@ -11,6 +11,7 @@ const fn op_slow() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             3usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({ op_fast().fast_fn() }),
@@ -127,6 +128,7 @@ const fn op_fast() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -305,6 +307,7 @@ const fn op_slow_generic<T: Trait>() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             3usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({ op_fast_generic::<T>().fast_fn() }),
@@ -421,6 +424,7 @@ const fn op_fast_generic<T: Trait>() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/from_v8.out b/ops/op2/test_cases/sync/from_v8.out
index 432025d..5aa25ac 100644
--- a/ops/op2/test_cases/sync/from_v8.out
+++ b/ops/op2/test_cases/sync/from_v8.out
@@ -11,6 +11,7 @@ pub const fn op_from_v8_arg() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/generics.out b/ops/op2/test_cases/sync/generics.out
index 847d4bf..50f832e 100644
--- a/ops/op2/test_cases/sync/generics.out
+++ b/ops/op2/test_cases/sync/generics.out
@@ -11,6 +11,7 @@ pub const fn op_generics<T: Trait>() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -146,6 +147,7 @@ pub const fn op_generics_static<T: Trait + 'static>() -> ::deno_core::_ops::OpDe
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -281,6 +283,7 @@ pub const fn op_generics_static_where<T: Trait + 'static>() -> ::deno_core::_ops
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/nofast.out b/ops/op2/test_cases/sync/nofast.out
index 02b410c..6f71efb 100644
--- a/ops/op2/test_cases/sync/nofast.out
+++ b/ops/op2/test_cases/sync/nofast.out
@@ -11,6 +11,7 @@ const fn op_nofast() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/op_state_attr.out b/ops/op2/test_cases/sync/op_state_attr.out
index 35e6b78..20c86df 100644
--- a/ops/op2/test_cases/sync/op_state_attr.out
+++ b/ops/op2/test_cases/sync/op_state_attr.out
@@ -11,6 +11,7 @@ const fn op_state_rc() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/op_state_rc.out b/ops/op2/test_cases/sync/op_state_rc.out
index 3f2bd1a..d1ab969 100644
--- a/ops/op2/test_cases/sync/op_state_rc.out
+++ b/ops/op2/test_cases/sync/op_state_rc.out
@@ -11,6 +11,7 @@ const fn op_state_rc() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/op_state_ref.out b/ops/op2/test_cases/sync/op_state_ref.out
index 2fd0bb0..55d5b9d 100644
--- a/ops/op2/test_cases/sync/op_state_ref.out
+++ b/ops/op2/test_cases/sync/op_state_ref.out
@@ -11,6 +11,7 @@ const fn op_state_ref() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -174,6 +175,7 @@ const fn op_state_mut() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -337,6 +339,7 @@ const fn op_state_and_v8() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -448,6 +451,7 @@ const fn op_state_and_v8_local() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/result_external.out b/ops/op2/test_cases/sync/result_external.out
index bcc4341..5efdc1c 100644
--- a/ops/op2/test_cases/sync/result_external.out
+++ b/ops/op2/test_cases/sync/result_external.out
@@ -11,6 +11,7 @@ pub const fn op_external_with_result() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/result_primitive.out b/ops/op2/test_cases/sync/result_primitive.out
index d0151cd..ffd95ce 100644
--- a/ops/op2/test_cases/sync/result_primitive.out
+++ b/ops/op2/test_cases/sync/result_primitive.out
@@ -11,6 +11,7 @@ pub const fn op_u32_with_result() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/result_scope.out b/ops/op2/test_cases/sync/result_scope.out
index 5395295..952f5da 100644
--- a/ops/op2/test_cases/sync/result_scope.out
+++ b/ops/op2/test_cases/sync/result_scope.out
@@ -11,6 +11,7 @@ pub const fn op_void_with_result() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/result_void.out b/ops/op2/test_cases/sync/result_void.out
index 36af2ec..ac8de1a 100644
--- a/ops/op2/test_cases/sync/result_void.out
+++ b/ops/op2/test_cases/sync/result_void.out
@@ -11,6 +11,7 @@ pub const fn op_void_with_result() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/serde_v8.out b/ops/op2/test_cases/sync/serde_v8.out
index 2e26962..767bf9f 100644
--- a/ops/op2/test_cases/sync/serde_v8.out
+++ b/ops/op2/test_cases/sync/serde_v8.out
@@ -11,6 +11,7 @@ pub const fn op_serde_v8() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/smi.out b/ops/op2/test_cases/sync/smi.out
index 66c2457..45d147e 100644
--- a/ops/op2/test_cases/sync/smi.out
+++ b/ops/op2/test_cases/sync/smi.out
@@ -11,6 +11,7 @@ const fn op_smi_unsigned_return() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             4usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -236,6 +237,7 @@ const fn op_smi_signed_return() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             4usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
@@ -461,6 +463,7 @@ const fn op_smi_option() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/string_cow.out b/ops/op2/test_cases/sync/string_cow.out
index c0e80e8..1194c96 100644
--- a/ops/op2/test_cases/sync/string_cow.out
+++ b/ops/op2/test_cases/sync/string_cow.out
@@ -11,6 +11,7 @@ const fn op_string_cow() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/string_onebyte.out b/ops/op2/test_cases/sync/string_onebyte.out
index 4abc6cb..465d52a 100644
--- a/ops/op2/test_cases/sync/string_onebyte.out
+++ b/ops/op2/test_cases/sync/string_onebyte.out
@@ -11,6 +11,7 @@ const fn op_string_onebyte() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/string_option_return.out b/ops/op2/test_cases/sync/string_option_return.out
index 25056fa..0715750 100644
--- a/ops/op2/test_cases/sync/string_option_return.out
+++ b/ops/op2/test_cases/sync/string_option_return.out
@@ -11,6 +11,7 @@ pub const fn op_string_return() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/string_owned.out b/ops/op2/test_cases/sync/string_owned.out
index c49d731..4307327 100644
--- a/ops/op2/test_cases/sync/string_owned.out
+++ b/ops/op2/test_cases/sync/string_owned.out
@@ -11,6 +11,7 @@ const fn op_string_owned() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/string_ref.out b/ops/op2/test_cases/sync/string_ref.out
index 4b0b330..6890fa2 100644
--- a/ops/op2/test_cases/sync/string_ref.out
+++ b/ops/op2/test_cases/sync/string_ref.out
@@ -11,6 +11,7 @@ const fn op_string_owned() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/string_return.out b/ops/op2/test_cases/sync/string_return.out
index da6d2b2..8b6bf4e 100644
--- a/ops/op2/test_cases/sync/string_return.out
+++ b/ops/op2/test_cases/sync/string_return.out
@@ -11,6 +11,7 @@ pub const fn op_string_return() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -107,6 +108,7 @@ pub const fn op_string_return_ref() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
@@ -203,6 +205,7 @@ pub const fn op_string_return_cow() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/to_v8.out b/ops/op2/test_cases/sync/to_v8.out
index 4c84450..d55855e 100644
--- a/ops/op2/test_cases/sync/to_v8.out
+++ b/ops/op2/test_cases/sync/to_v8.out
@@ -11,6 +11,7 @@ pub const fn op_to_v8_return() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             0usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/v8_global.out b/ops/op2/test_cases/sync/v8_global.out
index eb3b1e0..b23d06a 100644
--- a/ops/op2/test_cases/sync/v8_global.out
+++ b/ops/op2/test_cases/sync/v8_global.out
@@ -11,6 +11,7 @@ pub const fn op_global() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/v8_handlescope.out b/ops/op2/test_cases/sync/v8_handlescope.out
index ad4aa9b..1206e62 100644
--- a/ops/op2/test_cases/sync/v8_handlescope.out
+++ b/ops/op2/test_cases/sync/v8_handlescope.out
@@ -11,6 +11,7 @@ const fn op_handlescope() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/v8_lifetime.out b/ops/op2/test_cases/sync/v8_lifetime.out
index 7c5de24..05b9325 100644
--- a/ops/op2/test_cases/sync/v8_lifetime.out
+++ b/ops/op2/test_cases/sync/v8_lifetime.out
@@ -11,6 +11,7 @@ pub const fn op_v8_lifetime() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             1usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,
diff --git a/ops/op2/test_cases/sync/v8_ref_option.out b/ops/op2/test_cases/sync/v8_ref_option.out
index e98ad94..525c432 100644
--- a/ops/op2/test_cases/sync/v8_ref_option.out
+++ b/ops/op2/test_cases/sync/v8_ref_option.out
@@ -11,6 +11,7 @@ pub const fn op_v8_lifetime() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             Some({
diff --git a/ops/op2/test_cases/sync/v8_string.out b/ops/op2/test_cases/sync/v8_string.out
index 6f972e2..42ee2e2 100644
--- a/ops/op2/test_cases/sync/v8_string.out
+++ b/ops/op2/test_cases/sync/v8_string.out
@@ -11,6 +11,7 @@ const fn op_v8_string() -> ::deno_core::_ops::OpDecl {
             false,
             false,
             2usize as u8,
+            false,
             Self::v8_fn_ptr as _,
             Self::v8_fn_ptr_metrics as _,
             None,