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

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 10914008: Add explicit smi-checks to smi comparisons. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/cha.h" 7 #include "vm/cha.h"
8 #include "vm/flow_graph_builder.h" 8 #include "vm/flow_graph_builder.h"
9 #include "vm/hash_map.h" 9 #include "vm/hash_map.h"
10 #include "vm/il_printer.h" 10 #include "vm/il_printer.h"
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 if (op_kind == Token::kASSIGN_INDEX) return false; 219 if (op_kind == Token::kASSIGN_INDEX) return false;
220 // Fall through. 220 // Fall through.
221 case kArrayCid: 221 case kArrayCid:
222 case kGrowableObjectArrayCid: { 222 case kGrowableObjectArrayCid: {
223 Value* array = comp->ArgumentAt(0)->value(); 223 Value* array = comp->ArgumentAt(0)->value();
224 Value* index = comp->ArgumentAt(1)->value(); 224 Value* index = comp->ArgumentAt(1)->value();
225 // Insert class check and index smi checks and attach a copy of the 225 // Insert class check and index smi checks and attach a copy of the
226 // original environment because the operation can still deoptimize. 226 // original environment because the operation can still deoptimize.
227 AddCheckClass(instr, comp, array->Copy()); 227 AddCheckClass(instr, comp, array->Copy());
228 InsertBefore(instr, 228 InsertBefore(instr,
229 new CheckSmiComp(index->Copy(), comp), 229 new CheckSmiComp(index->Copy(), comp->deopt_id()),
230 instr->env(), 230 instr->env(),
231 BindInstr::kUnused); 231 BindInstr::kUnused);
232 // Insert array bounds check. 232 // Insert array bounds check.
233 InsertBefore(instr, 233 InsertBefore(instr,
234 new CheckArrayBoundComp(array->Copy(), 234 new CheckArrayBoundComp(array->Copy(),
235 index->Copy(), 235 index->Copy(),
236 class_id, 236 class_id,
237 comp), 237 comp),
238 instr->env(), 238 instr->env(),
239 BindInstr::kUnused); 239 BindInstr::kUnused);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 bin_op->set_ic_data(comp->ic_data()); 390 bin_op->set_ic_data(comp->ic_data());
391 instr->set_computation(bin_op); 391 instr->set_computation(bin_op);
392 RemovePushArguments(comp); 392 RemovePushArguments(comp);
393 } else { 393 } else {
394 ASSERT(operands_type == kSmiCid); 394 ASSERT(operands_type == kSmiCid);
395 Value* left = comp->ArgumentAt(0)->value(); 395 Value* left = comp->ArgumentAt(0)->value();
396 Value* right = comp->ArgumentAt(1)->value(); 396 Value* right = comp->ArgumentAt(1)->value();
397 // Insert two smi checks and attach a copy of the original 397 // Insert two smi checks and attach a copy of the original
398 // environment because the smi operation can still deoptimize. 398 // environment because the smi operation can still deoptimize.
399 InsertBefore(instr, 399 InsertBefore(instr,
400 new CheckSmiComp(left->Copy(), comp), 400 new CheckSmiComp(left->Copy(), comp->deopt_id()),
401 instr->env(), 401 instr->env(),
402 BindInstr::kUnused); 402 BindInstr::kUnused);
403 InsertBefore(instr, 403 InsertBefore(instr,
404 new CheckSmiComp(right->Copy(), comp), 404 new CheckSmiComp(right->Copy(), comp->deopt_id()),
405 instr->env(), 405 instr->env(),
406 BindInstr::kUnused); 406 BindInstr::kUnused);
407 BinarySmiOpComp* bin_op = new BinarySmiOpComp(op_kind, 407 BinarySmiOpComp* bin_op = new BinarySmiOpComp(op_kind,
408 comp, 408 comp,
409 left, 409 left,
410 right); 410 right);
411 bin_op->set_ic_data(comp->ic_data()); 411 bin_op->set_ic_data(comp->ic_data());
412 instr->set_computation(bin_op); 412 instr->set_computation(bin_op);
413 RemovePushArguments(comp); 413 RemovePushArguments(comp);
414 } 414 }
415 return true; 415 return true;
416 } 416 }
417 417
418 418
419 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(BindInstr* instr, 419 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(BindInstr* instr,
420 InstanceCallComp* comp, 420 InstanceCallComp* comp,
421 Token::Kind op_kind) { 421 Token::Kind op_kind) {
422 if (comp->ic_data()->NumberOfChecks() != 1) { 422 if (comp->ic_data()->NumberOfChecks() != 1) {
423 // TODO(srdjan): Not yet supported. 423 // TODO(srdjan): Not yet supported.
424 return false; 424 return false;
425 } 425 }
426 ASSERT(comp->ArgumentCount() == 1); 426 ASSERT(comp->ArgumentCount() == 1);
427 Computation* unary_op = NULL; 427 Computation* unary_op = NULL;
428 if (HasOneSmi(*comp->ic_data())) { 428 if (HasOneSmi(*comp->ic_data())) {
429 Value* value = comp->ArgumentAt(0)->value(); 429 Value* value = comp->ArgumentAt(0)->value();
430 InsertBefore(instr, 430 InsertBefore(instr,
431 new CheckSmiComp(value->Copy(), comp), 431 new CheckSmiComp(value->Copy(), comp->deopt_id()),
432 instr->env(), 432 instr->env(),
433 BindInstr::kUnused); 433 BindInstr::kUnused);
434 unary_op = new UnarySmiOpComp(op_kind, 434 unary_op = new UnarySmiOpComp(op_kind,
435 (op_kind == Token::kNEGATE) ? comp : NULL, 435 (op_kind == Token::kNEGATE) ? comp : NULL,
436 value); 436 value);
437 } else if (HasOneDouble(*comp->ic_data()) && (op_kind == Token::kNEGATE)) { 437 } else if (HasOneDouble(*comp->ic_data()) && (op_kind == Token::kNEGATE)) {
438 unary_op = new NumberNegateComp(comp, comp->ArgumentAt(0)->value()); 438 unary_op = new NumberNegateComp(comp, comp->ArgumentAt(0)->value());
439 } 439 }
440 if (unary_op == NULL) return false; 440 if (unary_op == NULL) return false;
441 441
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( 689 StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
690 field, 690 field,
691 comp->ArgumentAt(0)->value(), 691 comp->ArgumentAt(0)->value(),
692 comp->ArgumentAt(1)->value()); 692 comp->ArgumentAt(1)->value());
693 instr->set_computation(store); 693 instr->set_computation(store);
694 RemovePushArguments(comp); 694 RemovePushArguments(comp);
695 return true; 695 return true;
696 } 696 }
697 697
698 698
699 void FlowGraphOptimizer::VisitRelationalOp(RelationalOpComp* comp, 699 // TODO(fschneider): Once we get rid of the distinction between Instruction
700 BindInstr* instr) { 700 // and computation, this helper can go away.
701 static void HandleRelationalOp(FlowGraphOptimizer* optimizer,
702 RelationalOpComp* comp,
703 Instruction* instr) {
701 if (!comp->HasICData()) return; 704 if (!comp->HasICData()) return;
702 705
703 const ICData& ic_data = *comp->ic_data(); 706 const ICData& ic_data = *comp->ic_data();
704 if (ic_data.NumberOfChecks() == 0) return; 707 if (ic_data.NumberOfChecks() == 0) return;
705 // TODO(srdjan): Add multiple receiver type support. 708 // TODO(srdjan): Add multiple receiver type support.
706 if (ic_data.NumberOfChecks() != 1) return; 709 if (ic_data.NumberOfChecks() != 1) return;
707 ASSERT(HasOneTarget(ic_data)); 710 ASSERT(HasOneTarget(ic_data));
708 711
709 if (HasOnlyTwoSmi(ic_data)) { 712 if (HasOnlyTwoSmi(ic_data)) {
713 optimizer->InsertBefore(
714 instr,
715 new CheckSmiComp(comp->left()->Copy(), comp->deopt_id()),
716 instr->env(),
717 BindInstr::kUnused);
718 optimizer->InsertBefore(
719 instr,
720 new CheckSmiComp(comp->right()->Copy(), comp->deopt_id()),
721 instr->env(),
722 BindInstr::kUnused);
710 comp->set_operands_class_id(kSmiCid); 723 comp->set_operands_class_id(kSmiCid);
711 } else if (HasOnlyTwoDouble(ic_data)) { 724 } else if (HasOnlyTwoDouble(ic_data)) {
712 comp->set_operands_class_id(kDoubleCid); 725 comp->set_operands_class_id(kDoubleCid);
713 } else if (comp->ic_data()->AllReceiversAreNumbers()) { 726 } else if (comp->ic_data()->AllReceiversAreNumbers()) {
714 comp->set_operands_class_id(kNumberCid); 727 comp->set_operands_class_id(kNumberCid);
715 } 728 }
716 } 729 }
717 730
731 void FlowGraphOptimizer::VisitRelationalOp(RelationalOpComp* comp,
732 BindInstr* instr) {
733 HandleRelationalOp(this, comp, instr);
734 }
718 735
719 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp, 736
720 BindInstr* instr) { 737 // TODO(fschneider): Once we get rid of the distinction between Instruction
738 // and computation, this helper can go away.
739 template <typename T>
740 static void HandleEqualityCompare(FlowGraphOptimizer* optimizer,
741 EqualityCompareComp* comp,
742 T instr) {
721 // If one of the inputs is null, no ICdata will be collected. 743 // If one of the inputs is null, no ICdata will be collected.
722 if (comp->left()->BindsToConstantNull() || 744 if (comp->left()->BindsToConstantNull() ||
723 comp->right()->BindsToConstantNull()) { 745 comp->right()->BindsToConstantNull()) {
724 Token::Kind strict_kind = (comp->kind() == Token::kEQ) ? 746 Token::Kind strict_kind = (comp->kind() == Token::kEQ) ?
725 Token::kEQ_STRICT : Token::kNE_STRICT; 747 Token::kEQ_STRICT : Token::kNE_STRICT;
726 StrictCompareComp* strict_comp = 748 StrictCompareComp* strict_comp =
727 new StrictCompareComp(strict_kind, comp->left(), comp->right()); 749 new StrictCompareComp(strict_kind, comp->left(), comp->right());
728 instr->set_computation(strict_comp); 750 instr->set_computation(strict_comp);
729 return; 751 return;
730 } 752 }
731 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return; 753 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return;
732 if (comp->ic_data()->NumberOfChecks() == 1) { 754 if (comp->ic_data()->NumberOfChecks() == 1) {
733 ASSERT(comp->ic_data()->num_args_tested() == 2); 755 ASSERT(comp->ic_data()->num_args_tested() == 2);
734 GrowableArray<intptr_t> class_ids; 756 GrowableArray<intptr_t> class_ids;
735 Function& target = Function::Handle(); 757 Function& target = Function::Handle();
736 comp->ic_data()->GetCheckAt(0, &class_ids, &target); 758 comp->ic_data()->GetCheckAt(0, &class_ids, &target);
737 // TODO(srdjan): allow for mixed mode comparison. 759 // TODO(srdjan): allow for mixed mode comparison.
738 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { 760 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) {
761 optimizer->InsertBefore(
762 instr,
763 new CheckSmiComp(comp->left()->Copy(), comp->deopt_id()),
764 instr->env(),
765 BindInstr::kUnused);
766 optimizer->InsertBefore(
767 instr,
768 new CheckSmiComp(comp->right()->Copy(), comp->deopt_id()),
769 instr->env(),
770 BindInstr::kUnused);
739 comp->set_receiver_class_id(kSmiCid); 771 comp->set_receiver_class_id(kSmiCid);
740 } else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) { 772 } else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) {
741 comp->set_receiver_class_id(kDoubleCid); 773 comp->set_receiver_class_id(kDoubleCid);
742 } else { 774 } else {
743 ASSERT(comp->receiver_class_id() == kIllegalCid); 775 ASSERT(comp->receiver_class_id() == kIllegalCid);
744 } 776 }
745 } else if (comp->ic_data()->AllReceiversAreNumbers()) { 777 } else if (comp->ic_data()->AllReceiversAreNumbers()) {
746 comp->set_receiver_class_id(kNumberCid); 778 comp->set_receiver_class_id(kNumberCid);
747 } 779 }
748 } 780 }
749 781
750 782
783 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp,
784 BindInstr* instr) {
785 HandleEqualityCompare(this, comp, instr);
786 }
787
788
751 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { 789 void FlowGraphOptimizer::VisitBind(BindInstr* instr) {
752 instr->computation()->Accept(this, instr); 790 instr->computation()->Accept(this, instr);
753 } 791 }
754 792
755 793
756 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) { 794 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) {
757 instr->computation()->Accept(this, NULL); 795 ComparisonComp* comparison = instr->computation();
796 if (comparison->IsRelationalOp()) {
797 HandleRelationalOp(this, comparison->AsRelationalOp(), instr);
798 } else if (comparison->IsEqualityCompare()) {
799 HandleEqualityCompare(this, comparison->AsEqualityCompare(), instr);
800 } else {
801 ASSERT(comparison->IsStrictCompare());
802 // Nothing to do.
803 }
758 } 804 }
759 805
760 806
761 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp, 807 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp,
762 BindInstr* instr) { 808 BindInstr* instr) {
763 if (FLAG_eliminate_type_checks && 809 if (FLAG_eliminate_type_checks &&
764 !comp->is_eliminated() && 810 !comp->is_eliminated() &&
765 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) { 811 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) {
766 // TODO(regis): Remove is_eliminated_ field and support. 812 // TODO(regis): Remove is_eliminated_ field and support.
767 comp->eliminate(); 813 comp->eliminate();
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
1066 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map. 1112 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map.
1067 OptimizeRecursive(child, &child_map); 1113 OptimizeRecursive(child, &child_map);
1068 } else { 1114 } else {
1069 OptimizeRecursive(child, map); // Reuse map for the last child. 1115 OptimizeRecursive(child, map); // Reuse map for the last child.
1070 } 1116 }
1071 } 1117 }
1072 } 1118 }
1073 1119
1074 1120
1075 } // namespace dart 1121 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698