v8/test/mjsunit/es6/promise-resolve-thenable-job.js
Benedikt Meurer 1f8dcc5d2e [builtins] Optimize PromiseResolveThenableJob for the common case.
The idea here is that in case the `thenable` is a JSPromise and `then`
is the initial `Promise.prototype.then` method, and the @@species lookup
chain is intact, we can skip creating the temporary promise and the
closures (with the shared context), and instead directly call into our
PerformPromiseThen. This is sound since - given above mentioned
conditions - our short-cut

  PerformPromiseThen(thenable, undefined, undefined, promise_to_resolve)

is not observably different from the actual

  resolve, reject = CreateResolvingFunctions(promise_to_resolve)
  result_capability = NewPromiseCapability(%Promise%)
  PerformPromiseThen(thenable, resolve, reject, result_capability)

except through PromiseHooks (and potentially via the async stack
traces). So we disable the fast-path if either promise hooks are enabled
or the debugger is active for now.

This improves the performance on the wikipedia benchmark by 20-25% and
the bluebird-doxbee benchmark by around 20%.

Bug: v8:7253
Change-Id: I23c92ad365c2b71d65057573f2d8febe2afe00b0
Reviewed-on: https://chromium-review.googlesource.com/911800
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51261}
2018-02-13 05:36:39 +00:00

128 lines
2.5 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.
(function() {
let resolve;
let onFulfilledValue;
const p = new Promise(r => resolve = r);
resolve(Promise.resolve(1));
p.then(
v => {
onFulfilledValue = v;
},
e => {
assertUnreachable();
});
setTimeout(_ => assertEquals(1, onFulfilledValue));
})();
(function() {
let resolve;
let onRejectedReason;
const p = new Promise(r => resolve = r);
resolve(Promise.reject(1));
p.then(
v => {
assertUnreachable();
},
e => {
onRejectedReason = e;
});
setTimeout(_ => assertEquals(1, onRejectedReason));
})();
(function() {
let onFulfilledValue;
(async () => Promise.resolve(1))().then(
v => {
onFulfilledValue = v;
},
e => {
assertUnreachable();
});
setTimeout(_ => assertEquals(1, onFulfilledValue));
})();
(function() {
let onRejectedReason;
(async () => Promise.reject(1))().then(
v => {
assertUnreachable();
},
e => {
onRejectedReason = e;
});
setTimeout(_ => assertEquals(1, onRejectedReason));
})();
(function() {
let resolve;
let onFulfilledValue;
const p = new Promise(r => resolve = r);
resolve({
then(onFulfilled, onRejected) {
onFulfilled(1);
}
});
p.then(
v => {
onFulfilledValue = v;
},
e => {
assertUnreachable();
});
setTimeout(_ => assertEquals(1, onFulfilledValue));
})();
(function() {
let resolve;
let onRejectedReason;
const p = new Promise(r => resolve = r);
resolve({
then(onFulfilled, onRejected) {
onRejected(1);
}
});
p.then(
v => {
assertUnreachable();
},
e => {
onRejectedReason = e;
});
setTimeout(_ => assertEquals(1, onRejectedReason));
})();
(function() {
let onFulfilledValue;
(async () => ({
then(onFulfilled, onRejected) {
onFulfilled(1);
}
}))().then(
v => {
onFulfilledValue = v;
},
e => {
assertUnreachable();
});
setTimeout(_ => assertEquals(1, onFulfilledValue));
})();
(function() {
let onRejectedReason;
(async () => ({
then(onFulfilled, onRejected) {
onRejected(1);
}
}))().then(
v => {
assertUnreachable();
},
e => {
onRejectedReason = e;
});
setTimeout(_ => assertEquals(1, onRejectedReason));
})();