| Index: src/compiler/simplified-lowering.cc
|
| diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
| index c2e8e97e2329ed479ec99704d2a8b2fec076a593..e7aaf43535a54e0bf27a1361265758a28c9d7532 100644
|
| --- a/src/compiler/simplified-lowering.cc
|
| +++ b/src/compiler/simplified-lowering.cc
|
| @@ -1075,7 +1075,13 @@ class RepresentationSelector {
|
|
|
| void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
|
| SimplifiedLowering* lowering) {
|
| - if (truncation.IsUnused()) return VisitUnused(node);
|
| + // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can
|
| + // only eliminate an unused speculative number operation if we know that
|
| + // the inputs are PlainPrimitive, which excludes everything that's might
|
| + // have side effects or throws during a ToNumber conversion.
|
| + if (BothInputsAre(node, Type::PlainPrimitive())) {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| + }
|
| if (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) &&
|
| NodeProperties::GetType(node)->Is(Type::Signed32())) {
|
| // int32 + int32 = int32 ==> signed Int32Add/Sub
|
| @@ -1136,8 +1142,15 @@ class RepresentationSelector {
|
| // Unconditionally eliminate unused pure nodes (only relevant if there's
|
| // a pure operation in between two effectful ones, where the last one
|
| // is unused).
|
| - if (node->op()->HasProperty(Operator::kPure) && truncation.IsUnused()) {
|
| - return VisitUnused(node);
|
| + // Note: We must not do this for constants, as they are cached and we
|
| + // would thus kill the cached {node} during lowering (i.e. replace all
|
| + // uses with Dead), but at that point some node lowering might have
|
| + // already taken the constant {node} from the cache (while it was in
|
| + // a sane state still) and we would afterwards replace that use with
|
| + // Dead as well.
|
| + if (node->op()->ValueInputCount() > 0 &&
|
| + node->op()->HasProperty(Operator::kPure)) {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| }
|
| switch (node->opcode()) {
|
| //------------------------------------------------------------------
|
| @@ -1261,7 +1274,13 @@ class RepresentationSelector {
|
| case IrOpcode::kSpeculativeNumberLessThan:
|
| case IrOpcode::kSpeculativeNumberLessThanOrEqual:
|
| case IrOpcode::kSpeculativeNumberEqual: {
|
| - if (truncation.IsUnused()) return VisitUnused(node);
|
| + // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
|
| + // can only eliminate an unused speculative number operation if we know
|
| + // that the inputs are PlainPrimitive, which excludes everything that's
|
| + // might have side effects or throws during a ToNumber conversion.
|
| + if (BothInputsAre(node, Type::PlainPrimitive())) {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| + }
|
| // Number comparisons reduce to integer comparisons for integer inputs.
|
| if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
|
| TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
|
| @@ -1316,7 +1335,13 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kSpeculativeNumberMultiply: {
|
| - if (truncation.IsUnused()) return VisitUnused(node);
|
| + // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
|
| + // can only eliminate an unused speculative number operation if we know
|
| + // that the inputs are PlainPrimitive, which excludes everything that's
|
| + // might have side effects or throws during a ToNumber conversion.
|
| + if (BothInputsAre(node, Type::PlainPrimitive())) {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| + }
|
| if (BothInputsAre(node, Type::Integral32()) &&
|
| (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
|
| NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
|
| @@ -1391,7 +1416,13 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kSpeculativeNumberDivide: {
|
| - if (truncation.IsUnused()) return VisitUnused(node);
|
| + // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
|
| + // can only eliminate an unused speculative number operation if we know
|
| + // that the inputs are PlainPrimitive, which excludes everything that's
|
| + // might have side effects or throws during a ToNumber conversion.
|
| + if (BothInputsAre(node, Type::PlainPrimitive())) {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| + }
|
| if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
|
| // => unsigned Uint32Div
|
| VisitWord32TruncatingBinop(node);
|
| @@ -1497,7 +1528,13 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kSpeculativeNumberModulus: {
|
| - if (truncation.IsUnused()) return VisitUnused(node);
|
| + // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
|
| + // can only eliminate an unused speculative number operation if we know
|
| + // that the inputs are PlainPrimitive, which excludes everything that's
|
| + // might have side effects or throws during a ToNumber conversion.
|
| + if (BothInputsAre(node, Type::PlainPrimitive())) {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| + }
|
| if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
|
| // => unsigned Uint32Mod
|
| VisitWord32TruncatingBinop(node);
|
| @@ -1611,7 +1648,13 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kSpeculativeNumberShiftLeft: {
|
| - if (truncation.IsUnused()) return VisitUnused(node);
|
| + // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
|
| + // can only eliminate an unused speculative number operation if we know
|
| + // that the inputs are PlainPrimitive, which excludes everything that's
|
| + // might have side effects or throws during a ToNumber conversion.
|
| + if (BothInputsAre(node, Type::PlainPrimitive())) {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| + }
|
| if (BothInputsAre(node, Type::NumberOrOddball())) {
|
| Type* rhs_type = GetUpperBound(node->InputAt(1));
|
| VisitBinop(node, UseInfo::TruncatingWord32(),
|
|
|