Commit 2b236e33 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[nci] Add feedback input to Call nodes

This is likely the major change of the series, as Call nodes are the
focus of call reducer (and to a lesser extent other phases like
inlining).

This CL essentially adds the new input to Call nodes, and updates the
rest of the pipeline. As a (fairly large) drive-by, I also introduce
the JSCallNode wrapper class and apply it in call reducer.

This change, although large, will hopefully make future refactorings
*much* easier, since it is now clear where certain assumptions about
Call node layout are made.

Bug: v8:8888
Change-Id: Ia15fe0ba459b6034863a5815a4e4662cee41fc83
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2264353
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68616}
parent cd16e727
...@@ -99,28 +99,28 @@ class BytecodeGraphBuilder { ...@@ -99,28 +99,28 @@ class BytecodeGraphBuilder {
Node* NewNode(const Operator* op, Node* n1) { Node* NewNode(const Operator* op, Node* n1) {
Node* buffer[] = {n1}; Node* buffer[] = {n1};
return MakeNode(op, arraysize(buffer), buffer, false); return MakeNode(op, arraysize(buffer), buffer);
} }
Node* NewNode(const Operator* op, Node* n1, Node* n2) { Node* NewNode(const Operator* op, Node* n1, Node* n2) {
Node* buffer[] = {n1, n2}; Node* buffer[] = {n1, n2};
return MakeNode(op, arraysize(buffer), buffer, false); return MakeNode(op, arraysize(buffer), buffer);
} }
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) { Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
Node* buffer[] = {n1, n2, n3}; Node* buffer[] = {n1, n2, n3};
return MakeNode(op, arraysize(buffer), buffer, false); return MakeNode(op, arraysize(buffer), buffer);
} }
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) { Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
Node* buffer[] = {n1, n2, n3, n4}; Node* buffer[] = {n1, n2, n3, n4};
return MakeNode(op, arraysize(buffer), buffer, false); return MakeNode(op, arraysize(buffer), buffer);
} }
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
Node* n5, Node* n6) { Node* n5, Node* n6) {
Node* buffer[] = {n1, n2, n3, n4, n5, n6}; Node* buffer[] = {n1, n2, n3, n4, n5, n6};
return MakeNode(op, arraysize(buffer), buffer, false); return MakeNode(op, arraysize(buffer), buffer);
} }
// Helpers to create new control nodes. // Helpers to create new control nodes.
...@@ -150,25 +150,24 @@ class BytecodeGraphBuilder { ...@@ -150,25 +150,24 @@ class BytecodeGraphBuilder {
// The main node creation chokepoint. Adds context, frame state, effect, // The main node creation chokepoint. Adds context, frame state, effect,
// and control dependencies depending on the operator. // and control dependencies depending on the operator.
Node* MakeNode(const Operator* op, int value_input_count, Node* MakeNode(const Operator* op, int value_input_count,
Node* const* value_inputs, bool incomplete); Node* const* value_inputs, bool incomplete = false);
Node** EnsureInputBufferSize(int size); Node** EnsureInputBufferSize(int size);
Node* const* GetCallArgumentsFromRegisters(Node* callee, Node* receiver, Node* const* GetCallArgumentsFromRegisters(Node* callee, Node* receiver,
interpreter::Register first_arg, interpreter::Register first_arg,
int arg_count); int arg_count);
// Same as above, but for call nodes that take a feedback vector input.
// TODO(jgruber): Merge with the above.
Node* const* GetCallArgumentsFromRegisters1(Node* callee, Node* receiver,
interpreter::Register first_arg,
int arg_count);
Node* const* ProcessCallVarArgs(ConvertReceiverMode receiver_mode, Node* const* ProcessCallVarArgs(ConvertReceiverMode receiver_mode,
Node* callee, interpreter::Register first_reg, Node* callee, interpreter::Register first_reg,
int arg_count); int arg_count);
Node* ProcessCallArguments(const Operator* call_op, Node* const* args,
int arg_count);
Node* ProcessCallArguments(const Operator* call_op, Node* callee,
interpreter::Register receiver, size_t reg_count);
Node* const* GetConstructArgumentsFromRegister( Node* const* GetConstructArgumentsFromRegister(
Node* target, Node* new_target, interpreter::Register first_arg, Node* target, Node* new_target, interpreter::Register first_arg,
int arg_count); int arg_count);
Node* ProcessConstructArguments(const Operator* op, Node* const* args,
int arg_count);
Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op, Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op,
interpreter::Register receiver, interpreter::Register receiver,
size_t reg_count); size_t reg_count);
...@@ -2296,26 +2295,27 @@ Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegisters( ...@@ -2296,26 +2295,27 @@ Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegisters(
return all; return all;
} }
Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegisters1(
Node* const* args, Node* callee, Node* receiver, interpreter::Register first_arg,
int arg_count) { int arg_count) {
return MakeNode(call_op, arg_count, args, false); const int arity = JSCallNode::ArityForArgc(arg_count);
} Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
int cursor = 0;
Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, all[cursor++] = callee;
Node* callee, all[cursor++] = receiver;
interpreter::Register receiver,
size_t reg_count) { // The function arguments are in consecutive registers.
Node* receiver_node = environment()->LookupRegister(receiver); const int arg_base = first_arg.index();
// The receiver is followed by the arguments in the consecutive registers. for (int i = 0; i < arg_count; ++i) {
DCHECK_GE(reg_count, 1); all[cursor++] =
interpreter::Register first_arg = interpreter::Register(receiver.index() + 1); environment()->LookupRegister(interpreter::Register(arg_base + i));
int arg_count = static_cast<int>(reg_count) - 1; }
all[cursor++] = feedback_vector_node();
Node* const* call_args = GetCallArgumentsFromRegisters(callee, receiver_node, DCHECK_EQ(cursor, arity);
first_arg, arg_count); return all;
return ProcessCallArguments(call_op, call_args,
kTargetAndReceiver + arg_count);
} }
void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode, void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode,
...@@ -2342,7 +2342,7 @@ void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode, ...@@ -2342,7 +2342,7 @@ void BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode,
node = lowering.value(); node = lowering.value();
} else { } else {
DCHECK(!lowering.Changed()); DCHECK(!lowering.Changed());
node = ProcessCallArguments(op, args, static_cast<int>(arg_count)); node = MakeNode(op, static_cast<int>(arg_count), args);
} }
environment()->BindAccumulator(node, Environment::kAttachFrameState); environment()->BindAccumulator(node, Environment::kAttachFrameState);
} }
...@@ -2366,8 +2366,8 @@ Node* const* BytecodeGraphBuilder::ProcessCallVarArgs( ...@@ -2366,8 +2366,8 @@ Node* const* BytecodeGraphBuilder::ProcessCallVarArgs(
first_arg = interpreter::Register(first_reg.index() + 1); first_arg = interpreter::Register(first_reg.index() + 1);
} }
Node* const* call_args = GetCallArgumentsFromRegisters(callee, receiver_node, Node* const* call_args = GetCallArgumentsFromRegisters1(callee, receiver_node,
first_arg, arg_count); first_arg, arg_count);
return call_args; return call_args;
} }
...@@ -2386,8 +2386,8 @@ void BytecodeGraphBuilder::BuildCallVarArgs(ConvertReceiverMode receiver_mode) { ...@@ -2386,8 +2386,8 @@ void BytecodeGraphBuilder::BuildCallVarArgs(ConvertReceiverMode receiver_mode) {
: static_cast<int>(reg_count) - 1; : static_cast<int>(reg_count) - 1;
Node* const* call_args = Node* const* call_args =
ProcessCallVarArgs(receiver_mode, callee, first_reg, arg_count); ProcessCallVarArgs(receiver_mode, callee, first_reg, arg_count);
BuildCall(receiver_mode, call_args, BuildCall(receiver_mode, call_args, JSCallNode::ArityForArgc(arg_count),
static_cast<size_t>(kTargetAndReceiver + arg_count), slot_id); slot_id);
} }
void BytecodeGraphBuilder::VisitCallAnyReceiver() { void BytecodeGraphBuilder::VisitCallAnyReceiver() {
...@@ -2409,7 +2409,7 @@ void BytecodeGraphBuilder::VisitCallNoFeedback() { ...@@ -2409,7 +2409,7 @@ void BytecodeGraphBuilder::VisitCallNoFeedback() {
// The receiver is the first register, followed by the arguments in the // The receiver is the first register, followed by the arguments in the
// consecutive registers. // consecutive registers.
int arg_count = static_cast<int>(reg_count) - 1; int arg_count = static_cast<int>(reg_count) - 1;
int arity = kTargetAndReceiver + arg_count; int arity = JSCallNode::ArityForArgc(arg_count);
// Setting call frequency to a value less than min_inlining frequency to // Setting call frequency to a value less than min_inlining frequency to
// prevent inlining of one-shot call node. // prevent inlining of one-shot call node.
...@@ -2418,7 +2418,7 @@ void BytecodeGraphBuilder::VisitCallNoFeedback() { ...@@ -2418,7 +2418,7 @@ void BytecodeGraphBuilder::VisitCallNoFeedback() {
arity, CallFrequency(CallFrequency::kNoFeedbackCallFrequency)); arity, CallFrequency(CallFrequency::kNoFeedbackCallFrequency));
Node* const* call_args = ProcessCallVarArgs(ConvertReceiverMode::kAny, callee, Node* const* call_args = ProcessCallVarArgs(ConvertReceiverMode::kAny, callee,
first_reg, arg_count); first_reg, arg_count);
Node* value = ProcessCallArguments(call, call_args, arity); Node* value = MakeNode(call, arity, call_args);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
} }
...@@ -2432,8 +2432,8 @@ void BytecodeGraphBuilder::VisitCallProperty0() { ...@@ -2432,8 +2432,8 @@ void BytecodeGraphBuilder::VisitCallProperty0() {
Node* receiver = Node* receiver =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
int const slot_id = bytecode_iterator().GetIndexOperand(2); int const slot_id = bytecode_iterator().GetIndexOperand(2);
BuildCall(ConvertReceiverMode::kNotNullOrUndefined, {callee, receiver}, BuildCall(ConvertReceiverMode::kNotNullOrUndefined,
slot_id); {callee, receiver, feedback_vector_node()}, slot_id);
} }
void BytecodeGraphBuilder::VisitCallProperty1() { void BytecodeGraphBuilder::VisitCallProperty1() {
...@@ -2444,8 +2444,8 @@ void BytecodeGraphBuilder::VisitCallProperty1() { ...@@ -2444,8 +2444,8 @@ void BytecodeGraphBuilder::VisitCallProperty1() {
Node* arg0 = Node* arg0 =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
int const slot_id = bytecode_iterator().GetIndexOperand(3); int const slot_id = bytecode_iterator().GetIndexOperand(3);
BuildCall(ConvertReceiverMode::kNotNullOrUndefined, {callee, receiver, arg0}, BuildCall(ConvertReceiverMode::kNotNullOrUndefined,
slot_id); {callee, receiver, arg0, feedback_vector_node()}, slot_id);
} }
void BytecodeGraphBuilder::VisitCallProperty2() { void BytecodeGraphBuilder::VisitCallProperty2() {
...@@ -2459,7 +2459,7 @@ void BytecodeGraphBuilder::VisitCallProperty2() { ...@@ -2459,7 +2459,7 @@ void BytecodeGraphBuilder::VisitCallProperty2() {
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3));
int const slot_id = bytecode_iterator().GetIndexOperand(4); int const slot_id = bytecode_iterator().GetIndexOperand(4);
BuildCall(ConvertReceiverMode::kNotNullOrUndefined, BuildCall(ConvertReceiverMode::kNotNullOrUndefined,
{callee, receiver, arg0, arg1}, slot_id); {callee, receiver, arg0, arg1, feedback_vector_node()}, slot_id);
} }
void BytecodeGraphBuilder::VisitCallUndefinedReceiver() { void BytecodeGraphBuilder::VisitCallUndefinedReceiver() {
...@@ -2471,7 +2471,8 @@ void BytecodeGraphBuilder::VisitCallUndefinedReceiver0() { ...@@ -2471,7 +2471,8 @@ void BytecodeGraphBuilder::VisitCallUndefinedReceiver0() {
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* receiver = jsgraph()->UndefinedConstant(); Node* receiver = jsgraph()->UndefinedConstant();
int const slot_id = bytecode_iterator().GetIndexOperand(1); int const slot_id = bytecode_iterator().GetIndexOperand(1);
BuildCall(ConvertReceiverMode::kNullOrUndefined, {callee, receiver}, slot_id); BuildCall(ConvertReceiverMode::kNullOrUndefined,
{callee, receiver, feedback_vector_node()}, slot_id);
} }
void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() { void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() {
...@@ -2481,8 +2482,8 @@ void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() { ...@@ -2481,8 +2482,8 @@ void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() {
Node* arg0 = Node* arg0 =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
int const slot_id = bytecode_iterator().GetIndexOperand(2); int const slot_id = bytecode_iterator().GetIndexOperand(2);
BuildCall(ConvertReceiverMode::kNullOrUndefined, {callee, receiver, arg0}, BuildCall(ConvertReceiverMode::kNullOrUndefined,
slot_id); {callee, receiver, arg0, feedback_vector_node()}, slot_id);
} }
void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() { void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() {
...@@ -2495,7 +2496,7 @@ void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() { ...@@ -2495,7 +2496,7 @@ void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() {
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
int const slot_id = bytecode_iterator().GetIndexOperand(3); int const slot_id = bytecode_iterator().GetIndexOperand(3);
BuildCall(ConvertReceiverMode::kNullOrUndefined, BuildCall(ConvertReceiverMode::kNullOrUndefined,
{callee, receiver, arg0, arg1}, slot_id); {callee, receiver, arg0, arg1, feedback_vector_node()}, slot_id);
} }
void BytecodeGraphBuilder::VisitCallWithSpread() { void BytecodeGraphBuilder::VisitCallWithSpread() {
...@@ -2525,7 +2526,7 @@ void BytecodeGraphBuilder::VisitCallWithSpread() { ...@@ -2525,7 +2526,7 @@ void BytecodeGraphBuilder::VisitCallWithSpread() {
node = lowering.value(); node = lowering.value();
} else { } else {
DCHECK(!lowering.Changed()); DCHECK(!lowering.Changed());
node = ProcessCallArguments(op, args, kTargetAndReceiver + arg_count); node = MakeNode(op, kTargetAndReceiver + arg_count, args);
} }
environment()->BindAccumulator(node, Environment::kAttachFrameState); environment()->BindAccumulator(node, Environment::kAttachFrameState);
} }
...@@ -2537,12 +2538,12 @@ void BytecodeGraphBuilder::VisitCallJSRuntime() { ...@@ -2537,12 +2538,12 @@ void BytecodeGraphBuilder::VisitCallJSRuntime() {
interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
int arg_count = static_cast<int>(reg_count); int arg_count = static_cast<int>(reg_count);
int arity = JSCallNode::ArityForArgc(arg_count);
const Operator* call = javascript()->Call(kTargetAndReceiver + arg_count); const Operator* call = javascript()->Call(arity);
Node* const* call_args = ProcessCallVarArgs( Node* const* call_args = ProcessCallVarArgs(
ConvertReceiverMode::kNullOrUndefined, callee, first_reg, arg_count); ConvertReceiverMode::kNullOrUndefined, callee, first_reg, arg_count);
Node* value = Node* value = MakeNode(call, arity, call_args);
ProcessCallArguments(call, call_args, kTargetAndReceiver + arg_count);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
} }
...@@ -2558,7 +2559,7 @@ Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( ...@@ -2558,7 +2559,7 @@ Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
all[i] = environment()->LookupRegister( all[i] = environment()->LookupRegister(
interpreter::Register(first_arg_index + i)); interpreter::Register(first_arg_index + i));
} }
Node* value = MakeNode(call_runtime_op, arity, all, false); Node* value = MakeNode(call_runtime_op, arity, all);
return value; return value;
} }
...@@ -2611,12 +2612,6 @@ Node* const* BytecodeGraphBuilder::GetConstructArgumentsFromRegister( ...@@ -2611,12 +2612,6 @@ Node* const* BytecodeGraphBuilder::GetConstructArgumentsFromRegister(
return all; return all;
} }
Node* BytecodeGraphBuilder::ProcessConstructArguments(const Operator* op,
Node* const* args,
int arg_count) {
return MakeNode(op, arg_count, args, false);
}
void BytecodeGraphBuilder::VisitConstruct() { void BytecodeGraphBuilder::VisitConstruct() {
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
...@@ -2644,7 +2639,7 @@ void BytecodeGraphBuilder::VisitConstruct() { ...@@ -2644,7 +2639,7 @@ void BytecodeGraphBuilder::VisitConstruct() {
node = lowering.value(); node = lowering.value();
} else { } else {
DCHECK(!lowering.Changed()); DCHECK(!lowering.Changed());
node = ProcessConstructArguments(op, args, arg_count_with_extra_args); node = MakeNode(op, arg_count_with_extra_args, args);
} }
environment()->BindAccumulator(node, Environment::kAttachFrameState); environment()->BindAccumulator(node, Environment::kAttachFrameState);
} }
...@@ -2676,7 +2671,7 @@ void BytecodeGraphBuilder::VisitConstructWithSpread() { ...@@ -2676,7 +2671,7 @@ void BytecodeGraphBuilder::VisitConstructWithSpread() {
node = lowering.value(); node = lowering.value();
} else { } else {
DCHECK(!lowering.Changed()); DCHECK(!lowering.Changed());
node = ProcessConstructArguments(op, args, arg_count_with_extra_args); node = MakeNode(op, arg_count_with_extra_args, args);
} }
environment()->BindAccumulator(node, Environment::kAttachFrameState); environment()->BindAccumulator(node, Environment::kAttachFrameState);
} }
......
...@@ -71,7 +71,14 @@ class JSCallReducerAssembler : public JSGraphAssembler { ...@@ -71,7 +71,14 @@ class JSCallReducerAssembler : public JSGraphAssembler {
TNode<String> ReduceStringPrototypeSubstring(); TNode<String> ReduceStringPrototypeSubstring();
TNode<String> ReduceStringPrototypeSlice(); TNode<String> ReduceStringPrototypeSlice();
TNode<Object> TargetInput() const { return ValueInput(0); } TNode<Object> TargetInput() const { return JSCallNode{node_ptr()}.target(); }
template <typename T>
TNode<T> ReceiverInputAs() const {
return TNode<T>::UncheckedCast(JSCallNode{node_ptr()}.receiver());
}
TNode<Object> ReceiverInput() const { return ReceiverInputAs<Object>(); }
CatchScope* catch_scope() const { return catch_scope_; } CatchScope* catch_scope() const { return catch_scope_; }
Node* outermost_handler() const { return outermost_handler_; } Node* outermost_handler() const { return outermost_handler_; }
...@@ -270,8 +277,8 @@ class JSCallReducerAssembler : public JSGraphAssembler { ...@@ -270,8 +277,8 @@ class JSCallReducerAssembler : public JSGraphAssembler {
// TODO(jgruber): Implement MapInference::InsertMapChecks in graph // TODO(jgruber): Implement MapInference::InsertMapChecks in graph
// assembler. // assembler.
if (!has_stability_dependency) { if (!has_stability_dependency) {
Node* e = effect(); Effect e = effect();
inference->InsertMapChecks(jsgraph(), &e, control(), feedback()); inference->InsertMapChecks(jsgraph(), &e, Control{control()}, feedback());
InitializeEffectControl(e, control()); InitializeEffectControl(e, control());
} }
} }
...@@ -595,34 +602,30 @@ class JSCallReducerAssembler : public JSGraphAssembler { ...@@ -595,34 +602,30 @@ class JSCallReducerAssembler : public JSGraphAssembler {
return p.feedback(); return p.feedback();
} }
int ValueInputCount() const { return node_ptr()->op()->ValueInputCount(); } int ArgumentCount() const { return JSCallNode{node_ptr()}.ArgumentCount(); }
TNode<Object> ValueInput(int index) const { TNode<Object> Argument(int index) const {
return TNode<Object>::UncheckedCast( return TNode<Object>::UncheckedCast(JSCallNode{node_ptr()}.Argument(index));
NodeProperties::GetValueInput(node_, index));
} }
template <typename T> template <typename T>
TNode<T> ValueInputAs(int index) const { TNode<T> ArgumentAs(int index) const {
return TNode<T>::UncheckedCast(ValueInput(index)); return TNode<T>::UncheckedCast(Argument(index));
} }
TNode<Object> ValueInputOrNaN(int index) { TNode<Object> ArgumentOrNaN(int index) {
return TNode<Object>::UncheckedCast( return TNode<Object>::UncheckedCast(
ValueInputCount() > index ? NodeProperties::GetValueInput(node_, index) ArgumentCount() > index ? Argument(index) : NaNConstant());
: NaNConstant());
} }
TNode<Object> ValueInputOrUndefined(int index) { TNode<Object> ArgumentOrUndefined(int index) {
return TNode<Object>::UncheckedCast( return TNode<Object>::UncheckedCast(
ValueInputCount() > index ? NodeProperties::GetValueInput(node_, index) ArgumentCount() > index ? Argument(index) : UndefinedConstant());
: UndefinedConstant());
} }
TNode<Number> ValueInputOrZero(int index) { TNode<Number> ArgumentOrZero(int index) {
return TNode<Number>::UncheckedCast( return TNode<Number>::UncheckedCast(
ValueInputCount() > index ? NodeProperties::GetValueInput(node_, index) ArgumentCount() > index ? Argument(index) : ZeroConstant());
: ZeroConstant());
} }
TNode<Context> ContextInput() const { TNode<Context> ContextInput() const {
...@@ -795,6 +798,11 @@ class PromiseBuiltinReducerAssembler : public JSCallReducerAssembler { ...@@ -795,6 +798,11 @@ class PromiseBuiltinReducerAssembler : public JSCallReducerAssembler {
return p.arity_without_implicit_args(); return p.arity_without_implicit_args();
} }
TNode<Object> TargetInput() const {
return TNode<Object>::UncheckedCast(
NodeProperties::GetValueInput(node_ptr(), 0));
}
TNode<Object> NewTargetInput() const { TNode<Object> NewTargetInput() const {
// new_target is the last input (after target and all other args). // new_target is the last input (after target and all other args).
static constexpr int kTarget = 1; static constexpr int kTarget = 1;
...@@ -839,13 +847,14 @@ class PromiseBuiltinReducerAssembler : public JSCallReducerAssembler { ...@@ -839,13 +847,14 @@ class PromiseBuiltinReducerAssembler : public JSCallReducerAssembler {
TNode<JSFunction> reject, FrameState frame_state) { TNode<JSFunction> reject, FrameState frame_state) {
const ConstructParameters& p = ConstructParametersOf(node_ptr()->op()); const ConstructParameters& p = ConstructParametersOf(node_ptr()->op());
FeedbackSource no_feedback_source{}; FeedbackSource no_feedback_source{};
Node* feedback = UndefinedConstant();
MayThrow(_ { MayThrow(_ {
return AddNode<Object>(graph()->NewNode( return AddNode<Object>(graph()->NewNode(
javascript()->Call(2 + kTargetAndReceiver, p.frequency(), javascript()->Call(JSCallNode::ArityForArgc(2), p.frequency(),
no_feedback_source, no_feedback_source,
ConvertReceiverMode::kNullOrUndefined), ConvertReceiverMode::kNullOrUndefined),
executor, UndefinedConstant(), resolve, reject, ContextInput(), executor, UndefinedConstant(), resolve, reject, feedback,
frame_state, effect(), control())); ContextInput(), frame_state, effect(), control()));
}); });
} }
...@@ -853,13 +862,14 @@ class PromiseBuiltinReducerAssembler : public JSCallReducerAssembler { ...@@ -853,13 +862,14 @@ class PromiseBuiltinReducerAssembler : public JSCallReducerAssembler {
FrameState frame_state) { FrameState frame_state) {
const ConstructParameters& p = ConstructParametersOf(node_ptr()->op()); const ConstructParameters& p = ConstructParametersOf(node_ptr()->op());
FeedbackSource no_feedback_source{}; FeedbackSource no_feedback_source{};
Node* feedback = UndefinedConstant();
MayThrow(_ { MayThrow(_ {
return AddNode<Object>(graph()->NewNode( return AddNode<Object>(graph()->NewNode(
javascript()->Call(1 + kTargetAndReceiver, p.frequency(), javascript()->Call(JSCallNode::ArityForArgc(1), p.frequency(),
no_feedback_source, no_feedback_source,
ConvertReceiverMode::kNullOrUndefined), ConvertReceiverMode::kNullOrUndefined),
reject, UndefinedConstant(), exception, ContextInput(), frame_state, reject, UndefinedConstant(), exception, feedback, ContextInput(),
effect(), control())); frame_state, effect(), control()));
}); });
} }
...@@ -887,11 +897,17 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler { ...@@ -887,11 +897,17 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
inputs.emplace_back(function_node); inputs.emplace_back(function_node);
int wrapper_object_index = isolate()->embedder_wrapper_object_index(); int wrapper_object_index = isolate()->embedder_wrapper_object_index();
CHECK_GE(wrapper_object_index, 0); CHECK_GE(wrapper_object_index, 0);
const int value_input_count_without_vector =
node_ptr()->op()->ValueInputCount() -
JSCallNode::kFeedbackVectorInputCount;
for (int i = 0; i < c_arg_count; ++i) { for (int i = 0; i < c_arg_count; ++i) {
if (i + kFunctionArgCount < ValueInputCount()) { if (i + kFunctionArgCount < value_input_count_without_vector) {
inputs.emplace_back(ConvertArgumentIfJSWrapper( inputs.emplace_back(ConvertArgumentIfJSWrapper(
c_signature_->ArgumentInfo(i).GetType(), c_signature_->ArgumentInfo(i).GetType(),
ValueInput(i + kFunctionArgCount), wrapper_object_index)); NodeProperties::GetValueInput(node_ptr(), i + kFunctionArgCount),
wrapper_object_index));
} else { } else {
inputs.emplace_back(UndefinedConstant()); inputs.emplace_back(UndefinedConstant());
} }
...@@ -930,7 +946,7 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler { ...@@ -930,7 +946,7 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
return load; return load;
} }
Node* ConvertArgumentIfJSWrapper(CTypeInfo::Type type, TNode<Object> node, Node* ConvertArgumentIfJSWrapper(CTypeInfo::Type type, Node* node,
int wrapper_object_index) { int wrapper_object_index) {
switch (type) { switch (type) {
case CTypeInfo::Type::kUnwrappedApiObject: case CTypeInfo::Type::kUnwrappedApiObject:
...@@ -1006,14 +1022,16 @@ TNode<Object> JSCallReducerAssembler::Call4( ...@@ -1006,14 +1022,16 @@ TNode<Object> JSCallReducerAssembler::Call4(
TNode<Object> JSCallReducerAssembler::JSCall3( TNode<Object> JSCallReducerAssembler::JSCall3(
TNode<Object> function, TNode<Object> this_arg, TNode<Object> arg0, TNode<Object> function, TNode<Object> this_arg, TNode<Object> arg0,
TNode<Object> arg1, TNode<Object> arg2, FrameState frame_state) { TNode<Object> arg1, TNode<Object> arg2, FrameState frame_state) {
CallParameters const& p = CallParametersOf(node_ptr()->op()); JSCallNode n(node_ptr());
CallParameters const& p = n.Parameters();
return MayThrow(_ { return MayThrow(_ {
return AddNode<Object>(graph()->NewNode( return AddNode<Object>(graph()->NewNode(
javascript()->Call(3 + kTargetAndReceiver, p.frequency(), p.feedback(), javascript()->Call(JSCallNode::ArityForArgc(3), p.frequency(),
ConvertReceiverMode::kAny, p.speculation_mode(), p.feedback(), ConvertReceiverMode::kAny,
p.speculation_mode(),
CallFeedbackRelation::kUnrelated), CallFeedbackRelation::kUnrelated),
function, this_arg, arg0, arg1, arg2, ContextInput(), frame_state, function, this_arg, arg0, arg1, arg2, n.feedback_vector(),
effect(), control())); ContextInput(), frame_state, effect(), control()));
}); });
} }
...@@ -1021,14 +1039,16 @@ TNode<Object> JSCallReducerAssembler::JSCall4( ...@@ -1021,14 +1039,16 @@ TNode<Object> JSCallReducerAssembler::JSCall4(
TNode<Object> function, TNode<Object> this_arg, TNode<Object> arg0, TNode<Object> function, TNode<Object> this_arg, TNode<Object> arg0,
TNode<Object> arg1, TNode<Object> arg2, TNode<Object> arg3, TNode<Object> arg1, TNode<Object> arg2, TNode<Object> arg3,
FrameState frame_state) { FrameState frame_state) {
CallParameters const& p = CallParametersOf(node_ptr()->op()); JSCallNode n(node_ptr());
CallParameters const& p = n.Parameters();
return MayThrow(_ { return MayThrow(_ {
return AddNode<Object>(graph()->NewNode( return AddNode<Object>(graph()->NewNode(
javascript()->Call(4 + kTargetAndReceiver, p.frequency(), p.feedback(), javascript()->Call(JSCallNode::ArityForArgc(4), p.frequency(),
ConvertReceiverMode::kAny, p.speculation_mode(), p.feedback(), ConvertReceiverMode::kAny,
p.speculation_mode(),
CallFeedbackRelation::kUnrelated), CallFeedbackRelation::kUnrelated),
function, this_arg, arg0, arg1, arg2, arg3, ContextInput(), frame_state, function, this_arg, arg0, arg1, arg2, arg3, n.feedback_vector(),
effect(), control())); ContextInput(), frame_state, effect(), control()));
}); });
} }
...@@ -1072,14 +1092,14 @@ TNode<JSArray> JSCallReducerAssembler::AllocateEmptyJSArray( ...@@ -1072,14 +1092,14 @@ TNode<JSArray> JSCallReducerAssembler::AllocateEmptyJSArray(
} }
TNode<Object> JSCallReducerAssembler::ReduceMathUnary(const Operator* op) { TNode<Object> JSCallReducerAssembler::ReduceMathUnary(const Operator* op) {
TNode<Object> input = ValueInput(2); TNode<Object> input = Argument(0);
TNode<Number> input_as_number = SpeculativeToNumber(input); TNode<Number> input_as_number = SpeculativeToNumber(input);
return TNode<Object>::UncheckedCast(graph()->NewNode(op, input_as_number)); return TNode<Object>::UncheckedCast(graph()->NewNode(op, input_as_number));
} }
TNode<Object> JSCallReducerAssembler::ReduceMathBinary(const Operator* op) { TNode<Object> JSCallReducerAssembler::ReduceMathBinary(const Operator* op) {
TNode<Object> left = ValueInput(2); TNode<Object> left = Argument(0);
TNode<Object> right = ValueInputOrNaN(3); TNode<Object> right = ArgumentOrNaN(1);
TNode<Number> left_number = SpeculativeToNumber(left); TNode<Number> left_number = SpeculativeToNumber(left);
TNode<Number> right_number = SpeculativeToNumber(right); TNode<Number> right_number = SpeculativeToNumber(right);
return TNode<Object>::UncheckedCast( return TNode<Object>::UncheckedCast(
...@@ -1087,9 +1107,9 @@ TNode<Object> JSCallReducerAssembler::ReduceMathBinary(const Operator* op) { ...@@ -1087,9 +1107,9 @@ TNode<Object> JSCallReducerAssembler::ReduceMathBinary(const Operator* op) {
} }
TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSubstring() { TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSubstring() {
TNode<Object> receiver = ValueInput(1); TNode<Object> receiver = ReceiverInput();
TNode<Object> start = ValueInput(2); TNode<Object> start = Argument(0);
TNode<Object> end = ValueInputOrUndefined(3); TNode<Object> end = ArgumentOrUndefined(1);
TNode<String> receiver_string = CheckString(receiver); TNode<String> receiver_string = CheckString(receiver);
TNode<Number> start_smi = CheckSmi(start); TNode<Number> start_smi = CheckSmi(start);
...@@ -1112,9 +1132,9 @@ TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSubstring() { ...@@ -1112,9 +1132,9 @@ TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSubstring() {
} }
TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSlice() { TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSlice() {
TNode<Object> receiver = ValueInput(1); TNode<Object> receiver = ReceiverInput();
TNode<Object> start = ValueInput(2); TNode<Object> start = Argument(0);
TNode<Object> end = ValueInputOrUndefined(3); TNode<Object> end = ArgumentOrUndefined(1);
TNode<String> receiver_string = CheckString(receiver); TNode<String> receiver_string = CheckString(receiver);
TNode<Number> start_smi = CheckSmi(start); TNode<Number> start_smi = CheckSmi(start);
...@@ -1200,9 +1220,9 @@ IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeForEach( ...@@ -1200,9 +1220,9 @@ IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeForEach(
FrameState outer_frame_state = FrameStateInput(); FrameState outer_frame_state = FrameStateInput();
TNode<Context> context = ContextInput(); TNode<Context> context = ContextInput();
TNode<Object> target = TargetInput(); TNode<Object> target = TargetInput();
TNode<JSArray> receiver = ValueInputAs<JSArray>(1); TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
TNode<Object> fncallback = ValueInputOrUndefined(2); TNode<Object> fncallback = ArgumentOrUndefined(0);
TNode<Object> this_arg = ValueInputOrUndefined(3); TNode<Object> this_arg = ArgumentOrUndefined(1);
TNode<Number> original_length = LoadJSArrayLength(receiver, kind); TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
...@@ -1318,8 +1338,8 @@ TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeReduce( ...@@ -1318,8 +1338,8 @@ TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeReduce(
FrameState outer_frame_state = FrameStateInput(); FrameState outer_frame_state = FrameStateInput();
TNode<Context> context = ContextInput(); TNode<Context> context = ContextInput();
TNode<Object> target = TargetInput(); TNode<Object> target = TargetInput();
TNode<JSArray> receiver = ValueInputAs<JSArray>(1); TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
TNode<Object> fncallback = ValueInputOrUndefined(2); TNode<Object> fncallback = ArgumentOrUndefined(0);
ReduceFrameStateParams frame_state_params{ ReduceFrameStateParams frame_state_params{
jsgraph(), shared, direction, context, target, outer_frame_state}; jsgraph(), shared, direction, context, target, outer_frame_state};
...@@ -1348,8 +1368,8 @@ TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeReduce( ...@@ -1348,8 +1368,8 @@ TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeReduce(
// Set initial accumulator value. // Set initial accumulator value.
TNode<Object> accumulator; TNode<Object> accumulator;
if (node_ptr()->op()->ValueInputCount() > 3) { if (ArgumentCount() > 1) {
accumulator = ValueInput(3); // Initial value specified by the user. accumulator = Argument(1); // Initial value specified by the user.
} else { } else {
// The initial value was not specified by the user. In this case, the first // The initial value was not specified by the user. In this case, the first
// (or last in the case of reduceRight) non-holey value of the array is // (or last in the case of reduceRight) non-holey value of the array is
...@@ -1463,9 +1483,9 @@ TNode<JSArray> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeMap( ...@@ -1463,9 +1483,9 @@ TNode<JSArray> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeMap(
FrameState outer_frame_state = FrameStateInput(); FrameState outer_frame_state = FrameStateInput();
TNode<Context> context = ContextInput(); TNode<Context> context = ContextInput();
TNode<Object> target = TargetInput(); TNode<Object> target = TargetInput();
TNode<JSArray> receiver = ValueInputAs<JSArray>(1); TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
TNode<Object> fncallback = ValueInputOrUndefined(2); TNode<Object> fncallback = ArgumentOrUndefined(0);
TNode<Object> this_arg = ValueInputOrUndefined(3); TNode<Object> this_arg = ArgumentOrUndefined(1);
TNode<Number> original_length = LoadJSArrayLength(receiver, kind); TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
...@@ -1599,9 +1619,9 @@ IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeFilter( ...@@ -1599,9 +1619,9 @@ IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeFilter(
FrameState outer_frame_state = FrameStateInput(); FrameState outer_frame_state = FrameStateInput();
TNode<Context> context = ContextInput(); TNode<Context> context = ContextInput();
TNode<Object> target = TargetInput(); TNode<Object> target = TargetInput();
TNode<JSArray> receiver = ValueInputAs<JSArray>(1); TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
TNode<Object> fncallback = ValueInputOrUndefined(2); TNode<Object> fncallback = ArgumentOrUndefined(0);
TNode<Object> this_arg = ValueInputOrUndefined(3); TNode<Object> this_arg = ArgumentOrUndefined(1);
// The output array is packed (filter doesn't visit holes). // The output array is packed (filter doesn't visit holes).
const ElementsKind packed_kind = GetPackedElementsKind(kind); const ElementsKind packed_kind = GetPackedElementsKind(kind);
...@@ -1737,9 +1757,9 @@ TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeFind( ...@@ -1737,9 +1757,9 @@ TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeFind(
FrameState outer_frame_state = FrameStateInput(); FrameState outer_frame_state = FrameStateInput();
TNode<Context> context = ContextInput(); TNode<Context> context = ContextInput();
TNode<Object> target = TargetInput(); TNode<Object> target = TargetInput();
TNode<JSArray> receiver = ValueInputAs<JSArray>(1); TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
TNode<Object> fncallback = ValueInputOrUndefined(2); TNode<Object> fncallback = ArgumentOrUndefined(0);
TNode<Object> this_arg = ValueInputOrUndefined(3); TNode<Object> this_arg = ArgumentOrUndefined(1);
TNode<Number> original_length = LoadJSArrayLength(receiver, kind); TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
...@@ -1839,9 +1859,9 @@ IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeEverySome( ...@@ -1839,9 +1859,9 @@ IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeEverySome(
FrameState outer_frame_state = FrameStateInput(); FrameState outer_frame_state = FrameStateInput();
TNode<Context> context = ContextInput(); TNode<Context> context = ContextInput();
TNode<Object> target = TargetInput(); TNode<Object> target = TargetInput();
TNode<JSArray> receiver = ValueInputAs<JSArray>(1); TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
TNode<Object> fncallback = ValueInputOrUndefined(2); TNode<Object> fncallback = ArgumentOrUndefined(0);
TNode<Object> this_arg = ValueInputOrUndefined(3); TNode<Object> this_arg = ArgumentOrUndefined(1);
TNode<Number> original_length = LoadJSArrayLength(receiver, kind); TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
...@@ -1934,9 +1954,9 @@ TNode<Object> ...@@ -1934,9 +1954,9 @@ TNode<Object>
IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeIndexOfIncludes( IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeIndexOfIncludes(
ElementsKind kind, ArrayIndexOfIncludesVariant variant) { ElementsKind kind, ArrayIndexOfIncludesVariant variant) {
TNode<Context> context = ContextInput(); TNode<Context> context = ContextInput();
TNode<JSArray> receiver = ValueInputAs<JSArray>(1); TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
TNode<Object> search_element = ValueInputOrUndefined(2); TNode<Object> search_element = ArgumentOrUndefined(0);
TNode<Object> from_index = ValueInputOrZero(3); TNode<Object> from_index = ArgumentOrZero(1);
// TODO(jgruber): This currently only reduces to a stub call. Create a full // TODO(jgruber): This currently only reduces to a stub call. Create a full
// reduction (similar to other higher-order array builtins) instead of // reduction (similar to other higher-order array builtins) instead of
...@@ -1946,7 +1966,7 @@ IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeIndexOfIncludes( ...@@ -1946,7 +1966,7 @@ IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeIndexOfIncludes(
TNode<Number> length = LoadJSArrayLength(receiver, kind); TNode<Number> length = LoadJSArrayLength(receiver, kind);
TNode<FixedArrayBase> elements = LoadElements(receiver); TNode<FixedArrayBase> elements = LoadElements(receiver);
const bool have_from_index = ValueInputCount() > 3; const bool have_from_index = ArgumentCount() > 1;
if (have_from_index) { if (have_from_index) {
TNode<Smi> from_index_smi = CheckSmi(from_index); TNode<Smi> from_index_smi = CheckSmi(from_index);
...@@ -2067,7 +2087,8 @@ TNode<Object> PromiseBuiltinReducerAssembler::ReducePromiseConstructor( ...@@ -2067,7 +2087,8 @@ TNode<Object> PromiseBuiltinReducerAssembler::ReducePromiseConstructor(
FrameState outer_frame_state = FrameStateInput(); FrameState outer_frame_state = FrameStateInput();
TNode<Context> context = ContextInput(); TNode<Context> context = ContextInput();
TNode<Object> target = TargetInput(); TNode<Object> target = TargetInput();
TNode<Object> executor = ValueInput(1); TNode<Object> executor = TNode<Object>::UncheckedCast(
NodeProperties::GetValueInput(node_ptr(), 1));
DCHECK_EQ(target, NewTargetInput()); DCHECK_EQ(target, NewTargetInput());
SharedFunctionInfoRef promise_shared = SharedFunctionInfoRef promise_shared =
...@@ -2168,11 +2189,12 @@ Reduction JSCallReducer::ReplaceWithSubgraph(JSCallReducerAssembler* gasm, ...@@ -2168,11 +2189,12 @@ Reduction JSCallReducer::ReplaceWithSubgraph(JSCallReducerAssembler* gasm,
} }
Reduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) { Reduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) {
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() < 3) { if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->NaNConstant(); Node* value = jsgraph()->NaNConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
...@@ -2184,11 +2206,12 @@ Reduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) { ...@@ -2184,11 +2206,12 @@ Reduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) {
} }
Reduction JSCallReducer::ReduceMathBinary(Node* node, const Operator* op) { Reduction JSCallReducer::ReduceMathBinary(Node* node, const Operator* op) {
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() < 3) { if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->NaNConstant(); Node* value = jsgraph()->NaNConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
...@@ -2201,21 +2224,20 @@ Reduction JSCallReducer::ReduceMathBinary(Node* node, const Operator* op) { ...@@ -2201,21 +2224,20 @@ Reduction JSCallReducer::ReduceMathBinary(Node* node, const Operator* op) {
// ES6 section 20.2.2.19 Math.imul ( x, y ) // ES6 section 20.2.2.19 Math.imul ( x, y )
Reduction JSCallReducer::ReduceMathImul(Node* node) { Reduction JSCallReducer::ReduceMathImul(Node* node) {
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() < 3) { if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->ZeroConstant(); Node* value = jsgraph()->ZeroConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
Node* left = NodeProperties::GetValueInput(node, 2); Node* left = n.Argument(0);
Node* right = node->op()->ValueInputCount() > 3 Node* right = n.ArgumentOr(1, jsgraph()->ZeroConstant());
? NodeProperties::GetValueInput(node, 3) Effect effect = n.effect();
: jsgraph()->ZeroConstant(); Control control = n.control();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
left = effect = left = effect =
graph()->NewNode(simplified()->SpeculativeToNumber( graph()->NewNode(simplified()->SpeculativeToNumber(
...@@ -2234,18 +2256,19 @@ Reduction JSCallReducer::ReduceMathImul(Node* node) { ...@@ -2234,18 +2256,19 @@ Reduction JSCallReducer::ReduceMathImul(Node* node) {
// ES6 section 20.2.2.11 Math.clz32 ( x ) // ES6 section 20.2.2.11 Math.clz32 ( x )
Reduction JSCallReducer::ReduceMathClz32(Node* node) { Reduction JSCallReducer::ReduceMathClz32(Node* node) {
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() < 3) { if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->Constant(32); Node* value = jsgraph()->Constant(32);
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
Node* input = NodeProperties::GetValueInput(node, 2); Node* input = n.Argument(0);
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
input = effect = input = effect =
graph()->NewNode(simplified()->SpeculativeToNumber( graph()->NewNode(simplified()->SpeculativeToNumber(
...@@ -2261,11 +2284,12 @@ Reduction JSCallReducer::ReduceMathClz32(Node* node) { ...@@ -2261,11 +2284,12 @@ Reduction JSCallReducer::ReduceMathClz32(Node* node) {
// ES6 section 20.2.2.25 Math.min ( value1, value2, ...values ) // ES6 section 20.2.2.25 Math.min ( value1, value2, ...values )
Reduction JSCallReducer::ReduceMathMinMax(Node* node, const Operator* op, Reduction JSCallReducer::ReduceMathMinMax(Node* node, const Operator* op,
Node* empty_value) { Node* empty_value) {
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() <= 2) { if (n.ArgumentCount() < 1) {
ReplaceWithValue(node, empty_value); ReplaceWithValue(node, empty_value);
return Replace(empty_value); return Replace(empty_value);
} }
...@@ -2275,12 +2299,12 @@ Reduction JSCallReducer::ReduceMathMinMax(Node* node, const Operator* op, ...@@ -2275,12 +2299,12 @@ Reduction JSCallReducer::ReduceMathMinMax(Node* node, const Operator* op,
Node* value = effect = Node* value = effect =
graph()->NewNode(simplified()->SpeculativeToNumber( graph()->NewNode(simplified()->SpeculativeToNumber(
NumberOperationHint::kNumberOrOddball, p.feedback()), NumberOperationHint::kNumberOrOddball, p.feedback()),
NodeProperties::GetValueInput(node, 2), effect, control); n.Argument(0), effect, control);
for (int i = 3; i < node->op()->ValueInputCount(); i++) { for (int i = 1; i < n.ArgumentCount(); i++) {
Node* input = effect = graph()->NewNode( Node* input = effect = graph()->NewNode(
simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball, simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
p.feedback()), p.feedback()),
NodeProperties::GetValueInput(node, i), effect, control); n.Argument(i), effect, control);
value = graph()->NewNode(op, value, input); value = graph()->NewNode(op, value, input);
} }
...@@ -2332,12 +2356,13 @@ void JSCallReducer::Finalize() { ...@@ -2332,12 +2356,13 @@ void JSCallReducer::Finalize() {
Reduction JSCallReducer::ReduceArrayConstructor(Node* node) { Reduction JSCallReducer::ReduceArrayConstructor(Node* node) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* target = NodeProperties::GetValueInput(node, 0); Node* target = n.target();
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
// Turn the {node} into a {JSCreateArray} call. // Turn the {node} into a {JSCreateArray} call.
size_t const arity = p.arity_without_implicit_args(); size_t const arity = p.arity_without_implicit_args();
node->RemoveInput(n.FeedbackVectorIndex());
NodeProperties::ReplaceValueInput(node, target, 0); NodeProperties::ReplaceValueInput(node, target, 0);
NodeProperties::ReplaceValueInput(node, target, 1); NodeProperties::ReplaceValueInput(node, target, 1);
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
...@@ -2347,13 +2372,9 @@ Reduction JSCallReducer::ReduceArrayConstructor(Node* node) { ...@@ -2347,13 +2372,9 @@ Reduction JSCallReducer::ReduceArrayConstructor(Node* node) {
// ES6 section 19.3.1.1 Boolean ( value ) // ES6 section 19.3.1.1 Boolean ( value )
Reduction JSCallReducer::ReduceBooleanConstructor(Node* node) { Reduction JSCallReducer::ReduceBooleanConstructor(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
CallParameters const& p = CallParametersOf(node->op());
// Replace the {node} with a proper {ToBoolean} operator. // Replace the {node} with a proper {ToBoolean} operator.
Node* value = (p.arity_without_implicit_args() == 0) JSCallNode n(node);
? jsgraph()->UndefinedConstant() Node* value = n.ArgumentOrUndefined(0, jsgraph());
: NodeProperties::GetValueInput(node, 2);
value = graph()->NewNode(simplified()->ToBoolean(), value); value = graph()->NewNode(simplified()->ToBoolean(), value);
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
...@@ -2361,11 +2382,10 @@ Reduction JSCallReducer::ReduceBooleanConstructor(Node* node) { ...@@ -2361,11 +2382,10 @@ Reduction JSCallReducer::ReduceBooleanConstructor(Node* node) {
// ES section #sec-object-constructor // ES section #sec-object-constructor
Reduction JSCallReducer::ReduceObjectConstructor(Node* node) { Reduction JSCallReducer::ReduceObjectConstructor(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); if (n.ArgumentCount() < 1) return NoChange();
if (p.arity_without_implicit_args() < 1) return NoChange(); Node* value = n.Argument(0);
Node* value = NodeProperties::GetValueInput(node, 2); Effect effect = n.effect();
Node* effect = NodeProperties::GetEffectInput(node);
// We can fold away the Object(x) call if |x| is definitely not a primitive. // We can fold away the Object(x) call if |x| is definitely not a primitive.
if (NodeProperties::CanBePrimitive(broker(), value, effect)) { if (NodeProperties::CanBePrimitive(broker(), value, effect)) {
...@@ -2385,39 +2405,40 @@ Reduction JSCallReducer::ReduceObjectConstructor(Node* node) { ...@@ -2385,39 +2405,40 @@ Reduction JSCallReducer::ReduceObjectConstructor(Node* node) {
// ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray ) // ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
DisallowHeapAccessIf no_heap_acess(should_disallow_heap_access()); DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
size_t arity = p.arity_without_implicit_args(); int arity = p.arity_without_implicit_args();
ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny; ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny;
if (arity == 0) { if (arity == 0) {
// Neither thisArg nor argArray was provided. // Neither thisArg nor argArray was provided.
convert_mode = ConvertReceiverMode::kNullOrUndefined; convert_mode = ConvertReceiverMode::kNullOrUndefined;
node->ReplaceInput(0, node->InputAt(1)); node->ReplaceInput(n.TargetIndex(), n.receiver());
node->ReplaceInput(1, jsgraph()->UndefinedConstant()); node->ReplaceInput(n.ReceiverIndex(), jsgraph()->UndefinedConstant());
} else if (arity == 1) { } else if (arity == 1) {
// The argArray was not provided, just remove the {target}. // The argArray was not provided, just remove the {target}.
node->RemoveInput(0); node->RemoveInput(n.TargetIndex());
--arity; --arity;
} else { } else {
Node* target = NodeProperties::GetValueInput(node, 1); Node* target = n.receiver();
Node* this_argument = NodeProperties::GetValueInput(node, 2); Node* this_argument = n.Argument(0);
Node* arguments_list = NodeProperties::GetValueInput(node, 3); Node* arguments_list = n.Argument(1);
Node* context = NodeProperties::GetContextInput(node); Node* context = n.context();
Node* frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state = n.frame_state();
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
// If {arguments_list} cannot be null or undefined, we don't need // If {arguments_list} cannot be null or undefined, we don't need
// to expand this {node} to control-flow. // to expand this {node} to control-flow.
if (!NodeProperties::CanBeNullOrUndefined(broker(), arguments_list, if (!NodeProperties::CanBeNullOrUndefined(broker(), arguments_list,
effect)) { effect)) {
// Massage the value inputs appropriately. // Massage the value inputs appropriately.
node->ReplaceInput(0, target); node->RemoveInput(n.FeedbackVectorIndex());
node->ReplaceInput(1, this_argument); node->ReplaceInput(n.TargetIndex(), target);
node->ReplaceInput(2, arguments_list); node->ReplaceInput(n.ReceiverIndex(), this_argument);
while (arity-- > 1) node->RemoveInput(3); node->ReplaceInput(n.ArgumentIndex(0), arguments_list);
while (arity-- > 1) node->RemoveInput(n.ArgumentIndex(1));
// Morph the {node} to a {JSCallWithArrayLike}. // Morph the {node} to a {JSCallWithArrayLike}.
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
...@@ -2459,9 +2480,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { ...@@ -2459,9 +2480,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
Node* effect1 = effect; Node* effect1 = effect;
Node* control1 = Node* control1 =
graph()->NewNode(common()->Merge(2), if_null, if_undefined); graph()->NewNode(common()->Merge(2), if_null, if_undefined);
Node* value1 = effect1 = control1 = graph()->NewNode( Node* value1 = effect1 = control1 =
javascript()->Call(0 + kTargetAndReceiver), target, this_argument, graph()->NewNode(javascript()->Call(JSCallNode::ArityForArgc(0)),
context, frame_state, effect1, control1); target, this_argument, n.feedback_vector(), context,
frame_state, effect1, control1);
// Rewire potential exception edges. // Rewire potential exception edges.
Node* if_exception = nullptr; Node* if_exception = nullptr;
...@@ -2498,7 +2520,7 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { ...@@ -2498,7 +2520,7 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
} }
// Change {node} to the new {JSCall} operator. // Change {node} to the new {JSCall} operator.
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
node, javascript()->Call(arity + kTargetAndReceiver, p.frequency(), node, javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
p.feedback(), convert_mode, p.speculation_mode(), p.feedback(), convert_mode, p.speculation_mode(),
CallFeedbackRelation::kUnrelated)); CallFeedbackRelation::kUnrelated));
// Try to further reduce the JSCall {node}. // Try to further reduce the JSCall {node}.
...@@ -2507,10 +2529,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { ...@@ -2507,10 +2529,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
// ES section #sec-function.prototype.bind // ES section #sec-function.prototype.bind
Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) { Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
DisallowHeapAccessIf no_heap_acess(should_disallow_heap_access()); DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
...@@ -2521,13 +2543,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) { ...@@ -2521,13 +2543,10 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
// - receiver, which is the [[BoundTargetFunction]] // - receiver, which is the [[BoundTargetFunction]]
// - bound_this (optional), which is the [[BoundThis]] // - bound_this (optional), which is the [[BoundThis]]
// - and all the remaining value inputs are [[BoundArguments]] // - and all the remaining value inputs are [[BoundArguments]]
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* bound_this = (node->op()->ValueInputCount() < 3) Node* context = n.context();
? jsgraph()->UndefinedConstant() Effect effect = n.effect();
: NodeProperties::GetValueInput(node, 2); Control control = n.control();
Node* context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Ensure that the {receiver} is known to be a JSBoundFunction or // Ensure that the {receiver} is known to be a JSBoundFunction or
// a JSFunction with the same [[Prototype]], and all maps we've // a JSFunction with the same [[Prototype]], and all maps we've
...@@ -2619,21 +2638,26 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) { ...@@ -2619,21 +2638,26 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
control, p.feedback()); control, p.feedback());
// Replace the {node} with a JSCreateBoundFunction. // Replace the {node} with a JSCreateBoundFunction.
static constexpr int kContextEffectAndControl = 3; static constexpr int kBoundThis = 1;
int const arity = static constexpr int kReceiverContextEffectAndControl = 4;
std::max(0, node->op()->ValueInputCount() - kContextEffectAndControl); int const arity = n.ArgumentCount();
int const input_count = kTargetAndReceiver + arity + kContextEffectAndControl; int const arity_with_bound_this = std::max(arity, kBoundThis);
int const input_count =
arity_with_bound_this + kReceiverContextEffectAndControl;
Node** inputs = graph()->zone()->NewArray<Node*>(input_count); Node** inputs = graph()->zone()->NewArray<Node*>(input_count);
inputs[0] = receiver; int cursor = 0;
inputs[1] = bound_this; inputs[cursor++] = receiver;
for (int i = 0; i < arity; ++i) { inputs[cursor++] = n.ArgumentOrUndefined(0, jsgraph()); // bound_this.
inputs[kTargetAndReceiver + i] = NodeProperties::GetValueInput(node, 3 + i); for (int i = 1; i < arity; ++i) {
} inputs[cursor++] = n.Argument(i);
inputs[kTargetAndReceiver + arity + 0] = context; }
inputs[kTargetAndReceiver + arity + 1] = effect; inputs[cursor++] = context;
inputs[kTargetAndReceiver + arity + 2] = control; inputs[cursor++] = effect;
inputs[cursor++] = control;
DCHECK_EQ(cursor, input_count);
Node* value = effect = Node* value = effect =
graph()->NewNode(javascript()->CreateBoundFunction(arity, map.object()), graph()->NewNode(javascript()->CreateBoundFunction(
arity_with_bound_this - kBoundThis, map.object()),
input_count, inputs); input_count, inputs);
ReplaceWithValue(node, value, effect, control); ReplaceWithValue(node, value, effect, control);
return Replace(value); return Replace(value);
...@@ -2641,13 +2665,13 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) { ...@@ -2641,13 +2665,13 @@ Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
// ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args) // ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args)
Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) { Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
DisallowHeapAccessIf no_heap_acess(should_disallow_heap_access()); DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
Node* target = NodeProperties::GetValueInput(node, 0); Node* target = n.target();
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
// Change context of {node} to the Function.prototype.call context, // Change context of {node} to the Function.prototype.call context,
// to ensure any exception is thrown in the correct context. // to ensure any exception is thrown in the correct context.
...@@ -2671,21 +2695,21 @@ Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) { ...@@ -2671,21 +2695,21 @@ Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
// Remove the target from {node} and use the receiver as target instead, and // Remove the target from {node} and use the receiver as target instead, and
// the thisArg becomes the new target. If thisArg was not provided, insert // the thisArg becomes the new target. If thisArg was not provided, insert
// undefined instead. // undefined instead.
size_t arity = p.arity_without_implicit_args(); int arity = p.arity_without_implicit_args();
ConvertReceiverMode convert_mode; ConvertReceiverMode convert_mode;
if (arity == 0) { if (arity == 0) {
// The thisArg was not provided, use undefined as receiver. // The thisArg was not provided, use undefined as receiver.
convert_mode = ConvertReceiverMode::kNullOrUndefined; convert_mode = ConvertReceiverMode::kNullOrUndefined;
node->ReplaceInput(0, node->InputAt(1)); node->ReplaceInput(n.TargetIndex(), n.receiver());
node->ReplaceInput(1, jsgraph()->UndefinedConstant()); node->ReplaceInput(n.ReceiverIndex(), jsgraph()->UndefinedConstant());
} else { } else {
// Just remove the target, which is the first value input. // Just remove the target, which is the first value input.
convert_mode = ConvertReceiverMode::kAny; convert_mode = ConvertReceiverMode::kAny;
node->RemoveInput(0); node->RemoveInput(n.TargetIndex());
--arity; --arity;
} }
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
node, javascript()->Call(arity + kTargetAndReceiver, p.frequency(), node, javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
p.feedback(), convert_mode, p.speculation_mode(), p.feedback(), convert_mode, p.speculation_mode(),
CallFeedbackRelation::kUnrelated)); CallFeedbackRelation::kUnrelated));
// Try to further reduce the JSCall {node}. // Try to further reduce the JSCall {node}.
...@@ -2694,15 +2718,13 @@ Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) { ...@@ -2694,15 +2718,13 @@ Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] (V) // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] (V)
Reduction JSCallReducer::ReduceFunctionPrototypeHasInstance(Node* node) { Reduction JSCallReducer::ReduceFunctionPrototypeHasInstance(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* object = (node->op()->ValueInputCount() >= 3) Node* object = n.ArgumentOrUndefined(0, jsgraph());
? NodeProperties::GetValueInput(node, 2) Node* context = n.context();
: jsgraph()->UndefinedConstant(); FrameState frame_state = n.frame_state();
Node* context = NodeProperties::GetContextInput(node); Effect effect = n.effect();
Node* frame_state = NodeProperties::GetFrameStateInput(node); Control control = n.control();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// TODO(turbofan): If JSOrdinaryToInstance raises an exception, the // TODO(turbofan): If JSOrdinaryToInstance raises an exception, the
// stack trace doesn't contain the @@hasInstance call; we have the // stack trace doesn't contain the @@hasInstance call; we have the
...@@ -2764,22 +2786,16 @@ Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) { ...@@ -2764,22 +2786,16 @@ Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) {
// ES6 section 19.1.2.11 Object.getPrototypeOf ( O ) // ES6 section 19.1.2.11 Object.getPrototypeOf ( O )
Reduction JSCallReducer::ReduceObjectGetPrototypeOf(Node* node) { Reduction JSCallReducer::ReduceObjectGetPrototypeOf(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* object = (node->op()->ValueInputCount() >= 3) Node* object = n.ArgumentOrUndefined(0, jsgraph());
? NodeProperties::GetValueInput(node, 2)
: jsgraph()->UndefinedConstant();
return ReduceObjectGetPrototype(node, object); return ReduceObjectGetPrototype(node, object);
} }
// ES section #sec-object.is // ES section #sec-object.is
Reduction JSCallReducer::ReduceObjectIs(Node* node) { Reduction JSCallReducer::ReduceObjectIs(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& params = CallParametersOf(node->op()); Node* lhs = n.ArgumentOrUndefined(0, jsgraph());
int const argc = params.arity_without_implicit_args(); Node* rhs = n.ArgumentOrUndefined(1, jsgraph());
Node* lhs = (argc >= 1) ? NodeProperties::GetValueInput(node, 2)
: jsgraph()->UndefinedConstant();
Node* rhs = (argc >= 2) ? NodeProperties::GetValueInput(node, 3)
: jsgraph()->UndefinedConstant();
Node* value = graph()->NewNode(simplified()->SameValue(), lhs, rhs); Node* value = graph()->NewNode(simplified()->SameValue(), lhs, rhs);
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
...@@ -2787,21 +2803,17 @@ Reduction JSCallReducer::ReduceObjectIs(Node* node) { ...@@ -2787,21 +2803,17 @@ Reduction JSCallReducer::ReduceObjectIs(Node* node) {
// ES6 section B.2.2.1.1 get Object.prototype.__proto__ // ES6 section B.2.2.1.1 get Object.prototype.__proto__
Reduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) { Reduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* receiver = NodeProperties::GetValueInput(node, 1); return ReduceObjectGetPrototype(node, n.receiver());
return ReduceObjectGetPrototype(node, receiver);
} }
// ES #sec-object.prototype.hasownproperty // ES #sec-object.prototype.hasownproperty
Reduction JSCallReducer::ReduceObjectPrototypeHasOwnProperty(Node* node) { Reduction JSCallReducer::ReduceObjectPrototypeHasOwnProperty(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& params = CallParametersOf(node->op()); Node* receiver = n.receiver();
int const argc = params.arity_without_implicit_args(); Node* name = n.ArgumentOrUndefined(0, jsgraph());
Node* receiver = NodeProperties::GetValueInput(node, 1); Effect effect = n.effect();
Node* name = (argc >= 1) ? NodeProperties::GetValueInput(node, 2) Control control = n.control();
: jsgraph()->UndefinedConstant();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// We can optimize a call to Object.prototype.hasOwnProperty if it's being // We can optimize a call to Object.prototype.hasOwnProperty if it's being
// used inside a fast-mode for..in, so for code like this: // used inside a fast-mode for..in, so for code like this:
...@@ -2875,12 +2887,10 @@ Reduction JSCallReducer::ReduceObjectPrototypeHasOwnProperty(Node* node) { ...@@ -2875,12 +2887,10 @@ Reduction JSCallReducer::ReduceObjectPrototypeHasOwnProperty(Node* node) {
Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) { Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) {
DisallowHeapAccessIf no_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* value = node->op()->ValueInputCount() > 2 Node* value = n.ArgumentOrUndefined(0, jsgraph());
? NodeProperties::GetValueInput(node, 2) Effect effect = n.effect();
: jsgraph()->UndefinedConstant();
Node* effect = NodeProperties::GetEffectInput(node);
// Ensure that the {receiver} is known to be a JSReceiver (so that // Ensure that the {receiver} is known to be a JSReceiver (so that
// the ToObject step of Object.prototype.isPrototypeOf is a no-op). // the ToObject step of Object.prototype.isPrototypeOf is a no-op).
...@@ -2893,10 +2903,9 @@ Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) { ...@@ -2893,10 +2903,9 @@ Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) {
// and don't explicitly rule out Primitive {value}s, since all of them // and don't explicitly rule out Primitive {value}s, since all of them
// have null as their prototype, so the prototype chain walk inside the // have null as their prototype, so the prototype chain walk inside the
// JSHasInPrototypeChain operator immediately aborts and yields false. // JSHasInPrototypeChain operator immediately aborts and yields false.
NodeProperties::ReplaceValueInput(node, value, 0); NodeProperties::ReplaceValueInput(node, value, n.TargetIndex());
NodeProperties::ReplaceValueInput(node, receiver, 1); for (int i = node->op()->ValueInputCount(); i > 2; i--) {
for (int i = node->op()->ValueInputCount(); i-- > 2;) { node->RemoveInput(2);
node->RemoveInput(i);
} }
NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain()); NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
return Changed(node); return Changed(node);
...@@ -2904,11 +2913,12 @@ Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) { ...@@ -2904,11 +2913,12 @@ Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) {
// ES6 section 26.1.1 Reflect.apply ( target, thisArgument, argumentsList ) // ES6 section 26.1.1 Reflect.apply ( target, thisArgument, argumentsList )
Reduction JSCallReducer::ReduceReflectApply(Node* node) { Reduction JSCallReducer::ReduceReflectApply(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
int arity = p.arity_without_implicit_args(); int arity = p.arity_without_implicit_args();
// Massage value inputs appropriately. // Massage value inputs appropriately.
node->RemoveInput(0); node->RemoveInput(n.FeedbackVectorIndex());
node->RemoveInput(1);
node->RemoveInput(0); node->RemoveInput(0);
while (arity < 3) { while (arity < 3) {
node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant()); node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
...@@ -2925,11 +2935,12 @@ Reduction JSCallReducer::ReduceReflectApply(Node* node) { ...@@ -2925,11 +2935,12 @@ Reduction JSCallReducer::ReduceReflectApply(Node* node) {
// ES6 section 26.1.2 Reflect.construct ( target, argumentsList [, newTarget] ) // ES6 section 26.1.2 Reflect.construct ( target, argumentsList [, newTarget] )
Reduction JSCallReducer::ReduceReflectConstruct(Node* node) { Reduction JSCallReducer::ReduceReflectConstruct(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
int arity = p.arity_without_implicit_args(); int arity = p.arity_without_implicit_args();
// Massage value inputs appropriately. // Massage value inputs appropriately.
node->RemoveInput(0); node->RemoveInput(n.FeedbackVectorIndex());
node->RemoveInput(1);
node->RemoveInput(0); node->RemoveInput(0);
while (arity < 2) { while (arity < 2) {
node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant()); node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
...@@ -2947,26 +2958,22 @@ Reduction JSCallReducer::ReduceReflectConstruct(Node* node) { ...@@ -2947,26 +2958,22 @@ Reduction JSCallReducer::ReduceReflectConstruct(Node* node) {
// ES6 section 26.1.7 Reflect.getPrototypeOf ( target ) // ES6 section 26.1.7 Reflect.getPrototypeOf ( target )
Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) { Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* target = (node->op()->ValueInputCount() >= 3) Node* target = n.ArgumentOrUndefined(0, jsgraph());
? NodeProperties::GetValueInput(node, 2)
: jsgraph()->UndefinedConstant();
return ReduceObjectGetPrototype(node, target); return ReduceObjectGetPrototype(node, target);
} }
// ES6 section #sec-object.create Object.create(proto, properties) // ES6 section #sec-object.create Object.create(proto, properties)
Reduction JSCallReducer::ReduceObjectCreate(Node* node) { Reduction JSCallReducer::ReduceObjectCreate(Node* node) {
int arg_count = node->op()->ValueInputCount(); JSCallNode n(node);
Node* properties = arg_count >= 4 ? NodeProperties::GetValueInput(node, 3) Node* properties = n.ArgumentOrUndefined(1, jsgraph());
: jsgraph()->UndefinedConstant();
if (properties != jsgraph()->UndefinedConstant()) return NoChange(); if (properties != jsgraph()->UndefinedConstant()) return NoChange();
Node* effect = NodeProperties::GetEffectInput(node); Node* context = n.context();
Node* control = NodeProperties::GetControlInput(node); FrameState frame_state = n.frame_state();
Node* context = NodeProperties::GetContextInput(node); Effect effect = n.effect();
Node* frame_state = NodeProperties::GetFrameStateInput(node); Control control = n.control();
Node* prototype = arg_count >= 3 ? NodeProperties::GetValueInput(node, 2) Node* prototype = n.ArgumentOrUndefined(0, jsgraph());
: jsgraph()->UndefinedConstant();
node->ReplaceInput(0, prototype); node->ReplaceInput(0, prototype);
node->ReplaceInput(1, context); node->ReplaceInput(1, context);
node->ReplaceInput(2, frame_state); node->ReplaceInput(2, frame_state);
...@@ -2979,16 +2986,16 @@ Reduction JSCallReducer::ReduceObjectCreate(Node* node) { ...@@ -2979,16 +2986,16 @@ Reduction JSCallReducer::ReduceObjectCreate(Node* node) {
// ES section #sec-reflect.get // ES section #sec-reflect.get
Reduction JSCallReducer::ReduceReflectGet(Node* node) { Reduction JSCallReducer::ReduceReflectGet(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
int arity = p.arity_without_implicit_args(); int arity = p.arity_without_implicit_args();
if (arity != 2) return NoChange(); if (arity != 2) return NoChange();
Node* target = NodeProperties::GetValueInput(node, 2); Node* target = n.Argument(0);
Node* key = NodeProperties::GetValueInput(node, 3); Node* key = n.Argument(1);
Node* context = NodeProperties::GetContextInput(node); Node* context = n.context();
Node* frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state = n.frame_state();
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
// Check whether {target} is a JSReceiver. // Check whether {target} is a JSReceiver.
Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target); Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
...@@ -3054,17 +3061,13 @@ Reduction JSCallReducer::ReduceReflectGet(Node* node) { ...@@ -3054,17 +3061,13 @@ Reduction JSCallReducer::ReduceReflectGet(Node* node) {
// ES section #sec-reflect.has // ES section #sec-reflect.has
Reduction JSCallReducer::ReduceReflectHas(Node* node) { Reduction JSCallReducer::ReduceReflectHas(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); Node* target = n.ArgumentOrUndefined(0, jsgraph());
int arity = p.arity_without_implicit_args(); Node* key = n.ArgumentOrUndefined(1, jsgraph());
Node* target = (arity >= 1) ? NodeProperties::GetValueInput(node, 2) Node* context = n.context();
: jsgraph()->UndefinedConstant(); Effect effect = n.effect();
Node* key = (arity >= 2) ? NodeProperties::GetValueInput(node, 3) Control control = n.control();
: jsgraph()->UndefinedConstant(); FrameState frame_state = n.frame_state();
Node* context = NodeProperties::GetContextInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Check whether {target} is a JSReceiver. // Check whether {target} is a JSReceiver.
Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target); Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
...@@ -3391,22 +3394,22 @@ Reduction JSCallReducer::ReduceArraySome(Node* node, ...@@ -3391,22 +3394,22 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
Reduction JSCallReducer::ReduceCallApiFunction( Reduction JSCallReducer::ReduceCallApiFunction(
Node* node, const SharedFunctionInfoRef& shared) { Node* node, const SharedFunctionInfoRef& shared) {
DisallowHeapAccessIf no_heap_acess(should_disallow_heap_access()); DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
int const argc = p.arity_without_implicit_args(); int const argc = p.arity_without_implicit_args();
Node* target = NodeProperties::GetValueInput(node, 0); Node* target = n.target();
Node* global_proxy = Node* global_proxy =
jsgraph()->Constant(native_context().global_proxy_object()); jsgraph()->Constant(native_context().global_proxy_object());
Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined) Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
? global_proxy ? global_proxy
: NodeProperties::GetValueInput(node, 1); : n.receiver();
Node* holder; Node* holder;
Node* effect = NodeProperties::GetEffectInput(node); Node* context = n.context();
Node* control = NodeProperties::GetControlInput(node); Effect effect = n.effect();
Node* context = NodeProperties::GetContextInput(node); Control control = n.control();
Node* frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state = n.frame_state();
if (!shared.function_template_info().has_value()) { if (!shared.function_template_info().has_value()) {
TRACE_BROKER_MISSING( TRACE_BROKER_MISSING(
...@@ -3539,6 +3542,7 @@ Reduction JSCallReducer::ReduceCallApiFunction( ...@@ -3539,6 +3542,7 @@ Reduction JSCallReducer::ReduceCallApiFunction(
auto call_descriptor = Linkage::GetStubCallDescriptor( auto call_descriptor = Linkage::GetStubCallDescriptor(
graph()->zone(), callable.descriptor(), graph()->zone(), callable.descriptor(),
argc + 1 /* implicit receiver */, CallDescriptor::kNeedsFrameState); argc + 1 /* implicit receiver */, CallDescriptor::kNeedsFrameState);
node->RemoveInput(n.FeedbackVectorIndex());
node->InsertInput(graph()->zone(), 0, node->InsertInput(graph()->zone(), 0,
jsgraph()->HeapConstant(callable.code())); jsgraph()->HeapConstant(callable.code()));
node->ReplaceInput(1, jsgraph()->Constant(function_template_info)); node->ReplaceInput(1, jsgraph()->Constant(function_template_info));
...@@ -3583,6 +3587,7 @@ Reduction JSCallReducer::ReduceCallApiFunction( ...@@ -3583,6 +3587,7 @@ Reduction JSCallReducer::ReduceCallApiFunction(
Node* continuation_frame_state = CreateGenericLazyDeoptContinuationFrameState( Node* continuation_frame_state = CreateGenericLazyDeoptContinuationFrameState(
jsgraph(), shared, target, context, receiver, frame_state); jsgraph(), shared, target, context, receiver, frame_state);
node->RemoveInput(n.FeedbackVectorIndex());
node->InsertInput(graph()->zone(), 0, node->InsertInput(graph()->zone(), 0,
jsgraph()->HeapConstant(call_api_callback.code())); jsgraph()->HeapConstant(call_api_callback.code()));
node->ReplaceInput(1, jsgraph()->ExternalConstant(function_reference)); node->ReplaceInput(1, jsgraph()->ExternalConstant(function_reference));
...@@ -3626,6 +3631,9 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread( ...@@ -3626,6 +3631,9 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation, DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
feedback.IsValid()); feedback.IsValid());
// TODO(jgruber): The `arity` arg is confusing; for Call variants, it includes
// kTargetAndReceiver, for Construct variants it doesn't. Understand it.
Node* arguments_list = NodeProperties::GetValueInput(node, arity); Node* arguments_list = NodeProperties::GetValueInput(node, arity);
if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) { if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) {
return NoChange(); return NoChange();
...@@ -3764,10 +3772,15 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread( ...@@ -3764,10 +3772,15 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
if (node->opcode() == IrOpcode::kJSCallWithArrayLike || if (node->opcode() == IrOpcode::kJSCallWithArrayLike ||
node->opcode() == IrOpcode::kJSCallWithSpread) { node->opcode() == IrOpcode::kJSCallWithSpread) {
// TODO(jgruber): Clarify arity. Why `- 2`?
// TODO(jgruber): Use the non-HeapConstant vector input once it exists.
node->InsertInput(graph()->zone(), static_cast<int>(++arity),
jsgraph()->HeapConstant(feedback.vector));
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
node, javascript()->Call(arity + 1, frequency, feedback, node,
ConvertReceiverMode::kAny, speculation_mode, javascript()->Call(JSCallNode::ArityForArgc(arity - 2), frequency,
CallFeedbackRelation::kUnrelated)); feedback, ConvertReceiverMode::kAny,
speculation_mode, CallFeedbackRelation::kUnrelated));
return Changed(node).FollowedBy(ReduceJSCall(node)); return Changed(node).FollowedBy(ReduceJSCall(node));
} else { } else {
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
...@@ -3867,12 +3880,12 @@ bool JSCallReducer::IsBuiltinOrApiFunction(JSFunctionRef function) const { ...@@ -3867,12 +3880,12 @@ bool JSCallReducer::IsBuiltinOrApiFunction(JSFunctionRef function) const {
} }
Reduction JSCallReducer::ReduceJSCall(Node* node) { Reduction JSCallReducer::ReduceJSCall(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
Node* target = NodeProperties::GetValueInput(node, 0); Node* target = n.target();
Node* control = NodeProperties::GetControlInput(node); Effect effect = n.effect();
Node* effect = NodeProperties::GetEffectInput(node); Control control = n.control();
size_t arity = p.arity_without_implicit_args(); int arity = p.arity_without_implicit_args();
// Try to specialize JSCall {node}s with constant {target}s. // Try to specialize JSCall {node}s with constant {target}s.
HeapObjectMatcher m(target); HeapObjectMatcher m(target);
...@@ -3906,9 +3919,10 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -3906,9 +3919,10 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
// Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]]. // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
NodeProperties::ReplaceValueInput( NodeProperties::ReplaceValueInput(
node, jsgraph()->Constant(function.bound_target_function()), 0); node, jsgraph()->Constant(function.bound_target_function()),
JSCallNode::TargetIndex());
NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this), NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
1); JSCallNode::ReceiverIndex());
// Insert the [[BoundArguments]] for {node}. // Insert the [[BoundArguments]] for {node}.
FixedArrayRef bound_arguments = function.bound_arguments(); FixedArrayRef bound_arguments = function.bound_arguments();
...@@ -3920,7 +3934,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -3920,7 +3934,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
node, node,
javascript()->Call(arity + kTargetAndReceiver, p.frequency(), javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
p.feedback(), convert_mode, p.speculation_mode(), p.feedback(), convert_mode, p.speculation_mode(),
CallFeedbackRelation::kUnrelated)); CallFeedbackRelation::kUnrelated));
...@@ -3957,13 +3971,14 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -3957,13 +3971,14 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity()); static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity());
// Patch the {node} to use [[BoundTargetFunction]] and [[BoundThis]]. // Patch the {node} to use [[BoundTargetFunction]] and [[BoundThis]].
NodeProperties::ReplaceValueInput(node, bound_target_function, 0); NodeProperties::ReplaceValueInput(node, bound_target_function,
NodeProperties::ReplaceValueInput(node, bound_this, 1); n.TargetIndex());
NodeProperties::ReplaceValueInput(node, bound_this, n.ReceiverIndex());
// Insert the [[BoundArguments]] for {node}. // Insert the [[BoundArguments]] for {node}.
for (int i = 0; i < bound_arguments_length; ++i) { for (int i = 0; i < bound_arguments_length; ++i) {
Node* value = NodeProperties::GetValueInput(target, 2 + i); Node* value = NodeProperties::GetValueInput(target, 2 + i);
node->InsertInput(graph()->zone(), 2 + i, value); node->InsertInput(graph()->zone(), n.ArgumentIndex(i), value);
arity++; arity++;
} }
...@@ -3974,7 +3989,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -3974,7 +3989,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
: ConvertReceiverMode::kNotNullOrUndefined; : ConvertReceiverMode::kNotNullOrUndefined;
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
node, node,
javascript()->Call(arity + kTargetAndReceiver, p.frequency(), javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
p.feedback(), convert_mode, p.speculation_mode(), p.feedback(), convert_mode, p.speculation_mode(),
CallFeedbackRelation::kUnrelated)); CallFeedbackRelation::kUnrelated));
...@@ -4014,7 +4029,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -4014,7 +4029,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
effect, control); effect, control);
// Specialize the JSCall node to the {target_function}. // Specialize the JSCall node to the {target_function}.
NodeProperties::ReplaceValueInput(node, target_function, 0); NodeProperties::ReplaceValueInput(node, target_function, n.TargetIndex());
NodeProperties::ReplaceEffectInput(node, effect); NodeProperties::ReplaceEffectInput(node, effect);
// Try to further reduce the JSCall {node}. // Try to further reduce the JSCall {node}.
...@@ -4043,7 +4058,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -4043,7 +4058,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
target, effect, control); target, effect, control);
// Specialize the JSCall node to the {target_closure}. // Specialize the JSCall node to the {target_closure}.
NodeProperties::ReplaceValueInput(node, target_closure, 0); NodeProperties::ReplaceValueInput(node, target_closure, n.TargetIndex());
NodeProperties::ReplaceEffectInput(node, effect); NodeProperties::ReplaceEffectInput(node, effect);
// Try to further reduce the JSCall {node}. // Try to further reduce the JSCall {node}.
...@@ -4055,8 +4070,8 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -4055,8 +4070,8 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
Reduction JSCallReducer::ReduceJSCall(Node* node, Reduction JSCallReducer::ReduceJSCall(Node* node,
const SharedFunctionInfoRef& shared) { const SharedFunctionInfoRef& shared) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* target = NodeProperties::GetValueInput(node, 0); Node* target = n.target();
// Do not reduce calls to functions with break points. // Do not reduce calls to functions with break points.
if (shared.HasBreakInfo()) return NoChange(); if (shared.HasBreakInfo()) return NoChange();
...@@ -4426,10 +4441,8 @@ Reduction JSCallReducer::ReduceJSCallWithSpread(Node* node) { ...@@ -4426,10 +4441,8 @@ Reduction JSCallReducer::ReduceJSCallWithSpread(Node* node) {
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = CallParametersOf(node->op());
int arity = p.arity_without_implicit_args(); int arity = p.arity_without_implicit_args();
DCHECK_GE(p.arity(), 1); DCHECK_GE(p.arity(), 1);
CallFrequency frequency = p.frequency();
FeedbackSource feedback = p.feedback();
return ReduceCallOrConstructWithArrayLikeOrSpread( return ReduceCallOrConstructWithArrayLikeOrSpread(
node, arity + kTargetAndReceiver - 1, frequency, feedback, node, arity + kTargetAndReceiver - 1, p.frequency(), p.feedback(),
p.speculation_mode(), p.feedback_relation()); p.speculation_mode(), p.feedback_relation());
} }
...@@ -4664,27 +4677,27 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -4664,27 +4677,27 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
// ES #sec-string.prototype.indexof // ES #sec-string.prototype.indexof
Reduction JSCallReducer::ReduceStringPrototypeIndexOf(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeIndexOf(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
if (node->op()->ValueInputCount() >= 3) { if (n.ArgumentCount() > 0) {
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* new_receiver = effect = graph()->NewNode( Node* new_receiver = effect = graph()->NewNode(
simplified()->CheckString(p.feedback()), receiver, effect, control); simplified()->CheckString(p.feedback()), receiver, effect, control);
Node* search_string = NodeProperties::GetValueInput(node, 2); Node* search_string = n.Argument(0);
Node* new_search_string = effect = Node* new_search_string = effect =
graph()->NewNode(simplified()->CheckString(p.feedback()), search_string, graph()->NewNode(simplified()->CheckString(p.feedback()), search_string,
effect, control); effect, control);
Node* new_position = jsgraph()->ZeroConstant(); Node* new_position = jsgraph()->ZeroConstant();
if (node->op()->ValueInputCount() >= 4) { if (n.ArgumentCount() > 1) {
Node* position = NodeProperties::GetValueInput(node, 3); Node* position = n.Argument(1);
new_position = effect = graph()->NewNode( new_position = effect = graph()->NewNode(
simplified()->CheckSmi(p.feedback()), position, effect, control); simplified()->CheckSmi(p.feedback()), position, effect, control);
} }
...@@ -4703,8 +4716,9 @@ Reduction JSCallReducer::ReduceStringPrototypeIndexOf(Node* node) { ...@@ -4703,8 +4716,9 @@ Reduction JSCallReducer::ReduceStringPrototypeIndexOf(Node* node) {
// ES #sec-string.prototype.substring // ES #sec-string.prototype.substring
Reduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) {
if (node->op()->ValueInputCount() < 3) return NoChange(); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (n.ArgumentCount() < 1) return NoChange();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
...@@ -4716,8 +4730,9 @@ Reduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) { ...@@ -4716,8 +4730,9 @@ Reduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) {
// ES #sec-string.prototype.slice // ES #sec-string.prototype.slice
Reduction JSCallReducer::ReduceStringPrototypeSlice(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeSlice(Node* node) {
if (node->op()->ValueInputCount() < 3) return NoChange(); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (n.ArgumentCount() < 1) return NoChange();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
...@@ -4729,19 +4744,18 @@ Reduction JSCallReducer::ReduceStringPrototypeSlice(Node* node) { ...@@ -4729,19 +4744,18 @@ Reduction JSCallReducer::ReduceStringPrototypeSlice(Node* node) {
// ES #sec-string.prototype.substr // ES #sec-string.prototype.substr
Reduction JSCallReducer::ReduceStringPrototypeSubstr(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeSubstr(Node* node) {
if (node->op()->ValueInputCount() < 3) return NoChange(); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (n.ArgumentCount() < 1) return NoChange();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* start = NodeProperties::GetValueInput(node, 2); Node* start = n.Argument(0);
Node* end = node->op()->ValueInputCount() > 3 Node* end = n.ArgumentOrUndefined(1, jsgraph());
? NodeProperties::GetValueInput(node, 3)
: jsgraph()->UndefinedConstant();
receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()), receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
receiver, effect, control); receiver, effect, control);
...@@ -4853,8 +4867,8 @@ Reduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) { ...@@ -4853,8 +4867,8 @@ Reduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) {
} }
Reduction JSCallReducer::ReduceReturnReceiver(Node* node) { Reduction JSCallReducer::ReduceReturnReceiver(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
ReplaceWithValue(node, receiver); ReplaceWithValue(node, receiver);
return Replace(receiver); return Replace(receiver);
} }
...@@ -4884,20 +4898,22 @@ Reduction JSCallReducer::ReduceForInsufficientFeedback( ...@@ -4884,20 +4898,22 @@ Reduction JSCallReducer::ReduceForInsufficientFeedback(
return Changed(node); return Changed(node);
} }
Node* JSCallReducer::LoadReceiverElementsKind(Node* receiver, Node** effect, Node* JSCallReducer::LoadReceiverElementsKind(Node* receiver, Effect* effect,
Node** control) { Control control) {
Node* receiver_map = *effect = Node* effect_node = *effect;
Node* receiver_map = effect_node =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
receiver, *effect, *control); receiver, effect_node, control);
Node* receiver_bit_field2 = *effect = graph()->NewNode( Node* receiver_bit_field2 = effect_node = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMapBitField2()), receiver_map, simplified()->LoadField(AccessBuilder::ForMapBitField2()), receiver_map,
*effect, *control); effect_node, control);
Node* receiver_elements_kind = graph()->NewNode( Node* receiver_elements_kind = graph()->NewNode(
simplified()->NumberShiftRightLogical(), simplified()->NumberShiftRightLogical(),
graph()->NewNode( graph()->NewNode(
simplified()->NumberBitwiseAnd(), receiver_bit_field2, simplified()->NumberBitwiseAnd(), receiver_bit_field2,
jsgraph()->Constant(Map::Bits2::ElementsKindBits::kMask)), jsgraph()->Constant(Map::Bits2::ElementsKindBits::kMask)),
jsgraph()->Constant(Map::Bits2::ElementsKindBits::kShift)); jsgraph()->Constant(Map::Bits2::ElementsKindBits::kShift));
*effect = effect_node;
return receiver_elements_kind; return receiver_elements_kind;
} }
...@@ -4935,16 +4951,16 @@ void JSCallReducer::CheckIfElementsKind(Node* receiver_elements_kind, ...@@ -4935,16 +4951,16 @@ void JSCallReducer::CheckIfElementsKind(Node* receiver_elements_kind,
Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) { Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
int const num_values = node->op()->ValueInputCount() - 2; int const num_values = n.ArgumentCount();
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
MapInference inference(broker(), receiver, effect); MapInference inference(broker(), receiver, effect);
if (!inference.HaveMaps()) return NoChange(); if (!inference.HaveMaps()) return NoChange();
...@@ -4964,7 +4980,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) { ...@@ -4964,7 +4980,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
Node* return_value = jsgraph()->UndefinedConstant(); Node* return_value = jsgraph()->UndefinedConstant();
Node* receiver_elements_kind = Node* receiver_elements_kind =
LoadReceiverElementsKind(receiver, &effect, &control); LoadReceiverElementsKind(receiver, &effect, control);
Node* next_control = control; Node* next_control = control;
Node* next_effect = effect; Node* next_effect = effect;
for (size_t i = 0; i < kinds.size(); i++) { for (size_t i = 0; i < kinds.size(); i++) {
...@@ -4973,14 +4989,16 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) { ...@@ -4973,14 +4989,16 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
effect = next_effect; effect = next_effect;
// We do not need branch for the last elements kind. // We do not need branch for the last elements kind.
if (i != kinds.size() - 1) { if (i != kinds.size() - 1) {
CheckIfElementsKind(receiver_elements_kind, kind, control, &control, Node* control_node = control;
&next_control); CheckIfElementsKind(receiver_elements_kind, kind, control_node,
&control_node, &next_control);
control = control_node;
} }
// Collect the value inputs to push. // Collect the value inputs to push.
std::vector<Node*> values(num_values); std::vector<Node*> values(num_values);
for (int i = 0; i < num_values; ++i) { for (int i = 0; i < num_values; ++i) {
values[i] = NodeProperties::GetValueInput(node, 2 + i); values[i] = n.Argument(i);
} }
for (auto& value : values) { for (auto& value : values) {
...@@ -5071,15 +5089,15 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) { ...@@ -5071,15 +5089,15 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) { Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* receiver = NodeProperties::GetValueInput(node, 1); Effect effect = n.effect();
Node* effect = NodeProperties::GetEffectInput(node); Control control = n.control();
Node* control = NodeProperties::GetControlInput(node); Node* receiver = n.receiver();
MapInference inference(broker(), receiver, effect); MapInference inference(broker(), receiver, effect);
if (!inference.HaveMaps()) return NoChange(); if (!inference.HaveMaps()) return NoChange();
...@@ -5099,7 +5117,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) { ...@@ -5099,7 +5117,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
Node* value = jsgraph()->UndefinedConstant(); Node* value = jsgraph()->UndefinedConstant();
Node* receiver_elements_kind = Node* receiver_elements_kind =
LoadReceiverElementsKind(receiver, &effect, &control); LoadReceiverElementsKind(receiver, &effect, control);
Node* next_control = control; Node* next_control = control;
Node* next_effect = effect; Node* next_effect = effect;
for (size_t i = 0; i < kinds.size(); i++) { for (size_t i = 0; i < kinds.size(); i++) {
...@@ -5108,8 +5126,10 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) { ...@@ -5108,8 +5126,10 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
effect = next_effect; effect = next_effect;
// We do not need branch for the last elements kind. // We do not need branch for the last elements kind.
if (i != kinds.size() - 1) { if (i != kinds.size() - 1) {
CheckIfElementsKind(receiver_elements_kind, kind, control, &control, Node* control_node = control;
&next_control); CheckIfElementsKind(receiver_elements_kind, kind, control_node,
&control_node, &next_control);
control = control_node;
} }
// Load the "length" property of the {receiver}. // Load the "length" property of the {receiver}.
...@@ -5206,18 +5226,18 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) { ...@@ -5206,18 +5226,18 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) { Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* target = NodeProperties::GetValueInput(node, 0); Node* target = n.target();
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* context = NodeProperties::GetContextInput(node); Node* context = n.context();
Node* frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state = n.frame_state();
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
MapInference inference(broker(), receiver, effect); MapInference inference(broker(), receiver, effect);
if (!inference.HaveMaps()) return NoChange(); if (!inference.HaveMaps()) return NoChange();
...@@ -5237,7 +5257,7 @@ Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) { ...@@ -5237,7 +5257,7 @@ Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
Node* value = jsgraph()->UndefinedConstant(); Node* value = jsgraph()->UndefinedConstant();
Node* receiver_elements_kind = Node* receiver_elements_kind =
LoadReceiverElementsKind(receiver, &effect, &control); LoadReceiverElementsKind(receiver, &effect, control);
Node* next_control = control; Node* next_control = control;
Node* next_effect = effect; Node* next_effect = effect;
for (size_t i = 0; i < kinds.size(); i++) { for (size_t i = 0; i < kinds.size(); i++) {
...@@ -5246,8 +5266,10 @@ Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) { ...@@ -5246,8 +5266,10 @@ Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
effect = next_effect; effect = next_effect;
// We do not need branch for the last elements kind. // We do not need branch for the last elements kind.
if (i != kinds.size() - 1) { if (i != kinds.size() - 1) {
CheckIfElementsKind(receiver_elements_kind, kind, control, &control, Node* control_node = control;
&next_control); CheckIfElementsKind(receiver_elements_kind, kind, control_node,
&control_node, &next_control);
control = control_node;
} }
// Load length of the {receiver}. // Load length of the {receiver}.
...@@ -5425,22 +5447,18 @@ Reduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) { ...@@ -5425,22 +5447,18 @@ Reduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
if (!FLAG_turbo_inline_array_builtins) return NoChange(); if (!FLAG_turbo_inline_array_builtins) return NoChange();
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* start = node->op()->ValueInputCount() > 2 Node* start = n.ArgumentOr(0, jsgraph()->ZeroConstant());
? NodeProperties::GetValueInput(node, 2) Node* end = n.ArgumentOrUndefined(1, jsgraph());
: jsgraph()->ZeroConstant(); Node* context = n.context();
Node* end = node->op()->ValueInputCount() > 3 Effect effect = n.effect();
? NodeProperties::GetValueInput(node, 3) Control control = n.control();
: jsgraph()->UndefinedConstant();
Node* context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Optimize for the case where we simply clone the {receiver}, // Optimize for the case where we simply clone the {receiver},
// i.e. when the {start} is zero and the {end} is undefined // i.e. when the {start} is zero and the {end} is undefined
...@@ -5503,17 +5521,18 @@ Reduction JSCallReducer::ReduceArrayIsArray(Node* node) { ...@@ -5503,17 +5521,18 @@ Reduction JSCallReducer::ReduceArrayIsArray(Node* node) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
// We certainly know that undefined is not an array. // We certainly know that undefined is not an array.
if (node->op()->ValueInputCount() < 3) { JSCallNode n(node);
if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->FalseConstant(); Node* value = jsgraph()->FalseConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* context = NodeProperties::GetContextInput(node); Node* context = n.context();
Node* frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state = n.frame_state();
Node* object = NodeProperties::GetValueInput(node, 2); Node* object = n.Argument(0);
node->ReplaceInput(0, object); node->ReplaceInput(0, object);
node->ReplaceInput(1, context); node->ReplaceInput(1, context);
node->ReplaceInput(2, frame_state); node->ReplaceInput(2, frame_state);
...@@ -5529,11 +5548,11 @@ Reduction JSCallReducer::ReduceArrayIterator(Node* node, ...@@ -5529,11 +5548,11 @@ Reduction JSCallReducer::ReduceArrayIterator(Node* node,
IterationKind iteration_kind) { IterationKind iteration_kind) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* context = NodeProperties::GetContextInput(node); Node* context = n.context();
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
// Check if we know that {receiver} is a valid JSReceiver. // Check if we know that {receiver} is a valid JSReceiver.
MapInference inference(broker(), receiver, effect); MapInference inference(broker(), receiver, effect);
...@@ -5590,12 +5609,12 @@ Reduction JSCallReducer::ReduceArrayIterator(Node* node, ...@@ -5590,12 +5609,12 @@ Reduction JSCallReducer::ReduceArrayIterator(Node* node,
Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) { Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
Node* iterator = NodeProperties::GetValueInput(node, 1); Node* iterator = n.receiver();
Node* context = NodeProperties::GetContextInput(node); Node* context = n.context();
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
...@@ -5838,18 +5857,16 @@ Reduction JSCallReducer::ReduceStringPrototypeStringAt( ...@@ -5838,18 +5857,16 @@ Reduction JSCallReducer::ReduceStringPrototypeStringAt(
const Operator* string_access_operator, Node* node) { const Operator* string_access_operator, Node* node) {
DCHECK(string_access_operator->opcode() == IrOpcode::kStringCharCodeAt || DCHECK(string_access_operator->opcode() == IrOpcode::kStringCharCodeAt ||
string_access_operator->opcode() == IrOpcode::kStringCodePointAt); string_access_operator->opcode() == IrOpcode::kStringCodePointAt);
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* index = node->op()->ValueInputCount() >= 3 Node* index = n.ArgumentOr(0, jsgraph()->ZeroConstant());
? NodeProperties::GetValueInput(node, 2) Effect effect = n.effect();
: jsgraph()->ZeroConstant(); Control control = n.control();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Ensure that the {receiver} is actually a String. // Ensure that the {receiver} is actually a String.
receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()), receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
...@@ -5875,17 +5892,17 @@ Reduction JSCallReducer::ReduceStringPrototypeStringAt( ...@@ -5875,17 +5892,17 @@ Reduction JSCallReducer::ReduceStringPrototypeStringAt(
// ES section 21.1.3.20 // ES section 21.1.3.20
// String.prototype.startsWith ( searchString [ , position ] ) // String.prototype.startsWith ( searchString [ , position ] )
Reduction JSCallReducer::ReduceStringPrototypeStartsWith(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeStartsWith(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
if (node->op()->ValueInputCount() < 3) { if (n.ArgumentCount() < 1) {
effect = graph()->NewNode(simplified()->CheckString(p.feedback()), receiver, effect = graph()->NewNode(simplified()->CheckString(p.feedback()), receiver,
effect, control); effect, control);
...@@ -5894,10 +5911,8 @@ Reduction JSCallReducer::ReduceStringPrototypeStartsWith(Node* node) { ...@@ -5894,10 +5911,8 @@ Reduction JSCallReducer::ReduceStringPrototypeStartsWith(Node* node) {
return Replace(value); return Replace(value);
} }
Node* search_string = NodeProperties::GetValueInput(node, 2); Node* search_string = n.Argument(0);
Node* position = node->op()->ValueInputCount() >= 4 Node* position = n.ArgumentOr(1, jsgraph()->ZeroConstant());
? NodeProperties::GetValueInput(node, 3)
: jsgraph()->ZeroConstant();
HeapObjectMatcher m(search_string); HeapObjectMatcher m(search_string);
if (m.HasValue()) { if (m.HasValue()) {
...@@ -5958,18 +5973,16 @@ Reduction JSCallReducer::ReduceStringPrototypeStartsWith(Node* node) { ...@@ -5958,18 +5973,16 @@ Reduction JSCallReducer::ReduceStringPrototypeStartsWith(Node* node) {
// ES section 21.1.3.1 String.prototype.charAt ( pos ) // ES section 21.1.3.1 String.prototype.charAt ( pos )
Reduction JSCallReducer::ReduceStringPrototypeCharAt(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeCharAt(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* index = node->op()->ValueInputCount() >= 3 Node* index = n.ArgumentOr(0, jsgraph()->ZeroConstant());
? NodeProperties::GetValueInput(node, 2) Effect effect = n.effect();
: jsgraph()->ZeroConstant(); Control control = n.control();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Ensure that the {receiver} is actually a String. // Ensure that the {receiver} is actually a String.
receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()), receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
...@@ -5997,17 +6010,16 @@ Reduction JSCallReducer::ReduceStringPrototypeCharAt(Node* node) { ...@@ -5997,17 +6010,16 @@ Reduction JSCallReducer::ReduceStringPrototypeCharAt(Node* node) {
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
Reduction JSCallReducer::ReduceStringPrototypeToLowerCaseIntl(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeToLowerCaseIntl(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* receiver = effect = Node* receiver = effect = graph()->NewNode(
graph()->NewNode(simplified()->CheckString(p.feedback()), simplified()->CheckString(p.feedback()), n.receiver(), effect, control);
NodeProperties::GetValueInput(node, 1), effect, control);
NodeProperties::ReplaceEffectInput(node, effect); NodeProperties::ReplaceEffectInput(node, effect);
RelaxEffectsAndControls(node); RelaxEffectsAndControls(node);
...@@ -6019,17 +6031,16 @@ Reduction JSCallReducer::ReduceStringPrototypeToLowerCaseIntl(Node* node) { ...@@ -6019,17 +6031,16 @@ Reduction JSCallReducer::ReduceStringPrototypeToLowerCaseIntl(Node* node) {
} }
Reduction JSCallReducer::ReduceStringPrototypeToUpperCaseIntl(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeToUpperCaseIntl(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* receiver = effect = Node* receiver = effect = graph()->NewNode(
graph()->NewNode(simplified()->CheckString(p.feedback()), simplified()->CheckString(p.feedback()), n.receiver(), effect, control);
NodeProperties::GetValueInput(node, 1), effect, control);
NodeProperties::ReplaceEffectInput(node, effect); NodeProperties::ReplaceEffectInput(node, effect);
RelaxEffectsAndControls(node); RelaxEffectsAndControls(node);
...@@ -6044,15 +6055,15 @@ Reduction JSCallReducer::ReduceStringPrototypeToUpperCaseIntl(Node* node) { ...@@ -6044,15 +6055,15 @@ Reduction JSCallReducer::ReduceStringPrototypeToUpperCaseIntl(Node* node) {
// ES #sec-string.fromcharcode // ES #sec-string.fromcharcode
Reduction JSCallReducer::ReduceStringFromCharCode(Node* node) { Reduction JSCallReducer::ReduceStringFromCharCode(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() == 3) { if (n.ArgumentCount() == 1) {
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* input = NodeProperties::GetValueInput(node, 2); Node* input = n.Argument(0);
input = effect = graph()->NewNode( input = effect = graph()->NewNode(
simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball, simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
...@@ -6069,27 +6080,26 @@ Reduction JSCallReducer::ReduceStringFromCharCode(Node* node) { ...@@ -6069,27 +6080,26 @@ Reduction JSCallReducer::ReduceStringFromCharCode(Node* node) {
// ES #sec-string.fromcodepoint // ES #sec-string.fromcodepoint
Reduction JSCallReducer::ReduceStringFromCodePoint(Node* node) { Reduction JSCallReducer::ReduceStringFromCodePoint(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() == 3) { if (n.ArgumentCount() != 1) return NoChange();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* input = NodeProperties::GetValueInput(node, 2);
input = effect = graph()->NewNode( Effect effect = n.effect();
simplified()->CheckBounds(p.feedback(), Control control = n.control();
CheckBoundsFlag::kConvertStringAndMinusZero), Node* input = n.Argument(0);
input, jsgraph()->Constant(0x10FFFF + 1), effect, control);
Node* value = input = effect = graph()->NewNode(
graph()->NewNode(simplified()->StringFromSingleCodePoint(), input); simplified()->CheckBounds(p.feedback(),
ReplaceWithValue(node, value, effect); CheckBoundsFlag::kConvertStringAndMinusZero),
return Replace(value); input, jsgraph()->Constant(0x10FFFF + 1), effect, control);
}
return NoChange(); Node* value =
graph()->NewNode(simplified()->StringFromSingleCodePoint(), input);
ReplaceWithValue(node, value, effect);
return Replace(value);
} }
Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) {
...@@ -6097,15 +6107,15 @@ Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) { ...@@ -6097,15 +6107,15 @@ Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) {
// independent code, if LowerJSCreateStringIterator were implemented in // independent code, if LowerJSCreateStringIterator were implemented in
// generic lowering. // generic lowering.
if (broker()->is_native_context_independent()) return NoChange(); if (broker()->is_native_context_independent()) return NoChange();
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
Node* receiver = effect = Node* receiver = effect = graph()->NewNode(
graph()->NewNode(simplified()->CheckString(p.feedback()), simplified()->CheckString(p.feedback()), n.receiver(), effect, control);
NodeProperties::GetValueInput(node, 1), effect, control);
Node* iterator = effect = Node* iterator = effect =
graph()->NewNode(javascript()->CreateStringIterator(), receiver, graph()->NewNode(javascript()->CreateStringIterator(), receiver,
jsgraph()->NoContextConstant(), effect); jsgraph()->NoContextConstant(), effect);
...@@ -6114,10 +6124,11 @@ Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) { ...@@ -6114,10 +6124,11 @@ Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) {
} }
Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) { Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) {
Node* receiver = NodeProperties::GetValueInput(node, 1); JSCallNode n(node);
Node* effect = NodeProperties::GetEffectInput(node); Node* receiver = n.receiver();
Node* control = NodeProperties::GetControlInput(node); Effect effect = n.effect();
Node* context = NodeProperties::GetContextInput(node); Control control = n.control();
Node* context = n.context();
MapInference inference(broker(), receiver, effect); MapInference inference(broker(), receiver, effect);
if (!inference.HaveMaps() || if (!inference.HaveMaps() ||
...@@ -6182,28 +6193,26 @@ Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) { ...@@ -6182,28 +6193,26 @@ Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) {
// ES #sec-string.prototype.concat // ES #sec-string.prototype.concat
Reduction JSCallReducer::ReduceStringPrototypeConcat(Node* node) { Reduction JSCallReducer::ReduceStringPrototypeConcat(Node* node) {
if (node->op()->ValueInputCount() < 2 || node->op()->ValueInputCount() > 3) { JSCallNode n(node);
return NoChange(); CallParameters const& p = n.Parameters();
} const int parameter_count = n.ArgumentCount();
CallParameters const& p = CallParametersOf(node->op()); if (parameter_count > 1) return NoChange();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* receiver = effect = Node* receiver = effect = graph()->NewNode(
graph()->NewNode(simplified()->CheckString(p.feedback()), simplified()->CheckString(p.feedback()), n.receiver(), effect, control);
NodeProperties::GetValueInput(node, 1), effect, control);
if (node->op()->ValueInputCount() < 3) { if (parameter_count == 0) {
ReplaceWithValue(node, receiver, effect, control); ReplaceWithValue(node, receiver, effect, control);
return Replace(receiver); return Replace(receiver);
} }
Node* argument = effect = Node* argument = effect = graph()->NewNode(
graph()->NewNode(simplified()->CheckString(p.feedback()), simplified()->CheckString(p.feedback()), n.Argument(0), effect, control);
NodeProperties::GetValueInput(node, 2), effect, control);
Node* receiver_length = Node* receiver_length =
graph()->NewNode(simplified()->StringLength(), receiver); graph()->NewNode(simplified()->StringLength(), receiver);
Node* argument_length = Node* argument_length =
...@@ -6277,8 +6286,9 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) { ...@@ -6277,8 +6286,9 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
MapInference inference(broker(), receiver, effect); MapInference inference(broker(), receiver, effect);
if (!DoPromiseChecks(&inference)) return inference.NoChange(); if (!DoPromiseChecks(&inference)) return inference.NoChange();
if (!dependencies()->DependOnPromiseThenProtector()) if (!dependencies()->DependOnPromiseThenProtector()) {
return inference.NoChange(); return inference.NoChange();
}
inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect, inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
control, p.feedback()); control, p.feedback());
...@@ -6294,7 +6304,7 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) { ...@@ -6294,7 +6304,7 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
} }
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
node, javascript()->Call( node, javascript()->Call(
arity + kTargetAndReceiver, p.frequency(), p.feedback(), JSCallNode::ArityForArgc(arity), p.frequency(), p.feedback(),
ConvertReceiverMode::kNotNullOrUndefined, p.speculation_mode(), ConvertReceiverMode::kNotNullOrUndefined, p.speculation_mode(),
CallFeedbackRelation::kUnrelated)); CallFeedbackRelation::kUnrelated));
return Changed(node).FollowedBy(ReducePromisePrototypeThen(node)); return Changed(node).FollowedBy(ReducePromisePrototypeThen(node));
...@@ -6315,14 +6325,13 @@ Node* JSCallReducer::CreateClosureFromBuiltinSharedFunctionInfo( ...@@ -6315,14 +6325,13 @@ Node* JSCallReducer::CreateClosureFromBuiltinSharedFunctionInfo(
Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) { Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
DisallowHeapAccessIf no_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
int arity = p.arity_without_implicit_args(); int arity = p.arity_without_implicit_args();
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* on_finally = arity >= 1 ? NodeProperties::GetValueInput(node, 2) Node* on_finally = n.ArgumentOrUndefined(0, jsgraph());
: jsgraph()->UndefinedConstant(); Effect effect = n.effect();
Node* effect = NodeProperties::GetEffectInput(node); Control control = n.control();
Node* control = NodeProperties::GetControlInput(node);
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
...@@ -6331,12 +6340,15 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) { ...@@ -6331,12 +6340,15 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
if (!DoPromiseChecks(&inference)) return inference.NoChange(); if (!DoPromiseChecks(&inference)) return inference.NoChange();
MapHandles const& receiver_maps = inference.GetMaps(); MapHandles const& receiver_maps = inference.GetMaps();
if (!dependencies()->DependOnPromiseHookProtector()) if (!dependencies()->DependOnPromiseHookProtector()) {
return inference.NoChange(); return inference.NoChange();
if (!dependencies()->DependOnPromiseThenProtector()) }
if (!dependencies()->DependOnPromiseThenProtector()) {
return inference.NoChange(); return inference.NoChange();
if (!dependencies()->DependOnPromiseSpeciesProtector()) }
if (!dependencies()->DependOnPromiseSpeciesProtector()) {
return inference.NoChange(); return inference.NoChange();
}
inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect, inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
control, p.feedback()); control, p.feedback());
...@@ -6413,17 +6425,18 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) { ...@@ -6413,17 +6425,18 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
// following the onFinally parameter, and then replacing the only parameter // following the onFinally parameter, and then replacing the only parameter
// input with the {on_finally} value. // input with the {on_finally} value.
Node* target = jsgraph()->Constant(native_context().promise_then()); Node* target = jsgraph()->Constant(native_context().promise_then());
NodeProperties::ReplaceValueInput(node, target, 0); NodeProperties::ReplaceValueInput(node, target, n.TargetIndex());
NodeProperties::ReplaceEffectInput(node, effect); NodeProperties::ReplaceEffectInput(node, effect);
NodeProperties::ReplaceControlInput(node, control); NodeProperties::ReplaceControlInput(node, control);
for (; arity > 2; --arity) node->RemoveInput(2); for (; arity > 2; --arity) node->RemoveInput(2);
for (; arity < 2; ++arity) for (; arity < 2; ++arity) {
node->InsertInput(graph()->zone(), 2, then_finally); node->InsertInput(graph()->zone(), 2, then_finally);
}
node->ReplaceInput(2, then_finally); node->ReplaceInput(2, then_finally);
node->ReplaceInput(3, catch_finally); node->ReplaceInput(3, catch_finally);
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
node, javascript()->Call( node, javascript()->Call(
arity + kTargetAndReceiver, p.frequency(), p.feedback(), JSCallNode::ArityForArgc(arity), p.frequency(), p.feedback(),
ConvertReceiverMode::kNotNullOrUndefined, p.speculation_mode(), ConvertReceiverMode::kNotNullOrUndefined, p.speculation_mode(),
CallFeedbackRelation::kUnrelated)); CallFeedbackRelation::kUnrelated));
return Changed(node).FollowedBy(ReducePromisePrototypeThen(node)); return Changed(node).FollowedBy(ReducePromisePrototypeThen(node));
...@@ -6432,31 +6445,29 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) { ...@@ -6432,31 +6445,29 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) { Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
DisallowHeapAccessIf no_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* on_fulfilled = node->op()->ValueInputCount() > 2 Node* on_fulfilled = n.ArgumentOrUndefined(0, jsgraph());
? NodeProperties::GetValueInput(node, 2) Node* on_rejected = n.ArgumentOrUndefined(1, jsgraph());
: jsgraph()->UndefinedConstant(); Node* context = n.context();
Node* on_rejected = node->op()->ValueInputCount() > 3 Effect effect = n.effect();
? NodeProperties::GetValueInput(node, 3) Control control = n.control();
: jsgraph()->UndefinedConstant(); FrameState frame_state = n.frame_state();
Node* context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node);
MapInference inference(broker(), receiver, effect); MapInference inference(broker(), receiver, effect);
if (!DoPromiseChecks(&inference)) return inference.NoChange(); if (!DoPromiseChecks(&inference)) return inference.NoChange();
if (!dependencies()->DependOnPromiseHookProtector()) if (!dependencies()->DependOnPromiseHookProtector()) {
return inference.NoChange(); return inference.NoChange();
if (!dependencies()->DependOnPromiseSpeciesProtector()) }
if (!dependencies()->DependOnPromiseSpeciesProtector()) {
return inference.NoChange(); return inference.NoChange();
}
inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect, inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
control, p.feedback()); control, p.feedback());
...@@ -6500,15 +6511,13 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) { ...@@ -6500,15 +6511,13 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
Reduction JSCallReducer::ReducePromiseResolveTrampoline(Node* node) { Reduction JSCallReducer::ReducePromiseResolveTrampoline(Node* node) {
DisallowHeapAccessIf no_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Node* value = node->op()->ValueInputCount() > 2 Node* value = n.ArgumentOrUndefined(0, jsgraph());
? NodeProperties::GetValueInput(node, 2) Node* context = n.context();
: jsgraph()->UndefinedConstant(); Effect effect = n.effect();
Node* context = NodeProperties::GetContextInput(node); Control control = n.control();
Node* frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state = n.frame_state();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Only reduce when the receiver is guaranteed to be a JSReceiver. // Only reduce when the receiver is guaranteed to be a JSReceiver.
MapInference inference(broker(), receiver, effect); MapInference inference(broker(), receiver, effect);
...@@ -6643,12 +6652,13 @@ Reduction JSCallReducer::ReduceTypedArrayPrototypeToStringTag(Node* node) { ...@@ -6643,12 +6652,13 @@ Reduction JSCallReducer::ReduceTypedArrayPrototypeToStringTag(Node* node) {
// ES #sec-number.isfinite // ES #sec-number.isfinite
Reduction JSCallReducer::ReduceNumberIsFinite(Node* node) { Reduction JSCallReducer::ReduceNumberIsFinite(Node* node) {
if (node->op()->ValueInputCount() < 3) { JSCallNode n(node);
if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->FalseConstant(); Node* value = jsgraph()->FalseConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
Node* input = NodeProperties::GetValueInput(node, 2); Node* input = n.Argument(0);
Node* value = graph()->NewNode(simplified()->ObjectIsFiniteNumber(), input); Node* value = graph()->NewNode(simplified()->ObjectIsFiniteNumber(), input);
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
...@@ -6656,12 +6666,13 @@ Reduction JSCallReducer::ReduceNumberIsFinite(Node* node) { ...@@ -6656,12 +6666,13 @@ Reduction JSCallReducer::ReduceNumberIsFinite(Node* node) {
// ES #sec-number.isfinite // ES #sec-number.isfinite
Reduction JSCallReducer::ReduceNumberIsInteger(Node* node) { Reduction JSCallReducer::ReduceNumberIsInteger(Node* node) {
if (node->op()->ValueInputCount() < 3) { JSCallNode n(node);
if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->FalseConstant(); Node* value = jsgraph()->FalseConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
Node* input = NodeProperties::GetValueInput(node, 2); Node* input = n.Argument(0);
Node* value = graph()->NewNode(simplified()->ObjectIsInteger(), input); Node* value = graph()->NewNode(simplified()->ObjectIsInteger(), input);
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
...@@ -6669,12 +6680,13 @@ Reduction JSCallReducer::ReduceNumberIsInteger(Node* node) { ...@@ -6669,12 +6680,13 @@ Reduction JSCallReducer::ReduceNumberIsInteger(Node* node) {
// ES #sec-number.issafeinteger // ES #sec-number.issafeinteger
Reduction JSCallReducer::ReduceNumberIsSafeInteger(Node* node) { Reduction JSCallReducer::ReduceNumberIsSafeInteger(Node* node) {
if (node->op()->ValueInputCount() < 3) { JSCallNode n(node);
if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->FalseConstant(); Node* value = jsgraph()->FalseConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
Node* input = NodeProperties::GetValueInput(node, 2); Node* input = n.Argument(0);
Node* value = graph()->NewNode(simplified()->ObjectIsSafeInteger(), input); Node* value = graph()->NewNode(simplified()->ObjectIsSafeInteger(), input);
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
...@@ -6682,12 +6694,13 @@ Reduction JSCallReducer::ReduceNumberIsSafeInteger(Node* node) { ...@@ -6682,12 +6694,13 @@ Reduction JSCallReducer::ReduceNumberIsSafeInteger(Node* node) {
// ES #sec-number.isnan // ES #sec-number.isnan
Reduction JSCallReducer::ReduceNumberIsNaN(Node* node) { Reduction JSCallReducer::ReduceNumberIsNaN(Node* node) {
if (node->op()->ValueInputCount() < 3) { JSCallNode n(node);
if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->FalseConstant(); Node* value = jsgraph()->FalseConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
Node* input = NodeProperties::GetValueInput(node, 2); Node* input = n.Argument(0);
Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input); Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input);
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
...@@ -6695,7 +6708,8 @@ Reduction JSCallReducer::ReduceNumberIsNaN(Node* node) { ...@@ -6695,7 +6708,8 @@ Reduction JSCallReducer::ReduceNumberIsNaN(Node* node) {
Reduction JSCallReducer::ReduceMapPrototypeGet(Node* node) { Reduction JSCallReducer::ReduceMapPrototypeGet(Node* node) {
// We only optimize if we have target, receiver and key parameters. // We only optimize if we have target, receiver and key parameters.
if (node->op()->ValueInputCount() != 3) return NoChange(); JSCallNode n(node);
if (n.ArgumentCount() != 1) return NoChange();
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
...@@ -6741,7 +6755,8 @@ Reduction JSCallReducer::ReduceMapPrototypeGet(Node* node) { ...@@ -6741,7 +6755,8 @@ Reduction JSCallReducer::ReduceMapPrototypeGet(Node* node) {
Reduction JSCallReducer::ReduceMapPrototypeHas(Node* node) { Reduction JSCallReducer::ReduceMapPrototypeHas(Node* node) {
// We only optimize if we have target, receiver and key parameters. // We only optimize if we have target, receiver and key parameters.
if (node->op()->ValueInputCount() != 3) return NoChange(); JSCallNode n(node);
if (n.ArgumentCount() != 1) return NoChange();
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
...@@ -7124,9 +7139,8 @@ Reduction JSCallReducer::ReduceCollectionIteratorPrototypeNext( ...@@ -7124,9 +7139,8 @@ Reduction JSCallReducer::ReduceCollectionIteratorPrototypeNext(
Reduction JSCallReducer::ReduceArrayBufferIsView(Node* node) { Reduction JSCallReducer::ReduceArrayBufferIsView(Node* node) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
Node* value = node->op()->ValueInputCount() >= 3 JSCallNode n(node);
? NodeProperties::GetValueInput(node, 2) Node* value = n.ArgumentOrUndefined(0, jsgraph());
: jsgraph()->UndefinedConstant();
RelaxEffectsAndControls(node); RelaxEffectsAndControls(node);
node->ReplaceInput(0, value); node->ReplaceInput(0, value);
node->TrimInputCount(1); node->TrimInputCount(1);
...@@ -7199,26 +7213,20 @@ uint32_t ExternalArrayElementSize(const ExternalArrayType element_type) { ...@@ -7199,26 +7213,20 @@ uint32_t ExternalArrayElementSize(const ExternalArrayType element_type) {
Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access, Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access,
ExternalArrayType element_type) { ExternalArrayType element_type) {
DCHECK_EQ(node->opcode(), IrOpcode::kJSCall); JSCallNode n(node);
CallParameters const& p = n.Parameters();
size_t const element_size = ExternalArrayElementSize(element_type); size_t const element_size = ExternalArrayElementSize(element_type);
CallParameters const& p = CallParametersOf(node->op()); Effect effect = n.effect();
Node* effect = NodeProperties::GetEffectInput(node); Control control = n.control();
Node* control = NodeProperties::GetControlInput(node); Node* receiver = n.receiver();
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* offset = n.ArgumentOr(0, jsgraph()->ZeroConstant());
Node* offset = node->op()->ValueInputCount() > 2
? NodeProperties::GetValueInput(node, 2)
: jsgraph()->ZeroConstant();
Node* value = nullptr; Node* value = nullptr;
if (access == DataViewAccess::kSet) { if (access == DataViewAccess::kSet) {
value = node->op()->ValueInputCount() > 3 value = n.ArgumentOrUndefined(1, jsgraph());
? NodeProperties::GetValueInput(node, 3)
: jsgraph()->UndefinedConstant();
} }
const int endian_index = (access == DataViewAccess::kGet ? 3 : 4); const int endian_index = (access == DataViewAccess::kGet ? 1 : 2);
Node* is_little_endian = Node* is_little_endian =
(node->op()->ValueInputCount() > endian_index n.ArgumentOr(endian_index, jsgraph()->FalseConstant());
? NodeProperties::GetValueInput(node, endian_index)
: jsgraph()->FalseConstant());
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
...@@ -7340,19 +7348,20 @@ Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access, ...@@ -7340,19 +7348,20 @@ Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access,
// ES6 section 18.2.2 isFinite ( number ) // ES6 section 18.2.2 isFinite ( number )
Reduction JSCallReducer::ReduceGlobalIsFinite(Node* node) { Reduction JSCallReducer::ReduceGlobalIsFinite(Node* node) {
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() < 3) { if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->FalseConstant(); Node* value = jsgraph()->FalseConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* input = NodeProperties::GetValueInput(node, 2); Node* input = n.Argument(0);
input = effect = input = effect =
graph()->NewNode(simplified()->SpeculativeToNumber( graph()->NewNode(simplified()->SpeculativeToNumber(
...@@ -7365,19 +7374,20 @@ Reduction JSCallReducer::ReduceGlobalIsFinite(Node* node) { ...@@ -7365,19 +7374,20 @@ Reduction JSCallReducer::ReduceGlobalIsFinite(Node* node) {
// ES6 section 18.2.3 isNaN ( number ) // ES6 section 18.2.3 isNaN ( number )
Reduction JSCallReducer::ReduceGlobalIsNaN(Node* node) { Reduction JSCallReducer::ReduceGlobalIsNaN(Node* node) {
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() < 3) { if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->TrueConstant(); Node* value = jsgraph()->TrueConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* input = NodeProperties::GetValueInput(node, 2); Node* input = n.Argument(0);
input = effect = input = effect =
graph()->NewNode(simplified()->SpeculativeToNumber( graph()->NewNode(simplified()->SpeculativeToNumber(
...@@ -7418,21 +7428,19 @@ Reduction JSCallReducer::ReduceDateNow(Node* node) { ...@@ -7418,21 +7428,19 @@ Reduction JSCallReducer::ReduceDateNow(Node* node) {
// ES6 section 20.1.2.13 Number.parseInt ( string, radix ) // ES6 section 20.1.2.13 Number.parseInt ( string, radix )
Reduction JSCallReducer::ReduceNumberParseInt(Node* node) { Reduction JSCallReducer::ReduceNumberParseInt(Node* node) {
// We certainly know that undefined is not an array. JSCallNode n(node);
if (node->op()->ValueInputCount() < 3) { if (n.ArgumentCount() < 1) {
Node* value = jsgraph()->NaNConstant(); Node* value = jsgraph()->NaNConstant();
ReplaceWithValue(node, value); ReplaceWithValue(node, value);
return Replace(value); return Replace(value);
} }
int arg_count = node->op()->ValueInputCount(); Effect effect = n.effect();
Node* effect = NodeProperties::GetEffectInput(node); Control control = n.control();
Node* control = NodeProperties::GetControlInput(node); Node* context = n.context();
Node* context = NodeProperties::GetContextInput(node); FrameState frame_state = n.frame_state();
Node* frame_state = NodeProperties::GetFrameStateInput(node); Node* object = n.Argument(0);
Node* object = NodeProperties::GetValueInput(node, 2); Node* radix = n.ArgumentOrUndefined(1, jsgraph());
Node* radix = arg_count >= 4 ? NodeProperties::GetValueInput(node, 3)
: jsgraph()->UndefinedConstant();
node->ReplaceInput(0, object); node->ReplaceInput(0, object);
node->ReplaceInput(1, radix); node->ReplaceInput(1, radix);
node->ReplaceInput(2, context); node->ReplaceInput(2, context);
...@@ -7447,17 +7455,18 @@ Reduction JSCallReducer::ReduceNumberParseInt(Node* node) { ...@@ -7447,17 +7455,18 @@ Reduction JSCallReducer::ReduceNumberParseInt(Node* node) {
Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) { Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access()); DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (FLAG_force_slow_path) return NoChange(); if (FLAG_force_slow_path) return NoChange();
if (node->op()->ValueInputCount() < 3) return NoChange(); if (n.ArgumentCount() < 1) return NoChange();
CallParameters const& p = CallParametersOf(node->op());
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* regexp = NodeProperties::GetValueInput(node, 1); Node* regexp = n.receiver();
// Only the initial JSRegExp map is valid here, since the following lastIndex // Only the initial JSRegExp map is valid here, since the following lastIndex
// check as well as the lowered builtin call rely on a known location of the // check as well as the lowered builtin call rely on a known location of the
...@@ -7520,9 +7529,9 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) { ...@@ -7520,9 +7529,9 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect, inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
control, p.feedback()); control, p.feedback());
Node* context = NodeProperties::GetContextInput(node); Node* context = n.context();
Node* frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state = n.frame_state();
Node* search = NodeProperties::GetValueInput(node, 2); Node* search = n.Argument(0);
Node* search_string = effect = graph()->NewNode( Node* search_string = effect = graph()->NewNode(
simplified()->CheckString(p.feedback()), search, effect, control); simplified()->CheckString(p.feedback()), search, effect, control);
...@@ -7553,14 +7562,12 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) { ...@@ -7553,14 +7562,12 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
// ES section #sec-number-constructor // ES section #sec-number-constructor
Reduction JSCallReducer::ReduceNumberConstructor(Node* node) { Reduction JSCallReducer::ReduceNumberConstructor(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); Node* target = n.target();
Node* target = NodeProperties::GetValueInput(node, 0); Node* receiver = n.receiver();
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* value = n.ArgumentOr(0, jsgraph()->ZeroConstant());
Node* value = p.arity() < 3 ? jsgraph()->ZeroConstant() Node* context = n.context();
: NodeProperties::GetValueInput(node, 2); FrameState frame_state = n.frame_state();
Node* context = NodeProperties::GetContextInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node);
// Create the artificial frame state in the middle of the Number constructor. // Create the artificial frame state in the middle of the Number constructor.
SharedFunctionInfoRef shared_info = SharedFunctionInfoRef shared_info =
...@@ -7581,22 +7588,21 @@ Reduction JSCallReducer::ReduceNumberConstructor(Node* node) { ...@@ -7581,22 +7588,21 @@ Reduction JSCallReducer::ReduceNumberConstructor(Node* node) {
} }
Reduction JSCallReducer::ReduceBigIntAsUintN(Node* node) { Reduction JSCallReducer::ReduceBigIntAsUintN(Node* node) {
if (!jsgraph()->machine()->Is64()) { if (!jsgraph()->machine()->Is64()) return NoChange();
return NoChange();
}
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) { if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange(); return NoChange();
} }
if (node->op()->ValueInputCount() < 4) { if (n.ArgumentCount() < 2) {
return NoChange(); return NoChange();
} }
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
Node* bits = NodeProperties::GetValueInput(node, 2); Node* bits = n.Argument(0);
Node* value = NodeProperties::GetValueInput(node, 3); Node* value = n.Argument(1);
NumberMatcher matcher(bits); NumberMatcher matcher(bits);
if (matcher.IsInteger() && matcher.IsInRange(0, 64)) { if (matcher.IsInteger() && matcher.IsInRange(0, 64)) {
......
...@@ -216,7 +216,8 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { ...@@ -216,7 +216,8 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
void CheckIfElementsKind(Node* receiver_elements_kind, ElementsKind kind, void CheckIfElementsKind(Node* receiver_elements_kind, ElementsKind kind,
Node* control, Node** if_true, Node** if_false); Node* control, Node** if_true, Node** if_false);
Node* LoadReceiverElementsKind(Node* receiver, Node** effect, Node** control); Node* LoadReceiverElementsKind(Node* receiver, Effect* effect,
Control control);
bool IsBuiltinOrApiFunction(JSFunctionRef target_ref) const; bool IsBuiltinOrApiFunction(JSFunctionRef target_ref) const;
......
...@@ -935,10 +935,14 @@ void JSGenericLowering::LowerJSCallForwardVarargs(Node* node) { ...@@ -935,10 +935,14 @@ void JSGenericLowering::LowerJSCallForwardVarargs(Node* node) {
} }
void JSGenericLowering::LowerJSCall(Node* node) { void JSGenericLowering::LowerJSCall(Node* node) {
CallParameters const& p = CallParametersOf(node->op()); JSCallNode n(node);
CallParameters const& p = n.Parameters();
int const arg_count = p.arity_without_implicit_args(); int const arg_count = p.arity_without_implicit_args();
ConvertReceiverMode const mode = p.convert_mode(); ConvertReceiverMode const mode = p.convert_mode();
Node* feedback_vector = n.feedback_vector();
node->RemoveInput(n.FeedbackVectorIndex());
if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) { if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
Callable callable = CodeFactory::Call_WithFeedback(isolate(), mode); Callable callable = CodeFactory::Call_WithFeedback(isolate(), mode);
CallDescriptor::Flags flags = FrameStateFlagForCall(node); CallDescriptor::Flags flags = FrameStateFlagForCall(node);
...@@ -946,7 +950,6 @@ void JSGenericLowering::LowerJSCall(Node* node) { ...@@ -946,7 +950,6 @@ void JSGenericLowering::LowerJSCall(Node* node) {
zone(), callable.descriptor(), arg_count + 1, flags); zone(), callable.descriptor(), arg_count + 1, flags);
Node* stub_code = jsgraph()->HeapConstant(callable.code()); Node* stub_code = jsgraph()->HeapConstant(callable.code());
Node* stub_arity = jsgraph()->Int32Constant(arg_count); Node* stub_arity = jsgraph()->Int32Constant(arg_count);
Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector);
Node* slot = jsgraph()->Int32Constant(p.feedback().index()); Node* slot = jsgraph()->Int32Constant(p.feedback().index());
node->InsertInput(zone(), 0, stub_code); node->InsertInput(zone(), 0, stub_code);
node->InsertInput(zone(), 2, stub_arity); node->InsertInput(zone(), 2, stub_arity);
......
...@@ -50,36 +50,44 @@ class JSCallAccessor { ...@@ -50,36 +50,44 @@ class JSCallAccessor {
call->opcode() == IrOpcode::kJSConstruct); call->opcode() == IrOpcode::kJSConstruct);
} }
Node* target() { Node* target() const {
// Both, {JSCall} and {JSConstruct}, have same layout here. // Both, {JSCall} and {JSConstruct}, have same layout here.
return call_->InputAt(0); return call_->InputAt(0);
} }
Node* receiver() { Node* receiver() const {
DCHECK_EQ(IrOpcode::kJSCall, call_->opcode()); DCHECK_EQ(IrOpcode::kJSCall, call_->opcode());
return call_->InputAt(1); return JSCallNode{call_}.receiver();
} }
Node* new_target() { Node* new_target() const {
DCHECK_EQ(IrOpcode::kJSConstruct, call_->opcode()); DCHECK_EQ(IrOpcode::kJSConstruct, call_->opcode());
return call_->InputAt(formal_arguments() + 1); return call_->InputAt(formal_arguments() + 1);
} }
Node* frame_state() { Node* argument(int i) const {
// Both, {JSCall} and {JSConstruct}, have same layout here.
static constexpr int kFirstArgumentIndex = 2;
STATIC_ASSERT(kFirstArgumentIndex == JSCallNode::FirstArgumentIndex());
return call_->InputAt(kFirstArgumentIndex + i);
}
Node* frame_state() const {
// Both, {JSCall} and {JSConstruct}, have frame state. // Both, {JSCall} and {JSConstruct}, have frame state.
return NodeProperties::GetFrameStateInput(call_); return NodeProperties::GetFrameStateInput(call_);
} }
int formal_arguments() { int formal_arguments() const {
// Both, {JSCall} and {JSConstruct}, have two extra inputs: // TODO(jgruber): Remove once the JSConstructNode wrapper is
// - JSConstruct: Includes target function and new target. // implemented.
// - JSCall: Includes target function and receiver. return (call_->opcode() == IrOpcode::kJSCall)
return call_->op()->ValueInputCount() - 2; ? JSCallNode{call_}.ArgumentCount()
: call_->op()->ValueInputCount() - kTargetAndNewTarget;
} }
CallFrequency const& frequency() const { CallFrequency const& frequency() const {
return (call_->opcode() == IrOpcode::kJSCall) return (call_->opcode() == IrOpcode::kJSCall)
? CallParametersOf(call_->op()).frequency() ? JSCallNode{call_}.Parameters().frequency()
: ConstructParametersOf(call_->op()).frequency(); : ConstructParametersOf(call_->op()).frequency();
} }
...@@ -106,7 +114,13 @@ Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context, ...@@ -106,7 +114,13 @@ Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context,
// {inliner_inputs} counts JSFunction, receiver, arguments, but not // {inliner_inputs} counts JSFunction, receiver, arguments, but not
// new target value, argument count, context, effect or control. // new target value, argument count, context, effect or control.
int inliner_inputs = call->op()->ValueInputCount(); // TODO(jgruber): Refactor this once JSConstructNode is implemented.
STATIC_ASSERT(kTargetAndNewTarget == 2);
const bool inliner_is_call = call->opcode() == IrOpcode::kJSCall;
const int inliner_inputs = inliner_is_call
? call->op()->ValueInputCount() -
JSCallNode::kFeedbackVectorInputCount
: call->op()->ValueInputCount();
// Iterate over all uses of the start node. // Iterate over all uses of the start node.
for (Edge edge : start->use_edges()) { for (Edge edge : start->use_edges()) {
Node* use = edge.from(); Node* use = edge.from();
...@@ -123,6 +137,9 @@ Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context, ...@@ -123,6 +137,9 @@ Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context,
Replace(use, new_target); Replace(use, new_target);
} else if (index == inlinee_arity_index) { } else if (index == inlinee_arity_index) {
// The projection is requesting the number of arguments. // The projection is requesting the number of arguments.
STATIC_ASSERT(JSCallNode::kExtraInputCount ==
JSCallNode::kFeedbackVectorInputCount + 2);
STATIC_ASSERT(kTargetAndNewTarget == 2);
Replace(use, jsgraph()->Constant(inliner_inputs - 2)); Replace(use, jsgraph()->Constant(inliner_inputs - 2));
} else if (index == inlinee_context_index) { } else if (index == inlinee_context_index) {
// The projection is requesting the inlinee function context. // The projection is requesting the inlinee function context.
...@@ -240,31 +257,36 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state, ...@@ -240,31 +257,36 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state,
FrameStateType frame_state_type, FrameStateType frame_state_type,
SharedFunctionInfoRef shared, SharedFunctionInfoRef shared,
Node* context) { Node* context) {
const int parameter_count_with_receiver =
parameter_count + JSCallNode::kReceiverInputCount;
const FrameStateFunctionInfo* state_info = const FrameStateFunctionInfo* state_info =
common()->CreateFrameStateFunctionInfo( common()->CreateFrameStateFunctionInfo(
frame_state_type, parameter_count + 1, 0, shared.object()); frame_state_type, parameter_count_with_receiver, 0, shared.object());
const Operator* op = common()->FrameState( const Operator* op = common()->FrameState(
bailout_id, OutputFrameStateCombine::Ignore(), state_info); bailout_id, OutputFrameStateCombine::Ignore(), state_info);
const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense()); const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
Node* node0 = graph()->NewNode(op0); Node* node0 = graph()->NewNode(op0);
static constexpr int kTargetInputIndex = 0; // Note how we refer to 'receiver' even though `node` may be a
static constexpr int kReceiverInputIndex = 1; // JSConstruct node. That's because the layout of construct nodes
const int parameter_count_with_receiver = parameter_count + 1; // has been modified to look like call nodes in `ReduceJSCall`; the
// `new_target` has been put into the receiver slot.
// TODO(jgruber): Either unify the layout of these two nodes, or
// refactor this to be more expected in some way.
JSCallAccessor call(node);
NodeVector params(local_zone_); NodeVector params(local_zone_);
for (int i = 0; i < parameter_count_with_receiver; i++) { params.push_back(node->InputAt(JSCallNode::ReceiverIndex()));
params.push_back(node->InputAt(kReceiverInputIndex + i)); for (int i = 0; i < parameter_count; i++) {
params.push_back(call.argument(i));
} }
const Operator* op_param = common()->StateValues( const Operator* op_param = common()->StateValues(
static_cast<int>(params.size()), SparseInputMask::Dense()); static_cast<int>(params.size()), SparseInputMask::Dense());
Node* params_node = graph()->NewNode( Node* params_node = graph()->NewNode(
op_param, static_cast<int>(params.size()), &params.front()); op_param, static_cast<int>(params.size()), &params.front());
if (!context) { if (context == nullptr) context = jsgraph()->UndefinedConstant();
context = jsgraph()->UndefinedConstant(); return graph()->NewNode(op, params_node, node0, node0, context, call.target(),
} outer_frame_state);
return graph()->NewNode(op, params_node, node0, node0, context,
node->InputAt(kTargetInputIndex), outer_frame_state);
} }
namespace { namespace {
...@@ -283,7 +305,7 @@ bool NeedsImplicitReceiver(SharedFunctionInfoRef shared_info) { ...@@ -283,7 +305,7 @@ bool NeedsImplicitReceiver(SharedFunctionInfoRef shared_info) {
base::Optional<SharedFunctionInfoRef> JSInliner::DetermineCallTarget( base::Optional<SharedFunctionInfoRef> JSInliner::DetermineCallTarget(
Node* node) { Node* node) {
DCHECK(IrOpcode::IsInlineeOpcode(node->opcode())); DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
HeapObjectMatcher match(node->InputAt(0)); HeapObjectMatcher match(node->InputAt(JSCallNode::TargetIndex()));
// This reducer can handle both normal function calls as well a constructor // This reducer can handle both normal function calls as well a constructor
// calls whenever the target is a constant function object, as follows: // calls whenever the target is a constant function object, as follows:
...@@ -336,7 +358,7 @@ base::Optional<SharedFunctionInfoRef> JSInliner::DetermineCallTarget( ...@@ -336,7 +358,7 @@ base::Optional<SharedFunctionInfoRef> JSInliner::DetermineCallTarget(
FeedbackVectorRef JSInliner::DetermineCallContext(Node* node, FeedbackVectorRef JSInliner::DetermineCallContext(Node* node,
Node** context_out) { Node** context_out) {
DCHECK(IrOpcode::IsInlineeOpcode(node->opcode())); DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
HeapObjectMatcher match(node->InputAt(0)); HeapObjectMatcher match(node->InputAt(JSCallNode::TargetIndex()));
if (match.HasValue() && match.Ref(broker()).IsJSFunction()) { if (match.HasValue() && match.Ref(broker()).IsJSFunction()) {
JSFunctionRef function = match.Ref(broker()).AsJSFunction(); JSFunctionRef function = match.Ref(broker()).AsJSFunction();
...@@ -507,8 +529,10 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -507,8 +529,10 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// normal {JSCall} node so that the rest of the inlining machinery // normal {JSCall} node so that the rest of the inlining machinery
// behaves as if we were dealing with a regular function invocation. // behaves as if we were dealing with a regular function invocation.
new_target = call.new_target(); // Retrieve new target value input. new_target = call.new_target(); // Retrieve new target value input.
// TODO(jgruber,v8:8888): Update when JSConstruct nodes also gain a
// feedback vector input.
node->RemoveInput(call.formal_arguments() + 1); // Drop new target. node->RemoveInput(call.formal_arguments() + 1); // Drop new target.
node->InsertInput(graph()->zone(), 1, new_target); node->InsertInput(graph()->zone(), JSCallNode::ReceiverIndex(), new_target);
// Insert nodes around the call that model the behavior required for a // Insert nodes around the call that model the behavior required for a
// constructor dispatch (allocate implicit receiver and check return value). // constructor dispatch (allocate implicit receiver and check return value).
...@@ -575,7 +599,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -575,7 +599,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// Fix input destroyed by the above {ReplaceWithValue} call. // Fix input destroyed by the above {ReplaceWithValue} call.
NodeProperties::ReplaceControlInput(branch_is_receiver, node_success, 0); NodeProperties::ReplaceControlInput(branch_is_receiver, node_success, 0);
} }
node->ReplaceInput(1, receiver); node->ReplaceInput(JSCallNode::ReceiverIndex(), receiver);
// Insert a construct stub frame into the chain of frame states. This will // Insert a construct stub frame into the chain of frame states. This will
// reconstruct the proper frame when deoptimizing within the constructor. // reconstruct the proper frame when deoptimizing within the constructor.
frame_state = CreateArtificialFrameState( frame_state = CreateArtificialFrameState(
...@@ -596,7 +620,8 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -596,7 +620,8 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
Node* receiver = effect = Node* receiver = effect =
graph()->NewNode(simplified()->ConvertReceiver(p.convert_mode()), graph()->NewNode(simplified()->ConvertReceiver(p.convert_mode()),
call.receiver(), global_proxy, effect, start); call.receiver(), global_proxy, effect, start);
NodeProperties::ReplaceValueInput(node, receiver, 1); NodeProperties::ReplaceValueInput(node, receiver,
JSCallNode::ReceiverIndex());
NodeProperties::ReplaceEffectInput(node, effect); NodeProperties::ReplaceEffectInput(node, effect);
} }
} }
......
...@@ -330,8 +330,14 @@ Reduction JSIntrinsicLowering::ReduceToString(Node* node) { ...@@ -330,8 +330,14 @@ Reduction JSIntrinsicLowering::ReduceToString(Node* node) {
Reduction JSIntrinsicLowering::ReduceCall(Node* node) { Reduction JSIntrinsicLowering::ReduceCall(Node* node) {
size_t const arity = CallRuntimeParametersOf(node->op()).arity(); int const arity =
NodeProperties::ChangeOp(node, javascript()->Call(arity)); static_cast<int>(CallRuntimeParametersOf(node->op()).arity());
static constexpr int kTargetAndReceiver = 2;
Node* feedback = jsgraph()->UndefinedConstant();
node->InsertInput(graph()->zone(), arity, feedback);
NodeProperties::ChangeOp(
node,
javascript()->Call(JSCallNode::ArityForArgc(arity - kTargetAndReceiver)));
return Changed(node); return Changed(node);
} }
......
...@@ -482,13 +482,20 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { ...@@ -482,13 +482,20 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
// Call the @@hasInstance handler. // Call the @@hasInstance handler.
Node* target = jsgraph()->Constant(*constant); Node* target = jsgraph()->Constant(*constant);
node->InsertInput(graph()->zone(), 0, target); Node* feedback = jsgraph()->UndefinedConstant();
node->ReplaceInput(1, constructor); // Value inputs plus context, frame state, effect, control.
node->ReplaceInput(2, object); STATIC_ASSERT(JSCallNode::ArityForArgc(1) + 4 == 8);
node->ReplaceInput(4, continuation_frame_state); node->EnsureInputCount(graph()->zone(), 8);
node->ReplaceInput(5, effect); node->ReplaceInput(JSCallNode::TargetIndex(), target);
node->ReplaceInput(JSCallNode::ReceiverIndex(), constructor);
node->ReplaceInput(JSCallNode::ArgumentIndex(0), object);
node->ReplaceInput(3, feedback);
node->ReplaceInput(4, context);
node->ReplaceInput(5, continuation_frame_state);
node->ReplaceInput(6, effect);
node->ReplaceInput(7, control);
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
node, javascript()->Call(1 + kTargetAndReceiver, CallFrequency(), node, javascript()->Call(JSCallNode::ArityForArgc(1), CallFrequency(),
FeedbackSource(), FeedbackSource(),
ConvertReceiverMode::kNotNullOrUndefined)); ConvertReceiverMode::kNotNullOrUndefined));
...@@ -1430,11 +1437,12 @@ Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) { ...@@ -1430,11 +1437,12 @@ Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) {
? SpeculationMode::kDisallowSpeculation ? SpeculationMode::kDisallowSpeculation
: feedback.AsCall().speculation_mode(); : feedback.AsCall().speculation_mode();
const Operator* call_op = javascript()->Call( const Operator* call_op = javascript()->Call(
0 + kTargetAndReceiver, CallFrequency(), p.callFeedback(), JSCallNode::ArityForArgc(0), CallFrequency(), p.callFeedback(),
ConvertReceiverMode::kNotNullOrUndefined, mode, ConvertReceiverMode::kNotNullOrUndefined, mode,
CallFeedbackRelation::kRelated); CallFeedbackRelation::kRelated);
Node* call_property = graph()->NewNode(call_op, load_property, receiver, Node* call_property =
context, frame_state, effect, control); graph()->NewNode(call_op, load_property, receiver, n.feedback_vector(),
context, frame_state, effect, control);
return Replace(call_property); return Replace(call_property);
} }
...@@ -2043,11 +2051,12 @@ Node* JSNativeContextSpecialization::InlinePropertyGetterCall( ...@@ -2043,11 +2051,12 @@ Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
// Introduce the call to the getter function. // Introduce the call to the getter function.
Node* value; Node* value;
if (constant.IsJSFunction()) { if (constant.IsJSFunction()) {
Node* feedback = jsgraph()->UndefinedConstant();
value = *effect = *control = graph()->NewNode( value = *effect = *control = graph()->NewNode(
jsgraph()->javascript()->Call(0 + kTargetAndReceiver, CallFrequency(), jsgraph()->javascript()->Call(JSCallNode::ArityForArgc(0),
FeedbackSource(), CallFrequency(), FeedbackSource(),
ConvertReceiverMode::kNotNullOrUndefined), ConvertReceiverMode::kNotNullOrUndefined),
target, receiver, context, frame_state, *effect, *control); target, receiver, feedback, context, frame_state, *effect, *control);
} else { } else {
Node* holder = access_info.holder().is_null() Node* holder = access_info.holder().is_null()
? receiver ? receiver
...@@ -2081,11 +2090,13 @@ void JSNativeContextSpecialization::InlinePropertySetterCall( ...@@ -2081,11 +2090,13 @@ void JSNativeContextSpecialization::InlinePropertySetterCall(
FrameStateInfo const& frame_info = FrameStateInfoOf(frame_state->op()); FrameStateInfo const& frame_info = FrameStateInfoOf(frame_state->op());
// Introduce the call to the setter function. // Introduce the call to the setter function.
if (constant.IsJSFunction()) { if (constant.IsJSFunction()) {
Node* feedback = jsgraph()->UndefinedConstant();
*effect = *control = graph()->NewNode( *effect = *control = graph()->NewNode(
jsgraph()->javascript()->Call(1 + kTargetAndReceiver, CallFrequency(), jsgraph()->javascript()->Call(JSCallNode::ArityForArgc(1),
FeedbackSource(), CallFrequency(), FeedbackSource(),
ConvertReceiverMode::kNotNullOrUndefined), ConvertReceiverMode::kNotNullOrUndefined),
target, receiver, value, context, frame_state, *effect, *control); target, receiver, value, feedback, context, frame_state, *effect,
*control);
} else { } else {
Node* holder = access_info.holder().is_null() Node* holder = access_info.holder().is_null()
? receiver ? receiver
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <limits> #include <limits>
#include "src/base/lazy-instance.h" #include "src/base/lazy-instance.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/operator.h" #include "src/compiler/operator.h"
#include "src/handles/handles-inl.h" #include "src/handles/handles-inl.h"
#include "src/objects/objects-inl.h" #include "src/objects/objects-inl.h"
...@@ -27,6 +28,10 @@ constexpr Operator::Properties BinopProperties(Operator::Opcode opcode) { ...@@ -27,6 +28,10 @@ constexpr Operator::Properties BinopProperties(Operator::Opcode opcode) {
} // namespace } // namespace
TNode<Object> JSCallNode::ArgumentOrUndefined(int i, JSGraph* jsgraph) const {
return ArgumentOr(i, jsgraph->UndefinedConstant());
}
std::ostream& operator<<(std::ostream& os, CallFrequency const& f) { std::ostream& operator<<(std::ostream& os, CallFrequency const& f) {
if (f.IsUnknown()) return os << "unknown"; if (f.IsUnknown()) return os << "unknown";
return os << f.value(); return os << f.value();
...@@ -768,7 +773,7 @@ const Operator* JSOperatorBuilder::Call( ...@@ -768,7 +773,7 @@ const Operator* JSOperatorBuilder::Call(
FeedbackSource const& feedback, ConvertReceiverMode convert_mode, FeedbackSource const& feedback, ConvertReceiverMode convert_mode,
SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation) { SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation) {
CallParameters parameters(arity, frequency, feedback, convert_mode, CallParameters parameters(arity, frequency, feedback, convert_mode,
speculation_mode, feedback_relation); speculation_mode, feedback_relation, true);
return new (zone()) Operator1<CallParameters>( // -- return new (zone()) Operator1<CallParameters>( // --
IrOpcode::kJSCall, Operator::kNoProperties, // opcode IrOpcode::kJSCall, Operator::kNoProperties, // opcode
"JSCall", // name "JSCall", // name
...@@ -780,7 +785,7 @@ const Operator* JSOperatorBuilder::CallWithArrayLike( ...@@ -780,7 +785,7 @@ const Operator* JSOperatorBuilder::CallWithArrayLike(
const CallFrequency& frequency, const FeedbackSource& feedback, const CallFrequency& frequency, const FeedbackSource& feedback,
SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation) { SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation) {
CallParameters parameters(2, frequency, feedback, ConvertReceiverMode::kAny, CallParameters parameters(2, frequency, feedback, ConvertReceiverMode::kAny,
speculation_mode, feedback_relation); speculation_mode, feedback_relation, false);
return new (zone()) Operator1<CallParameters>( // -- return new (zone()) Operator1<CallParameters>( // --
IrOpcode::kJSCallWithArrayLike, Operator::kNoProperties, // opcode IrOpcode::kJSCallWithArrayLike, Operator::kNoProperties, // opcode
"JSCallWithArrayLike", // name "JSCallWithArrayLike", // name
...@@ -796,7 +801,7 @@ const Operator* JSOperatorBuilder::CallWithSpread( ...@@ -796,7 +801,7 @@ const Operator* JSOperatorBuilder::CallWithSpread(
feedback.IsValid()); feedback.IsValid());
CallParameters parameters(arity, frequency, feedback, CallParameters parameters(arity, frequency, feedback,
ConvertReceiverMode::kAny, speculation_mode, ConvertReceiverMode::kAny, speculation_mode,
feedback_relation); feedback_relation, false);
return new (zone()) Operator1<CallParameters>( // -- return new (zone()) Operator1<CallParameters>( // --
IrOpcode::kJSCallWithSpread, Operator::kNoProperties, // opcode IrOpcode::kJSCallWithSpread, Operator::kNoProperties, // opcode
"JSCallWithSpread", // name "JSCallWithSpread", // name
......
...@@ -28,6 +28,7 @@ class SharedFunctionInfo; ...@@ -28,6 +28,7 @@ class SharedFunctionInfo;
namespace compiler { namespace compiler {
// Forward declarations. // Forward declarations.
class JSGraph;
class Operator; class Operator;
struct JSOperatorGlobalCache; struct JSOperatorGlobalCache;
...@@ -218,7 +219,9 @@ CallForwardVarargsParameters const& CallForwardVarargsParametersOf( ...@@ -218,7 +219,9 @@ CallForwardVarargsParameters const& CallForwardVarargsParametersOf(
Operator const*) V8_WARN_UNUSED_RESULT; Operator const*) V8_WARN_UNUSED_RESULT;
// Part of CallParameters::arity. // Part of CallParameters::arity.
// TODO(jgruber): Fold this into JSCallNode.
static constexpr int kTargetAndReceiver = 2; static constexpr int kTargetAndReceiver = 2;
static constexpr int kTargetAndReceiverAndVector = 3;
// Defines the arity (parameters plus the target and receiver) and the call // Defines the arity (parameters plus the target and receiver) and the call
// flags for a JavaScript function call. This is used as a parameter by JSCall, // flags for a JavaScript function call. This is used as a parameter by JSCall,
...@@ -229,19 +232,21 @@ class CallParameters final { ...@@ -229,19 +232,21 @@ class CallParameters final {
FeedbackSource const& feedback, FeedbackSource const& feedback,
ConvertReceiverMode convert_mode, ConvertReceiverMode convert_mode,
SpeculationMode speculation_mode, SpeculationMode speculation_mode,
CallFeedbackRelation feedback_relation) CallFeedbackRelation feedback_relation, bool has_vector)
: bit_field_(ArityField::encode(arity) | : bit_field_(ArityField::encode(arity) |
CallFeedbackRelationField::encode(feedback_relation) | CallFeedbackRelationField::encode(feedback_relation) |
SpeculationModeField::encode(speculation_mode) | SpeculationModeField::encode(speculation_mode) |
ConvertReceiverModeField::encode(convert_mode)), ConvertReceiverModeField::encode(convert_mode)),
frequency_(frequency), frequency_(frequency),
feedback_(feedback) { feedback_(feedback),
has_vector_(has_vector) {
// CallFeedbackRelation is ignored if the feedback slot is invalid. // CallFeedbackRelation is ignored if the feedback slot is invalid.
DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation, DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
feedback.IsValid()); feedback.IsValid());
DCHECK_IMPLIES(!feedback.IsValid(), DCHECK_IMPLIES(!feedback.IsValid(),
feedback_relation == CallFeedbackRelation::kUnrelated); feedback_relation == CallFeedbackRelation::kUnrelated);
DCHECK_GE(arity, kTargetAndReceiver); DCHECK_GE(arity,
has_vector_ ? kTargetAndReceiverAndVector : kTargetAndReceiver);
DCHECK(is_int32(arity)); DCHECK(is_int32(arity));
} }
...@@ -249,7 +254,8 @@ class CallParameters final { ...@@ -249,7 +254,8 @@ class CallParameters final {
// without extra args in CallParameters. // without extra args in CallParameters.
size_t arity() const { return ArityField::decode(bit_field_); } size_t arity() const { return ArityField::decode(bit_field_); }
int arity_without_implicit_args() const { int arity_without_implicit_args() const {
return static_cast<int>(arity() - kTargetAndReceiver); return static_cast<int>(arity() - (has_vector_ ? kTargetAndReceiverAndVector
: kTargetAndReceiver));
} }
CallFrequency const& frequency() const { return frequency_; } CallFrequency const& frequency() const { return frequency_; }
...@@ -288,6 +294,8 @@ class CallParameters final { ...@@ -288,6 +294,8 @@ class CallParameters final {
uint32_t const bit_field_; uint32_t const bit_field_;
CallFrequency const frequency_; CallFrequency const frequency_;
FeedbackSource const feedback_; FeedbackSource const feedback_;
// TODO(jgruber): Remove once Call variants all have a feedback vector input.
bool has_vector_;
}; };
size_t hash_value(CallParameters const&); size_t hash_value(CallParameters const&);
...@@ -1214,6 +1222,61 @@ class JSStorePropertyNode final : public JSNodeWrapperBase { ...@@ -1214,6 +1222,61 @@ class JSStorePropertyNode final : public JSNodeWrapperBase {
#undef INPUTS #undef INPUTS
}; };
class JSCallNode final : public JSNodeWrapperBase {
public:
explicit constexpr JSCallNode(Node* node) : JSNodeWrapperBase(node) {
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSCall);
}
const CallParameters& Parameters() const {
return CallParametersOf(node()->op());
}
#define INPUTS(V) \
V(Target, target, 0, Object) \
V(Receiver, receiver, 1, Object)
INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
// Besides actual arguments, JSCall nodes also take:
static constexpr int kTargetInputCount = 1;
static constexpr int kReceiverInputCount = 1;
static constexpr int kFeedbackVectorInputCount = 1;
static constexpr int kExtraInputCount =
kTargetInputCount + kReceiverInputCount + kFeedbackVectorInputCount;
// This is the arity fed into CallArguments.
static constexpr int ArityForArgc(int parameters) {
return parameters + kExtraInputCount;
}
static constexpr int FirstArgumentIndex() { return ReceiverIndex() + 1; }
static constexpr int ArgumentIndex(int i) { return FirstArgumentIndex() + i; }
TNode<Object> Argument(int i) const {
DCHECK_LT(i, ArgumentCount());
return TNode<Object>::UncheckedCast(
NodeProperties::GetValueInput(node(), ArgumentIndex(i)));
}
TNode<Object> ArgumentOr(int i, Node* default_value) const {
return i < ArgumentCount() ? Argument(i)
: TNode<Object>::UncheckedCast(default_value);
}
TNode<Object> ArgumentOrUndefined(int i, JSGraph* jsgraph) const;
int ArgumentCount() const {
DCHECK_GE(node()->op()->ValueInputCount(), kExtraInputCount);
return node()->op()->ValueInputCount() - kExtraInputCount;
}
int FeedbackVectorIndex() const {
DCHECK_GE(node()->op()->ValueInputCount(), 1);
return node()->op()->ValueInputCount() - 1;
}
TNode<HeapObject> feedback_vector() const {
return TNode<HeapObject>::UncheckedCast(
NodeProperties::GetValueInput(node(), FeedbackVectorIndex()));
}
};
#undef DEFINE_INPUT_ACCESSORS #undef DEFINE_INPUT_ACCESSORS
} // namespace compiler } // namespace compiler
......
...@@ -1710,16 +1710,16 @@ Reduction JSTypedLowering::ReduceJSCallForwardVarargs(Node* node) { ...@@ -1710,16 +1710,16 @@ Reduction JSTypedLowering::ReduceJSCallForwardVarargs(Node* node) {
} }
Reduction JSTypedLowering::ReduceJSCall(Node* node) { Reduction JSTypedLowering::ReduceJSCall(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); JSCallNode n(node);
CallParameters const& p = CallParametersOf(node->op()); CallParameters const& p = n.Parameters();
int arity = p.arity_without_implicit_args(); int arity = p.arity_without_implicit_args();
ConvertReceiverMode convert_mode = p.convert_mode(); ConvertReceiverMode convert_mode = p.convert_mode();
Node* target = NodeProperties::GetValueInput(node, 0); Node* target = n.target();
Type target_type = NodeProperties::GetType(target); Type target_type = NodeProperties::GetType(target);
Node* receiver = NodeProperties::GetValueInput(node, 1); Node* receiver = n.receiver();
Type receiver_type = NodeProperties::GetType(receiver); Type receiver_type = NodeProperties::GetType(receiver);
Node* effect = NodeProperties::GetEffectInput(node); Effect effect = n.effect();
Node* control = NodeProperties::GetControlInput(node); Control control = n.control();
// Try to infer receiver {convert_mode} from {receiver} type. // Try to infer receiver {convert_mode} from {receiver} type.
if (receiver_type.Is(Type::NullOrUndefined())) { if (receiver_type.Is(Type::NullOrUndefined())) {
...@@ -1787,6 +1787,9 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) { ...@@ -1787,6 +1787,9 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) {
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
Node* new_target = jsgraph()->UndefinedConstant(); Node* new_target = jsgraph()->UndefinedConstant();
// The node will change operators, remove the feedback vector.
node->RemoveInput(n.FeedbackVectorIndex());
if (NeedsArgumentAdaptorFrame(*shared, arity)) { if (NeedsArgumentAdaptorFrame(*shared, arity)) {
// Check if it's safe to skip the arguments adaptor for {shared}, // Check if it's safe to skip the arguments adaptor for {shared},
// that is whether the target function anyways cannot observe the // that is whether the target function anyways cannot observe the
...@@ -1865,6 +1868,8 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) { ...@@ -1865,6 +1868,8 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) {
// Check if {target} is a JSFunction. // Check if {target} is a JSFunction.
if (target_type.Is(Type::Function())) { if (target_type.Is(Type::Function())) {
// The node will change operators, remove the feedback vector.
node->RemoveInput(n.FeedbackVectorIndex());
// Compute flags for the call. // Compute flags for the call.
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
// Patch {node} to an indirect call via the CallFunction builtin. // Patch {node} to an indirect call via the CallFunction builtin.
......
...@@ -98,8 +98,8 @@ bool MapInference::Is(Handle<Map> expected_map) { ...@@ -98,8 +98,8 @@ bool MapInference::Is(Handle<Map> expected_map) {
return maps[0].equals(expected_map); return maps[0].equals(expected_map);
} }
void MapInference::InsertMapChecks(JSGraph* jsgraph, Node** effect, void MapInference::InsertMapChecks(JSGraph* jsgraph, Effect* effect,
Node* control, Control control,
const FeedbackSource& feedback) { const FeedbackSource& feedback) {
CHECK(HaveMaps()); CHECK(HaveMaps());
CHECK(feedback.IsValid()); CHECK(feedback.IsValid());
...@@ -114,7 +114,7 @@ void MapInference::InsertMapChecks(JSGraph* jsgraph, Node** effect, ...@@ -114,7 +114,7 @@ void MapInference::InsertMapChecks(JSGraph* jsgraph, Node** effect,
bool MapInference::RelyOnMapsViaStability( bool MapInference::RelyOnMapsViaStability(
CompilationDependencies* dependencies) { CompilationDependencies* dependencies) {
CHECK(HaveMaps()); CHECK(HaveMaps());
return RelyOnMapsHelper(dependencies, nullptr, nullptr, nullptr, {}); return RelyOnMapsHelper(dependencies, nullptr, nullptr, Control{nullptr}, {});
} }
bool MapInference::RelyOnMapsPreferStability( bool MapInference::RelyOnMapsPreferStability(
...@@ -123,13 +123,16 @@ bool MapInference::RelyOnMapsPreferStability( ...@@ -123,13 +123,16 @@ bool MapInference::RelyOnMapsPreferStability(
CHECK(HaveMaps()); CHECK(HaveMaps());
if (Safe()) return false; if (Safe()) return false;
if (RelyOnMapsViaStability(dependencies)) return true; if (RelyOnMapsViaStability(dependencies)) return true;
CHECK(RelyOnMapsHelper(nullptr, jsgraph, effect, control, feedback)); // TODO(jgruber): Change this to take (typed) Effect and Control parameters.
Effect e{*effect};
CHECK(RelyOnMapsHelper(nullptr, jsgraph, &e, Control{control}, feedback));
*effect = e;
return false; return false;
} }
bool MapInference::RelyOnMapsHelper(CompilationDependencies* dependencies, bool MapInference::RelyOnMapsHelper(CompilationDependencies* dependencies,
JSGraph* jsgraph, Node** effect, JSGraph* jsgraph, Effect* effect,
Node* control, Control control,
const FeedbackSource& feedback) { const FeedbackSource& feedback) {
if (Safe()) return true; if (Safe()) return true;
......
...@@ -69,8 +69,20 @@ class MapInference { ...@@ -69,8 +69,20 @@ class MapInference {
bool RelyOnMapsPreferStability(CompilationDependencies* dependencies, bool RelyOnMapsPreferStability(CompilationDependencies* dependencies,
JSGraph* jsgraph, Node** effect, Node* control, JSGraph* jsgraph, Node** effect, Node* control,
const FeedbackSource& feedback); const FeedbackSource& feedback);
// TODO(jgruber): Once all callsites pass Effect/Control types,
// remove the untyped version above.
bool RelyOnMapsPreferStability(CompilationDependencies* dependencies,
JSGraph* jsgraph, Effect* effect,
Control control,
const FeedbackSource& feedback) {
Node* effect_node = *effect;
bool result = RelyOnMapsPreferStability(dependencies, jsgraph, &effect_node,
control, feedback);
*effect = effect_node;
return result;
}
// Inserts map checks even if maps were already reliable. // Inserts map checks even if maps were already reliable.
void InsertMapChecks(JSGraph* jsgraph, Node** effect, Node* control, void InsertMapChecks(JSGraph* jsgraph, Effect* effect, Control control,
const FeedbackSource& feedback); const FeedbackSource& feedback);
// Internally marks the maps as reliable (thus bypassing the safety check) and // Internally marks the maps as reliable (thus bypassing the safety check) and
...@@ -98,8 +110,8 @@ class MapInference { ...@@ -98,8 +110,8 @@ class MapInference {
V8_WARN_UNUSED_RESULT bool AnyOfInstanceTypesUnsafe( V8_WARN_UNUSED_RESULT bool AnyOfInstanceTypesUnsafe(
std::function<bool(InstanceType)> f) const; std::function<bool(InstanceType)> f) const;
V8_WARN_UNUSED_RESULT bool RelyOnMapsHelper( V8_WARN_UNUSED_RESULT bool RelyOnMapsHelper(
CompilationDependencies* dependencies, JSGraph* jsgraph, Node** effect, CompilationDependencies* dependencies, JSGraph* jsgraph, Effect* effect,
Node* control, const FeedbackSource& feedback); Control control, const FeedbackSource& feedback);
}; };
} // namespace compiler } // namespace compiler
......
...@@ -258,6 +258,19 @@ void Node::TrimInputCount(int new_input_count) { ...@@ -258,6 +258,19 @@ void Node::TrimInputCount(int new_input_count) {
} }
} }
void Node::EnsureInputCount(Zone* zone, int new_input_count) {
int current_count = InputCount();
DCHECK_NE(current_count, 0);
if (current_count > new_input_count) {
TrimInputCount(new_input_count);
} else if (current_count < new_input_count) {
Node* dummy = InputAt(current_count - 1);
do {
AppendInput(zone, dummy);
current_count++;
} while (current_count < new_input_count);
}
}
int Node::UseCount() const { int Node::UseCount() const {
int use_count = 0; int use_count = 0;
......
...@@ -92,6 +92,8 @@ class V8_EXPORT_PRIVATE Node final { ...@@ -92,6 +92,8 @@ class V8_EXPORT_PRIVATE Node final {
void RemoveInput(int index); void RemoveInput(int index);
void NullAllInputs(); void NullAllInputs();
void TrimInputCount(int new_input_count); void TrimInputCount(int new_input_count);
// Can trim, extend by appending new inputs, or do nothing.
void EnsureInputCount(Zone* zone, int new_input_count);
int UseCount() const; int UseCount() const;
void ReplaceUses(Node* replace_to); void ReplaceUses(Node* replace_to);
......
...@@ -116,9 +116,10 @@ class JSCallReducerTest : public TypedGraphTest { ...@@ -116,9 +116,10 @@ class JSCallReducerTest : public TypedGraphTest {
Handle<FeedbackVector> vector = FeedbackVector::New( Handle<FeedbackVector> vector = FeedbackVector::New(
isolate(), shared, closure_feedback_cell_array, &is_compiled_scope); isolate(), shared, closure_feedback_cell_array, &is_compiled_scope);
FeedbackSource feedback(vector, FeedbackSlot(0)); FeedbackSource feedback(vector, FeedbackSlot(0));
return javascript()->Call( return javascript()->Call(JSCallNode::ArityForArgc(arity), CallFrequency(),
arity, CallFrequency(), feedback, ConvertReceiverMode::kAny, feedback, ConvertReceiverMode::kAny,
SpeculationMode::kAllowSpeculation, CallFeedbackRelation::kRelated); SpeculationMode::kAllowSpeculation,
CallFeedbackRelation::kRelated);
} }
private: private:
...@@ -223,8 +224,10 @@ TEST_F(JSCallReducerTest, MathUnaryWithNumber) { ...@@ -223,8 +224,10 @@ TEST_F(JSCallReducerTest, MathUnaryWithNumber) {
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* jsfunction = MathFunction(fnc); Node* jsfunction = MathFunction(fnc);
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(1), jsfunction, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(std::string(IrOpcode::Mnemonic(r.replacement()->opcode())), EXPECT_THAT(std::string(IrOpcode::Mnemonic(r.replacement()->opcode())),
...@@ -251,8 +254,10 @@ TEST_F(JSCallReducerTest, MathBinaryWithNumber) { ...@@ -251,8 +254,10 @@ TEST_F(JSCallReducerTest, MathBinaryWithNumber) {
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* p1 = Parameter(Type::Any(), 0); Node* p1 = Parameter(Type::Any(), 0);
Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
p1, context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(2), jsfunction, UndefinedConstant(), p0, p1,
feedback, context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -272,8 +277,10 @@ TEST_F(JSCallReducerTest, MathClz32WithUnsigned32) { ...@@ -272,8 +277,10 @@ TEST_F(JSCallReducerTest, MathClz32WithUnsigned32) {
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Unsigned32(), 0); Node* p0 = Parameter(Type::Unsigned32(), 0);
Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(1), jsfunction, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -288,8 +295,10 @@ TEST_F(JSCallReducerTest, MathClz32WithUnsigned32NoArg) { ...@@ -288,8 +295,10 @@ TEST_F(JSCallReducerTest, MathClz32WithUnsigned32NoArg) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* call = graph()->NewNode(Call(2), jsfunction, UndefinedConstant(), Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(0), jsfunction, UndefinedConstant(), feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -308,8 +317,10 @@ TEST_F(JSCallReducerTest, MathImulWithUnsigned32) { ...@@ -308,8 +317,10 @@ TEST_F(JSCallReducerTest, MathImulWithUnsigned32) {
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Unsigned32(), 0); Node* p0 = Parameter(Type::Unsigned32(), 0);
Node* p1 = Parameter(Type::Unsigned32(), 1); Node* p1 = Parameter(Type::Unsigned32(), 1);
Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
p1, context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(2), jsfunction, UndefinedConstant(), p0, p1,
feedback, context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -326,8 +337,10 @@ TEST_F(JSCallReducerTest, MathMinWithNoArguments) { ...@@ -326,8 +337,10 @@ TEST_F(JSCallReducerTest, MathMinWithNoArguments) {
Node* control = graph()->start(); Node* control = graph()->start();
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* call = graph()->NewNode(Call(2), jsfunction, UndefinedConstant(), Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(0), jsfunction, UndefinedConstant(), feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -341,8 +354,10 @@ TEST_F(JSCallReducerTest, MathMinWithNumber) { ...@@ -341,8 +354,10 @@ TEST_F(JSCallReducerTest, MathMinWithNumber) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(1), jsfunction, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -357,8 +372,10 @@ TEST_F(JSCallReducerTest, MathMinWithTwoArguments) { ...@@ -357,8 +372,10 @@ TEST_F(JSCallReducerTest, MathMinWithTwoArguments) {
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* p1 = Parameter(Type::Any(), 1); Node* p1 = Parameter(Type::Any(), 1);
Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
p1, context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(2), jsfunction, UndefinedConstant(), p0, p1,
feedback, context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -376,8 +393,10 @@ TEST_F(JSCallReducerTest, MathMaxWithNoArguments) { ...@@ -376,8 +393,10 @@ TEST_F(JSCallReducerTest, MathMaxWithNoArguments) {
Node* control = graph()->start(); Node* control = graph()->start();
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* call = graph()->NewNode(Call(2), jsfunction, UndefinedConstant(), Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(0), jsfunction, UndefinedConstant(), feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -391,8 +410,10 @@ TEST_F(JSCallReducerTest, MathMaxWithNumber) { ...@@ -391,8 +410,10 @@ TEST_F(JSCallReducerTest, MathMaxWithNumber) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* call = graph()->NewNode(Call(3), jsfunction, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(1), jsfunction, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -408,8 +429,10 @@ TEST_F(JSCallReducerTest, MathMaxWithTwoArguments) { ...@@ -408,8 +429,10 @@ TEST_F(JSCallReducerTest, MathMaxWithTwoArguments) {
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* p1 = Parameter(Type::Any(), 1); Node* p1 = Parameter(Type::Any(), 1);
Node* call = graph()->NewNode(Call(4), jsfunction, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
p1, context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(2), jsfunction, UndefinedConstant(), p0, p1,
feedback, context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -428,8 +451,10 @@ TEST_F(JSCallReducerTest, StringFromSingleCharCodeWithNumber) { ...@@ -428,8 +451,10 @@ TEST_F(JSCallReducerTest, StringFromSingleCharCodeWithNumber) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(1), function, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -445,8 +470,10 @@ TEST_F(JSCallReducerTest, StringFromSingleCharCodeWithPlainPrimitive) { ...@@ -445,8 +470,10 @@ TEST_F(JSCallReducerTest, StringFromSingleCharCodeWithPlainPrimitive) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::PlainPrimitive(), 0); Node* p0 = Parameter(Type::PlainPrimitive(), 0);
Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(1), function, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -465,8 +492,10 @@ TEST_F(JSCallReducerTest, NumberIsFinite) { ...@@ -465,8 +492,10 @@ TEST_F(JSCallReducerTest, NumberIsFinite) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(1), function, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -484,8 +513,9 @@ TEST_F(JSCallReducerTest, NumberIsIntegerWithNumber) { ...@@ -484,8 +513,9 @@ TEST_F(JSCallReducerTest, NumberIsIntegerWithNumber) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* feedback = UndefinedConstant();
Node* call = Node* call =
graph()->NewNode(javascript()->Call(3), function, UndefinedConstant(), p0, graph()->NewNode(Call(1), function, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control); context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
...@@ -504,8 +534,9 @@ TEST_F(JSCallReducerTest, NumberIsNaNWithNumber) { ...@@ -504,8 +534,9 @@ TEST_F(JSCallReducerTest, NumberIsNaNWithNumber) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* feedback = UndefinedConstant();
Node* call = Node* call =
graph()->NewNode(javascript()->Call(3), function, UndefinedConstant(), p0, graph()->NewNode(Call(1), function, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control); context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
...@@ -524,8 +555,9 @@ TEST_F(JSCallReducerTest, NumberIsSafeIntegerWithIntegral32) { ...@@ -524,8 +555,9 @@ TEST_F(JSCallReducerTest, NumberIsSafeIntegerWithIntegral32) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* feedback = UndefinedConstant();
Node* call = Node* call =
graph()->NewNode(javascript()->Call(3), function, UndefinedConstant(), p0, graph()->NewNode(Call(1), function, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control); context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
...@@ -544,8 +576,10 @@ TEST_F(JSCallReducerTest, GlobalIsFiniteWithNumber) { ...@@ -544,8 +576,10 @@ TEST_F(JSCallReducerTest, GlobalIsFiniteWithNumber) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(1), function, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -563,8 +597,10 @@ TEST_F(JSCallReducerTest, GlobalIsNaN) { ...@@ -563,8 +597,10 @@ TEST_F(JSCallReducerTest, GlobalIsNaN) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(1), function, UndefinedConstant(), p0, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -583,8 +619,10 @@ TEST_F(JSCallReducerTest, NumberParseInt) { ...@@ -583,8 +619,10 @@ TEST_F(JSCallReducerTest, NumberParseInt) {
Node* frame_state = graph()->start(); Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0); Node* p0 = Parameter(Type::Any(), 0);
Node* p1 = Parameter(Type::Any(), 1); Node* p1 = Parameter(Type::Any(), 1);
Node* call = graph()->NewNode(Call(4), function, UndefinedConstant(), p0, p1, Node* feedback = UndefinedConstant();
context, frame_state, effect, control); Node* call =
graph()->NewNode(Call(2), function, UndefinedConstant(), p0, p1, feedback,
context, frame_state, effect, control);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
......
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