[dart2wasm] Add more JS interop benchmarks

In prep for [1], benchmark `dartify` performance when converting JS call
return values to Dart values.

[1]: https://dart-review.googlesource.com/c/sdk/+/424021

Change-Id: I43549276f0ccdfefcc689c0574f82cad4a856aa5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/424940
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
diff --git a/benchmarks/WasmJSInterop/WasmJSInterop.dart b/benchmarks/WasmJSInterop/WasmJSInterop.dart
index 33d50cf..205a911 100644
--- a/benchmarks/WasmJSInterop/WasmJSInterop.dart
+++ b/benchmarks/WasmJSInterop/WasmJSInterop.dart
@@ -65,10 +65,213 @@
       calls;
 }
 
+@JS()
+external bool dartifyBool();
+
+@JS()
+external bool? dartifyNullableBool();
+
+@JS()
+external num dartifyNum();
+
+@JS()
+external num? dartifyNullableNum();
+
+@JS()
+external double dartifyDouble();
+
+@JS()
+external double? dartifyNullableDouble();
+
+@JS()
+external int dartifyInt();
+
+@JS()
+external int? dartifyNullableInt();
+
+@JS()
+external String dartifyString();
+
+@JS()
+external String? dartifyNullableString();
+
+@JS()
+external JSArray dartifyJSArray();
+
+@JS()
+external JSArray? dartifyNullableJSArray();
+
+// `dart:typed_data` types are all boxed the same way, so no need to test each
+// one of them separately.
+@JS()
+external JSUint8Array dartifyJSUint8Array();
+
+@JS()
+external JSUint8Array? dartifyNullableJSUint8Array();
+
+const int ITERATIONS = 10000;
+
+bool boolSink = false;
+
+double dartifyBoolBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        boolSink = dartifyBool();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+bool? nullableBoolSink = null;
+
+double dartifyNullableBoolBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        nullableBoolSink = dartifyNullableBool();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+num numSink = 1;
+
+double dartifyNumBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        numSink = dartifyNum();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+num? nullableNumSink = null;
+
+double dartifyNullableNumBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        nullableNumSink = dartifyNullableNum();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+double doubleSink = 0.0;
+
+double dartifyDoubleBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        doubleSink = dartifyDouble();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+double? nullableDoubleSink = null;
+
+double dartifyNullableDoubleBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        nullableDoubleSink = dartifyNullableDouble();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+int intSink = 0;
+
+double dartifyIntBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        intSink = dartifyInt();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+int? nullableIntSink = null;
+
+double dartifyNullableIntBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        nullableIntSink = dartifyNullableInt();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+String stringSink = "";
+
+double dartifyStringBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        stringSink = dartifyString();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+String? nullableStringSink = null;
+
+double dartifyNullableStringBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        nullableStringSink = dartifyNullableString();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+JSArray jsArraySink = JSArray();
+
+double dartifyJSArrayBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        jsArraySink = dartifyJSArray();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+JSArray? nullableJsArraySink = null;
+
+double dartifyNullableJSArrayBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        nullableJsArraySink = dartifyNullableJSArray();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+JSUint8Array jsUint8ArraySink = JSUint8Array();
+
+double dartifyJSUint8ArrayBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        jsUint8ArraySink = dartifyJSUint8Array();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
+JSUint8Array? nullableJsUint8ArraySink = null;
+
+double dartifyNullableJSUint8ArrayBenchmark() =>
+    BenchmarkBase.measureFor(() {
+      for (int i = 0; i < ITERATIONS; i += 1) {
+        nullableJsUint8ArraySink = dartifyNullableJSUint8Array();
+      }
+    }, minimumMeasureDurationMillis) /
+    ITERATIONS;
+
 void main() {
   eval('''
     self.intFun = (i) => i;
     self.doubleFun = (d) => d;
+    self.dartifyBool = () => true;
+    self.dartifyNullableBool = () => false;
+    self.dartifyNum = () => 12.34;
+    self.dartifyNullableNum = () => 56.78;
+    self.dartifyDouble = () => 10.20;
+    self.dartifyNullableDouble = () => 30.40;
+    self.dartifyInt = () => 123;
+    self.dartifyNullableInt = () => 456;
+    self.dartifyString = () => "abc";
+    self.dartifyNullableString = () => "def";
+
+    // Arrays are all empty to not add element conversion overheads to the
+    // benchmark results.
+    self.dartifyJSArray = () => new Array();
+    self.dartifyNullableJSArray = () => new Array();
+    self.dartifyJSUint8Array = () => new Uint8Array(0);
+    self.dartifyNullableJSUint8Array = () => new Uint8Array(0);
     ''');
 
   final maxI31 = (1 << 30) - 1;
@@ -84,6 +287,57 @@
   DoublePassingBenchmark(1.0, 1.0, 10).measure();
   final double = DoublePassingBenchmark(1.0, 12.34, 1000000).measure();
   report('WasmJSInterop.call.void.1ArgsDouble', double);
+
+  report('WasmJSInterop.call.bool.0Args', dartifyBoolBenchmark());
+  report(
+    'WasmJSInterop.call.nullableBool.0Args',
+    dartifyNullableBoolBenchmark(),
+  );
+  report('WasmJSInterop.call.num.0Args', dartifyNumBenchmark());
+  report('WasmJSInterop.call.nullableNum.0Args', dartifyNullableNumBenchmark());
+  report('WasmJSInterop.call.double.0Args', dartifyDoubleBenchmark());
+  report(
+    'WasmJSInterop.call.nullableDouble.0Args',
+    dartifyNullableDoubleBenchmark(),
+  );
+  report('WasmJSInterop.call.int.0Args', dartifyIntBenchmark());
+  report('WasmJSInterop.call.nullableInt.0Args', dartifyNullableIntBenchmark());
+  report('WasmJSInterop.call.string.0Args', dartifyStringBenchmark());
+  report(
+    'WasmJSInterop.call.nullableString.0Args',
+    dartifyNullableStringBenchmark(),
+  );
+  report('WasmJSInterop.call.JSArray.0Args', dartifyJSArrayBenchmark());
+  report(
+    'WasmJSInterop.call.nullableJSArray.0Args',
+    dartifyNullableJSArrayBenchmark(),
+  );
+  report(
+    'WasmJSInterop.call.JSUint8Array.0Args',
+    dartifyJSUint8ArrayBenchmark(),
+  );
+  report(
+    'WasmJSInterop.call.nullableJSUint8Array.0Args',
+    dartifyNullableJSUint8ArrayBenchmark(),
+  );
+
+  // To keep the sinks alive
+  if (int.parse('1') == 0) {
+    print(boolSink);
+    print(nullableBoolSink);
+    print(numSink);
+    print(nullableNumSink);
+    print(doubleSink);
+    print(nullableDoubleSink);
+    print(intSink);
+    print(nullableIntSink);
+    print(stringSink);
+    print(nullableStringSink);
+    print(jsArraySink);
+    print(nullableJsArraySink);
+    print(jsUint8ArraySink);
+    print(nullableJsUint8ArraySink);
+  }
 }
 
 /// Reports in Golem-specific format.