| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 } | 80 } |
| 81 } | 81 } |
| 82 | 82 |
| 83 | 83 |
| 84 void AstOptimizer::VisitBlock(Block* node) { | 84 void AstOptimizer::VisitBlock(Block* node) { |
| 85 Optimize(node->statements()); | 85 Optimize(node->statements()); |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 void AstOptimizer::VisitExpressionStatement(ExpressionStatement* node) { | 89 void AstOptimizer::VisitExpressionStatement(ExpressionStatement* node) { |
| 90 node->expression()->set_no_negative_zero(true); |
| 90 Visit(node->expression()); | 91 Visit(node->expression()); |
| 91 } | 92 } |
| 92 | 93 |
| 93 | 94 |
| 94 void AstOptimizer::VisitIfStatement(IfStatement* node) { | 95 void AstOptimizer::VisitIfStatement(IfStatement* node) { |
| 96 node->condition()->set_no_negative_zero(true); |
| 95 Visit(node->condition()); | 97 Visit(node->condition()); |
| 96 Visit(node->then_statement()); | 98 Visit(node->then_statement()); |
| 97 if (node->HasElseStatement()) { | 99 if (node->HasElseStatement()) { |
| 98 Visit(node->else_statement()); | 100 Visit(node->else_statement()); |
| 99 } | 101 } |
| 100 } | 102 } |
| 101 | 103 |
| 102 | 104 |
| 103 void AstOptimizer::VisitDoWhileStatement(DoWhileStatement* node) { | 105 void AstOptimizer::VisitDoWhileStatement(DoWhileStatement* node) { |
| 106 node->cond()->set_no_negative_zero(true); |
| 104 Visit(node->cond()); | 107 Visit(node->cond()); |
| 105 Visit(node->body()); | 108 Visit(node->body()); |
| 106 } | 109 } |
| 107 | 110 |
| 108 | 111 |
| 109 void AstOptimizer::VisitWhileStatement(WhileStatement* node) { | 112 void AstOptimizer::VisitWhileStatement(WhileStatement* node) { |
| 110 has_function_literal_ = false; | 113 has_function_literal_ = false; |
| 114 node->cond()->set_no_negative_zero(true); |
| 111 Visit(node->cond()); | 115 Visit(node->cond()); |
| 112 node->may_have_function_literal_ = has_function_literal_; | 116 node->may_have_function_literal_ = has_function_literal_; |
| 113 Visit(node->body()); | 117 Visit(node->body()); |
| 114 } | 118 } |
| 115 | 119 |
| 116 | 120 |
| 117 void AstOptimizer::VisitForStatement(ForStatement* node) { | 121 void AstOptimizer::VisitForStatement(ForStatement* node) { |
| 118 if (node->init() != NULL) { | 122 if (node->init() != NULL) { |
| 119 Visit(node->init()); | 123 Visit(node->init()); |
| 120 } | 124 } |
| 121 if (node->cond() != NULL) { | 125 if (node->cond() != NULL) { |
| 122 has_function_literal_ = false; | 126 has_function_literal_ = false; |
| 127 node->cond()->set_no_negative_zero(true); |
| 123 Visit(node->cond()); | 128 Visit(node->cond()); |
| 124 node->may_have_function_literal_ = has_function_literal_; | 129 node->may_have_function_literal_ = has_function_literal_; |
| 125 } | 130 } |
| 126 Visit(node->body()); | 131 Visit(node->body()); |
| 127 if (node->next() != NULL) { | 132 if (node->next() != NULL) { |
| 128 Visit(node->next()); | 133 Visit(node->next()); |
| 129 } | 134 } |
| 130 } | 135 } |
| 131 | 136 |
| 132 | 137 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 144 } | 149 } |
| 145 | 150 |
| 146 | 151 |
| 147 void AstOptimizer::VisitTryFinallyStatement(TryFinallyStatement* node) { | 152 void AstOptimizer::VisitTryFinallyStatement(TryFinallyStatement* node) { |
| 148 Visit(node->try_block()); | 153 Visit(node->try_block()); |
| 149 Visit(node->finally_block()); | 154 Visit(node->finally_block()); |
| 150 } | 155 } |
| 151 | 156 |
| 152 | 157 |
| 153 void AstOptimizer::VisitSwitchStatement(SwitchStatement* node) { | 158 void AstOptimizer::VisitSwitchStatement(SwitchStatement* node) { |
| 159 node->tag()->set_no_negative_zero(true); |
| 154 Visit(node->tag()); | 160 Visit(node->tag()); |
| 155 for (int i = 0; i < node->cases()->length(); i++) { | 161 for (int i = 0; i < node->cases()->length(); i++) { |
| 156 CaseClause* clause = node->cases()->at(i); | 162 CaseClause* clause = node->cases()->at(i); |
| 157 if (!clause->is_default()) { | 163 if (!clause->is_default()) { |
| 158 Visit(clause->label()); | 164 Visit(clause->label()); |
| 159 } | 165 } |
| 160 Optimize(clause->statements()); | 166 Optimize(clause->statements()); |
| 161 } | 167 } |
| 162 } | 168 } |
| 163 | 169 |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) { | 443 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) { |
| 438 if (node->op() == Token::ADD || node->op() == Token::SUB) { | 444 if (node->op() == Token::ADD || node->op() == Token::SUB) { |
| 439 node->expression()->set_no_negative_zero(node->no_negative_zero()); | 445 node->expression()->set_no_negative_zero(node->no_negative_zero()); |
| 440 } else { | 446 } else { |
| 441 node->expression()->set_no_negative_zero(true); | 447 node->expression()->set_no_negative_zero(true); |
| 442 } | 448 } |
| 443 Visit(node->expression()); | 449 Visit(node->expression()); |
| 444 if (FLAG_safe_int32_compiler) { | 450 if (FLAG_safe_int32_compiler) { |
| 445 switch (node->op()) { | 451 switch (node->op()) { |
| 446 case Token::BIT_NOT: | 452 case Token::BIT_NOT: |
| 453 node->expression()->set_no_negative_zero(true); |
| 447 node->expression()->set_to_int32(true); | 454 node->expression()->set_to_int32(true); |
| 448 // Fall through. | 455 // Fall through. |
| 449 case Token::ADD: | 456 case Token::ADD: |
| 450 case Token::SUB: | 457 case Token::SUB: |
| 451 node->set_side_effect_free(node->expression()->side_effect_free()); | 458 node->set_side_effect_free(node->expression()->side_effect_free()); |
| 452 break; | 459 break; |
| 453 case Token::NOT: | 460 case Token::NOT: |
| 454 case Token::DELETE: | 461 case Token::DELETE: |
| 455 case Token::TYPEOF: | 462 case Token::TYPEOF: |
| 456 case Token::VOID: | 463 case Token::VOID: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 469 // Count operations assume that they work on Smis. | 476 // Count operations assume that they work on Smis. |
| 470 node->expression()->set_no_negative_zero(node->is_prefix() ? | 477 node->expression()->set_no_negative_zero(node->is_prefix() ? |
| 471 true : | 478 true : |
| 472 node->no_negative_zero()); | 479 node->no_negative_zero()); |
| 473 node->type()->SetAsLikelySmiIfUnknown(); | 480 node->type()->SetAsLikelySmiIfUnknown(); |
| 474 node->expression()->type()->SetAsLikelySmiIfUnknown(); | 481 node->expression()->type()->SetAsLikelySmiIfUnknown(); |
| 475 Visit(node->expression()); | 482 Visit(node->expression()); |
| 476 } | 483 } |
| 477 | 484 |
| 478 | 485 |
| 486 static bool CouldBeNegativeZero(AstNode* node) { |
| 487 Literal* literal = node->AsLiteral(); |
| 488 if (literal != NULL) { |
| 489 Handle<Object> handle = literal->handle(); |
| 490 if (handle->IsString() || handle->IsSmi()) { |
| 491 return false; |
| 492 } else if (handle->IsHeapNumber()) { |
| 493 double double_value = HeapNumber::cast(*handle)->value(); |
| 494 if (double_value != 0) { |
| 495 return false; |
| 496 } |
| 497 } |
| 498 } |
| 499 BinaryOperation* binary = node->AsBinaryOperation(); |
| 500 if (binary != NULL && Token::IsBitOp(binary->op())) { |
| 501 return false; |
| 502 } |
| 503 return true; |
| 504 } |
| 505 |
| 506 |
| 507 static bool CouldBePositiveZero(AstNode* node) { |
| 508 Literal* literal = node->AsLiteral(); |
| 509 if (literal != NULL) { |
| 510 Handle<Object> handle = literal->handle(); |
| 511 if (handle->IsSmi()) { |
| 512 if (Smi::cast(*handle) != Smi::FromInt(0)) { |
| 513 return false; |
| 514 } |
| 515 } else if (handle->IsHeapNumber()) { |
| 516 // Heap number literal can't be +0, because that's a Smi. |
| 517 return false; |
| 518 } |
| 519 } |
| 520 return true; |
| 521 } |
| 522 |
| 523 |
| 479 void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) { | 524 void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) { |
| 480 // Depending on the operation we can propagate this node's type down the | 525 // Depending on the operation we can propagate this node's type down the |
| 481 // AST nodes. | 526 // AST nodes. |
| 482 switch (node->op()) { | 527 Token::Value op = node->op(); |
| 528 switch (op) { |
| 483 case Token::COMMA: | 529 case Token::COMMA: |
| 484 case Token::OR: | 530 case Token::OR: |
| 485 node->left()->set_no_negative_zero(true); | 531 node->left()->set_no_negative_zero(true); |
| 486 node->right()->set_no_negative_zero(node->no_negative_zero()); | 532 node->right()->set_no_negative_zero(node->no_negative_zero()); |
| 487 break; | 533 break; |
| 488 case Token::AND: | 534 case Token::AND: |
| 489 node->left()->set_no_negative_zero(node->no_negative_zero()); | 535 node->left()->set_no_negative_zero(node->no_negative_zero()); |
| 490 node->right()->set_no_negative_zero(node->no_negative_zero()); | 536 node->right()->set_no_negative_zero(node->no_negative_zero()); |
| 491 break; | 537 break; |
| 492 case Token::BIT_OR: | 538 case Token::BIT_OR: |
| 493 case Token::BIT_XOR: | 539 case Token::BIT_XOR: |
| 494 case Token::BIT_AND: | 540 case Token::BIT_AND: |
| 495 case Token::SHL: | 541 case Token::SHL: |
| 496 case Token::SAR: | 542 case Token::SAR: |
| 497 case Token::SHR: | 543 case Token::SHR: |
| 498 node->type()->SetAsLikelySmiIfUnknown(); | 544 node->type()->SetAsLikelySmiIfUnknown(); |
| 499 node->left()->type()->SetAsLikelySmiIfUnknown(); | 545 node->left()->type()->SetAsLikelySmiIfUnknown(); |
| 500 node->right()->type()->SetAsLikelySmiIfUnknown(); | 546 node->right()->type()->SetAsLikelySmiIfUnknown(); |
| 501 node->left()->set_to_int32(true); | 547 node->left()->set_to_int32(true); |
| 502 node->right()->set_to_int32(true); | 548 node->right()->set_to_int32(true); |
| 503 node->left()->set_no_negative_zero(true); | 549 node->left()->set_no_negative_zero(true); |
| 504 node->right()->set_no_negative_zero(true); | 550 node->right()->set_no_negative_zero(true); |
| 505 break; | 551 break; |
| 552 case Token::MUL: { |
| 553 VariableProxy* lvar_proxy = node->left()->AsVariableProxy(); |
| 554 VariableProxy* rvar_proxy = node->right()->AsVariableProxy(); |
| 555 if (lvar_proxy != NULL && rvar_proxy != NULL) { |
| 556 Variable* lvar = lvar_proxy->AsVariable(); |
| 557 Variable* rvar = rvar_proxy->AsVariable(); |
| 558 if (lvar != NULL && rvar != NULL) { |
| 559 if (lvar->mode() == Variable::VAR && rvar->mode() == Variable::VAR) { |
| 560 Slot* lslot = lvar->slot(); |
| 561 Slot* rslot = rvar->slot(); |
| 562 if (lslot->type() == rslot->type() && |
| 563 (lslot->type() == Slot::PARAMETER || |
| 564 lslot->type() == Slot::LOCAL) && |
| 565 lslot->index() == rslot->index()) { |
| 566 // A number squared doesn't give negative zero. |
| 567 node->set_no_negative_zero(true); |
| 568 } |
| 569 } |
| 570 } |
| 571 } |
| 572 } |
| 506 case Token::ADD: | 573 case Token::ADD: |
| 507 case Token::SUB: | 574 case Token::SUB: |
| 508 case Token::MUL: | |
| 509 case Token::DIV: | 575 case Token::DIV: |
| 510 case Token::MOD: | 576 case Token::MOD: { |
| 511 if (node->type()->IsLikelySmi()) { | 577 if (node->type()->IsLikelySmi()) { |
| 512 node->left()->type()->SetAsLikelySmiIfUnknown(); | 578 node->left()->type()->SetAsLikelySmiIfUnknown(); |
| 513 node->right()->type()->SetAsLikelySmiIfUnknown(); | 579 node->right()->type()->SetAsLikelySmiIfUnknown(); |
| 514 } | 580 } |
| 515 node->left()->set_no_negative_zero(node->no_negative_zero()); | 581 if (op == Token::ADD && (!CouldBeNegativeZero(node->left()) || |
| 516 node->right()->set_no_negative_zero(node->no_negative_zero()); | 582 !CouldBeNegativeZero(node->right()))) { |
| 583 node->left()->set_no_negative_zero(true); |
| 584 node->right()->set_no_negative_zero(true); |
| 585 } else if (op == Token::SUB && (!CouldBeNegativeZero(node->left()) || |
| 586 !CouldBePositiveZero(node->right()))) { |
| 587 node->left()->set_no_negative_zero(true); |
| 588 node->right()->set_no_negative_zero(true); |
| 589 } else { |
| 590 node->left()->set_no_negative_zero(node->no_negative_zero()); |
| 591 node->right()->set_no_negative_zero(node->no_negative_zero()); |
| 592 } |
| 517 if (node->op() == Token::DIV) { | 593 if (node->op() == Token::DIV) { |
| 518 node->right()->set_no_negative_zero(false); | 594 node->right()->set_no_negative_zero(false); |
| 519 } else if (node->op() == Token::MOD) { | 595 } else if (node->op() == Token::MOD) { |
| 520 node->right()->set_no_negative_zero(true); | 596 node->right()->set_no_negative_zero(true); |
| 521 } | 597 } |
| 522 break; | 598 break; |
| 599 } |
| 523 default: | 600 default: |
| 524 UNREACHABLE(); | 601 UNREACHABLE(); |
| 525 break; | 602 break; |
| 526 } | 603 } |
| 527 | 604 |
| 528 Visit(node->left()); | 605 Visit(node->left()); |
| 529 Visit(node->right()); | 606 Visit(node->right()); |
| 530 | 607 |
| 531 // After visiting the operand nodes we have to check if this node's type | 608 // After visiting the operand nodes we have to check if this node's type |
| 532 // can be updated. If it does, then we can push that information down | 609 // can be updated. If it does, then we can push that information down |
| 533 // towards the leafs again if the new information is an upgrade over the | 610 // towards the leaves again if the new information is an upgrade over the |
| 534 // previous type of the operand nodes. | 611 // previous type of the operand nodes. |
| 535 if (node->type()->IsUnknown()) { | 612 if (node->type()->IsUnknown()) { |
| 536 if (node->left()->type()->IsLikelySmi() || | 613 if (node->left()->type()->IsLikelySmi() || |
| 537 node->right()->type()->IsLikelySmi()) { | 614 node->right()->type()->IsLikelySmi()) { |
| 538 node->type()->SetAsLikelySmi(); | 615 node->type()->SetAsLikelySmi(); |
| 539 } | 616 } |
| 540 if (node->type()->IsLikelySmi()) { | 617 if (node->type()->IsLikelySmi()) { |
| 541 // The type of this node changed to LIKELY_SMI. Propagate this knowledge | 618 // The type of this node changed to LIKELY_SMI. Propagate this knowledge |
| 542 // down through the nodes. | 619 // down through the nodes. |
| 543 if (node->left()->type()->IsUnknown()) { | 620 if (node->left()->type()->IsUnknown()) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 default: | 660 default: |
| 584 UNREACHABLE(); | 661 UNREACHABLE(); |
| 585 break; | 662 break; |
| 586 } | 663 } |
| 587 } | 664 } |
| 588 } | 665 } |
| 589 | 666 |
| 590 | 667 |
| 591 void AstOptimizer::VisitCompareOperation(CompareOperation* node) { | 668 void AstOptimizer::VisitCompareOperation(CompareOperation* node) { |
| 592 if (node->type()->IsKnown()) { | 669 if (node->type()->IsKnown()) { |
| 593 // Propagate useful information down towards the leafs. | 670 // Propagate useful information down towards the leaves. |
| 594 node->left()->type()->SetAsLikelySmiIfUnknown(); | 671 node->left()->type()->SetAsLikelySmiIfUnknown(); |
| 595 node->right()->type()->SetAsLikelySmiIfUnknown(); | 672 node->right()->type()->SetAsLikelySmiIfUnknown(); |
| 596 } | 673 } |
| 597 | 674 |
| 598 node->left()->set_no_negative_zero(true); | 675 node->left()->set_no_negative_zero(true); |
| 599 // Only [[HasInstance]] has the right argument passed unchanged to it. | 676 // Only [[HasInstance]] has the right argument passed unchanged to it. |
| 600 node->right()->set_no_negative_zero(true); | 677 node->right()->set_no_negative_zero(true); |
| 601 | 678 |
| 602 Visit(node->left()); | 679 Visit(node->left()); |
| 603 Visit(node->right()); | 680 Visit(node->right()); |
| 604 | 681 |
| 605 // After visiting the operand nodes we have to check if this node's type | 682 // After visiting the operand nodes we have to check if this node's type |
| 606 // can be updated. If it does, then we can push that information down | 683 // can be updated. If it does, then we can push that information down |
| 607 // towards the leafs again if the new information is an upgrade over the | 684 // towards the leaves again if the new information is an upgrade over the |
| 608 // previous type of the operand nodes. | 685 // previous type of the operand nodes. |
| 609 if (node->type()->IsUnknown()) { | 686 if (node->type()->IsUnknown()) { |
| 610 if (node->left()->type()->IsLikelySmi() || | 687 if (node->left()->type()->IsLikelySmi() || |
| 611 node->right()->type()->IsLikelySmi()) { | 688 node->right()->type()->IsLikelySmi()) { |
| 612 node->type()->SetAsLikelySmi(); | 689 node->type()->SetAsLikelySmi(); |
| 613 } | 690 } |
| 614 if (node->type()->IsLikelySmi()) { | 691 if (node->type()->IsLikelySmi()) { |
| 615 // The type of this node changed to LIKELY_SMI. Propagate this knowledge | 692 // The type of this node changed to LIKELY_SMI. Propagate this knowledge |
| 616 // down through the nodes. | 693 // down through the nodes. |
| 617 if (node->left()->type()->IsUnknown()) { | 694 if (node->left()->type()->IsUnknown()) { |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 optimizer.Optimize(body); | 1029 optimizer.Optimize(body); |
| 953 if (optimizer.HasStackOverflow()) { | 1030 if (optimizer.HasStackOverflow()) { |
| 954 return false; | 1031 return false; |
| 955 } | 1032 } |
| 956 } | 1033 } |
| 957 return true; | 1034 return true; |
| 958 } | 1035 } |
| 959 | 1036 |
| 960 | 1037 |
| 961 } } // namespace v8::internal | 1038 } } // namespace v8::internal |
| OLD | NEW |