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 |