be6d129207
This CL introduces new operators JSFulfillPromise and JSPromiseResolve, corresponding to the specification operations with the same name, and uses that to lower calls to Promise.resolve() builtin to JSPromiseResolve. We also optimize JSPromiseResolve and JSResolvePromise further based on information found about the value/resolution in the graph. This applies to both Promise.resolve() builtin calls and implicit resolve operations in async functions and async generators. On a very simple microbenchmark like console.time('resolve'); for (let i = 0; i < 1e8; ++i) Promise.resolve({i}); console.timeEnd('resolve'); this CL reduces the execution time from around 3049ms to around 947ms, which is a pretty significant 3x improvement. On the wikipedia benchmark we observe an improvement around 2% with this CL. Bug: v8:7253 Change-Id: Ic69086cdc1b724f35dbe83305795539c562ab817 Reviewed-on: https://chromium-review.googlesource.com/913488 Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#51387}
120 lines
3.3 KiB
JavaScript
120 lines
3.3 KiB
JavaScript
// Copyright 2018 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.
|
|
|
|
// Flags: --allow-natives-syntax
|
|
|
|
function assertFulfilledWith(expected, thenable) {
|
|
assertPromiseResult(thenable, v => assertEquals(expected, v));
|
|
}
|
|
|
|
(function() {
|
|
function foo() { return Promise.resolve(); }
|
|
assertFulfilledWith(undefined, foo());
|
|
assertFulfilledWith(undefined, foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(undefined, foo());
|
|
})();
|
|
|
|
(function() {
|
|
function foo(x) { return Promise.resolve(x); }
|
|
assertFulfilledWith(3, foo(3));
|
|
assertFulfilledWith(3, foo(3));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(3, foo(3));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(x, y) { return Promise.resolve(x, y); }
|
|
assertFulfilledWith(1, foo(1, 0));
|
|
assertFulfilledWith(2, foo(2, 1));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(3, foo(3, 2));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(x) { return Promise.resolve({x}); }
|
|
assertFulfilledWith({x:1}, foo(1));
|
|
assertFulfilledWith({x:2}, foo(2));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith({x:3}, foo(3));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(x) { return Promise.resolve(Promise.resolve(x)); }
|
|
assertFulfilledWith(null, foo(null));
|
|
assertFulfilledWith('a', foo('a'));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(42, foo(42));
|
|
})();
|
|
|
|
(function() {
|
|
const thenable = new class Thenable {
|
|
then(fulfill, reject) {
|
|
fulfill(1);
|
|
}
|
|
};
|
|
function foo() { return Promise.resolve(thenable); }
|
|
assertFulfilledWith(1, foo());
|
|
assertFulfilledWith(1, foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(1, foo());
|
|
})();
|
|
|
|
(function() {
|
|
const MyPromise = class MyPromise extends Promise {};
|
|
|
|
(function() {
|
|
function foo() { return MyPromise.resolve(); }
|
|
assertFulfilledWith(undefined, foo());
|
|
assertFulfilledWith(undefined, foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(undefined, foo());
|
|
})();
|
|
|
|
(function() {
|
|
function foo(x) { return MyPromise.resolve(x); }
|
|
assertFulfilledWith(3, foo(3));
|
|
assertFulfilledWith(3, foo(3));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(3, foo(3));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(x, y) { return MyPromise.resolve(x, y); }
|
|
assertFulfilledWith(1, foo(1, 0));
|
|
assertFulfilledWith(2, foo(2, 1));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(3, foo(3, 2));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(x) { return MyPromise.resolve({x}); }
|
|
assertFulfilledWith({x:1}, foo(1));
|
|
assertFulfilledWith({x:2}, foo(2));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith({x:3}, foo(3));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(x) { return MyPromise.resolve(Promise.resolve(x)); }
|
|
assertFulfilledWith(null, foo(null));
|
|
assertFulfilledWith('a', foo('a'));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(42, foo(42));
|
|
})();
|
|
|
|
(function() {
|
|
const thenable = new class Thenable {
|
|
then(fulfill, reject) {
|
|
fulfill(1);
|
|
}
|
|
};
|
|
function foo() { return MyPromise.resolve(thenable); }
|
|
assertFulfilledWith(1, foo());
|
|
assertFulfilledWith(1, foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFulfilledWith(1, foo());
|
|
})();
|
|
})();
|