Skip to content

Commit

Permalink
deps: cherry-pick 2075910 from upstream V8
Browse files Browse the repository at this point in the history
Original commit message:

    [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: Jaroslav Sevcik <jarin@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#54210}

Refs: v8/v8@2075910

Backport-PR-URL: #21668
PR-URL: #21838
Refs: nodejs/promises-debugging#8
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yang Guo <yangguo@chromium.org>
Reviewed-By: Benedikt Meurer <benedikt.meurer@gmail.com>
  • Loading branch information
targos authored and rvagg committed Aug 15, 2018
1 parent 4f24256 commit afacfd2
Show file tree
Hide file tree
Showing 3 changed files with 1 addition and 121 deletions.
2 changes: 1 addition & 1 deletion common.gypi
Expand Up @@ -29,7 +29,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.8',
'v8_embedder_string': '-node.9',

# Enable disassembler for `--print-code` v8 options
'v8_enable_disassembler': 1,
Expand Down
118 changes: 0 additions & 118 deletions deps/v8/src/compiler/js-call-reducer.cc
Expand Up @@ -3551,10 +3551,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:
Expand Down Expand Up @@ -5310,120 +5306,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,
Expand Down
2 changes: 0 additions & 2 deletions deps/v8/src/compiler/js-call-reducer.h
Expand Up @@ -132,8 +132,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);
Expand Down

0 comments on commit afacfd2

Please sign in to comment.