Commit 2075910f authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[turbofan] Remove optimization of default Promise capability functions.

The JSCallReducer could in theory inline the default resolve and reject
functions passed to the executor in the Promise constructor. But that
inlining is almost never triggered because we don't have SFI based feedback
in the CallIC. Also the use of the Promise constructor is discouraged,
so we shouldn't really need to squeeze the last bit of performance out
of this even in the future.

Getting rid of this optimization will make significantly easier to
implement the Swallowed Rejection Hook, as there's less churn on the
TurboFan side then.

Bug: v8:7919
Change-Id: If0c54f1c6c7ce95686cd74232be6b8693ac688c9
Reviewed-on: https://chromium-review.googlesource.com/1125926
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54210}
parent 7416d4f3
......@@ -3579,10 +3579,6 @@ Reduction JSCallReducer::ReduceJSCall(Node* node,
return ReduceAsyncFunctionPromiseCreate(node);
case Builtins::kAsyncFunctionPromiseRelease:
return ReduceAsyncFunctionPromiseRelease(node);
case Builtins::kPromiseCapabilityDefaultReject:
return ReducePromiseCapabilityDefaultReject(node);
case Builtins::kPromiseCapabilityDefaultResolve:
return ReducePromiseCapabilityDefaultResolve(node);
case Builtins::kPromiseInternalConstructor:
return ReducePromiseInternalConstructor(node);
case Builtins::kPromiseInternalReject:
......@@ -5343,120 +5339,6 @@ Reduction JSCallReducer::ReduceAsyncFunctionPromiseRelease(Node* node) {
return Replace(value);
}
// ES section #sec-promise-reject-functions
Reduction JSCallReducer::ReducePromiseCapabilityDefaultReject(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
Node* target = NodeProperties::GetValueInput(node, 0);
Node* resolution = node->op()->ValueInputCount() > 2
? NodeProperties::GetValueInput(node, 2)
: jsgraph()->UndefinedConstant();
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// We need to execute in the {target}s context.
Node* context = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
effect, control);
// Grab the promise closed over by {target}.
Node* promise = effect =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForContextSlot(
PromiseBuiltinsAssembler::kPromiseSlot)),
context, effect, control);
// Check if the {promise} is still pending or already settled.
Node* check = graph()->NewNode(simplified()->ReferenceEqual(), promise,
jsgraph()->UndefinedConstant());
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue = effect;
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
{
// Mark the {promise} as settled.
efalse = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForContextSlot(
PromiseBuiltinsAssembler::kPromiseSlot)),
context, jsgraph()->UndefinedConstant(), efalse, if_false);
// Check if we should emit a debug event.
Node* debug_event = efalse =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForContextSlot(
PromiseBuiltinsAssembler::kDebugEventSlot)),
context, efalse, if_false);
// Actually reject the {promise}.
efalse =
graph()->NewNode(javascript()->RejectPromise(), promise, resolution,
debug_event, context, frame_state, efalse, if_false);
}
control = graph()->NewNode(common()->Merge(2), if_true, if_false);
effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
Node* value = jsgraph()->UndefinedConstant();
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
// ES section #sec-promise-resolve-functions
Reduction JSCallReducer::ReducePromiseCapabilityDefaultResolve(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
Node* target = NodeProperties::GetValueInput(node, 0);
Node* resolution = node->op()->ValueInputCount() > 2
? NodeProperties::GetValueInput(node, 2)
: jsgraph()->UndefinedConstant();
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// We need to execute in the {target}s context.
Node* context = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
effect, control);
// Grab the promise closed over by {target}.
Node* promise = effect =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForContextSlot(
PromiseBuiltinsAssembler::kPromiseSlot)),
context, effect, control);
// Check if the {promise} is still pending or already settled.
Node* check = graph()->NewNode(simplified()->ReferenceEqual(), promise,
jsgraph()->UndefinedConstant());
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue = effect;
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
{
// Mark the {promise} as settled.
efalse = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForContextSlot(
PromiseBuiltinsAssembler::kPromiseSlot)),
context, jsgraph()->UndefinedConstant(), efalse, if_false);
// Actually resolve the {promise}.
efalse =
graph()->NewNode(javascript()->ResolvePromise(), promise, resolution,
context, frame_state, efalse, if_false);
}
control = graph()->NewNode(common()->Merge(2), if_true, if_false);
effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
Node* value = jsgraph()->UndefinedConstant();
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
Node* JSCallReducer::CreateArtificialFrameState(
Node* node, Node* outer_frame_state, int parameter_count,
BailoutId bailout_id, FrameStateType frame_state_type,
......
......@@ -135,8 +135,6 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Reduction ReduceAsyncFunctionPromiseCreate(Node* node);
Reduction ReduceAsyncFunctionPromiseRelease(Node* node);
Reduction ReducePromiseCapabilityDefaultReject(Node* node);
Reduction ReducePromiseCapabilityDefaultResolve(Node* node);
Reduction ReducePromiseConstructor(Node* node);
Reduction ReducePromiseInternalConstructor(Node* node);
Reduction ReducePromiseInternalReject(Node* node);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment