Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
index 8099533..fcfe134 100644
--- a/src/compiler/js-typed-lowering.cc
+++ b/src/compiler/js-typed-lowering.cc
@@ -27,7 +27,42 @@
JSBinopReduction(JSTypedLowering* lowering, Node* node)
: lowering_(lowering), node_(node) {}
- void ConvertInputsToNumberOrUndefined(Node* frame_state) {
+ BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() {
+ if (!(lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) ||
+ !(lowering_->flags() & JSTypedLowering::kTypeFeedbackEnabled)) {
+ return BinaryOperationHints::kAny;
+ }
+ DCHECK_NE(0, node_->op()->ControlOutputCount());
+ DCHECK_EQ(1, node_->op()->EffectOutputCount());
+ DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
+ BinaryOperationHints hints = BinaryOperationHintsOf(node_->op());
+ BinaryOperationHints::Hint combined = hints.combined();
+ if (combined == BinaryOperationHints::kSignedSmall ||
+ combined == BinaryOperationHints::kSigned32 ||
+ combined == BinaryOperationHints::kNumberOrUndefined) {
+ return combined;
+ }
+ return BinaryOperationHints::kAny;
+ }
+
+ CompareOperationHints::Hint GetNumberCompareOperationFeedback() {
+ if (!(lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) ||
+ !(lowering_->flags() & JSTypedLowering::kTypeFeedbackEnabled)) {
+ return CompareOperationHints::kAny;
+ }
+ DCHECK_NE(0, node_->op()->ControlOutputCount());
+ DCHECK_EQ(1, node_->op()->EffectOutputCount());
+ DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
+ CompareOperationHints hints = CompareOperationHintsOf(node_->op());
+ CompareOperationHints::Hint combined = hints.combined();
+ if (combined == CompareOperationHints::kSignedSmall ||
+ combined == CompareOperationHints::kNumber) {
+ return combined;
+ }
+ return CompareOperationHints::kAny;
+ }
+
+ void ConvertInputsToNumber(Node* frame_state) {
// To convert the inputs to numbers, we have to provide frame states
// for lazy bailouts in the ToNumber conversions.
// We use a little hack here: we take the frame state before the binary
@@ -46,11 +81,11 @@
ConvertBothInputsToNumber(&left_input, &right_input, frame_state);
} else {
left_input = left_is_primitive
- ? ConvertPlainPrimitiveToNumberOrUndefined(left())
+ ? ConvertPlainPrimitiveToNumber(left())
: ConvertSingleInputToNumber(
left(), CreateFrameStateForLeftInput(frame_state));
right_input = right_is_primitive
- ? ConvertPlainPrimitiveToNumberOrUndefined(right())
+ ? ConvertPlainPrimitiveToNumber(right())
: ConvertSingleInputToNumber(
right(), CreateFrameStateForRightInput(
frame_state, left_input));
@@ -107,6 +142,53 @@
return lowering_->Changed(node_);
}
+ Reduction ChangeToSpeculativeOperator(const Operator* op, Type* upper_bound) {
+ DCHECK_EQ(1, op->EffectInputCount());
+ DCHECK_EQ(1, op->EffectOutputCount());
+ DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
+ DCHECK_EQ(1, op->ControlInputCount());
+ DCHECK_EQ(0, op->ControlOutputCount());
+ DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
+ DCHECK_EQ(2, op->ValueInputCount());
+
+ DCHECK_EQ(1, node_->op()->EffectInputCount());
+ DCHECK_EQ(1, node_->op()->EffectOutputCount());
+ DCHECK_EQ(1, node_->op()->ControlInputCount());
+ DCHECK_LT(1, node_->op()->ControlOutputCount());
+ DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
+ DCHECK_EQ(2, node_->op()->ValueInputCount());
+
+ // Reconnect the control output to bypass the IfSuccess node and
+ // possibly disconnect from the IfException node.
+ for (Edge edge : node_->use_edges()) {
+ Node* const user = edge.from();
+ DCHECK(!user->IsDead());
+ if (NodeProperties::IsControlEdge(edge)) {
+ if (user->opcode() == IrOpcode::kIfSuccess) {
+ user->ReplaceUses(NodeProperties::GetControlInput(node_));
+ user->Kill();
+ } else {
+ DCHECK_EQ(user->opcode(), IrOpcode::kIfException);
+ edge.UpdateTo(jsgraph()->Dead());
+ }
+ }
+ }
+
+ // Remove both bailout frame states and the context.
+ node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_) + 1);
+ node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
+ node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
+
+ NodeProperties::ChangeOp(node_, op);
+
+ // Update the type to number.
+ Type* node_type = NodeProperties::GetType(node_);
+ NodeProperties::SetType(node_,
+ Type::Intersect(node_type, upper_bound, zone()));
+
+ return lowering_->Changed(node_);
+ }
+
Reduction ChangeToPureOperator(const Operator* op, Type* type) {
return ChangeToPureOperator(op, false, type);
}
@@ -216,17 +298,15 @@
frame_state->InputAt(kFrameStateOuterStateInput));
}
- Node* ConvertPlainPrimitiveToNumberOrUndefined(Node* node) {
+ Node* ConvertPlainPrimitiveToNumber(Node* node) {
DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
// Avoid inserting too many eager ToNumber() operations.
Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
if (reduction.Changed()) return reduction.replacement();
- if (NodeProperties::GetType(node)->Is(Type::NumberOrUndefined())) {
+ if (NodeProperties::GetType(node)->Is(Type::Number())) {
return node;
}
- return graph()->NewNode(
- javascript()->ToNumber(), node, jsgraph()->NoContextConstant(),
- jsgraph()->EmptyFrameState(), graph()->start(), graph()->start());
+ return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
}
Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) {
@@ -339,14 +419,31 @@
if (flags() & kDisableBinaryOpReduction) return NoChange();
JSBinopReduction r(this, node);
- if (r.BothInputsAre(Type::NumberOrUndefined())) {
+
+ BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+ if (feedback == BinaryOperationHints::kNumberOrUndefined &&
+ r.BothInputsAre(Type::PlainPrimitive()) &&
+ r.NeitherInputCanBe(Type::StringOrReceiver())) {
+ // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
+ Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+ r.ConvertInputsToNumber(frame_state);
+ return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
+ }
+ if (feedback != BinaryOperationHints::kAny) {
+ // Lower to the optimistic number binop.
+ return r.ChangeToSpeculativeOperator(
+ simplified()->SpeculativeNumberAdd(feedback), Type::Number());
+ }
+ if (r.BothInputsAre(Type::Number())) {
// JSAdd(x:number, y:number) => NumberAdd(x, y)
- return ReduceNumberBinop(node, simplified()->NumberAdd());
+ Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+ r.ConvertInputsToNumber(frame_state);
+ return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
}
if (r.NeitherInputCanBe(Type::StringOrReceiver())) {
// JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
- r.ConvertInputsToNumberOrUndefined(frame_state);
+ r.ConvertInputsToNumber(frame_state);
return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
}
if (r.OneInputIs(Type::String())) {
@@ -376,31 +473,69 @@
Reduction JSTypedLowering::ReduceJSModulus(Node* node) {
if (flags() & kDisableBinaryOpReduction) return NoChange();
-
JSBinopReduction r(this, node);
if (r.BothInputsAre(Type::Number())) {
// JSModulus(x:number, x:number) => NumberModulus(x, y)
return r.ChangeToPureOperator(simplified()->NumberModulus(),
Type::Number());
}
+ BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+ if (feedback != BinaryOperationHints::kAny) {
+ return r.ChangeToSpeculativeOperator(
+ simplified()->SpeculativeNumberModulus(feedback), Type::Number());
+ }
return NoChange();
}
-
-Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
- const Operator* numberOp) {
+Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
if (flags() & kDisableBinaryOpReduction) return NoChange();
-
JSBinopReduction r(this, node);
- if (numberOp == simplified()->NumberModulus()) {
- if (r.BothInputsAre(Type::NumberOrUndefined())) {
- return r.ChangeToPureOperator(numberOp, Type::Number());
- }
- return NoChange();
+ BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+ if (feedback == BinaryOperationHints::kNumberOrUndefined &&
+ r.BothInputsAre(Type::PlainPrimitive())) {
+ // JSSubtract(x:plain-primitive, y:plain-primitive)
+ // => NumberSubtract(ToNumber(x), ToNumber(y))
+ Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+ r.ConvertInputsToNumber(frame_state);
+ return r.ChangeToPureOperator(simplified()->NumberSubtract(),
+ Type::Number());
+ }
+ if (feedback != BinaryOperationHints::kAny) {
+ // Lower to the optimistic number binop.
+ return r.ChangeToSpeculativeOperator(
+ simplified()->SpeculativeNumberSubtract(feedback), Type::Number());
}
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
- r.ConvertInputsToNumberOrUndefined(frame_state);
- return r.ChangeToPureOperator(numberOp, Type::Number());
+ r.ConvertInputsToNumber(frame_state);
+ return r.ChangeToPureOperator(simplified()->NumberSubtract(), Type::Number());
+}
+
+Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
+ if (flags() & kDisableBinaryOpReduction) return NoChange();
+ JSBinopReduction r(this, node);
+
+ BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+ if (feedback != BinaryOperationHints::kAny) {
+ return r.ChangeToSpeculativeOperator(
+ simplified()->SpeculativeNumberMultiply(feedback), Type::Number());
+ }
+
+ Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+ r.ConvertInputsToNumber(frame_state);
+ return r.ChangeToPureOperator(simplified()->NumberMultiply(), Type::Number());
+}
+
+Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
+ if (flags() & kDisableBinaryOpReduction) return NoChange();
+ JSBinopReduction r(this, node);
+ BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+ if (feedback != BinaryOperationHints::kAny) {
+ return r.ChangeToSpeculativeOperator(
+ simplified()->SpeculativeNumberDivide(feedback), Type::Number());
+ }
+ Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+ r.ConvertInputsToNumber(frame_state);
+ return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number());
}
@@ -409,7 +544,7 @@
JSBinopReduction r(this, node);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
- r.ConvertInputsToNumberOrUndefined(frame_state);
+ r.ConvertInputsToNumber(frame_state);
r.ConvertInputsToUI32(kSigned, kSigned);
return r.ChangeToPureOperator(intOp, Type::Integral32());
}
@@ -422,7 +557,7 @@
JSBinopReduction r(this, node);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
- r.ConvertInputsToNumberOrUndefined(frame_state);
+ r.ConvertInputsToNumber(frame_state);
r.ConvertInputsToUI32(left_signedness, kUnsigned);
return r.ChangeToPureOperator(shift_op);
}
@@ -456,7 +591,10 @@
r.ChangeToPureOperator(stringOp);
return Changed(node);
}
- if (r.OneInputCannotBe(Type::StringOrReceiver())) {
+
+ CompareOperationHints::Hint hint = r.GetNumberCompareOperationFeedback();
+ if (hint != CompareOperationHints::kAny ||
+ r.OneInputCannotBe(Type::StringOrReceiver())) {
const Operator* less_than;
const Operator* less_than_or_equal;
if (r.BothInputsAre(Type::Unsigned32())) {
@@ -465,10 +603,13 @@
} else if (r.BothInputsAre(Type::Signed32())) {
less_than = machine()->Int32LessThan();
less_than_or_equal = machine()->Int32LessThanOrEqual();
+ } else if (hint != CompareOperationHints::kAny) {
+ less_than = simplified()->SpeculativeNumberLessThan(hint);
+ less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint);
} else {
// TODO(turbofan): mixed signed/unsigned int32 comparisons.
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
- r.ConvertInputsToNumberOrUndefined(frame_state);
+ r.ConvertInputsToNumber(frame_state);
less_than = simplified()->NumberLessThan();
less_than_or_equal = simplified()->NumberLessThanOrEqual();
}
@@ -491,7 +632,11 @@
default:
return NoChange();
}
- return r.ChangeToPureOperator(comparison);
+ if (comparison->EffectInputCount() > 0) {
+ return r.ChangeToSpeculativeOperator(comparison, Type::Boolean());
+ } else {
+ return r.ChangeToPureOperator(comparison);
+ }
}
// TODO(turbofan): relax/remove effects of this operator in other cases.
return NoChange(); // Keep a generic comparison.
@@ -592,9 +737,10 @@
return Replace(replacement);
}
}
- if (r.OneInputCannotBe(Type::NumberOrString())) {
- // For values with canonical representation (i.e. not string nor number) an
- // empty type intersection means the values cannot be strictly equal.
+ if (r.OneInputCannotBe(Type::NumberOrSimdOrString())) {
+ // For values with canonical representation (i.e. neither String, nor
+ // Simd128Value nor Number) an empty type intersection means the values
+ // cannot be strictly equal.
if (!r.left_type()->Maybe(r.right_type())) {
Node* replacement = jsgraph()->BooleanConstant(invert);
ReplaceWithValue(node, replacement);
@@ -636,7 +782,7 @@
if (r.BothInputsAre(Type::String())) {
return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
}
- if (r.BothInputsAre(Type::NumberOrUndefined())) {
+ if (r.BothInputsAre(Type::Number())) {
return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
}
// TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
@@ -719,21 +865,6 @@
}
Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
- // Check for ToNumber truncation of signaling NaN to undefined mapping.
- if (input->opcode() == IrOpcode::kSelect) {
- Node* check = NodeProperties::GetValueInput(input, 0);
- Node* vtrue = NodeProperties::GetValueInput(input, 1);
- Type* vtrue_type = NodeProperties::GetType(vtrue);
- Node* vfalse = NodeProperties::GetValueInput(input, 2);
- Type* vfalse_type = NodeProperties::GetType(vfalse);
- if (vtrue_type->Is(Type::Undefined()) && vfalse_type->Is(Type::Number())) {
- if (check->opcode() == IrOpcode::kNumberIsHoleNaN &&
- check->InputAt(0) == vfalse) {
- // JSToNumber(Select(NumberIsHoleNaN(x), y:undefined, x:number)) => x
- return Replace(vfalse);
- }
- }
- }
// Try constant-folding of JSToNumber with constant inputs.
Type* input_type = NodeProperties::GetType(input);
if (input_type->IsConstant()) {
@@ -780,21 +911,10 @@
}
Type* const input_type = NodeProperties::GetType(input);
if (input_type->Is(Type::PlainPrimitive())) {
- if (NodeProperties::GetContextInput(node) !=
- jsgraph()->NoContextConstant() ||
- NodeProperties::GetEffectInput(node) != graph()->start() ||
- NodeProperties::GetControlInput(node) != graph()->start()) {
- // JSToNumber(x:plain-primitive,context,effect,control)
- // => JSToNumber(x,no-context,start,start)
- RelaxEffectsAndControls(node);
- NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
- NodeProperties::ReplaceControlInput(node, graph()->start());
- NodeProperties::ReplaceEffectInput(node, graph()->start());
- DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
- NodeProperties::ReplaceFrameStateInput(node, 0,
- jsgraph()->EmptyFrameState());
- return Changed(node);
- }
+ RelaxEffectsAndControls(node);
+ node->TrimInputCount(1);
+ NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber());
+ return Changed(node);
}
return NoChange();
}
@@ -1013,13 +1133,13 @@
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Convert to a number first.
- if (!value_type->Is(Type::NumberOrUndefined())) {
+ if (!value_type->Is(Type::Number())) {
Reduction number_reduction = ReduceJSToNumberInput(value);
if (number_reduction.Changed()) {
value = number_reduction.replacement();
} else {
Node* frame_state_for_to_number =
- NodeProperties::GetFrameStateInput(node, 1);
+ NodeProperties::FindFrameStateBefore(node);
value = effect =
graph()->NewNode(javascript()->ToNumber(), value, context,
frame_state_for_to_number, effect, control);
@@ -1103,17 +1223,13 @@
Node* prototype =
jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
- Node* if_is_smi = nullptr;
- Node* e_is_smi = nullptr;
// If the left hand side is an object, no smi check is needed.
- if (r.left_type()->Maybe(Type::TaggedSigned())) {
- Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left());
- Node* branch_is_smi =
- graph()->NewNode(common()->Branch(BranchHint::kFalse), is_smi, control);
- if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi);
- e_is_smi = effect;
- control = graph()->NewNode(common()->IfFalse(), branch_is_smi);
- }
+ Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left());
+ Node* branch_is_smi =
+ graph()->NewNode(common()->Branch(BranchHint::kFalse), is_smi, control);
+ Node* if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi);
+ Node* e_is_smi = effect;
+ control = graph()->NewNode(common()->IfFalse(), branch_is_smi);
Node* object_map = effect =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
@@ -1179,6 +1295,17 @@
simplified()->LoadField(AccessBuilder::ForMapPrototype()),
loop_object_map, loop_effect, control);
+ // If not, check if object prototype is the null prototype.
+ Node* null_proto =
+ graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
+ object_prototype, jsgraph()->NullConstant());
+ Node* branch_null_proto = graph()->NewNode(
+ common()->Branch(BranchHint::kFalse), null_proto, control);
+ Node* if_null_proto = graph()->NewNode(common()->IfTrue(), branch_null_proto);
+ Node* e_null_proto = effect;
+
+ control = graph()->NewNode(common()->IfFalse(), branch_null_proto);
+
// Check if object prototype is equal to function prototype.
Node* eq_proto =
graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
@@ -1190,16 +1317,6 @@
control = graph()->NewNode(common()->IfFalse(), branch_eq_proto);
- // If not, check if object prototype is the null prototype.
- Node* null_proto =
- graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
- object_prototype, jsgraph()->NullConstant());
- Node* branch_null_proto = graph()->NewNode(
- common()->Branch(BranchHint::kFalse), null_proto, control);
- Node* if_null_proto = graph()->NewNode(common()->IfTrue(), branch_null_proto);
- Node* e_null_proto = effect;
-
- control = graph()->NewNode(common()->IfFalse(), branch_null_proto);
Node* load_object_map = effect =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
object_prototype, effect, control);
@@ -1219,14 +1336,12 @@
bool_result_runtime_has_in_proto_chain_case, jsgraph()->TrueConstant(),
jsgraph()->FalseConstant(), control);
- if (if_is_smi != nullptr) {
- DCHECK_NOT_NULL(e_is_smi);
- control = graph()->NewNode(common()->Merge(2), if_is_smi, control);
- effect =
- graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control);
- result = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
- jsgraph()->FalseConstant(), result, control);
- }
+ DCHECK_NOT_NULL(e_is_smi);
+ control = graph()->NewNode(common()->Merge(2), if_is_smi, control);
+ effect =
+ graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control);
+ result = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+ jsgraph()->FalseConstant(), result, control);
ReplaceWithValue(node, result, effect, control);
return Changed(result);
@@ -1387,9 +1502,6 @@
Handle<JSFunction>::cast(target_type->AsConstant()->Value());
Handle<SharedFunctionInfo> shared(function->shared(), isolate());
- // Remove the eager bailout frame state.
- NodeProperties::RemoveFrameStateInput(node, 1);
-
// Patch {node} to an indirect call via the {function}s construct stub.
Callable callable(handle(shared->construct_stub(), isolate()),
ConstructStubDescriptor(isolate()));
@@ -1409,9 +1521,6 @@
// Check if {target} is a JSFunction.
if (target_type->Is(Type::Function())) {
- // Remove the eager bailout frame state.
- NodeProperties::RemoveFrameStateInput(node, 1);
-
// Patch {node} to an indirect call via the ConstructFunction builtin.
Callable callable = CodeFactory::ConstructFunction(isolate());
node->RemoveInput(arity + 1);
@@ -1440,9 +1549,9 @@
Type* target_type = NodeProperties::GetType(target);
Node* receiver = NodeProperties::GetValueInput(node, 1);
Type* receiver_type = NodeProperties::GetType(receiver);
- Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
+ Node* frame_state = NodeProperties::FindFrameStateBefore(node);
// Try to infer receiver {convert_mode} from {receiver} type.
if (receiver_type->Is(Type::NullOrUndefined())) {
@@ -1480,9 +1589,6 @@
// Update the effect dependency for the {node}.
NodeProperties::ReplaceEffectInput(node, effect);
- // Remove the eager bailout frame state.
- NodeProperties::RemoveFrameStateInput(node, 1);
-
// Compute flags for the call.
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
if (p.tail_call_mode() == TailCallMode::kAllow) {
@@ -1520,9 +1626,6 @@
// Check if {target} is a JSFunction.
if (target_type->Is(Type::Function())) {
- // Remove the eager bailout frame state.
- NodeProperties::RemoveFrameStateInput(node, 1);
-
// Compute flags for the call.
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
if (p.tail_call_mode() == TailCallMode::kAllow) {
@@ -1630,6 +1733,84 @@
return Changed(node);
}
+Reduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
+ DCHECK_EQ(IrOpcode::kJSGeneratorStore, node->opcode());
+ Node* generator = NodeProperties::GetValueInput(node, 0);
+ Node* continuation = NodeProperties::GetValueInput(node, 1);
+ Node* offset = NodeProperties::GetValueInput(node, 2);
+ Node* context = NodeProperties::GetContextInput(node);
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+ int register_count = OpParameter<int>(node);
+
+ FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectOperandStack();
+ FieldAccess context_field = AccessBuilder::ForJSGeneratorObjectContext();
+ FieldAccess continuation_field =
+ AccessBuilder::ForJSGeneratorObjectContinuation();
+ FieldAccess input_or_debug_pos_field =
+ AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
+
+ Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
+ generator, effect, control);
+
+ for (int i = 0; i < register_count; ++i) {
+ Node* value = NodeProperties::GetValueInput(node, 3 + i);
+ effect = graph()->NewNode(
+ simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), array,
+ value, effect, control);
+ }
+
+ effect = graph()->NewNode(simplified()->StoreField(context_field), generator,
+ context, effect, control);
+ effect = graph()->NewNode(simplified()->StoreField(continuation_field),
+ generator, continuation, effect, control);
+ effect = graph()->NewNode(simplified()->StoreField(input_or_debug_pos_field),
+ generator, offset, effect, control);
+
+ ReplaceWithValue(node, effect, effect, control);
+ return Changed(effect);
+}
+
+Reduction JSTypedLowering::ReduceJSGeneratorRestoreContinuation(Node* node) {
+ DCHECK_EQ(IrOpcode::kJSGeneratorRestoreContinuation, node->opcode());
+ Node* generator = NodeProperties::GetValueInput(node, 0);
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+
+ FieldAccess continuation_field =
+ AccessBuilder::ForJSGeneratorObjectContinuation();
+
+ Node* continuation = effect = graph()->NewNode(
+ simplified()->LoadField(continuation_field), generator, effect, control);
+ Node* executing = jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting);
+ effect = graph()->NewNode(simplified()->StoreField(continuation_field),
+ generator, executing, effect, control);
+
+ ReplaceWithValue(node, continuation, effect, control);
+ return Changed(continuation);
+}
+
+Reduction JSTypedLowering::ReduceJSGeneratorRestoreRegister(Node* node) {
+ DCHECK_EQ(IrOpcode::kJSGeneratorRestoreRegister, node->opcode());
+ Node* generator = NodeProperties::GetValueInput(node, 0);
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+ int index = OpParameter<int>(node);
+
+ FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectOperandStack();
+ FieldAccess element_field = AccessBuilder::ForFixedArraySlot(index);
+
+ Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
+ generator, effect, control);
+ Node* element = effect = graph()->NewNode(
+ simplified()->LoadField(element_field), array, effect, control);
+ Node* stale = jsgraph()->StaleRegisterConstant();
+ effect = graph()->NewNode(simplified()->StoreField(element_field), array,
+ stale, effect, control);
+
+ ReplaceWithValue(node, element, effect, control);
+ return Changed(element);
+}
Reduction JSTypedLowering::ReduceSelect(Node* node) {
DCHECK_EQ(IrOpcode::kSelect, node->opcode());
@@ -1666,31 +1847,38 @@
// result value and can simply replace the node if it's eliminable.
if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
node->op()->HasProperty(Operator::kEliminatable)) {
+ // We can only constant-fold nodes here, that are known to not cause any
+ // side-effect, may it be a JavaScript observable side-effect or a possible
+ // eager deoptimization exit (i.e. {node} has an operator that doesn't have
+ // the Operator::kNoDeopt property).
Type* upper = NodeProperties::GetType(node);
- if (upper->IsConstant()) {
- Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value());
- ReplaceWithValue(node, replacement);
- return Changed(replacement);
- } else if (upper->Is(Type::MinusZero())) {
- Node* replacement = jsgraph()->Constant(factory()->minus_zero_value());
- ReplaceWithValue(node, replacement);
- return Changed(replacement);
- } else if (upper->Is(Type::NaN())) {
- Node* replacement = jsgraph()->NaNConstant();
- ReplaceWithValue(node, replacement);
- return Changed(replacement);
- } else if (upper->Is(Type::Null())) {
- Node* replacement = jsgraph()->NullConstant();
- ReplaceWithValue(node, replacement);
- return Changed(replacement);
- } else if (upper->Is(Type::PlainNumber()) && upper->Min() == upper->Max()) {
- Node* replacement = jsgraph()->Constant(upper->Min());
- ReplaceWithValue(node, replacement);
- return Changed(replacement);
- } else if (upper->Is(Type::Undefined())) {
- Node* replacement = jsgraph()->UndefinedConstant();
- ReplaceWithValue(node, replacement);
- return Changed(replacement);
+ if (upper->IsInhabited()) {
+ if (upper->IsConstant()) {
+ Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value());
+ ReplaceWithValue(node, replacement);
+ return Changed(replacement);
+ } else if (upper->Is(Type::MinusZero())) {
+ Node* replacement = jsgraph()->Constant(factory()->minus_zero_value());
+ ReplaceWithValue(node, replacement);
+ return Changed(replacement);
+ } else if (upper->Is(Type::NaN())) {
+ Node* replacement = jsgraph()->NaNConstant();
+ ReplaceWithValue(node, replacement);
+ return Changed(replacement);
+ } else if (upper->Is(Type::Null())) {
+ Node* replacement = jsgraph()->NullConstant();
+ ReplaceWithValue(node, replacement);
+ return Changed(replacement);
+ } else if (upper->Is(Type::PlainNumber()) &&
+ upper->Min() == upper->Max()) {
+ Node* replacement = jsgraph()->Constant(upper->Min());
+ ReplaceWithValue(node, replacement);
+ return Changed(replacement);
+ } else if (upper->Is(Type::Undefined())) {
+ Node* replacement = jsgraph()->UndefinedConstant();
+ ReplaceWithValue(node, replacement);
+ return Changed(replacement);
+ }
}
}
switch (node->opcode()) {
@@ -1723,11 +1911,11 @@
case IrOpcode::kJSAdd:
return ReduceJSAdd(node);
case IrOpcode::kJSSubtract:
- return ReduceNumberBinop(node, simplified()->NumberSubtract());
+ return ReduceJSSubtract(node);
case IrOpcode::kJSMultiply:
- return ReduceNumberBinop(node, simplified()->NumberMultiply());
+ return ReduceJSMultiply(node);
case IrOpcode::kJSDivide:
- return ReduceNumberBinop(node, simplified()->NumberDivide());
+ return ReduceJSDivide(node);
case IrOpcode::kJSModulus:
return ReduceJSModulus(node);
case IrOpcode::kJSToBoolean:
@@ -1766,6 +1954,12 @@
return ReduceJSForInNext(node);
case IrOpcode::kJSForInStep:
return ReduceJSForInStep(node);
+ case IrOpcode::kJSGeneratorStore:
+ return ReduceJSGeneratorStore(node);
+ case IrOpcode::kJSGeneratorRestoreContinuation:
+ return ReduceJSGeneratorRestoreContinuation(node);
+ case IrOpcode::kJSGeneratorRestoreRegister:
+ return ReduceJSGeneratorRestoreRegister(node);
case IrOpcode::kSelect:
return ReduceSelect(node);
default:
@@ -1781,6 +1975,14 @@
jsgraph()->Int32Constant(rhs));
}
+Node* JSTypedLowering::EmptyFrameState() {
+ return graph()->NewNode(
+ common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
+ nullptr),
+ jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
+ jsgraph()->EmptyStateValues(), jsgraph()->NoContextConstant(),
+ jsgraph()->UndefinedConstant(), graph()->start());
+}
Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }