// 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.

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();
  }
}
