Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: src/rewriter.cc

Issue 2799048: Make ignore-negative-zeros analysis a little sharper. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698