| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/address-map.h" | 9 #include "src/address-map.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 | 234 |
| 235 MachineRepresentation representation() const { return representation_; } | 235 MachineRepresentation representation() const { return representation_; } |
| 236 | 236 |
| 237 // Helpers for feedback typing. | 237 // Helpers for feedback typing. |
| 238 void set_feedback_type(Type* type) { feedback_type_ = type; } | 238 void set_feedback_type(Type* type) { feedback_type_ = type; } |
| 239 Type* feedback_type() const { return feedback_type_; } | 239 Type* feedback_type() const { return feedback_type_; } |
| 240 void set_weakened() { weakened_ = true; } | 240 void set_weakened() { weakened_ = true; } |
| 241 bool weakened() const { return weakened_; } | 241 bool weakened() const { return weakened_; } |
| 242 void set_restriction_type(Type* type) { restriction_type_ = type; } | 242 void set_restriction_type(Type* type) { restriction_type_ = type; } |
| 243 Type* restriction_type() const { return restriction_type_; } | 243 Type* restriction_type() const { return restriction_type_; } |
| 244 void set_unrestricted_feedback_type(Type* type) { |
| 245 unrestricted_feedback_type_ = type; |
| 246 } |
| 247 Type* unrestricted_feedback_type() const { |
| 248 return unrestricted_feedback_type_; |
| 249 } |
| 244 | 250 |
| 245 private: | 251 private: |
| 246 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; | 252 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; |
| 247 State state_ = kUnvisited; | 253 State state_ = kUnvisited; |
| 248 MachineRepresentation representation_ = | 254 MachineRepresentation representation_ = |
| 249 MachineRepresentation::kNone; // Output representation. | 255 MachineRepresentation::kNone; // Output representation. |
| 250 Truncation truncation_ = Truncation::None(); // Information about uses. | 256 Truncation truncation_ = Truncation::None(); // Information about uses. |
| 251 | 257 |
| 252 Type* restriction_type_ = Type::Any(); | 258 Type* restriction_type_ = Type::Any(); |
| 253 Type* feedback_type_ = nullptr; | 259 Type* feedback_type_ = nullptr; |
| 260 Type* unrestricted_feedback_type_ = nullptr; |
| 254 bool weakened_ = false; | 261 bool weakened_ = false; |
| 255 }; | 262 }; |
| 256 | 263 |
| 257 RepresentationSelector(JSGraph* jsgraph, Zone* zone, | 264 RepresentationSelector(JSGraph* jsgraph, Zone* zone, |
| 258 RepresentationChanger* changer, | 265 RepresentationChanger* changer, |
| 259 SourcePositionTable* source_positions) | 266 SourcePositionTable* source_positions) |
| 260 : jsgraph_(jsgraph), | 267 : jsgraph_(jsgraph), |
| 261 zone_(zone), | 268 zone_(zone), |
| 262 count_(jsgraph->graph()->NodeCount()), | 269 count_(jsgraph->graph()->NodeCount()), |
| 263 info_(count_, zone), | 270 info_(count_, zone), |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 Type* TypeOf(Node* node) { | 364 Type* TypeOf(Node* node) { |
| 358 Type* type = GetInfo(node)->feedback_type(); | 365 Type* type = GetInfo(node)->feedback_type(); |
| 359 return type == nullptr ? NodeProperties::GetType(node) : type; | 366 return type == nullptr ? NodeProperties::GetType(node) : type; |
| 360 } | 367 } |
| 361 | 368 |
| 362 Type* FeedbackTypeOf(Node* node) { | 369 Type* FeedbackTypeOf(Node* node) { |
| 363 Type* type = GetInfo(node)->feedback_type(); | 370 Type* type = GetInfo(node)->feedback_type(); |
| 364 return type == nullptr ? Type::None() : type; | 371 return type == nullptr ? Type::None() : type; |
| 365 } | 372 } |
| 366 | 373 |
| 374 Type* UnrestrictedFeedbackTypeOf(Node* node) { |
| 375 Type* type = GetInfo(node)->unrestricted_feedback_type(); |
| 376 return type == nullptr ? NodeProperties::GetType(node) : type; |
| 377 } |
| 378 |
| 367 Type* TypePhi(Node* node) { | 379 Type* TypePhi(Node* node) { |
| 368 int arity = node->op()->ValueInputCount(); | 380 int arity = node->op()->ValueInputCount(); |
| 369 Type* type = FeedbackTypeOf(node->InputAt(0)); | 381 Type* type = FeedbackTypeOf(node->InputAt(0)); |
| 370 for (int i = 1; i < arity; ++i) { | 382 for (int i = 1; i < arity; ++i) { |
| 371 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); | 383 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); |
| 372 } | 384 } |
| 373 return type; | 385 return type; |
| 374 } | 386 } |
| 375 | 387 |
| 376 Type* TypeSelect(Node* node) { | 388 Type* TypeSelect(Node* node) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 399 switch (node->opcode()) { | 411 switch (node->opcode()) { |
| 400 #define DECLARE_CASE(Name) \ | 412 #define DECLARE_CASE(Name) \ |
| 401 case IrOpcode::k##Name: { \ | 413 case IrOpcode::k##Name: { \ |
| 402 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ | 414 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ |
| 403 FeedbackTypeOf(node->InputAt(1))); \ | 415 FeedbackTypeOf(node->InputAt(1))); \ |
| 404 break; \ | 416 break; \ |
| 405 } | 417 } |
| 406 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE) | 418 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE) |
| 407 #undef DECLARE_CASE | 419 #undef DECLARE_CASE |
| 408 | 420 |
| 409 #define DECLARE_CASE(Name) \ | 421 #define DECLARE_CASE(Name) \ |
| 410 case IrOpcode::k##Name: { \ | 422 case IrOpcode::k##Name: { \ |
| 411 new_type = \ | 423 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ |
| 412 Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ | 424 FeedbackTypeOf(node->InputAt(1))); \ |
| 413 FeedbackTypeOf(node->InputAt(1))), \ | 425 break; \ |
| 414 info->restriction_type(), graph_zone()); \ | |
| 415 break; \ | |
| 416 } | 426 } |
| 417 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE) | 427 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE) |
| 418 #undef DECLARE_CASE | 428 #undef DECLARE_CASE |
| 419 | 429 |
| 420 #define DECLARE_CASE(Name) \ | 430 #define DECLARE_CASE(Name) \ |
| 421 case IrOpcode::k##Name: { \ | 431 case IrOpcode::k##Name: { \ |
| 422 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0))); \ | 432 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0))); \ |
| 423 break; \ | 433 break; \ |
| 424 } | 434 } |
| 425 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) | 435 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 444 } | 454 } |
| 445 | 455 |
| 446 case IrOpcode::kSelect: { | 456 case IrOpcode::kSelect: { |
| 447 new_type = TypeSelect(node); | 457 new_type = TypeSelect(node); |
| 448 break; | 458 break; |
| 449 } | 459 } |
| 450 | 460 |
| 451 default: | 461 default: |
| 452 // Shortcut for operations that we do not handle. | 462 // Shortcut for operations that we do not handle. |
| 453 if (type == nullptr) { | 463 if (type == nullptr) { |
| 454 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node)); | 464 type = GetUpperBound(node); |
| 465 info->set_unrestricted_feedback_type(type); |
| 466 info->set_feedback_type( |
| 467 Type::Intersect(type, info->restriction_type(), graph_zone())); |
| 455 return true; | 468 return true; |
| 456 } | 469 } |
| 457 return false; | 470 return false; |
| 458 } | 471 } |
| 472 Type* unrestricted_feedback_type = new_type; |
| 473 new_type = |
| 474 Type::Intersect(new_type, info->restriction_type(), graph_zone()); |
| 459 // We need to guarantee that the feedback type is a subtype of the upper | 475 // We need to guarantee that the feedback type is a subtype of the upper |
| 460 // bound. Naively that should hold, but weakening can actually produce | 476 // bound. Naively that should hold, but weakening can actually produce |
| 461 // a bigger type if we are unlucky with ordering of phi typing. To be | 477 // a bigger type if we are unlucky with ordering of phi typing. To be |
| 462 // really sure, just intersect the upper bound with the feedback type. | 478 // really sure, just intersect the upper bound with the feedback type. |
| 463 new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone()); | 479 new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone()); |
| 464 | 480 |
| 465 if (type != nullptr && new_type->Is(type)) return false; | 481 if (type != nullptr && new_type->Is(type)) return false; |
| 466 GetInfo(node)->set_feedback_type(new_type); | 482 info->set_unrestricted_feedback_type(unrestricted_feedback_type); |
| 483 info->set_feedback_type(new_type); |
| 467 if (FLAG_trace_representation) { | 484 if (FLAG_trace_representation) { |
| 468 PrintNodeFeedbackType(node); | 485 PrintNodeFeedbackType(node); |
| 469 } | 486 } |
| 470 return true; | 487 return true; |
| 471 } | 488 } |
| 472 | 489 |
| 473 void PrintNodeFeedbackType(Node* n) { | 490 void PrintNodeFeedbackType(Node* n) { |
| 474 OFStream os(stdout); | 491 OFStream os(stdout); |
| 475 os << "#" << n->id() << ":" << *n->op() << "("; | 492 os << "#" << n->id() << ":" << *n->op() << "("; |
| 476 int j = 0; | 493 int j = 0; |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1099 return WriteBarrierKindFor(base_taggedness, field_representation, | 1116 return WriteBarrierKindFor(base_taggedness, field_representation, |
| 1100 field_type, value_representation, value); | 1117 field_type, value_representation, value); |
| 1101 } | 1118 } |
| 1102 | 1119 |
| 1103 Graph* graph() const { return jsgraph_->graph(); } | 1120 Graph* graph() const { return jsgraph_->graph(); } |
| 1104 CommonOperatorBuilder* common() const { return jsgraph_->common(); } | 1121 CommonOperatorBuilder* common() const { return jsgraph_->common(); } |
| 1105 SimplifiedOperatorBuilder* simplified() const { | 1122 SimplifiedOperatorBuilder* simplified() const { |
| 1106 return jsgraph_->simplified(); | 1123 return jsgraph_->simplified(); |
| 1107 } | 1124 } |
| 1108 | 1125 |
| 1109 void LowerToCheckedInt32Mul(Node* node, Truncation truncation, | |
| 1110 Type* input0_type, Type* input1_type) { | |
| 1111 // If one of the inputs is positive and/or truncation is being applied, | |
| 1112 // there is no need to return -0. | |
| 1113 CheckForMinusZeroMode mz_mode = | |
| 1114 truncation.IsUsedAsWord32() || | |
| 1115 (input0_type->Is(Type::OrderedNumber()) && | |
| 1116 input0_type->Min() > 0) || | |
| 1117 (input1_type->Is(Type::OrderedNumber()) && | |
| 1118 input1_type->Min() > 0) | |
| 1119 ? CheckForMinusZeroMode::kDontCheckForMinusZero | |
| 1120 : CheckForMinusZeroMode::kCheckForMinusZero; | |
| 1121 | |
| 1122 NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode)); | |
| 1123 } | |
| 1124 | |
| 1125 void ChangeToInt32OverflowOp(Node* node) { | 1126 void ChangeToInt32OverflowOp(Node* node) { |
| 1126 NodeProperties::ChangeOp(node, Int32OverflowOp(node)); | 1127 NodeProperties::ChangeOp(node, Int32OverflowOp(node)); |
| 1127 } | 1128 } |
| 1128 | 1129 |
| 1129 void ChangeToUint32OverflowOp(Node* node) { | 1130 void ChangeToUint32OverflowOp(Node* node) { |
| 1130 NodeProperties::ChangeOp(node, Uint32OverflowOp(node)); | 1131 NodeProperties::ChangeOp(node, Uint32OverflowOp(node)); |
| 1131 } | 1132 } |
| 1132 | 1133 |
| 1133 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, | 1134 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, |
| 1134 SimplifiedLowering* lowering) { | 1135 SimplifiedLowering* lowering) { |
| 1135 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can | 1136 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can |
| 1136 // only eliminate an unused speculative number operation if we know that | 1137 // only eliminate an unused speculative number operation if we know that |
| 1137 // the inputs are PlainPrimitive, which excludes everything that's might | 1138 // the inputs are PlainPrimitive, which excludes everything that's might |
| 1138 // have side effects or throws during a ToNumber conversion. | 1139 // have side effects or throws during a ToNumber conversion. |
| 1139 if (BothInputsAre(node, Type::PlainPrimitive())) { | 1140 if (BothInputsAre(node, Type::PlainPrimitive())) { |
| 1140 if (truncation.IsUnused()) return VisitUnused(node); | 1141 if (truncation.IsUnused()) return VisitUnused(node); |
| 1141 } | 1142 } |
| 1142 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && | 1143 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && |
| 1143 (GetUpperBound(node)->Is(Type::Signed32()) || | 1144 (GetUpperBound(node)->Is(Type::Signed32()) || |
| 1144 GetUpperBound(node)->Is(Type::Unsigned32()) || | 1145 GetUpperBound(node)->Is(Type::Unsigned32()) || |
| 1145 truncation.IsUsedAsWord32())) { | 1146 truncation.IsUsedAsWord32())) { |
| 1146 // => Int32Add/Sub | 1147 // => Int32Add/Sub |
| 1147 VisitWord32TruncatingBinop(node); | 1148 VisitWord32TruncatingBinop(node); |
| 1148 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1149 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
| 1149 return; | 1150 return; |
| 1150 } | 1151 } |
| 1151 | 1152 |
| 1152 // Try to use type feedback. | 1153 // We always take SignedSmall/Signed32 feedback otherwise. |
| 1153 NumberOperationHint hint = NumberOperationHintOf(node->op()); | 1154 NumberOperationHint const hint = NumberOperationHintOf(node->op()); |
| 1154 | 1155 if (hint == NumberOperationHint::kSignedSmall || |
| 1155 // Handle the case when no int32 checks on inputs are necessary | 1156 hint == NumberOperationHint::kSigned32) { |
| 1156 // (but an overflow check is needed on the output). | 1157 // Check if we can guarantee truncations for the inputs. |
| 1157 if (BothInputsAre(node, Type::Signed32()) || | 1158 if (BothInputsAre(node, Type::Signed32()) || |
| 1158 (BothInputsAre(node, Type::Signed32OrMinusZero()) && | 1159 (BothInputsAre(node, Type::Signed32OrMinusZero()) && |
| 1159 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { | 1160 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { |
| 1160 // If both the inputs the feedback are int32, use the overflow op. | |
| 1161 if (hint == NumberOperationHint::kSignedSmall || | |
| 1162 hint == NumberOperationHint::kSigned32) { | |
| 1163 VisitBinop(node, UseInfo::TruncatingWord32(), | 1161 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1164 MachineRepresentation::kWord32, Type::Signed32()); | 1162 MachineRepresentation::kWord32, Type::Signed32()); |
| 1165 if (lower()) ChangeToInt32OverflowOp(node); | 1163 } else { |
| 1166 return; | 1164 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), |
| 1165 MachineRepresentation::kWord32, Type::Signed32()); |
| 1167 } | 1166 } |
| 1168 } | 1167 if (lower()) { |
| 1169 | 1168 // Avoid overflow checks if the unrestricted feedback type of {node} |
| 1170 if (hint == NumberOperationHint::kSignedSmall || | 1169 // suggests that the result will fit into Signed32/Unsigned32 range. |
| 1171 hint == NumberOperationHint::kSigned32) { | 1170 Type* const type = UnrestrictedFeedbackTypeOf(node); |
| 1172 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), | 1171 if (type->Is(Type::Unsigned32())) { |
| 1173 MachineRepresentation::kWord32, Type::Signed32()); | 1172 ChangeToPureOp(node, Uint32Op(node)); |
| 1174 if (lower()) ChangeToInt32OverflowOp(node); | 1173 } else if (type->Is(Type::Signed32())) { |
| 1174 ChangeToPureOp(node, Int32Op(node)); |
| 1175 } else { |
| 1176 ChangeToInt32OverflowOp(node); |
| 1177 } |
| 1178 } |
| 1175 return; | 1179 return; |
| 1176 } | 1180 } |
| 1177 | 1181 |
| 1178 // default case => Float64Add/Sub | 1182 // default case => Float64Add/Sub |
| 1179 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | 1183 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), |
| 1180 MachineRepresentation::kFloat64, Type::Number()); | 1184 MachineRepresentation::kFloat64, Type::Number()); |
| 1181 if (lower()) { | 1185 if (lower()) { |
| 1182 ChangeToPureOp(node, Float64Op(node)); | 1186 ChangeToPureOp(node, Float64Op(node)); |
| 1183 } | 1187 } |
| 1184 return; | |
| 1185 } | 1188 } |
| 1186 | 1189 |
| 1187 void VisitSpeculativeNumberModulus(Node* node, Truncation truncation, | 1190 void VisitSpeculativeNumberModulus(Node* node, Truncation truncation, |
| 1188 SimplifiedLowering* lowering) { | 1191 SimplifiedLowering* lowering) { |
| 1189 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we | 1192 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we |
| 1190 // can only eliminate an unused speculative number operation if we know | 1193 // can only eliminate an unused speculative number operation if we know |
| 1191 // that the inputs are PlainPrimitive, which excludes everything that's | 1194 // that the inputs are PlainPrimitive, which excludes everything that's |
| 1192 // might have side effects or throws during a ToNumber conversion. | 1195 // might have side effects or throws during a ToNumber conversion. |
| 1193 if (BothInputsAre(node, Type::PlainPrimitive())) { | 1196 if (BothInputsAre(node, Type::PlainPrimitive())) { |
| 1194 if (truncation.IsUnused()) return VisitUnused(node); | 1197 if (truncation.IsUnused()) return VisitUnused(node); |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 type_cache_.kSafeIntegerOrMinusZero)))) { | 1519 type_cache_.kSafeIntegerOrMinusZero)))) { |
| 1517 // Multiply reduces to Int32Mul if the inputs are integers, and | 1520 // Multiply reduces to Int32Mul if the inputs are integers, and |
| 1518 // (a) the output is either known to be Signed32, or | 1521 // (a) the output is either known to be Signed32, or |
| 1519 // (b) the output is known to be Unsigned32, or | 1522 // (b) the output is known to be Unsigned32, or |
| 1520 // (c) the uses are truncating and the result is in the safe | 1523 // (c) the uses are truncating and the result is in the safe |
| 1521 // integer range. | 1524 // integer range. |
| 1522 VisitWord32TruncatingBinop(node); | 1525 VisitWord32TruncatingBinop(node); |
| 1523 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1526 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
| 1524 return; | 1527 return; |
| 1525 } | 1528 } |
| 1526 // Try to use type feedback. | |
| 1527 NumberOperationHint hint = NumberOperationHintOf(node->op()); | |
| 1528 Type* input0_type = TypeOf(node->InputAt(0)); | |
| 1529 Type* input1_type = TypeOf(node->InputAt(1)); | |
| 1530 | 1529 |
| 1531 // Handle the case when no int32 checks on inputs are necessary | 1530 // We always take SignedSmall/Signed32 feedback otherwise. |
| 1532 // (but an overflow check is needed on the output). | 1531 NumberOperationHint const hint = NumberOperationHintOf(node->op()); |
| 1533 if (BothInputsAre(node, Type::Signed32())) { | 1532 if (hint == NumberOperationHint::kSignedSmall || |
| 1534 // If both the inputs the feedback are int32, use the overflow op. | 1533 hint == NumberOperationHint::kSigned32) { |
| 1535 if (hint == NumberOperationHint::kSignedSmall || | 1534 // Handle the case when no int32 checks on inputs are necessary |
| 1536 hint == NumberOperationHint::kSigned32) { | 1535 // (but an overflow check is needed on the output). |
| 1536 if (BothInputsAre(node, Type::Signed32())) { |
| 1537 // If both the inputs the feedback are int32, use the overflow op. |
| 1537 VisitBinop(node, UseInfo::TruncatingWord32(), | 1538 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1538 MachineRepresentation::kWord32, Type::Signed32()); | 1539 MachineRepresentation::kWord32, Type::Signed32()); |
| 1539 if (lower()) { | 1540 } else { |
| 1540 LowerToCheckedInt32Mul(node, truncation, input0_type, | 1541 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), |
| 1541 input1_type); | 1542 MachineRepresentation::kWord32, Type::Signed32()); |
| 1543 } |
| 1544 if (lower()) { |
| 1545 // Avoid overflow checks if the unrestricted feedback type of {node} |
| 1546 // suggests that the result will fit into Signed32/Unsigned32 range, |
| 1547 // or at least try to avoid the expensive minus zero checks. |
| 1548 Type* const type = UnrestrictedFeedbackTypeOf(node); |
| 1549 if (type->Is(Type::Unsigned32())) { |
| 1550 ChangeToPureOp(node, Uint32Op(node)); |
| 1551 } else if (type->Is(Type::Signed32())) { |
| 1552 ChangeToPureOp(node, Int32Op(node)); |
| 1553 } else { |
| 1554 CheckForMinusZeroMode const mode = |
| 1555 (truncation.IdentifiesMinusZeroAndZero() || |
| 1556 !type->Maybe(Type::MinusZero())) |
| 1557 ? CheckForMinusZeroMode::kDontCheckForMinusZero |
| 1558 : CheckForMinusZeroMode::kCheckForMinusZero; |
| 1559 NodeProperties::ChangeOp(node, |
| 1560 simplified()->CheckedInt32Mul(mode)); |
| 1542 } | 1561 } |
| 1543 return; | |
| 1544 } | |
| 1545 } | |
| 1546 | |
| 1547 if (hint == NumberOperationHint::kSignedSmall || | |
| 1548 hint == NumberOperationHint::kSigned32) { | |
| 1549 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), | |
| 1550 MachineRepresentation::kWord32, Type::Signed32()); | |
| 1551 if (lower()) { | |
| 1552 LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type); | |
| 1553 } | 1562 } |
| 1554 return; | 1563 return; |
| 1555 } | 1564 } |
| 1556 | 1565 |
| 1557 // Checked float64 x float64 => float64 | 1566 // Checked float64 x float64 => float64 |
| 1558 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | 1567 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), |
| 1559 MachineRepresentation::kFloat64, Type::Number()); | 1568 MachineRepresentation::kFloat64, Type::Number()); |
| 1560 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1569 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1561 return; | 1570 return; |
| 1562 } | 1571 } |
| (...skipping 1640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3203 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3212 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 3204 Operator::kNoProperties); | 3213 Operator::kNoProperties); |
| 3205 to_number_operator_.set(common()->Call(desc)); | 3214 to_number_operator_.set(common()->Call(desc)); |
| 3206 } | 3215 } |
| 3207 return to_number_operator_.get(); | 3216 return to_number_operator_.get(); |
| 3208 } | 3217 } |
| 3209 | 3218 |
| 3210 } // namespace compiler | 3219 } // namespace compiler |
| 3211 } // namespace internal | 3220 } // namespace internal |
| 3212 } // namespace v8 | 3221 } // namespace v8 |
| OLD | NEW |