// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// These micro benchmarks track the speed of native calls.

// @dart=2.9

import 'dart:ffi';
import 'dart:io';

import 'package:benchmark_harness/benchmark_harness.dart';

import 'dlopen_helper.dart';

// Number of benchmark iterations per function.
const N = 1000;

// The native library that holds all the native functions being called.
final nativeFunctionsLib = dlopenPlatformSpecific(
  'native_functions',
  path: Platform.script.resolve('../native/out/').path,
);

final getRootLibraryUrl = nativeFunctionsLib
    .lookupFunction<Handle Function(), Object Function()>('GetRootLibraryUrl');

final setNativeResolverForTest = nativeFunctionsLib
    .lookupFunction<Void Function(Handle), void Function(Object)>(
      'SetNativeResolverForTest',
    );

//
// Benchmark fixtures.
//

abstract class NativeCallBenchmarkBase extends BenchmarkBase {
  NativeCallBenchmarkBase(String name) : super(name);

  void expectEquals(actual, expected) {
    if (actual != expected) {
      throw Exception('$name: Unexpected result: $actual, expected $expected');
    }
  }

  void expectApprox(actual, expected) {
    if (0.999 * expected > actual || actual > 1.001 * expected) {
      throw Exception('$name: Unexpected result: $actual, expected $expected');
    }
  }

  void expectIdentical(actual, expected) {
    if (!identical(actual, expected)) {
      throw Exception('$name: Unexpected result: $actual, expected $expected');
    }
  }
}

class Uint8x01 extends NativeCallBenchmarkBase {
  Uint8x01() : super('NativeCall.Uint8x01');

  @pragma('vm:external-name', 'Function1Uint8')
  external static int f(int a);

  @override
  void run() {
    int x = 0;
    for (int i = 0; i < N; i++) {
      x += f(17);
    }
    expectEquals(x, N * 17 + N * 42);
  }
}

class Int64x20 extends NativeCallBenchmarkBase {
  Int64x20() : super('NativeCall.Int64x20');

  @pragma('vm:external-name', 'Function20Int64')
  external static int f(
    int a,
    int b,
    int c,
    int d,
    int e,
    int f,
    int g,
    int h,
    int i,
    int j,
    int k,
    int l,
    int m,
    int n,
    int o,
    int p,
    int q,
    int r,
    int s,
    int t,
  );

  @override
  void run() {
    int x = 0;
    for (int i = 0; i < N; i++) {
      x += f(i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i);
    }
    expectEquals(x, N * (N - 1) * 20 / 2);
  }
}

class Doublex01 extends NativeCallBenchmarkBase {
  Doublex01() : super('NativeCall.Doublex01');

  @pragma('vm:external-name', 'Function1Double')
  external static double f(double a);

  @override
  void run() {
    double x = 0.0;
    for (int i = 0; i < N; i++) {
      x += f(17.0);
    }
    final double expected = N * (17.0 + 42.0);
    expectApprox(x, expected);
  }
}

class Doublex20 extends NativeCallBenchmarkBase {
  Doublex20() : super('NativeCall.Doublex20');

  @pragma('vm:external-name', 'Function20Double')
  external static double f(
    double a,
    double b,
    double c,
    double d,
    double e,
    double f,
    double g,
    double h,
    double i,
    double j,
    double k,
    double l,
    double m,
    double n,
    double o,
    double p,
    double q,
    double r,
    double s,
    double t,
  );

  @override
  void run() {
    double x = 0;
    for (int i = 0; i < N; i++) {
      x += f(
        1.0,
        2.0,
        3.0,
        4.0,
        5.0,
        6.0,
        7.0,
        8.0,
        9.0,
        10.0,
        11.0,
        12.0,
        13.0,
        14.0,
        15.0,
        16.0,
        17.0,
        18.0,
        19.0,
        20.0,
      );
    }
    final double expected =
        N *
        (1.0 +
            2.0 +
            3.0 +
            4.0 +
            5.0 +
            6.0 +
            7.0 +
            8.0 +
            9.0 +
            10.0 +
            11.0 +
            12.0 +
            13.0 +
            14.0 +
            15.0 +
            16.0 +
            17.0 +
            18.0 +
            19.0 +
            20.0);
    expectApprox(x, expected);
  }
}

class MyClass {
  int a;
  MyClass(this.a);
}

class Handlex01 extends NativeCallBenchmarkBase {
  Handlex01() : super('NativeCall.Handlex01');

  @pragma('vm:external-name', 'Function1Handle')
  external static Object f(Object a);

  @override
  void run() {
    final p1 = MyClass(123);
    Object x = p1;
    for (int i = 0; i < N; i++) {
      x = f(x);
    }
    expectIdentical(x, p1);
  }
}

class Handlex20 extends NativeCallBenchmarkBase {
  Handlex20() : super('NativeCall.Handlex20');

  @pragma('vm:external-name', 'Function20Handle')
  external static Object f(
    Object a,
    Object b,
    Object c,
    Object d,
    Object e,
    Object f,
    Object g,
    Object h,
    Object i,
    Object j,
    Object k,
    Object l,
    Object m,
    Object n,
    Object o,
    Object p,
    Object q,
    Object r,
    Object s,
    Object t,
  );

  @override
  void run() {
    final p1 = MyClass(123);
    final p2 = MyClass(2);
    final p3 = MyClass(3);
    final p4 = MyClass(4);
    final p5 = MyClass(5);
    final p6 = MyClass(6);
    final p7 = MyClass(7);
    final p8 = MyClass(8);
    final p9 = MyClass(9);
    final p10 = MyClass(10);
    final p11 = MyClass(11);
    final p12 = MyClass(12);
    final p13 = MyClass(13);
    final p14 = MyClass(14);
    final p15 = MyClass(15);
    final p16 = MyClass(16);
    final p17 = MyClass(17);
    final p18 = MyClass(18);
    final p19 = MyClass(19);
    final p20 = MyClass(20);
    Object x = p1;
    for (int i = 0; i < N; i++) {
      x = f(
        x,
        p2,
        p3,
        p4,
        p5,
        p6,
        p7,
        p8,
        p9,
        p10,
        p11,
        p12,
        p13,
        p14,
        p15,
        p16,
        p17,
        p18,
        p19,
        p20,
      );
    }
    expectIdentical(x, p1);
  }
}

//
// Main driver.
//

void main() {
  setNativeResolverForTest(getRootLibraryUrl());

  final benchmarks = [
    () => Uint8x01(),
    () => Int64x20(),
    () => Doublex01(),
    () => Doublex20(),
    () => Handlex01(),
    () => Handlex20(),
  ];
  for (final benchmark in benchmarks) {
    benchmark().report();
  }
}
