Chromium Code Reviews| 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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 }; | 176 }; | 
| 177 | 177 | 
| 178 #endif // DEBUG | 178 #endif // DEBUG | 
| 179 | 179 | 
| 180 } // namespace | 180 } // namespace | 
| 181 | 181 | 
| 182 | 182 | 
| 183 class RepresentationSelector { | 183 class RepresentationSelector { | 
| 184 public: | 184 public: | 
| 185 // Information for each node tracked during the fixpoint. | 185 // Information for each node tracked during the fixpoint. | 
| 186 class NodeInfo { | 186 class NodeInfo final { | 
| 187 public: | 187 public: | 
| 188 // Adds new use to the node. Returns true if something has changed | 188 // Adds new use to the node. Returns true if something has changed | 
| 189 // and the node has to be requeued. | 189 // and the node has to be requeued. | 
| 190 bool AddUse(UseInfo info) { | 190 bool AddUse(UseInfo info) { | 
| 191 Truncation old_truncation = truncation_; | 191 Truncation old_truncation = truncation_; | 
| 192 truncation_ = Truncation::Generalize(truncation_, info.truncation()); | 192 truncation_ = Truncation::Generalize(truncation_, info.truncation()); | 
| 193 return truncation_ != old_truncation; | 193 return truncation_ != old_truncation; | 
| 194 } | 194 } | 
| 195 | 195 | 
| 196 void set_queued() { state_ = kQueued; } | 196 void set_queued() { state_ = kQueued; } | 
| 197 void set_visited() { state_ = kVisited; } | 197 void set_visited() { state_ = kVisited; } | 
| 198 void set_pushed() { state_ = kPushed; } | 198 void set_pushed() { state_ = kPushed; } | 
| 199 void reset_state() { state_ = kUnvisited; } | 199 void reset_state() { state_ = kUnvisited; } | 
| 200 bool visited() const { return state_ == kVisited; } | 200 bool visited() const { return state_ == kVisited; } | 
| 201 bool queued() const { return state_ == kQueued; } | 201 bool queued() const { return state_ == kQueued; } | 
| 202 bool unvisited() const { return state_ == kUnvisited; } | 202 bool unvisited() const { return state_ == kUnvisited; } | 
| 203 Truncation truncation() const { return truncation_; } | 203 Truncation truncation() const { return truncation_; } | 
| 204 void set_output(MachineRepresentation output) { representation_ = output; } | 204 void set_output(MachineRepresentation output) { representation_ = output; } | 
| 205 | 205 | 
| 206 MachineRepresentation representation() const { return representation_; } | 206 MachineRepresentation representation() const { return representation_; } | 
| 207 | 207 | 
| 208 // Helpers for feedback typing. | 208 // Helpers for feedback typing. | 
| 209 void set_feedback_type(Type* type) { feedback_type_ = type; } | 209 void set_feedback_type(Type* type) { feedback_type_ = type; } | 
| 210 Type* feedback_type() { return feedback_type_; } | 210 Type* feedback_type() const { return feedback_type_; } | 
| 211 void set_weakened() { weakened_ = true; } | 211 void set_weakened() { weakened_ = true; } | 
| 212 bool weakened() { return weakened_; } | 212 bool weakened() const { return weakened_; } | 
| 213 TypeCheckKind type_check() { return type_check_; } | 213 void set_restriction_type(Type* type) { restriction_type_ = type; } | 
| 214 void set_type_check(TypeCheckKind type_check) { type_check_ = type_check; } | 214 Type* restriction_type() const { return restriction_type_; } | 
| 215 | 215 | 
| 216 private: | 216 private: | 
| 217 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; | 217 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; | 
| 218 State state_ = kUnvisited; | 218 State state_ = kUnvisited; | 
| 219 MachineRepresentation representation_ = | 219 MachineRepresentation representation_ = | 
| 220 MachineRepresentation::kNone; // Output representation. | 220 MachineRepresentation::kNone; // Output representation. | 
| 221 Truncation truncation_ = Truncation::None(); // Information about uses. | 221 Truncation truncation_ = Truncation::None(); // Information about uses. | 
| 222 TypeCheckKind type_check_ = TypeCheckKind::kNone; // Runtime check kind. | |
| 223 | 222 | 
| 223 Type* restriction_type_ = Type::Any(); | |
| 224 Type* feedback_type_ = nullptr; | 224 Type* feedback_type_ = nullptr; | 
| 225 bool weakened_ = false; | 225 bool weakened_ = false; | 
| 226 }; | 226 }; | 
| 227 | 227 | 
| 228 RepresentationSelector(JSGraph* jsgraph, Zone* zone, | 228 RepresentationSelector(JSGraph* jsgraph, Zone* zone, | 
| 229 RepresentationChanger* changer, | 229 RepresentationChanger* changer, | 
| 230 SourcePositionTable* source_positions) | 230 SourcePositionTable* source_positions) | 
| 231 : jsgraph_(jsgraph), | 231 : jsgraph_(jsgraph), | 
| 232 zone_(zone), | 232 zone_(zone), | 
| 233 count_(jsgraph->graph()->NodeCount()), | 233 count_(jsgraph->graph()->NodeCount()), | 
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); | 336 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); | 
| 337 } | 337 } | 
| 338 return type; | 338 return type; | 
| 339 } | 339 } | 
| 340 | 340 | 
| 341 Type* TypeSelect(Node* node) { | 341 Type* TypeSelect(Node* node) { | 
| 342 return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)), | 342 return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)), | 
| 343 FeedbackTypeOf(node->InputAt(2))); | 343 FeedbackTypeOf(node->InputAt(2))); | 
| 344 } | 344 } | 
| 345 | 345 | 
| 346 static Type* TypeOfSpeculativeOp(TypeCheckKind type_check) { | |
| 347 switch (type_check) { | |
| 348 case TypeCheckKind::kNone: | |
| 349 return Type::Any(); | |
| 350 case TypeCheckKind::kSigned32: | |
| 351 return Type::Signed32(); | |
| 352 case TypeCheckKind::kNumber: | |
| 353 return Type::Number(); | |
| 354 // Unexpected cases. | |
| 355 case TypeCheckKind::kNumberOrUndefined: | |
| 356 FATAL("Unexpected checked type."); | |
| 357 break; | |
| 358 } | |
| 359 UNREACHABLE(); | |
| 360 return nullptr; | |
| 361 } | |
| 362 | |
| 363 bool UpdateFeedbackType(Node* node) { | 346 bool UpdateFeedbackType(Node* node) { | 
| 364 if (node->op()->ValueOutputCount() == 0) return false; | 347 if (node->op()->ValueOutputCount() == 0) return false; | 
| 365 | 348 | 
| 366 NodeInfo* info = GetInfo(node); | 349 NodeInfo* info = GetInfo(node); | 
| 367 Type* type = info->feedback_type(); | 350 Type* type = info->feedback_type(); | 
| 368 Type* new_type = type; | 351 Type* new_type = type; | 
| 369 | 352 | 
| 370 // For any non-phi node just wait until we get all inputs typed. We only | 353 // For any non-phi node just wait until we get all inputs typed. We only | 
| 371 // allow untyped inputs for phi nodes because phis are the only places | 354 // allow untyped inputs for phi nodes because phis are the only places | 
| 372 // where cycles need to be broken. | 355 // where cycles need to be broken. | 
| 373 if (node->opcode() != IrOpcode::kPhi) { | 356 if (node->opcode() != IrOpcode::kPhi) { | 
| 374 for (int i = 0; i < node->op()->ValueInputCount(); i++) { | 357 for (int i = 0; i < node->op()->ValueInputCount(); i++) { | 
| 375 if (GetInfo(node->InputAt(i))->feedback_type() == nullptr) { | 358 if (GetInfo(node->InputAt(i))->feedback_type() == nullptr) { | 
| 376 return false; | 359 return false; | 
| 377 } | 360 } | 
| 378 } | 361 } | 
| 379 } | 362 } | 
| 380 | 363 | 
| 381 switch (node->opcode()) { | 364 switch (node->opcode()) { | 
| 365 case IrOpcode::kNumberAdd: | |
| 382 case IrOpcode::kSpeculativeNumberAdd: { | 366 case IrOpcode::kSpeculativeNumberAdd: { | 
| 383 // TODO(jarin) The ToNumber conversion is too conservative here, | 367 // TODO(jarin) The ToNumber conversion is too conservative here, | 
| 384 // e.g. it will treat true as 1 even though the number check will | 368 // e.g. it will treat true as 1 even though the number check will | 
| 385 // fail on a boolean. OperationTyper should have a function that | 369 // fail on a boolean. OperationTyper should have a function that | 
| 386 // computes a more precise type. | 370 // computes a more precise type. | 
| 387 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 371 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 
| 388 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 372 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 
| 389 Type* static_type = op_typer_.NumberAdd(lhs, rhs); | 373 Type* computed_type = op_typer_.NumberAdd(lhs, rhs); | 
| 390 if (info->type_check() == TypeCheckKind::kNone) { | 374 new_type = Type::Intersect(computed_type, info->restriction_type(), | 
| 391 new_type = static_type; | 375 graph_zone()); | 
| 392 } else { | |
| 393 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 394 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 395 } | |
| 396 break; | 376 break; | 
| 397 } | 377 } | 
| 398 | 378 | 
| 379 case IrOpcode::kNumberSubtract: | |
| 399 case IrOpcode::kSpeculativeNumberSubtract: { | 380 case IrOpcode::kSpeculativeNumberSubtract: { | 
| 400 // TODO(jarin) The ToNumber conversion is too conservative here, | 381 // TODO(jarin) The ToNumber conversion is too conservative here, | 
| 401 // e.g. it will treat true as 1 even though the number check will | 382 // e.g. it will treat true as 1 even though the number check will | 
| 402 // fail on a boolean. OperationTyper should have a function that | 383 // fail on a boolean. OperationTyper should have a function that | 
| 403 // computes a more precise type. | 384 // computes a more precise type. | 
| 404 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 385 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 
| 405 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 386 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 
| 406 Type* static_type = op_typer_.NumberSubtract(lhs, rhs); | 387 Type* computed_type = op_typer_.NumberSubtract(lhs, rhs); | 
| 407 if (info->type_check() == TypeCheckKind::kNone) { | 388 new_type = Type::Intersect(computed_type, info->restriction_type(), | 
| 408 new_type = static_type; | 389 graph_zone()); | 
| 409 } else { | |
| 410 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 411 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 412 } | |
| 413 break; | 390 break; | 
| 414 } | 391 } | 
| 415 | 392 | 
| 393 case IrOpcode::kNumberMultiply: | |
| 416 case IrOpcode::kSpeculativeNumberMultiply: { | 394 case IrOpcode::kSpeculativeNumberMultiply: { | 
| 417 // TODO(jarin) The ToNumber conversion is too conservative here, | 395 // TODO(jarin) The ToNumber conversion is too conservative here, | 
| 418 // e.g. it will treat true as 1 even though the number check will | 396 // e.g. it will treat true as 1 even though the number check will | 
| 419 // fail on a boolean. OperationTyper should have a function that | 397 // fail on a boolean. OperationTyper should have a function that | 
| 420 // computes a more precise type. | 398 // computes a more precise type. | 
| 421 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 399 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 
| 422 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 400 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 
| 423 Type* static_type = op_typer_.NumberMultiply(lhs, rhs); | 401 Type* computed_type = op_typer_.NumberMultiply(lhs, rhs); | 
| 424 if (info->type_check() == TypeCheckKind::kNone) { | 402 new_type = Type::Intersect(computed_type, info->restriction_type(), | 
| 425 new_type = static_type; | 403 graph_zone()); | 
| 426 } else { | |
| 427 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 428 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 429 } | |
| 430 break; | 404 break; | 
| 431 } | 405 } | 
| 432 | 406 | 
| 407 case IrOpcode::kNumberDivide: | |
| 433 case IrOpcode::kSpeculativeNumberDivide: { | 408 case IrOpcode::kSpeculativeNumberDivide: { | 
| 434 // TODO(jarin) The ToNumber conversion is too conservative here, | 409 // TODO(jarin) The ToNumber conversion is too conservative here, | 
| 435 // e.g. it will treat true as 1 even though the number check will | 410 // e.g. it will treat true as 1 even though the number check will | 
| 436 // fail on a boolean. OperationTyper should have a function that | 411 // fail on a boolean. OperationTyper should have a function that | 
| 437 // computes a more precise type. | 412 // computes a more precise type. | 
| 438 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 413 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 
| 439 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 414 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 
| 440 Type* static_type = op_typer_.NumberDivide(lhs, rhs); | 415 Type* computed_type = op_typer_.NumberDivide(lhs, rhs); | 
| 441 if (info->type_check() == TypeCheckKind::kNone) { | 416 new_type = Type::Intersect(computed_type, info->restriction_type(), | 
| 442 new_type = static_type; | 417 graph_zone()); | 
| 443 } else { | |
| 444 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 445 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 446 } | |
| 447 break; | 418 break; | 
| 448 } | 419 } | 
| 449 | 420 | 
| 421 case IrOpcode::kNumberModulus: | |
| 450 case IrOpcode::kSpeculativeNumberModulus: { | 422 case IrOpcode::kSpeculativeNumberModulus: { | 
| 451 // TODO(jarin) The ToNumber conversion is too conservative here, | 423 // TODO(jarin) The ToNumber conversion is too conservative here, | 
| 452 // e.g. it will treat true as 1 even though the number check will | 424 // e.g. it will treat true as 1 even though the number check will | 
| 453 // fail on a boolean. OperationTyper should have a function that | 425 // fail on a boolean. OperationTyper should have a function that | 
| 454 // computes a more precise type. | 426 // computes a more precise type. | 
| 455 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 427 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 
| 456 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 428 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 
| 457 Type* static_type = op_typer_.NumberModulus(lhs, rhs); | 429 Type* computed_type = op_typer_.NumberModulus(lhs, rhs); | 
| 458 if (info->type_check() == TypeCheckKind::kNone) { | 430 new_type = Type::Intersect(computed_type, info->restriction_type(), | 
| 459 new_type = static_type; | 431 graph_zone()); | 
| 460 } else { | |
| 461 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 462 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 463 } | |
| 464 break; | 432 break; | 
| 465 } | 433 } | 
| 466 | 434 | 
| 467 case IrOpcode::kNumberAbs: { | 435 case IrOpcode::kNumberAbs: { | 
| 468 new_type = op_typer_.NumberAbs(FeedbackTypeOf(node->InputAt(0))); | 436 new_type = op_typer_.NumberAbs(FeedbackTypeOf(node->InputAt(0))); | 
| 469 break; | 437 break; | 
| 470 } | 438 } | 
| 471 | 439 | 
| 472 case IrOpcode::kPhi: { | 440 case IrOpcode::kPhi: { | 
| 473 new_type = TypePhi(node); | 441 new_type = TypePhi(node); | 
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 650 } | 618 } | 
| 651 PrintTruncation(info->truncation()); | 619 PrintTruncation(info->truncation()); | 
| 652 } | 620 } | 
| 653 } | 621 } | 
| 654 | 622 | 
| 655 bool lower() const { return phase_ == LOWER; } | 623 bool lower() const { return phase_ == LOWER; } | 
| 656 bool retype() const { return phase_ == RETYPE; } | 624 bool retype() const { return phase_ == RETYPE; } | 
| 657 bool propagate() const { return phase_ == PROPAGATE; } | 625 bool propagate() const { return phase_ == PROPAGATE; } | 
| 658 | 626 | 
| 659 void SetOutput(Node* node, MachineRepresentation representation, | 627 void SetOutput(Node* node, MachineRepresentation representation, | 
| 660 TypeCheckKind type_check = TypeCheckKind::kNone) { | 628 Type* restriction_type = Type::Any()) { | 
| 661 NodeInfo* const info = GetInfo(node); | 629 NodeInfo* const info = GetInfo(node); | 
| 662 switch (phase_) { | 630 switch (phase_) { | 
| 663 case PROPAGATE: | 631 case PROPAGATE: | 
| 664 info->set_type_check(type_check); | 632 info->set_restriction_type(restriction_type); | 
| 665 break; | 633 break; | 
| 666 case RETYPE: | 634 case RETYPE: | 
| 667 DCHECK_EQ(info->type_check(), type_check); | 635 DCHECK(info->restriction_type()->Is(restriction_type)); | 
| 636 DCHECK(restriction_type->Is(info->restriction_type())); | |
| 668 info->set_output(representation); | 637 info->set_output(representation); | 
| 669 break; | 638 break; | 
| 670 case LOWER: | 639 case LOWER: | 
| 671 DCHECK_EQ(info->type_check(), type_check); | |
| 672 DCHECK_EQ(info->representation(), representation); | 640 DCHECK_EQ(info->representation(), representation); | 
| 641 DCHECK(info->restriction_type()->Is(restriction_type)); | |
| 642 DCHECK(restriction_type->Is(info->restriction_type())); | |
| 673 break; | 643 break; | 
| 674 } | 644 } | 
| 675 } | 645 } | 
| 676 | 646 | 
| 677 void ResetOutput(Node* node, MachineRepresentation representation, | |
| 678 TypeCheckKind type_check = TypeCheckKind::kNone) { | |
| 679 NodeInfo* info = GetInfo(node); | |
| 680 info->set_output(representation); | |
| 681 info->set_type_check(type_check); | |
| 682 } | |
| 683 | |
| 684 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } | 647 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } | 
| 685 | 648 | 
| 686 bool InputCannotBe(Node* node, Type* type) { | 649 bool InputCannotBe(Node* node, Type* type) { | 
| 687 DCHECK_EQ(1, node->op()->ValueInputCount()); | 650 DCHECK_EQ(1, node->op()->ValueInputCount()); | 
| 688 return !GetUpperBound(node->InputAt(0))->Maybe(type); | 651 return !GetUpperBound(node->InputAt(0))->Maybe(type); | 
| 689 } | 652 } | 
| 690 | 653 | 
| 691 bool InputIs(Node* node, Type* type) { | 654 bool InputIs(Node* node, Type* type) { | 
| 692 DCHECK_EQ(1, node->op()->ValueInputCount()); | 655 DCHECK_EQ(1, node->op()->ValueInputCount()); | 
| 693 return GetUpperBound(node->InputAt(0))->Is(type); | 656 return GetUpperBound(node->InputAt(0))->Is(type); | 
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 770 } | 733 } | 
| 771 // Only enqueue other inputs (framestates, effects, control). | 734 // Only enqueue other inputs (framestates, effects, control). | 
| 772 for (int i = tagged_count; i < node->InputCount(); i++) { | 735 for (int i = tagged_count; i < node->InputCount(); i++) { | 
| 773 EnqueueInput(node, i); | 736 EnqueueInput(node, i); | 
| 774 } | 737 } | 
| 775 } | 738 } | 
| 776 | 739 | 
| 777 // Helper for binops of the R x L -> O variety. | 740 // Helper for binops of the R x L -> O variety. | 
| 778 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, | 741 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, | 
| 779 MachineRepresentation output, | 742 MachineRepresentation output, | 
| 780 TypeCheckKind type_check = TypeCheckKind::kNone) { | 743 Type* restriction_type = Type::Any()) { | 
| 781 DCHECK_EQ(2, node->op()->ValueInputCount()); | 744 DCHECK_EQ(2, node->op()->ValueInputCount()); | 
| 782 ProcessInput(node, 0, left_use); | 745 ProcessInput(node, 0, left_use); | 
| 783 ProcessInput(node, 1, right_use); | 746 ProcessInput(node, 1, right_use); | 
| 784 for (int i = 2; i < node->InputCount(); i++) { | 747 for (int i = 2; i < node->InputCount(); i++) { | 
| 785 EnqueueInput(node, i); | 748 EnqueueInput(node, i); | 
| 786 } | 749 } | 
| 787 SetOutput(node, output, type_check); | 750 SetOutput(node, output, restriction_type); | 
| 788 } | 751 } | 
| 789 | 752 | 
| 790 // Helper for binops of the I x I -> O variety. | 753 // Helper for binops of the I x I -> O variety. | 
| 791 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output, | 754 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output, | 
| 792 TypeCheckKind type_check = TypeCheckKind::kNone) { | 755 Type* restriction_type = Type::Any()) { | 
| 793 VisitBinop(node, input_use, input_use, output, type_check); | 756 VisitBinop(node, input_use, input_use, output, restriction_type); | 
| 794 } | 757 } | 
| 795 | 758 | 
| 796 // Helper for unops of the I -> O variety. | 759 // Helper for unops of the I -> O variety. | 
| 797 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) { | 760 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) { | 
| 798 DCHECK_EQ(1, node->op()->ValueInputCount()); | 761 DCHECK_EQ(1, node->op()->ValueInputCount()); | 
| 799 ProcessInput(node, 0, input_use); | 762 ProcessInput(node, 0, input_use); | 
| 800 ProcessRemainingInputs(node, 1); | 763 ProcessRemainingInputs(node, 1); | 
| 801 SetOutput(node, output); | 764 SetOutput(node, output); | 
| 802 } | 765 } | 
| 803 | 766 | 
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 999 } | 962 } | 
| 1000 | 963 | 
| 1001 const Operator* Int32OverflowOp(Node* node) { | 964 const Operator* Int32OverflowOp(Node* node) { | 
| 1002 return changer_->Int32OverflowOperatorFor(node->opcode()); | 965 return changer_->Int32OverflowOperatorFor(node->opcode()); | 
| 1003 } | 966 } | 
| 1004 | 967 | 
| 1005 const Operator* Uint32Op(Node* node) { | 968 const Operator* Uint32Op(Node* node) { | 
| 1006 return changer_->Uint32OperatorFor(node->opcode()); | 969 return changer_->Uint32OperatorFor(node->opcode()); | 
| 1007 } | 970 } | 
| 1008 | 971 | 
| 972 const Operator* Uint32OverflowOp(Node* node) { | |
| 973 return changer_->Uint32OverflowOperatorFor(node->opcode()); | |
| 974 } | |
| 975 | |
| 1009 const Operator* Float64Op(Node* node) { | 976 const Operator* Float64Op(Node* node) { | 
| 1010 return changer_->Float64OperatorFor(node->opcode()); | 977 return changer_->Float64OperatorFor(node->opcode()); | 
| 1011 } | 978 } | 
| 1012 | 979 | 
| 1013 WriteBarrierKind WriteBarrierKindFor( | 980 WriteBarrierKind WriteBarrierKindFor( | 
| 1014 BaseTaggedness base_taggedness, | 981 BaseTaggedness base_taggedness, | 
| 1015 MachineRepresentation field_representation, Type* field_type, | 982 MachineRepresentation field_representation, Type* field_type, | 
| 1016 Node* value) { | 983 Node* value) { | 
| 1017 if (base_taggedness == kTaggedBase && | 984 if (base_taggedness == kTaggedBase && | 
| 1018 field_representation == MachineRepresentation::kTagged) { | 985 field_representation == MachineRepresentation::kTagged) { | 
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1101 Node* effect = NodeProperties::GetEffectInput(node); | 1068 Node* effect = NodeProperties::GetEffectInput(node); | 
| 1102 ReplaceEffectControlUses(node, effect, control); | 1069 ReplaceEffectControlUses(node, effect, control); | 
| 1103 node->TrimInputCount(new_op->ValueInputCount()); | 1070 node->TrimInputCount(new_op->ValueInputCount()); | 
| 1104 } else { | 1071 } else { | 
| 1105 DCHECK_EQ(0, node->op()->ControlInputCount()); | 1072 DCHECK_EQ(0, node->op()->ControlInputCount()); | 
| 1106 } | 1073 } | 
| 1107 | 1074 | 
| 1108 NodeProperties::ChangeOp(node, new_op); | 1075 NodeProperties::ChangeOp(node, new_op); | 
| 1109 } | 1076 } | 
| 1110 | 1077 | 
| 1111 void ChangeToInt32OverflowOp(Node* node, const Operator* new_op) { | 1078 void ChangeToInt32OverflowOp(Node* node) { | 
| 1112 NodeProperties::ChangeOp(node, new_op); | 1079 NodeProperties::ChangeOp(node, Int32OverflowOp(node)); | 
| 1080 } | |
| 1081 | |
| 1082 void ChangeToUint32OverflowOp(Node* node) { | |
| 1083 NodeProperties::ChangeOp(node, Uint32OverflowOp(node)); | |
| 1113 } | 1084 } | 
| 1114 | 1085 | 
| 1115 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, | 1086 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, | 
| 1116 SimplifiedLowering* lowering) { | 1087 SimplifiedLowering* lowering) { | 
| 1117 if (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && | 1088 if (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && | 
| 1118 NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1089 NodeProperties::GetType(node)->Is(Type::Signed32())) { | 
| 1119 // int32 + int32 = int32 ==> signed Int32Add/Sub | 1090 // int32 + int32 = int32 ==> signed Int32Add/Sub | 
| 1120 VisitInt32Binop(node); | 1091 VisitInt32Binop(node); | 
| 1121 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1092 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 
| 1122 return; | 1093 return; | 
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1137 | 1108 | 
| 1138 // Handle the case when no int32 checks on inputs are necessary | 1109 // Handle the case when no int32 checks on inputs are necessary | 
| 1139 // (but an overflow check is needed on the output). | 1110 // (but an overflow check is needed on the output). | 
| 1140 if (BothInputsAre(node, Type::Signed32()) || | 1111 if (BothInputsAre(node, Type::Signed32()) || | 
| 1141 (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && | 1112 (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && | 
| 1142 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { | 1113 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { | 
| 1143 // If both the inputs the feedback are int32, use the overflow op. | 1114 // If both the inputs the feedback are int32, use the overflow op. | 
| 1144 if (hint == BinaryOperationHints::kSignedSmall || | 1115 if (hint == BinaryOperationHints::kSignedSmall || | 
| 1145 hint == BinaryOperationHints::kSigned32) { | 1116 hint == BinaryOperationHints::kSigned32) { | 
| 1146 VisitBinop(node, UseInfo::TruncatingWord32(), | 1117 VisitBinop(node, UseInfo::TruncatingWord32(), | 
| 1147 MachineRepresentation::kWord32, TypeCheckKind::kSigned32); | 1118 MachineRepresentation::kWord32, Type::Signed32()); | 
| 1148 if (lower()) { | 1119 if (lower()) ChangeToInt32OverflowOp(node); | 
| 1149 ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1150 } | |
| 1151 return; | 1120 return; | 
| 1152 } | 1121 } | 
| 1153 } | 1122 } | 
| 1154 | 1123 | 
| 1155 if (hint == BinaryOperationHints::kSignedSmall || | 1124 if (hint == BinaryOperationHints::kSignedSmall || | 
| 1156 hint == BinaryOperationHints::kSigned32) { | 1125 hint == BinaryOperationHints::kSigned32) { | 
| 1157 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1126 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 
| 1158 MachineRepresentation::kWord32, TypeCheckKind::kSigned32); | 1127 MachineRepresentation::kWord32, Type::Signed32()); | 
| 1159 if (lower()) { | 1128 if (lower()) ChangeToInt32OverflowOp(node); | 
| 1160 ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1161 } | |
| 1162 return; | 1129 return; | 
| 1163 } | 1130 } | 
| 1164 | 1131 | 
| 1165 // default case => Float64Add/Sub | 1132 // default case => Float64Add/Sub | 
| 1166 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1133 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 
| 1167 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1134 MachineRepresentation::kFloat64, Type::Number()); | 
| 1168 if (lower()) { | 1135 if (lower()) { | 
| 1169 ChangeToPureOp(node, Float64Op(node)); | 1136 ChangeToPureOp(node, Float64Op(node)); | 
| 1170 } | 1137 } | 
| 1171 return; | 1138 return; | 
| 1172 } | 1139 } | 
| 1173 | 1140 | 
| 1174 // Dispatching routine for visiting the node {node} with the usage {use}. | 1141 // Dispatching routine for visiting the node {node} with the usage {use}. | 
| 1175 // Depending on the operator, propagate new usage info to the inputs. | 1142 // Depending on the operator, propagate new usage info to the inputs. | 
| 1176 void VisitNode(Node* node, Truncation truncation, | 1143 void VisitNode(Node* node, Truncation truncation, | 
| 1177 SimplifiedLowering* lowering) { | 1144 SimplifiedLowering* lowering) { | 
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1341 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1308 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 
| 1342 } else { | 1309 } else { | 
| 1343 // => Float64Add/Sub | 1310 // => Float64Add/Sub | 
| 1344 VisitFloat64Binop(node); | 1311 VisitFloat64Binop(node); | 
| 1345 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1312 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 
| 1346 } | 1313 } | 
| 1347 return; | 1314 return; | 
| 1348 } | 1315 } | 
| 1349 case IrOpcode::kSpeculativeNumberMultiply: | 1316 case IrOpcode::kSpeculativeNumberMultiply: | 
| 1350 case IrOpcode::kNumberMultiply: { | 1317 case IrOpcode::kNumberMultiply: { | 
| 1318 if (BothInputsAreUnsigned32(node)) { | |
| 1319 if (NodeProperties::GetType(node)->Is(Type::Unsigned32())) { | |
| 
 
Jarin
2016/07/13 07:25:38
As discussed offline, it might be the right time t
 
Benedikt Meurer
2016/07/13 07:54:00
Done.
 
 | |
| 1320 // Multiply reduces to Int32Mul if the inputs and the output | |
| 1321 // are unsigned integers. | |
| 1322 VisitUint32Binop(node); | |
| 1323 if (lower()) ChangeToPureOp(node, Uint32Op(node)); | |
| 1324 return; | |
| 1325 } | |
| 1326 if (truncation.TruncatesToWord32() && | |
| 1327 NodeProperties::GetType(node)->Is( | |
| 1328 type_cache_.kSafeIntegerOrMinusZero)) { | |
| 1329 // Multiply reduces to Int32Mul if the inputs are unsigned | |
| 1330 // integers, the uses are truncating and the result is in | |
| 1331 // the safe integer range. | |
| 1332 VisitWord32TruncatingBinop(node); | |
| 1333 if (lower()) ChangeToPureOp(node, Uint32Op(node)); | |
| 1334 return; | |
| 1335 } | |
| 1336 } | |
| 1351 if (BothInputsAreSigned32(node)) { | 1337 if (BothInputsAreSigned32(node)) { | 
| 1352 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1338 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 
| 1353 // Multiply reduces to Int32Mul if the inputs and the output | 1339 // Multiply reduces to Int32Mul if the inputs and the output | 
| 1354 // are integers. | 1340 // are integers. | 
| 1355 VisitInt32Binop(node); | 1341 VisitInt32Binop(node); | 
| 1356 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1342 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 
| 1357 return; | 1343 return; | 
| 1358 } | 1344 } | 
| 1359 if (truncation.TruncatesToWord32() && | 1345 if (truncation.TruncatesToWord32() && | 
| 1360 NodeProperties::GetType(node)->Is( | 1346 NodeProperties::GetType(node)->Is( | 
| 1361 type_cache_.kSafeIntegerOrMinusZero)) { | 1347 type_cache_.kSafeIntegerOrMinusZero)) { | 
| 1362 // Multiply reduces to Int32Mul if the inputs are integers, | 1348 // Multiply reduces to Int32Mul if the inputs are integers, | 
| 1363 // the uses are truncating and the result is in the safe | 1349 // the uses are truncating and the result is in the safe | 
| 1364 // integer range. | 1350 // integer range. | 
| 1365 VisitWord32TruncatingBinop(node); | 1351 VisitWord32TruncatingBinop(node); | 
| 1366 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1352 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 
| 1367 return; | 1353 return; | 
| 1368 } | 1354 } | 
| 1369 } | 1355 } | 
| 1370 // Number x Number => Float64Mul | 1356 // Number x Number => Float64Mul | 
| 1371 if (BothInputsAre(node, Type::NumberOrUndefined())) { | 1357 if (BothInputsAre(node, Type::NumberOrUndefined())) { | 
| 1372 VisitFloat64Binop(node); | 1358 VisitFloat64Binop(node); | 
| 1373 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1359 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 
| 1374 return; | 1360 return; | 
| 1375 } | 1361 } | 
| 1376 // Checked float64 x float64 => float64 | 1362 // Checked float64 x float64 => float64 | 
| 1377 DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode()); | 1363 DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode()); | 
| 1378 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1364 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 
| 1379 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1365 MachineRepresentation::kFloat64, Type::Number()); | 
| 1380 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1366 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 
| 1381 return; | 1367 return; | 
| 1382 } | 1368 } | 
| 1383 case IrOpcode::kSpeculativeNumberDivide: { | 1369 case IrOpcode::kSpeculativeNumberDivide: { | 
| 1384 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1370 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 
| 1385 // => unsigned Uint32Div | 1371 // => unsigned Uint32Div | 
| 1386 VisitWord32TruncatingBinop(node); | 1372 VisitWord32TruncatingBinop(node); | 
| 1387 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); | 1373 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); | 
| 1388 return; | 1374 return; | 
| 1389 } | 1375 } | 
| 1390 if (BothInputsAreSigned32(node)) { | 1376 if (BothInputsAreSigned32(node)) { | 
| 1391 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1377 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 
| 1392 // => signed Int32Div | 1378 // => signed Int32Div | 
| 1393 VisitInt32Binop(node); | 1379 VisitInt32Binop(node); | 
| 1394 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1380 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 
| 1395 return; | 1381 return; | 
| 1396 } | 1382 } | 
| 1397 if (truncation.TruncatesToWord32()) { | 1383 if (truncation.TruncatesToWord32()) { | 
| 1398 // => signed Int32Div | 1384 // => signed Int32Div | 
| 1399 VisitWord32TruncatingBinop(node); | 1385 VisitWord32TruncatingBinop(node); | 
| 1400 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1386 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 
| 1401 return; | 1387 return; | 
| 1402 } | 1388 } | 
| 1403 } | 1389 } | 
| 1404 | 1390 | 
| 1405 // Try to use type feedback. | 1391 // Try to use type feedback. | 
| 1406 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); | 1392 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); | 
| 1407 | 1393 | 
| 1394 // Handle the case when no uint32 checks on inputs are necessary | |
| 1395 // (but an overflow check is needed on the output). | |
| 1396 if (BothInputsAreUnsigned32(node)) { | |
| 1397 if (hint == BinaryOperationHints::kSignedSmall || | |
| 1398 hint == BinaryOperationHints::kSigned32) { | |
| 1399 VisitBinop(node, UseInfo::TruncatingWord32(), | |
| 1400 MachineRepresentation::kWord32, Type::Unsigned32()); | |
| 1401 if (lower()) ChangeToUint32OverflowOp(node); | |
| 1402 return; | |
| 1403 } | |
| 1404 } | |
| 1405 | |
| 1408 // Handle the case when no int32 checks on inputs are necessary | 1406 // Handle the case when no int32 checks on inputs are necessary | 
| 1409 // (but an overflow check is needed on the output). | 1407 // (but an overflow check is needed on the output). | 
| 1410 if (BothInputsAre(node, Type::Signed32())) { | 1408 if (BothInputsAreSigned32(node)) { | 
| 1411 // If both the inputs the feedback are int32, use the overflow op. | 1409 // If both the inputs the feedback are int32, use the overflow op. | 
| 1412 if (hint == BinaryOperationHints::kSignedSmall || | 1410 if (hint == BinaryOperationHints::kSignedSmall || | 
| 1413 hint == BinaryOperationHints::kSigned32) { | 1411 hint == BinaryOperationHints::kSigned32) { | 
| 1414 VisitBinop(node, UseInfo::TruncatingWord32(), | 1412 VisitBinop(node, UseInfo::TruncatingWord32(), | 
| 1415 MachineRepresentation::kWord32, | 1413 MachineRepresentation::kWord32, Type::Signed32()); | 
| 1416 TypeCheckKind::kSigned32); | 1414 if (lower()) ChangeToInt32OverflowOp(node); | 
| 1417 if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1418 return; | 1415 return; | 
| 1419 } | 1416 } | 
| 1420 } | 1417 } | 
| 1421 | 1418 | 
| 1422 if (hint == BinaryOperationHints::kSignedSmall || | 1419 if (hint == BinaryOperationHints::kSignedSmall || | 
| 1423 hint == BinaryOperationHints::kSigned32) { | 1420 hint == BinaryOperationHints::kSigned32) { | 
| 1424 // If the result is truncated, we only need to check the inputs. | 1421 // If the result is truncated, we only need to check the inputs. | 
| 1425 if (truncation.TruncatesToWord32()) { | 1422 if (truncation.TruncatesToWord32()) { | 
| 1426 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1423 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 
| 1427 MachineRepresentation::kWord32); | 1424 MachineRepresentation::kWord32); | 
| 1428 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1425 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 
| 1429 } else { | 1426 } else { | 
| 1430 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1427 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 
| 1431 MachineRepresentation::kWord32, | 1428 MachineRepresentation::kWord32, Type::Signed32()); | 
| 1432 TypeCheckKind::kSigned32); | 1429 if (lower()) ChangeToInt32OverflowOp(node); | 
| 1433 if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1434 } | 1430 } | 
| 1435 return; | 1431 return; | 
| 1436 } | 1432 } | 
| 1437 | 1433 | 
| 1438 // default case => Float64Div | 1434 // default case => Float64Div | 
| 1439 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1435 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 
| 1440 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1436 MachineRepresentation::kFloat64, Type::Number()); | 
| 1441 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1437 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 
| 1442 return; | 1438 return; | 
| 1443 } | 1439 } | 
| 1444 case IrOpcode::kNumberDivide: { | 1440 case IrOpcode::kNumberDivide: { | 
| 1445 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1441 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 
| 1446 // => unsigned Uint32Div | 1442 // => unsigned Uint32Div | 
| 1447 VisitWord32TruncatingBinop(node); | 1443 VisitWord32TruncatingBinop(node); | 
| 1448 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); | 1444 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); | 
| 1449 return; | 1445 return; | 
| 1450 } | 1446 } | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1464 } | 1460 } | 
| 1465 // Number x Number => Float64Div | 1461 // Number x Number => Float64Div | 
| 1466 if (BothInputsAre(node, Type::NumberOrUndefined())) { | 1462 if (BothInputsAre(node, Type::NumberOrUndefined())) { | 
| 1467 VisitFloat64Binop(node); | 1463 VisitFloat64Binop(node); | 
| 1468 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1464 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 
| 1469 return; | 1465 return; | 
| 1470 } | 1466 } | 
| 1471 // Checked float64 x float64 => float64 | 1467 // Checked float64 x float64 => float64 | 
| 1472 DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); | 1468 DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); | 
| 1473 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1469 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 
| 1474 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1470 MachineRepresentation::kFloat64, Type::Number()); | 
| 1475 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1471 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 
| 1476 return; | 1472 return; | 
| 1477 } | 1473 } | 
| 1478 case IrOpcode::kSpeculativeNumberModulus: { | 1474 case IrOpcode::kSpeculativeNumberModulus: { | 
| 1479 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1475 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 
| 1480 // => unsigned Uint32Mod | 1476 // => unsigned Uint32Mod | 
| 1481 VisitWord32TruncatingBinop(node); | 1477 VisitWord32TruncatingBinop(node); | 
| 1482 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 1478 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 
| 1483 return; | 1479 return; | 
| 1484 } | 1480 } | 
| 1485 if (BothInputsAreSigned32(node)) { | 1481 if (BothInputsAreSigned32(node)) { | 
| 1486 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1482 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 
| 1487 // => signed Int32Mod | 1483 // => signed Int32Mod | 
| 1488 VisitInt32Binop(node); | 1484 VisitInt32Binop(node); | 
| 1489 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1485 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 
| 1490 return; | 1486 return; | 
| 1491 } | 1487 } | 
| 1492 if (truncation.TruncatesToWord32()) { | 1488 if (truncation.TruncatesToWord32()) { | 
| 1493 // => signed Int32Mod | 1489 // => signed Int32Mod | 
| 1494 VisitWord32TruncatingBinop(node); | 1490 VisitWord32TruncatingBinop(node); | 
| 1495 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1491 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 
| 1496 return; | 1492 return; | 
| 1497 } | 1493 } | 
| 1498 } | 1494 } | 
| 1499 | 1495 | 
| 1500 // Try to use type feedback. | 1496 // Try to use type feedback. | 
| 1501 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); | 1497 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); | 
| 1502 | 1498 | 
| 1499 // Handle the case when no uint32 checks on inputs are necessary | |
| 1500 // (but an overflow check is needed on the output). | |
| 1501 if (BothInputsAreUnsigned32(node)) { | |
| 1502 if (hint == BinaryOperationHints::kSignedSmall || | |
| 1503 hint == BinaryOperationHints::kSigned32) { | |
| 1504 VisitBinop(node, UseInfo::TruncatingWord32(), | |
| 1505 MachineRepresentation::kWord32, Type::Unsigned32()); | |
| 1506 if (lower()) ChangeToUint32OverflowOp(node); | |
| 1507 return; | |
| 1508 } | |
| 1509 } | |
| 1510 | |
| 1503 // Handle the case when no int32 checks on inputs are necessary | 1511 // Handle the case when no int32 checks on inputs are necessary | 
| 1504 // (but an overflow check is needed on the output). | 1512 // (but an overflow check is needed on the output). | 
| 1505 if (BothInputsAre(node, Type::Signed32())) { | 1513 if (BothInputsAre(node, Type::Signed32())) { | 
| 1506 // If both the inputs the feedback are int32, use the overflow op. | 1514 // If both the inputs the feedback are int32, use the overflow op. | 
| 1507 if (hint == BinaryOperationHints::kSignedSmall || | 1515 if (hint == BinaryOperationHints::kSignedSmall || | 
| 1508 hint == BinaryOperationHints::kSigned32) { | 1516 hint == BinaryOperationHints::kSigned32) { | 
| 1509 VisitBinop(node, UseInfo::TruncatingWord32(), | 1517 VisitBinop(node, UseInfo::TruncatingWord32(), | 
| 1510 MachineRepresentation::kWord32, | 1518 MachineRepresentation::kWord32, Type::Signed32()); | 
| 1511 TypeCheckKind::kSigned32); | 1519 if (lower()) ChangeToInt32OverflowOp(node); | 
| 1512 if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1513 return; | 1520 return; | 
| 1514 } | 1521 } | 
| 1515 } | 1522 } | 
| 1516 | 1523 | 
| 1517 if (hint == BinaryOperationHints::kSignedSmall || | 1524 if (hint == BinaryOperationHints::kSignedSmall || | 
| 1518 hint == BinaryOperationHints::kSigned32) { | 1525 hint == BinaryOperationHints::kSigned32) { | 
| 1519 // If the result is truncated, we only need to check the inputs. | 1526 // If the result is truncated, we only need to check the inputs. | 
| 1520 if (truncation.TruncatesToWord32()) { | 1527 if (truncation.TruncatesToWord32()) { | 
| 1521 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1528 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 
| 1522 MachineRepresentation::kWord32); | 1529 MachineRepresentation::kWord32); | 
| 1523 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1530 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 
| 1524 } else { | 1531 } else { | 
| 1525 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1532 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 
| 1526 MachineRepresentation::kWord32, | 1533 MachineRepresentation::kWord32, Type::Signed32()); | 
| 1527 TypeCheckKind::kSigned32); | 1534 if (lower()) ChangeToInt32OverflowOp(node); | 
| 1528 if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1529 } | 1535 } | 
| 1530 return; | 1536 return; | 
| 1531 } | 1537 } | 
| 1532 | 1538 | 
| 1533 // default case => Float64Mod | 1539 // default case => Float64Mod | 
| 1534 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1540 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 
| 1535 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1541 MachineRepresentation::kFloat64, Type::Number()); | 
| 1536 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1542 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 
| 1537 return; | 1543 return; | 
| 1538 } | 1544 } | 
| 1539 case IrOpcode::kNumberModulus: { | 1545 case IrOpcode::kNumberModulus: { | 
| 1540 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1546 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 
| 1541 // => unsigned Uint32Mod | 1547 // => unsigned Uint32Mod | 
| 1542 VisitWord32TruncatingBinop(node); | 1548 VisitWord32TruncatingBinop(node); | 
| 1543 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 1549 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 
| 1544 return; | 1550 return; | 
| 1545 } | 1551 } | 
| (...skipping 1742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3288 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3294 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 
| 3289 Operator::kNoProperties); | 3295 Operator::kNoProperties); | 
| 3290 to_number_operator_.set(common()->Call(desc)); | 3296 to_number_operator_.set(common()->Call(desc)); | 
| 3291 } | 3297 } | 
| 3292 return to_number_operator_.get(); | 3298 return to_number_operator_.get(); | 
| 3293 } | 3299 } | 
| 3294 | 3300 | 
| 3295 } // namespace compiler | 3301 } // namespace compiler | 
| 3296 } // namespace internal | 3302 } // namespace internal | 
| 3297 } // namespace v8 | 3303 } // namespace v8 | 
| OLD | NEW |