diff --git a/src/compiler/node-properties.cc b/src/compiler/node-properties.cc index bcfb035a58..afb163eede 100644 --- a/src/compiler/node-properties.cc +++ b/src/compiler/node-properties.cc @@ -565,19 +565,19 @@ bool NodeProperties::CanBePrimitive(Node* receiver, Node* effect) { bool NodeProperties::CanBeNullOrUndefined(Node* receiver, Node* effect) { if (CanBePrimitive(receiver, effect)) { switch (receiver->opcode()) { - case IrOpcode::kCheckSmi: - case IrOpcode::kCheckNumber: - case IrOpcode::kCheckSymbol: - case IrOpcode::kCheckString: - case IrOpcode::kCheckSeqString: case IrOpcode::kCheckInternalizedString: - case IrOpcode::kToBoolean: + case IrOpcode::kCheckNumber: + case IrOpcode::kCheckSeqString: + case IrOpcode::kCheckSmi: + case IrOpcode::kCheckString: + case IrOpcode::kCheckSymbol: case IrOpcode::kJSToInteger: case IrOpcode::kJSToLength: case IrOpcode::kJSToName: case IrOpcode::kJSToNumber: case IrOpcode::kJSToNumeric: case IrOpcode::kJSToString: + case IrOpcode::kToBoolean: return false; case IrOpcode::kHeapConstant: { Handle value = HeapObjectMatcher(receiver).Value(); diff --git a/src/compiler/redundancy-elimination.cc b/src/compiler/redundancy-elimination.cc index da15c8c44c..eedf946fb6 100644 --- a/src/compiler/redundancy-elimination.cc +++ b/src/compiler/redundancy-elimination.cc @@ -20,26 +20,36 @@ Reduction RedundancyElimination::Reduce(Node* node) { if (node_checks_.Get(node)) return NoChange(); switch (node->opcode()) { case IrOpcode::kCheckBounds: + case IrOpcode::kCheckEqualsInternalizedString: + case IrOpcode::kCheckEqualsSymbol: case IrOpcode::kCheckFloat64Hole: case IrOpcode::kCheckHeapObject: case IrOpcode::kCheckIf: case IrOpcode::kCheckInternalizedString: + case IrOpcode::kCheckNotTaggedHole: case IrOpcode::kCheckNumber: case IrOpcode::kCheckReceiver: + case IrOpcode::kCheckSeqString: case IrOpcode::kCheckSmi: case IrOpcode::kCheckString: - case IrOpcode::kCheckSeqString: - case IrOpcode::kCheckNotTaggedHole: + case IrOpcode::kCheckSymbol: case IrOpcode::kCheckedFloat64ToInt32: case IrOpcode::kCheckedInt32Add: - case IrOpcode::kCheckedInt32Sub: case IrOpcode::kCheckedInt32Div: case IrOpcode::kCheckedInt32Mod: case IrOpcode::kCheckedInt32Mul: - case IrOpcode::kCheckedTaggedToFloat64: + case IrOpcode::kCheckedInt32Sub: + case IrOpcode::kCheckedInt32ToTaggedSigned: case IrOpcode::kCheckedTaggedSignedToInt32: + case IrOpcode::kCheckedTaggedToFloat64: case IrOpcode::kCheckedTaggedToInt32: + case IrOpcode::kCheckedTaggedToTaggedPointer: + case IrOpcode::kCheckedTaggedToTaggedSigned: + case IrOpcode::kCheckedTruncateTaggedToWord32: + case IrOpcode::kCheckedUint32Div: + case IrOpcode::kCheckedUint32Mod: case IrOpcode::kCheckedUint32ToInt32: + case IrOpcode::kCheckedUint32ToTaggedSigned: return ReduceCheckNode(node); case IrOpcode::kSpeculativeNumberAdd: case IrOpcode::kSpeculativeNumberSubtract: @@ -125,7 +135,8 @@ RedundancyElimination::EffectPathChecks::AddCheck(Zone* zone, namespace { -bool IsCompatibleCheck(Node const* a, Node const* b) { +// Does check {a} subsume check {b}? +bool CheckSubsumes(Node const* a, Node const* b) { if (a->op() != b->op()) { if (a->opcode() == IrOpcode::kCheckInternalizedString && b->opcode() == IrOpcode::kCheckString) { @@ -139,12 +150,12 @@ bool IsCompatibleCheck(Node const* a, Node const* b) { case IrOpcode::kCheckString: case IrOpcode::kCheckNumber: break; + case IrOpcode::kCheckedInt32ToTaggedSigned: case IrOpcode::kCheckedTaggedSignedToInt32: + case IrOpcode::kCheckedTaggedToTaggedPointer: case IrOpcode::kCheckedTaggedToTaggedSigned: case IrOpcode::kCheckedUint32ToInt32: case IrOpcode::kCheckedUint32ToTaggedSigned: - case IrOpcode::kCheckedInt32ToTaggedSigned: - case IrOpcode::kCheckedTaggedToTaggedPointer: break; case IrOpcode::kCheckedFloat64ToInt32: case IrOpcode::kCheckedTaggedToInt32: { @@ -158,6 +169,7 @@ bool IsCompatibleCheck(Node const* a, Node const* b) { break; } default: + DCHECK(!IsCheckedWithFeedback(a->op())); return false; } } @@ -172,7 +184,7 @@ bool IsCompatibleCheck(Node const* a, Node const* b) { Node* RedundancyElimination::EffectPathChecks::LookupCheck(Node* node) const { for (Check const* check = head_; check != nullptr; check = check->next) { - if (IsCompatibleCheck(check->node, node)) { + if (CheckSubsumes(check->node, node)) { DCHECK(!check->node->IsDead()); return check->node; } diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc index 45901cceb4..af5871a616 100644 --- a/src/compiler/simplified-operator.cc +++ b/src/compiler/simplified-operator.cc @@ -714,32 +714,32 @@ bool operator==(CheckMinusZeroParameters const& lhs, V(SpeculativeNumberLessThanOrEqual) #define CHECKED_OP_LIST(V) \ + V(CheckEqualsInternalizedString, 2, 0) \ + V(CheckEqualsSymbol, 2, 0) \ V(CheckHeapObject, 1, 1) \ V(CheckInternalizedString, 1, 1) \ + V(CheckNotTaggedHole, 1, 1) \ V(CheckReceiver, 1, 1) \ V(CheckSeqString, 1, 1) \ V(CheckSymbol, 1, 1) \ - V(CheckNotTaggedHole, 1, 1) \ - V(CheckEqualsInternalizedString, 2, 0) \ - V(CheckEqualsSymbol, 2, 0) \ V(CheckedInt32Add, 2, 1) \ - V(CheckedInt32Sub, 2, 1) \ V(CheckedInt32Div, 2, 1) \ V(CheckedInt32Mod, 2, 1) \ + V(CheckedInt32Sub, 2, 1) \ V(CheckedUint32Div, 2, 1) \ V(CheckedUint32Mod, 2, 1) #define CHECKED_WITH_FEEDBACK_OP_LIST(V) \ V(CheckBounds, 2, 1) \ + V(CheckNumber, 1, 1) \ V(CheckSmi, 1, 1) \ V(CheckString, 1, 1) \ + V(CheckedInt32ToTaggedSigned, 1, 1) \ V(CheckedTaggedSignedToInt32, 1, 1) \ + V(CheckedTaggedToTaggedPointer, 1, 1) \ V(CheckedTaggedToTaggedSigned, 1, 1) \ V(CheckedUint32ToInt32, 1, 1) \ - V(CheckedUint32ToTaggedSigned, 1, 1) \ - V(CheckedInt32ToTaggedSigned, 1, 1) \ - V(CheckedTaggedToTaggedPointer, 1, 1) \ - V(CheckNumber, 1, 1) + V(CheckedUint32ToTaggedSigned, 1, 1) struct SimplifiedOperatorGlobalCache final { #define PURE(Name, properties, value_input_count, control_input_count) \ @@ -1052,6 +1052,16 @@ GET_FROM_CACHE(LoadFieldByIndex) CHECKED_WITH_FEEDBACK_OP_LIST(GET_FROM_CACHE_WITH_FEEDBACK) #undef GET_FROM_CACHE_WITH_FEEDBACK +bool IsCheckedWithFeedback(const Operator* op) { +#define CASE(Name, ...) case IrOpcode::k##Name: + switch (op->opcode()) { + CHECKED_WITH_FEEDBACK_OP_LIST(CASE) return true; + default: + return false; + } +#undef CASE +} + const Operator* SimplifiedOperatorBuilder::RuntimeAbort(AbortReason reason) { return new (zone()) Operator1( // -- IrOpcode::kRuntimeAbort, // opcode diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h index 5341b35080..80dc577d1b 100644 --- a/src/compiler/simplified-operator.h +++ b/src/compiler/simplified-operator.h @@ -369,6 +369,8 @@ class AllocateParameters { PretenureFlag pretenure_; }; +bool IsCheckedWithFeedback(const Operator* op); + size_t hash_value(AllocateParameters); V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, AllocateParameters); @@ -535,53 +537,52 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final const Operator* TruncateTaggedToBit(); const Operator* TruncateTaggedPointerToBit(); - const Operator* CheckIf(DeoptimizeReason deoptimize_reason); - const Operator* CheckBounds(const VectorSlotPair& feedback); - const Operator* CheckMaps(CheckMapsFlags, ZoneHandleSet, - const VectorSlotPair& = VectorSlotPair()); const Operator* MaskIndexWithBound(); const Operator* CompareMaps(ZoneHandleSet); const Operator* MapGuard(ZoneHandleSet maps); + const Operator* CheckBounds(const VectorSlotPair& feedback); + const Operator* CheckEqualsInternalizedString(); + const Operator* CheckEqualsSymbol(); + const Operator* CheckFloat64Hole(CheckFloat64HoleMode); const Operator* CheckHeapObject(); + const Operator* CheckIf(DeoptimizeReason deoptimize_reason); const Operator* CheckInternalizedString(); + const Operator* CheckMaps(CheckMapsFlags, ZoneHandleSet, + const VectorSlotPair& = VectorSlotPair()); + const Operator* CheckNotTaggedHole(); const Operator* CheckNumber(const VectorSlotPair& feedback); + const Operator* CheckReceiver(); + const Operator* CheckSeqString(); const Operator* CheckSmi(const VectorSlotPair& feedback); const Operator* CheckString(const VectorSlotPair& feedback); - const Operator* CheckSeqString(); const Operator* CheckSymbol(); - const Operator* CheckReceiver(); - const Operator* CheckedInt32Add(); - const Operator* CheckedInt32Sub(); - const Operator* CheckedInt32Div(); - const Operator* CheckedInt32Mod(); - const Operator* CheckedUint32Div(); - const Operator* CheckedUint32Mod(); - const Operator* CheckedInt32Mul(CheckForMinusZeroMode); - const Operator* CheckedInt32ToTaggedSigned(const VectorSlotPair& feedback); - const Operator* CheckedUint32ToInt32(const VectorSlotPair& feedback); - const Operator* CheckedUint32ToTaggedSigned(const VectorSlotPair& feedback); const Operator* CheckedFloat64ToInt32(CheckForMinusZeroMode, const VectorSlotPair& feedback); + const Operator* CheckedInt32Add(); + const Operator* CheckedInt32Div(); + const Operator* CheckedInt32Mod(); + const Operator* CheckedInt32Mul(CheckForMinusZeroMode); + const Operator* CheckedInt32Sub(); + const Operator* CheckedInt32ToTaggedSigned(const VectorSlotPair& feedback); const Operator* CheckedTaggedSignedToInt32(const VectorSlotPair& feedback); + const Operator* CheckedTaggedToFloat64(CheckTaggedInputMode); const Operator* CheckedTaggedToInt32(CheckForMinusZeroMode, const VectorSlotPair& feedback); - const Operator* CheckedTaggedToFloat64(CheckTaggedInputMode); - const Operator* CheckedTaggedToTaggedSigned(const VectorSlotPair& feedback); const Operator* CheckedTaggedToTaggedPointer(const VectorSlotPair& feedback); + const Operator* CheckedTaggedToTaggedSigned(const VectorSlotPair& feedback); const Operator* CheckedTruncateTaggedToWord32(CheckTaggedInputMode, const VectorSlotPair& feedback); + const Operator* CheckedUint32Div(); + const Operator* CheckedUint32Mod(); + const Operator* CheckedUint32ToInt32(const VectorSlotPair& feedback); + const Operator* CheckedUint32ToTaggedSigned(const VectorSlotPair& feedback); const Operator* ConvertReceiver(ConvertReceiverMode); - const Operator* CheckFloat64Hole(CheckFloat64HoleMode); - const Operator* CheckNotTaggedHole(); const Operator* ConvertTaggedHoleToUndefined(); - const Operator* CheckEqualsInternalizedString(); - const Operator* CheckEqualsSymbol(); - const Operator* ObjectIsArrayBufferView(); const Operator* ObjectIsBigInt(); const Operator* ObjectIsCallable();