// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

function benchy(name, test, testSetup) {
  new BenchmarkSuite(name, [1000],
      [
        new Benchmark(name, false, false, 0, test, testSetup, ()=>{})
      ]);
}

benchy('NaiveFilterReplacement', NaiveFilter, NaiveFilterSetup);
benchy('DoubleFilter', DoubleFilter, DoubleFilterSetup);
benchy('SmiFilter', SmiFilter, SmiFilterSetup);
benchy('FastFilter', FastFilter, FastFilterSetup);
benchy('ObjectFilter', GenericFilter, ObjectFilterSetup);
benchy('OptFastFilter', OptFastFilter, FastFilterSetup);

var array;
// Initialize func variable to ensure the first test doesn't benefit from
// global object property tracking.
var func = 0;
var this_arg;
var result;
var array_size = 100;

// Although these functions have the same code, they are separated for
// clean IC feedback.
function DoubleFilter() {
  result = array.filter(func, this_arg);
}
function SmiFilter() {
  result = array.filter(func, this_arg);
}
function FastFilter() {
  result = array.filter(func, this_arg);
}

// Make sure we inline the callback, pick up all possible TurboFan
// optimizations.
function RunOptFastFilter(multiple) {
  // Use of variable multiple in the callback function forces
  // context creation without escape analysis.
  //
  // Also, the arrow function requires inlining based on
  // SharedFunctionInfo.
  result = array.filter((v, i, a) => multiple === 3);
}

// Don't optimize because I want to optimize RunOptFastMap with a parameter
// to be used in the callback.
%NeverOptimizeFunction(OptFastFilter);
function OptFastFilter() { RunOptFastFilter(3); }


function GenericFilter() {
  result = Array.prototype.filter.call(array, func, this_arg);
}

// From the lodash implementation.
function NaiveFilter() {
  let index = -1
  let resIndex = 0
  const length = array == null ? 0 : array.length
  const result = []

  while (++index < length) {
    const value = array[index]
    if (func(value, index, array)) {
      result[resIndex++] = value
    }
  }
  return result
}

function NaiveFilterSetup() {
  // Prime NaiveFilter with polymorphic cases.
  array = [1, 2, 3];
  func = ()=>true;
  NaiveFilter();
  NaiveFilter();
  array = [3.4]; NaiveFilter();
  array = new Array(10); array[0] = 'hello'; NaiveFilter();
  SmiFilterSetup();
  delete array[1];
}

function SmiFilterSetup() {
  array = new Array();
  for (var i = 0; i < array_size; i++) array[i] = i;
  func = (value, index, object) => { return value % 2 === 0; };
}

function DoubleFilterSetup() {
  array = new Array();
  for (var i = 0; i < array_size; i++) array[i] = (i + 0.5);
  func = (value, index, object) => { return Math.floor(value) % 2 === 0; };
}

function FastFilterSetup() {
  array = new Array();
  for (var i = 0; i < array_size; i++) array[i] = 'value ' + i;
  func = (value, index, object) => { return index % 2 === 0; };
}

function ObjectFilterSetup() {
  array = { length: array_size };
  for (var i = 0; i < array_size; i++) {
    array[i] = i;
  }
  func = (value, index, object) => { return index % 2 === 0; };
}
