diff --git a/test/js-perf-test/JSTests.json b/test/js-perf-test/JSTests.json index 484a8058d4..fb5d972226 100644 --- a/test/js-perf-test/JSTests.json +++ b/test/js-perf-test/JSTests.json @@ -1461,6 +1461,24 @@ "tests": [ {"name": "NumberToString"} ] + }, + { + "name": "StackTrace", + "path": ["StackTrace"], + "main": "run.js", + "flags": ["--allow-natives-syntax"], + "resources": ["capture.js", "serialize.js"], + "results_regexp": "^%s\\-StackTrace\\(Score\\): (.+)$", + "tests": [ + {"name": "Simple-Capture-Error"}, + {"name": "Custom-Capture-Error"}, + {"name": "Inline-Capture-Error"}, + {"name": "Recursive-Capture-Error"}, + {"name": "Simple-Serialize-Error.stack"}, + {"name": "Custom-Serialize-Error.stack"}, + {"name": "Inline-Serialize-Error.stack"}, + {"name": "Recursive-Serialize-Error.stack"} + ] } ] } diff --git a/test/js-perf-test/StackTrace/capture.js b/test/js-perf-test/StackTrace/capture.js new file mode 100644 index 0000000000..db2b997122 --- /dev/null +++ b/test/js-perf-test/StackTrace/capture.js @@ -0,0 +1,51 @@ +// Copyright 2019 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() { + +function Simple() { + new Error("Simple Error"); +} + +class CustomError extends Error {}; +function Custom() { + new CustomError("Custom Error"); +} + +function Inline() { + function Inner() { + new Error("Error from inlined function!"); + } + function Middle() { Inner(); } + function Outer() { Middle(); } + + Outer(); + Outer(); + %OptimizeFunctionOnNextCall(Outer); + Outer(); +} + +const kInitialRecursionValue = 10; +function Recursive() { + function StepOne(val) { + if (val <= 0) return new Error("Error in StepOne!"); + StepTwo(val - 3); + StepTwo(val - 4); + } + function StepTwo(val) { + if (val <= 0) return new Error("Error in StepTwo!"); + StepOne(val - 1); + StepOne(val - 2); + } + + StepOne(kInitialRecursionValue); +} + +createSuite('Simple-Capture-Error', 1000, Simple, () => {}); +createSuite('Custom-Capture-Error', 1000, Custom, () => {}); + +createSuite('Inline-Capture-Error', 1000, Inline, () => {}); +createSuite('Recursive-Capture-Error', 1000, Recursive, () => {}); + +})(); diff --git a/test/js-perf-test/StackTrace/run.js b/test/js-perf-test/StackTrace/run.js new file mode 100644 index 0000000000..2ceba4c5d6 --- /dev/null +++ b/test/js-perf-test/StackTrace/run.js @@ -0,0 +1,25 @@ +// Copyright 2019 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. + +load('../base.js'); + +load('serialize.js'); +load('capture.js'); + +function PrintResult(name, result) { + print(name + '-StackTrace(Score): ' + result); +} + +function PrintStep(name) {} + +function PrintError(name, error) { + PrintResult(name, error); +} + +BenchmarkSuite.config.doWarmup = undefined; +BenchmarkSuite.config.doDeterministic = undefined; + +BenchmarkSuite.RunSuites({ NotifyResult: PrintResult, + NotifyError: PrintError, + NotifyStep: PrintStep }); diff --git a/test/js-perf-test/StackTrace/serialize.js b/test/js-perf-test/StackTrace/serialize.js new file mode 100644 index 0000000000..ac87623383 --- /dev/null +++ b/test/js-perf-test/StackTrace/serialize.js @@ -0,0 +1,86 @@ +// Copyright 2019 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() { + +const kErrorCount = 100000; +let errorsCreatedBySetup; + +function CreateErrors(fn) { + counter = 0; + errorsCreatedBySetup = []; + for (let i = 0; i < kErrorCount; ++i) { + errorsCreatedBySetup[i] = fn(); + } +} + +function SimpleSetup() { + CreateErrors(() => new Error("Simple Error")); +} + +class CustomError extends Error {}; +function CustomSetup() { + CreateErrors(() => new CustomError("Custom Error")); +} + +function InlineSetup() { + function Inner() { + return new Error("Throwing from inlined function!"); + } + function Middle() { return Inner(); } + function Outer() { return Middle(); } + + Outer(); + Outer(); + %OptimizeFunctionOnNextCall(Outer); + Outer(); + + CreateErrors(() => Outer()); +} + +const kInitialRecursionValue = 12; +function RecursiveSetup() { + counter = 0; + errorsCreatedBySetup = []; + function StepOne(val) { + if (val <= 0) { + errorsCreatedBySetup.push(new Error("Error in StepOne!")); + return; + } + StepTwo(val - 3); + StepTwo(val - 4); + } + function StepTwo(val) { + if (val <= 0) { + errorsCreatedBySetup.push(new Error("Error in StepTwo!")); + return; + } + StepOne(val - 1); + StepOne(val - 2); + } + + while (errorsCreatedBySetup.length < kErrorCount) { + StepOne(kInitialRecursionValue); + } +} + +let counter; +function SerializeStack() { + if (counter < errorsCreatedBySetup.length) { + // Trigger serialization by accessing Error.stack. + %FlattenString(errorsCreatedBySetup[counter++].stack); + } else { + // The counter is reset after hitting the end, although + // Error.stack is cached at this point. + counter = 0; + } +} + +createSuite('Simple-Serialize-Error.stack', 1000, SerializeStack, SimpleSetup); +createSuite('Custom-Serialize-Error.stack', 1000, SerializeStack, CustomSetup); + +createSuite('Inline-Serialize-Error.stack', 1000, SerializeStack, InlineSetup); +createSuite('Recursive-Serialize-Error.stack', 1000, SerializeStack, RecursiveSetup); + +})();