| OLD | NEW |
| 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/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" |
| 10 #include "vm/hash_map.h" | 11 #include "vm/hash_map.h" |
| 11 #include "vm/il_printer.h" | 12 #include "vm/il_printer.h" |
| 12 #include "vm/intermediate_language.h" | 13 #include "vm/intermediate_language.h" |
| 13 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 14 #include "vm/parser.h" | 15 #include "vm/parser.h" |
| 15 #include "vm/scopes.h" | 16 #include "vm/scopes.h" |
| 16 #include "vm/symbols.h" | 17 #include "vm/symbols.h" |
| 17 | 18 |
| 18 namespace dart { | 19 namespace dart { |
| 19 | 20 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 } | 77 } |
| 77 } | 78 } |
| 78 } | 79 } |
| 79 } | 80 } |
| 80 | 81 |
| 81 | 82 |
| 82 static Definition* CreateConversion(Representation from, | 83 static Definition* CreateConversion(Representation from, |
| 83 Representation to, | 84 Representation to, |
| 84 Definition* def, | 85 Definition* def, |
| 85 Instruction* deopt_target) { | 86 Instruction* deopt_target) { |
| 86 if ((from == kUnboxedDouble) && (to == kTagged)) { | 87 if ((from == kTagged) && (to == kUnboxedMint)) { |
| 88 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 89 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 90 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); |
| 91 return new UnboxIntegerInstr(new Value(def), deopt_id); |
| 92 } else if ((from == kUnboxedMint) && (to == kTagged)) { |
| 93 return new BoxIntegerInstr(new Value(def)); |
| 94 } else if ((from == kUnboxedDouble) && (to == kTagged)) { |
| 87 return new BoxDoubleInstr(new Value(def), NULL); | 95 return new BoxDoubleInstr(new Value(def), NULL); |
| 88 } else if ((from == kTagged) && (to == kUnboxedDouble)) { | 96 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
| 89 const intptr_t deopt_id = (deopt_target != NULL) ? | 97 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 90 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 98 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 91 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); | 99 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); |
| 92 return new UnboxDoubleInstr(new Value(def), deopt_id); | 100 return new UnboxDoubleInstr(new Value(def), deopt_id); |
| 93 } else { | 101 } else { |
| 94 UNREACHABLE(); | 102 UNREACHABLE(); |
| 95 return NULL; | 103 return NULL; |
| 96 } | 104 } |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 } | 476 } |
| 469 break; | 477 break; |
| 470 case Token::kMOD: | 478 case Token::kMOD: |
| 471 if (HasOnlyTwoSmi(ic_data)) { | 479 if (HasOnlyTwoSmi(ic_data)) { |
| 472 operands_type = kSmiCid; | 480 operands_type = kSmiCid; |
| 473 } else { | 481 } else { |
| 474 return false; | 482 return false; |
| 475 } | 483 } |
| 476 break; | 484 break; |
| 477 case Token::kBIT_AND: | 485 case Token::kBIT_AND: |
| 486 case Token::kBIT_OR: |
| 487 case Token::kBIT_XOR: |
| 478 if (HasOnlyTwoSmi(ic_data)) { | 488 if (HasOnlyTwoSmi(ic_data)) { |
| 479 operands_type = kSmiCid; | 489 operands_type = kSmiCid; |
| 480 } else if (HasTwoMintOrSmi(ic_data)) { | 490 } else if (HasTwoMintOrSmi(ic_data) && |
| 491 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 481 operands_type = kMintCid; | 492 operands_type = kMintCid; |
| 482 } else { | 493 } else { |
| 483 return false; | 494 return false; |
| 484 } | 495 } |
| 485 break; | 496 break; |
| 486 case Token::kBIT_OR: | |
| 487 case Token::kBIT_XOR: | |
| 488 case Token::kTRUNCDIV: | 497 case Token::kTRUNCDIV: |
| 489 case Token::kSHR: | 498 case Token::kSHR: |
| 490 case Token::kSHL: | 499 case Token::kSHL: |
| 491 if (HasOnlyTwoSmi(ic_data)) { | 500 if (HasOnlyTwoSmi(ic_data)) { |
| 492 operands_type = kSmiCid; | 501 operands_type = kSmiCid; |
| 493 } else { | 502 } else { |
| 494 return false; | 503 return false; |
| 495 } | 504 } |
| 496 break; | 505 break; |
| 497 default: | 506 default: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 515 UnboxedDoubleBinaryOpInstr* double_bin_op = | 524 UnboxedDoubleBinaryOpInstr* double_bin_op = |
| 516 new UnboxedDoubleBinaryOpInstr(op_kind, | 525 new UnboxedDoubleBinaryOpInstr(op_kind, |
| 517 left->Copy(), | 526 left->Copy(), |
| 518 right->Copy(), | 527 right->Copy(), |
| 519 call); | 528 call); |
| 520 call->ReplaceWith(double_bin_op, current_iterator()); | 529 call->ReplaceWith(double_bin_op, current_iterator()); |
| 521 RemovePushArguments(call); | 530 RemovePushArguments(call); |
| 522 } else if (operands_type == kMintCid) { | 531 } else if (operands_type == kMintCid) { |
| 523 Value* left = call->ArgumentAt(0)->value(); | 532 Value* left = call->ArgumentAt(0)->value(); |
| 524 Value* right = call->ArgumentAt(1)->value(); | 533 Value* right = call->ArgumentAt(1)->value(); |
| 525 BinaryMintOpInstr* bin_op = new BinaryMintOpInstr(op_kind, | 534 UnboxedMintBinaryOpInstr* bin_op = |
| 526 call, | 535 new UnboxedMintBinaryOpInstr(op_kind, left, right, call); |
| 527 left, | |
| 528 right); | |
| 529 call->ReplaceWith(bin_op, current_iterator()); | 536 call->ReplaceWith(bin_op, current_iterator()); |
| 530 RemovePushArguments(call); | 537 RemovePushArguments(call); |
| 531 } else if (op_kind == Token::kMOD) { | 538 } else if (op_kind == Token::kMOD) { |
| 532 // TODO(vegorov): implement fast path code for modulo. | 539 // TODO(vegorov): implement fast path code for modulo. |
| 533 ASSERT(operands_type == kSmiCid); | 540 ASSERT(operands_type == kSmiCid); |
| 534 if (!call->ArgumentAt(1)->value()->BindsToConstant()) return false; | 541 if (!call->ArgumentAt(1)->value()->BindsToConstant()) return false; |
| 535 const Object& obj = call->ArgumentAt(1)->value()->BoundConstant(); | 542 const Object& obj = call->ArgumentAt(1)->value()->BoundConstant(); |
| 536 if (!obj.IsSmi()) return false; | 543 if (!obj.IsSmi()) return false; |
| 537 const intptr_t value = Smi::Cast(obj).Value(); | 544 const intptr_t value = Smi::Cast(obj).Value(); |
| 538 if ((value > 0) && Utils::IsPowerOfTwo(value)) { | 545 if ((value > 0) && Utils::IsPowerOfTwo(value)) { |
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 new StrictCompareInstr(strict_kind, comp->left(), comp->right()); | 1057 new StrictCompareInstr(strict_kind, comp->left(), comp->right()); |
| 1051 instr->ReplaceWith(strict_comp, iterator); | 1058 instr->ReplaceWith(strict_comp, iterator); |
| 1052 return; | 1059 return; |
| 1053 } | 1060 } |
| 1054 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return; | 1061 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return; |
| 1055 if (comp->ic_data()->NumberOfChecks() == 1) { | 1062 if (comp->ic_data()->NumberOfChecks() == 1) { |
| 1056 ASSERT(comp->ic_data()->num_args_tested() == 2); | 1063 ASSERT(comp->ic_data()->num_args_tested() == 2); |
| 1057 GrowableArray<intptr_t> class_ids; | 1064 GrowableArray<intptr_t> class_ids; |
| 1058 Function& target = Function::Handle(); | 1065 Function& target = Function::Handle(); |
| 1059 comp->ic_data()->GetCheckAt(0, &class_ids, &target); | 1066 comp->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 1060 // TODO(srdjan): allow for mixed mode comparison. | 1067 // TODO(srdjan): allow for mixed mode int/double comparison. |
| 1068 |
| 1061 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { | 1069 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 1062 optimizer->InsertBefore( | 1070 optimizer->InsertBefore( |
| 1063 instr, | 1071 instr, |
| 1064 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), | 1072 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), |
| 1065 instr->env(), | 1073 instr->env(), |
| 1066 Definition::kEffect); | 1074 Definition::kEffect); |
| 1067 optimizer->InsertBefore( | 1075 optimizer->InsertBefore( |
| 1068 instr, | 1076 instr, |
| 1069 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()), | 1077 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()), |
| 1070 instr->env(), | 1078 instr->env(), |
| 1071 Definition::kEffect); | 1079 Definition::kEffect); |
| 1072 comp->set_receiver_class_id(kSmiCid); | 1080 comp->set_receiver_class_id(kSmiCid); |
| 1073 } else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) { | 1081 } else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) { |
| 1074 comp->set_receiver_class_id(kDoubleCid); | 1082 comp->set_receiver_class_id(kDoubleCid); |
| 1083 } else if (HasTwoMintOrSmi(*comp->ic_data()) && |
| 1084 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1085 comp->set_receiver_class_id(kMintCid); |
| 1075 } else { | 1086 } else { |
| 1076 ASSERT(comp->receiver_class_id() == kIllegalCid); | 1087 ASSERT(comp->receiver_class_id() == kIllegalCid); |
| 1077 } | 1088 } |
| 1089 } else if (HasTwoMintOrSmi(*comp->ic_data())) { |
| 1090 comp->set_receiver_class_id(kMintCid); |
| 1078 } else if (comp->ic_data()->AllReceiversAreNumbers()) { | 1091 } else if (comp->ic_data()->AllReceiversAreNumbers()) { |
| 1079 comp->set_receiver_class_id(kNumberCid); | 1092 comp->set_receiver_class_id(kNumberCid); |
| 1080 } | 1093 } |
| 1081 } | 1094 } |
| 1082 | 1095 |
| 1083 | 1096 |
| 1084 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { | 1097 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { |
| 1085 HandleEqualityCompare(this, instr, instr, current_iterator()); | 1098 HandleEqualityCompare(this, instr, instr, current_iterator()); |
| 1086 } | 1099 } |
| 1087 | 1100 |
| (...skipping 1774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2862 SetValue(instr, non_constant_); | 2875 SetValue(instr, non_constant_); |
| 2863 } | 2876 } |
| 2864 } else { | 2877 } else { |
| 2865 // TODO(kmillikin): support other types. | 2878 // TODO(kmillikin): support other types. |
| 2866 SetValue(instr, non_constant_); | 2879 SetValue(instr, non_constant_); |
| 2867 } | 2880 } |
| 2868 } | 2881 } |
| 2869 } | 2882 } |
| 2870 | 2883 |
| 2871 | 2884 |
| 2885 void ConstantPropagator::VisitBoxInteger(BoxIntegerInstr* instr) { |
| 2886 // TODO(kmillikin): Handle box operation. |
| 2887 SetValue(instr, non_constant_); |
| 2888 } |
| 2889 |
| 2890 |
| 2891 void ConstantPropagator::VisitUnboxInteger(UnboxIntegerInstr* instr) { |
| 2892 // TODO(kmillikin): Handle unbox operation. |
| 2893 SetValue(instr, non_constant_); |
| 2894 } |
| 2895 |
| 2896 |
| 2897 void ConstantPropagator::VisitUnboxedMintBinaryOp( |
| 2898 UnboxedMintBinaryOpInstr* instr) { |
| 2899 // TODO(kmillikin): Handle binary operations. |
| 2900 SetValue(instr, non_constant_); |
| 2901 } |
| 2902 |
| 2903 |
| 2872 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { | 2904 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { |
| 2873 const Object& left = instr->left()->definition()->constant_value(); | 2905 const Object& left = instr->left()->definition()->constant_value(); |
| 2874 const Object& right = instr->right()->definition()->constant_value(); | 2906 const Object& right = instr->right()->definition()->constant_value(); |
| 2875 if (IsNonConstant(left) || IsNonConstant(right)) { | 2907 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 2876 SetValue(instr, non_constant_); | 2908 SetValue(instr, non_constant_); |
| 2877 } else if (IsConstant(left) && IsConstant(right)) { | 2909 } else if (IsConstant(left) && IsConstant(right)) { |
| 2878 // TODO(kmillikin): Handle binary operations. | 2910 // TODO(kmillikin): Handle binary operations. |
| 2879 SetValue(instr, non_constant_); | 2911 SetValue(instr, non_constant_); |
| 2880 } | 2912 } |
| 2881 } | 2913 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3117 | 3149 |
| 3118 if (FLAG_trace_constant_propagation) { | 3150 if (FLAG_trace_constant_propagation) { |
| 3119 OS::Print("\n==== After constant propagation ====\n"); | 3151 OS::Print("\n==== After constant propagation ====\n"); |
| 3120 FlowGraphPrinter printer(*graph_); | 3152 FlowGraphPrinter printer(*graph_); |
| 3121 printer.PrintBlocks(); | 3153 printer.PrintBlocks(); |
| 3122 } | 3154 } |
| 3123 } | 3155 } |
| 3124 | 3156 |
| 3125 | 3157 |
| 3126 } // namespace dart | 3158 } // namespace dart |
| OLD | NEW |