Skip to content

Commit 048cb84

Browse files
authored
feat(ops): op2 support for u64/i64 return values (#73)
We can support u64/i64 in the return value position, though due to an unknown bug in fastcalls (unsure if it is in rusty_v8 or deno_core), we cannot make them fast yet. In anticipation that this will be fixed at some point, we start using FastCall::new_with_bigint. Using a 64-bit value requires #[bigint] to remind implementers that this is more than just a simple number and may have some performance implications.
1 parent 80c7f55 commit 048cb84

25 files changed

+317
-189
lines changed

core/runtime/ops.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,8 @@ mod tests {
609609
op_test_bool_result,
610610
op_test_float,
611611
op_test_float_result,
612+
op_test_i64,
613+
op_test_u64,
612614
op_test_string_owned,
613615
op_test_string_ref,
614616
op_test_string_cow,
@@ -979,6 +981,38 @@ mod tests {
979981
Ok(())
980982
}
981983

984+
#[op2(core)]
985+
#[bigint]
986+
pub fn op_test_u64(#[bigint] input: u64) -> u64 {
987+
input
988+
}
989+
990+
#[op2(core)]
991+
#[bigint]
992+
pub fn op_test_i64(#[bigint] input: i64) -> i64 {
993+
input
994+
}
995+
996+
#[tokio::test]
997+
pub async fn test_op_64() -> Result<(), Box<dyn std::error::Error>> {
998+
run_test2(
999+
10,
1000+
"op_test_i64",
1001+
&format!("assert(op_test_i64({}n) == {}n)", i64::MAX, i64::MAX),
1002+
)?;
1003+
run_test2(
1004+
10,
1005+
"op_test_i64",
1006+
&format!("assert(op_test_i64({}n) == {}n)", i64::MIN, i64::MIN),
1007+
)?;
1008+
run_test2(
1009+
10,
1010+
"op_test_u64",
1011+
&format!("assert(op_test_u64({}n) == {}n)", u64::MAX, u64::MAX),
1012+
)?;
1013+
Ok(())
1014+
}
1015+
9821016
#[op2(core, fast)]
9831017
pub fn op_test_string_owned(#[string] s: String) -> u32 {
9841018
s.len() as _
@@ -1338,9 +1372,9 @@ mod tests {
13381372
#[op2(core, fast)]
13391373
pub fn op_buffer_slice(
13401374
#[buffer] input: &[u8],
1341-
inlen: usize,
1375+
#[bigint] inlen: usize,
13421376
#[buffer] output: &mut [u8],
1343-
outlen: usize,
1377+
#[bigint] outlen: usize,
13441378
) {
13451379
assert_eq!(inlen, input.len());
13461380
assert_eq!(outlen, output.len());

ops/op2/README.md

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ Uint32, Int32, Number, BigInt
145145
<td>
146146

147147
```rust
148-
i64
148+
#[bigint] i64
149149
```
150150

151151
</td><td>
@@ -159,7 +159,7 @@ Uint32, Int32, Number, BigInt
159159
<td>
160160

161161
```rust
162-
u64
162+
#[bigint] u64
163163
```
164164

165165
</td><td>
@@ -173,7 +173,7 @@ Uint32, Int32, Number, BigInt
173173
<td>
174174

175175
```rust
176-
isize
176+
#[bigint] isize
177177
```
178178

179179
</td><td>
@@ -187,7 +187,7 @@ Uint32, Int32, Number, BigInt
187187
<td>
188188

189189
```rust
190-
usize
190+
#[bigint] usize
191191
```
192192

193193
</td><td>
@@ -782,6 +782,62 @@ Uint32
782782
<tr>
783783
<td>
784784

785+
```rust
786+
#[bigint] i64
787+
```
788+
789+
</td><td>
790+
791+
</td><td>
792+
BigInt
793+
</td><td>
794+
795+
</td></tr>
796+
<tr>
797+
<td>
798+
799+
```rust
800+
#[bigint] u64
801+
```
802+
803+
</td><td>
804+
805+
</td><td>
806+
BigInt
807+
</td><td>
808+
809+
</td></tr>
810+
<tr>
811+
<td>
812+
813+
```rust
814+
#[bigint] isize
815+
```
816+
817+
</td><td>
818+
819+
</td><td>
820+
BigInt
821+
</td><td>
822+
823+
</td></tr>
824+
<tr>
825+
<td>
826+
827+
```rust
828+
#[bigint] usize
829+
```
830+
831+
</td><td>
832+
833+
</td><td>
834+
BigInt
835+
</td><td>
836+
837+
</td></tr>
838+
<tr>
839+
<td>
840+
785841
```rust
786842
f32
787843
```

ops/op2/dispatch_fast.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,9 @@ pub fn generate_dispatch_fast(
258258
let fast_definition = quote! {
259259
use #deno_core::v8::fast_api::Type;
260260
use #deno_core::v8::fast_api::CType;
261-
#deno_core::v8::fast_api::FastFunction::new(
261+
// TODO(mmastrac): We're setting this up for future success but returning
262+
// u64/i64 from fastcall functions does not work. Test again in the future.
263+
#deno_core::v8::fast_api::FastFunction::new_with_bigint(
262264
&[ Type::V8Value, #( #input_types ),* ],
263265
#output_type,
264266
Self::#fast_function as *const ::std::ffi::c_void
@@ -473,10 +475,14 @@ fn map_retval_to_v8_fastcall_type(
473475
| Arg::Numeric(NumericArg::i16)
474476
| Arg::Numeric(NumericArg::i8) => V8FastCallType::I32,
475477
Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
476-
V8FastCallType::U64
478+
// TODO(mmastrac): In my testing, I was not able to get this working properly
479+
// V8FastCallType::U64
480+
return Ok(None);
477481
}
478482
Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
479-
V8FastCallType::I64
483+
// TODO(mmastrac): In my testing, I was not able to get this working properly
484+
// V8FastCallType::I64
485+
return Ok(None);
480486
}
481487
Arg::Numeric(NumericArg::f32) => V8FastCallType::F32,
482488
Arg::Numeric(NumericArg::f64) => V8FastCallType::F64,

ops/op2/dispatch_slow.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,16 @@ pub fn return_value_infallible(
525525
| Arg::Numeric(NumericArg::i32) => {
526526
quote!(#retval.set_int32(#result as i32);)
527527
}
528+
Arg::Numeric(NumericArg::i64 | NumericArg::isize) => {
529+
*needs_retval = true;
530+
*needs_scope = true;
531+
quote!(#retval.set(v8::BigInt::new_from_i64(&mut scope, #result as _).into());)
532+
}
533+
Arg::Numeric(NumericArg::u64 | NumericArg::usize) => {
534+
*needs_retval = true;
535+
*needs_scope = true;
536+
quote!(#retval.set(v8::BigInt::new_from_u64(&mut #scope, #result as _).into());)
537+
}
528538
Arg::Numeric(NumericArg::f32 | NumericArg::f64) => {
529539
quote!(#retval.set_double(#result as _);)
530540
}

0 commit comments

Comments
 (0)