|  | // 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, keyGen) { | 
|  | if (keyOffset === undefined) keyOffset = 0; | 
|  | if (keyGen === undefined) keyGen = (i) => { return "key" + i }; | 
|  | var o = {}; | 
|  | for (var i = 0; i < count; i++) { | 
|  | var key = keyGen(i + keyOffset); | 
|  | o[key] = "value"; | 
|  | } | 
|  | return o | 
|  | } | 
|  |  | 
|  | function ObjectWithMixedKeys(count, keyOffset) { | 
|  | return ObjectWithKeys(count, keyOffset, (key) => { | 
|  | if (key % 2 == 0) return key; | 
|  | return "key" + key; | 
|  | }); | 
|  | } | 
|  |  | 
|  | // Create an object with #depth prototypes each having #keys properties. | 
|  | function ObjectWithProtoKeys(depth, keys, cacheable) { | 
|  | var o = ObjectWithKeys(keys); | 
|  | var current = o; | 
|  | var keyOffset = 0; | 
|  | for (var i = 0; i < depth; i++) { | 
|  | keyOffset += keys; | 
|  | current.__proto__ = ObjectWithKeys(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; | 
|  | } | 
|  |  | 
|  | // ============================================================================ | 
|  | var object_empty = {}; | 
|  | var array_empty = []; | 
|  |  | 
|  | var array_int_50 = IntArray(50); | 
|  | var array_int_50_proto_elements = IntArray(50); | 
|  | array_int_50_proto_elements.__proto__ = [51, 52, 53, 54]; | 
|  | var array_int_holey_50 = HoleyIntArray(50); | 
|  |  | 
|  | var empty_proto_5_10 = ObjectWithKeys(5); | 
|  | empty_proto_5_10.__proto__ = ObjectWithProtoKeys(10, 0); | 
|  |  | 
|  | var empty_proto_5_5_slow = ObjectWithKeys(5); | 
|  | empty_proto_5_5_slow.__proto__ = ObjectWithProtoKeys(5, 0, false); | 
|  |  | 
|  | var object_elements_proto_5_10 = ObjectWithKeys(5); | 
|  | object_elements_proto_5_10.__proto__ = ObjectWithProtoKeys(10, 0); | 
|  | // Add some properties further up the prototype chain, the rest stays | 
|  | // empty. | 
|  | for (var i = 0; i < 5; i++) { | 
|  | object_elements_proto_5_10.__proto__.__proto__.__proto__["proto" + i] = true; | 
|  | } | 
|  |  | 
|  | var TestObjects = { | 
|  | object_empty: object_empty, | 
|  | array_empty: array_empty, | 
|  | array_int_50: array_int_50, | 
|  | array_int_holey_50: array_int_holey_50, | 
|  | array_int_50_proto_elements: array_int_50_proto_elements, | 
|  | empty_proto_5_10: empty_proto_5_10, | 
|  | empty_proto_5_5_slow: empty_proto_5_5_slow, | 
|  | object_elements_proto_5_10: object_elements_proto_5_10 | 
|  | } | 
|  |  | 
|  | var TestArrays = { | 
|  | array_empty: array_empty, | 
|  | array_int_50: array_int_50, | 
|  | array_int_holey_50: array_int_holey_50, | 
|  | array_int_50_proto_elements: array_int_50_proto_elements, | 
|  | } | 
|  |  | 
|  | // ============================================================================ | 
|  |  | 
|  | function CreateTestFunctionGen(fn) { | 
|  | // Force a new function for each test-object to avoid side-effects due to ICs. | 
|  | return (object) => { | 
|  | var random_comment = "\n// random comment" + Math.random() + "\n"; | 
|  | return eval(random_comment + fn.toString()); | 
|  | } | 
|  | } | 
|  |  | 
|  | var TestFunctions = { | 
|  | "Object.keys()": CreateTestFunctionGen(() => {return Object.keys(object)}), | 
|  | "for-in": CreateTestFunctionGen(() => { | 
|  | var count = 0; | 
|  | var result; | 
|  | for (var key in object) { | 
|  | count++; | 
|  | result = object[key]; | 
|  | }; | 
|  | return [result, count]; | 
|  | }), | 
|  | "for-in hasOwnProperty()": CreateTestFunctionGen(() => { | 
|  | var count = 0; | 
|  | var result; | 
|  | for (var key in object) { | 
|  | if (!object.hasOwnProperty(key)) continue; | 
|  | count++; | 
|  | result = object[key]; | 
|  | }; | 
|  | return [result, count]; | 
|  | }), | 
|  | "for (i < Object.keys().length)": CreateTestFunctionGen(() => { | 
|  | var count = 0; | 
|  | var result; | 
|  | var keys = Object.keys(object); | 
|  | for (var i = 0; i < keys.length; i++) { | 
|  | count++; | 
|  | result = object[keys[i]]; | 
|  | }; | 
|  | return [result, count]; | 
|  | }), | 
|  | "Object.keys().forEach()": CreateTestFunctionGen(() => { | 
|  | var count = 0; | 
|  | var result; | 
|  | Object.keys(object).forEach((value, index, obj) => { | 
|  | count++; | 
|  | result = value; | 
|  | }); | 
|  | return [result, count]; | 
|  | }), | 
|  | } | 
|  |  | 
|  | var TestFunctionsArrays = { | 
|  | "for (i < array.length)": CreateTestFunctionGen(() => { | 
|  | var count = 0; | 
|  | var result; | 
|  | for (var i = 0; i < object.length; i++) { | 
|  | count++; | 
|  | result = object[i]; | 
|  | }; | 
|  | return [result, count]; | 
|  | }), | 
|  | "for (i < length)": CreateTestFunctionGen(() => { | 
|  | var count = 0; | 
|  | var result; | 
|  | var length = object.length; | 
|  | for (var i = 0; i < length; i++) { | 
|  | count++; | 
|  | result = object[i]; | 
|  | }; | 
|  | return [result, count]; | 
|  | }) | 
|  | } | 
|  |  | 
|  | // ============================================================================ | 
|  | // Create the benchmark suites. We create a suite for each of the test | 
|  | // functions above and each suite contains benchmarks for each object type. | 
|  | var Benchmarks = []; | 
|  |  | 
|  | function NewBenchmark( | 
|  | test_function_gen, test_function_name, test_object, test_object_name) { | 
|  | var object = test_object; | 
|  | var name = test_function_name + " " + test_object_name; | 
|  | var test_function = test_function_gen(object); | 
|  | return new Benchmark(name, false, false, 0, test_function) | 
|  | } | 
|  |  | 
|  | for (var test_function_name in TestFunctions) { | 
|  | var test_function_gen = TestFunctions[test_function_name]; | 
|  | var benchmarks = []; | 
|  | for (var test_object_name in TestObjects) { | 
|  | var test_object = TestObjects[test_object_name]; | 
|  | var benchmark = NewBenchmark( | 
|  | test_function_gen, test_function_name, test_object, test_object_name); | 
|  | benchmarks.push(benchmark); | 
|  | } | 
|  | Benchmarks.push(new BenchmarkSuite(test_function_name, [100], benchmarks)); | 
|  | } | 
|  |  | 
|  | for (var test_function_name in TestFunctionsArrays) { | 
|  | var test_function_gen = TestFunctionsArrays[test_function_name]; | 
|  | var benchmarks = []; | 
|  | for (var test_array_name in TestArrays) { | 
|  | var test_array = TestArrays[test_array_name]; | 
|  | var benchmark = NewBenchmark( | 
|  | test_function_gen, test_function_name, test_array, test_array_name); | 
|  | benchmarks.push(benchmark); | 
|  | } | 
|  | Benchmarks.push(new BenchmarkSuite(test_function_name, [100], benchmarks)); | 
|  | } | 
|  |  | 
|  | // ============================================================================ |