// Copyright 2016 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 ObjectWithKeys(count, keyOffset = 0, keyGen) {
  var body = "";
  for (var i = 0; i < count; i++) {
    var key = keyGen(i + keyOffset);
    if (typeof key === "string") {
      body += `this.${key} = 0\n`;
    } else {
      body += `this[${key}] = 0\n`;
    }
  }
  var f = new Function(body);
  return new f();
}

function ObjectWithProperties(count, keyOffset) {
  return ObjectWithKeys(count, keyOffset, (key) => "key" + key );
}

function ObjectWithElements(count, keyOffset) {
  return ObjectWithKeys(count, keyOffset, (key) => key );
}

function ObjectWithMixedKeys(count, keyOffset) {
  return ObjectWithKeys(count, keyOffset, (key) => {
    if (key % 2 == 0) return (key / 2);
    return "key" + ((key - 1)  / 2);
  });
}

// Create an object with #depth prototypes each having #keys properties
// generated by given keyGen.
function ObjectWithProtoKeys(depth, keys, cacheable,
                             keyGen = ObjectWithProperties) {
  var o = keyGen(keys);
  var current = o;
  var keyOffset = 0;
  for (var i = 0; i < depth; i++) {
    keyOffset += keys;
    current.__proto__ = keyGen(keys, keyOffset);
    current = current.__proto__;
  }
  if (cacheable === false) {
    // Add an empty proxy at the prototype chain to make caching properties
    // impossible.
    current.__proto__ = new Proxy({}, {});
  }
  return o;
}


function HoleyIntArray(size) {
  var array = new Array(size);
  for (var i = 0; i < size; i += 3) {
    array[i] = i;
  }
  return array
}

function IntArray(size) {
  var array = new Array(size);
  for (var i = 0; i < size; i++) {
    array[i] = i;
  }
  return array;
}

// Switch object's properties and elements to dictionary mode.
function MakeDictionaryMode(obj) {
  obj.foo = 0;
  obj.bar = 0;
  // Delete the second-to-last property first to force normalization.
  delete obj.foo;
  delete obj.bar;
  obj[1e9] = 0;
  return obj;
}

function Internalize(s) {
  return Object.keys({[s]:0})[0];
}

function Deinternalize(s) {
  return [...s].join("");
}

// ============================================================================

const QUERY_INTERNALIZED_PROP = "INTERN-prop";
const QUERY_DEINTERNALIZED_PROP = "DEINTERN-prop";
const QUERY_NON_EXISTING_INTERNALIZED_PROP = "NE-INTERN-prop";
const QUERY_NON_EXISTING_DEINTERNALIZED_PROP = "NE-DEINTERN-prop";
const QUERY_ELEMENT = "el";
const QUERY_ELEMENT_AS_STRING = "el-str";
const QUERY_NON_EXISTING_ELEMENT = "NE-el";

const OBJ_MODE_FAST = "fast";
const OBJ_MODE_SLOW = "slow";

var TestQueries = [
  QUERY_INTERNALIZED_PROP,
  QUERY_DEINTERNALIZED_PROP,
  QUERY_NON_EXISTING_INTERNALIZED_PROP,
  QUERY_NON_EXISTING_DEINTERNALIZED_PROP,
  QUERY_ELEMENT,
  QUERY_ELEMENT_AS_STRING,
  QUERY_NON_EXISTING_ELEMENT,
];

const QUERIES_PER_OBJECT_NUMBER = 10;

// Leave only every "count"th keys.
function FilterKeys(keys, count) {
  var len = keys.length;
  if (len < count) throw new Error("Keys array is too short: " + len);
  var step = len / count;
  if (step == 0) throw new Error("Bad count specified: " + count);
  return keys.filter((element, index) => index % step == 0);
}


function MakeKeyQueries(keys, query_kind) {
  var properties = keys.filter((element) => isNaN(Number(element)));
  var elements = keys.filter((element) => !isNaN(Number(element)));

  properties = FilterKeys(properties, QUERIES_PER_OBJECT_NUMBER);
  elements = FilterKeys(elements, QUERIES_PER_OBJECT_NUMBER);

  switch (query_kind) {
    case QUERY_INTERNALIZED_PROP:
      return properties;

    case QUERY_DEINTERNALIZED_PROP:
      return properties.map(Deinternalize);

    case QUERY_NON_EXISTING_INTERNALIZED_PROP:
    case QUERY_NON_EXISTING_DEINTERNALIZED_PROP:
      var non_existing = [];
      for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
        non_existing.push("non-existing" + i);
      }
      if (query_kind == QUERY_NON_EXISTING_INTERNALIZED_PROP) {
        return non_existing.map(Internalize);
      } else {
        return non_existing.map(Deinternalize);
      }

    case QUERY_ELEMENT:
      return elements.map(Number);

    case QUERY_ELEMENT_AS_STRING:
      return elements.map(String);

    case QUERY_NON_EXISTING_ELEMENT:
      var non_existing = [];
      for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
        non_existing.push(1200 + 100*i);
      }
      return non_existing;

    default:
      throw new Error("Bad query_kind: " + query_kind);
  }
}


var TestData = [];

[true, false].forEach((cachable) => {
  [OBJ_MODE_FAST, OBJ_MODE_SLOW].forEach((obj_mode) => {
    var proto_mode = cachable ? "" : "-with-slow-proto";
    var name = `${obj_mode}-obj${proto_mode}`;
    var objects = [];
    [10, 50, 100, 200, 500].forEach((prop_count) => {
      // Create object with prop_count properties and prop_count elements.
      obj = ObjectWithProtoKeys(5, prop_count * 2, cachable,
                                ObjectWithMixedKeys);
      if (obj_mode == OBJ_MODE_SLOW) {
        obj = MakeDictionaryMode(obj);
      }
      objects.push(obj);
    });
    TestData.push({name, objects});
  });
});


// ============================================================================

function CreateTestFunction(template, object, keys) {
  // Force a new function for each test-object to avoid side-effects due to ICs.
  var text = "// random comment " + Math.random() + "\n" +
             template(object, keys);
  var func = new Function("object", "keys", text);
  return () => func(object, keys);
}

function CombineTestFunctions(tests) {
  return () => {
    for (var i = 0; i < tests.length; i++ ) {
      tests[i]();
    }
  };
}

var TestFunctions = [
  {
    name: "in",
    // Query all keys.
    keys: (object) => Object.keys(object),
    template: (object, keys) => {
      var lines = [
        `var result = true;`,
        `for (var i = 0; i < keys.length; i++) {`,
        `  var key = keys[i];`,
        `  result = (key in object) && result;`,
        `}`,
        `return result;`,
      ];
      return lines.join("\n");
    },
  },
  {
    name: "Object.hasOwnProperty",
    // Query only own keys.
    keys: (object) => Object.getOwnPropertyNames(object),
    template: (object, keys) => {
      var lines = [
        `var result = true;`,
        `for (var i = 0; i < keys.length; i++) {`,
        `  var key = keys[i];`,
        `  result = object.hasOwnProperty(key) && result;`,
        `}`,
        `return result;`,
      ];
      return lines.join("\n");
    },
  },
];


// ============================================================================
// Create the benchmark suites. We create a suite for each pair of the test
// functions above and query kind. Each suite contains benchmarks for each
// object type.
var Benchmarks = [];

for (var test_function_desc of TestFunctions) {
  var test_function_name = test_function_desc.name;

  for (var query_kind of TestQueries) {
    var benchmarks = [];
    var suit_name = test_function_name + "--" + query_kind;
    for (var test_data of TestData) {
      var name = suit_name + "--" + test_data.name;

      var tests = [];
      for (var object of test_data.objects) {
        var keys = test_function_desc.keys(object);
        keys = MakeKeyQueries(keys, query_kind);

        var test = CreateTestFunction(test_function_desc.template, object,
                                      keys);
        tests.push(test);
      }
      var run_function = CombineTestFunctions(tests);
      var benchmark = new Benchmark(name, false, false, 0, run_function);
      benchmarks.push(benchmark);
    }
    Benchmarks.push(new BenchmarkSuite(suit_name, [100], benchmarks));
  }
}

// ============================================================================
