Chromium Code Reviews| 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/flow_graph_compiler.h" |
| (...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 880 | 880 |
| 881 return false; | 881 return false; |
| 882 } | 882 } |
| 883 | 883 |
| 884 | 884 |
| 885 // Inline only simple, frequently called core library methods. | 885 // Inline only simple, frequently called core library methods. |
| 886 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { | 886 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
| 887 ASSERT(call->HasICData()); | 887 ASSERT(call->HasICData()); |
| 888 const ICData& ic_data = *call->ic_data(); | 888 const ICData& ic_data = *call->ic_data(); |
| 889 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { | 889 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { |
| 890 // No type feedback collected. | 890 // No type feedback collected or multiple targets found. |
| 891 return false; | 891 return false; |
| 892 } | 892 } |
| 893 Function& target = Function::Handle(); | 893 Function& target = Function::Handle(); |
| 894 GrowableArray<intptr_t> class_ids; | 894 GrowableArray<intptr_t> class_ids; |
| 895 ic_data.GetCheckAt(0, &class_ids, &target); | 895 ic_data.GetCheckAt(0, &class_ids, &target); |
| 896 MethodRecognizer::Kind recognized_kind = | 896 MethodRecognizer::Kind recognized_kind = |
| 897 MethodRecognizer::RecognizeKind(target); | 897 MethodRecognizer::RecognizeKind(target); |
| 898 | 898 |
| 899 if ((recognized_kind == MethodRecognizer::kDoubleToDouble) && | 899 if ((recognized_kind == MethodRecognizer::kDoubleToDouble) && |
| 900 (class_ids[0] == kDoubleCid)) { | 900 (class_ids[0] == kDoubleCid)) { |
| 901 DoubleToDoubleInstr* d2d_instr = | 901 DoubleToDoubleInstr* d2d_instr = |
| 902 new DoubleToDoubleInstr(call->ArgumentAt(0)->value(), call); | 902 new DoubleToDoubleInstr(call->ArgumentAt(0)->value(), call); |
| 903 call->ReplaceWith(d2d_instr, current_iterator()); | 903 call->ReplaceWith(d2d_instr, current_iterator()); |
| 904 RemovePushArguments(call); | 904 RemovePushArguments(call); |
| 905 return true; | 905 return true; |
| 906 } | 906 } |
| 907 | 907 |
| 908 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && | 908 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && |
| 909 (class_ids[0] == kSmiCid)) { | 909 (class_ids[0] == kSmiCid)) { |
| 910 SmiToDoubleInstr* s2d_instr = new SmiToDoubleInstr(call); | 910 SmiToDoubleInstr* s2d_instr = new SmiToDoubleInstr(call); |
| 911 call->ReplaceWith(s2d_instr, current_iterator()); | 911 call->ReplaceWith(s2d_instr, current_iterator()); |
| 912 // Pushed arguments are not removed because SmiToDouble is implemented | 912 // Pushed arguments are not removed because SmiToDouble is implemented |
| 913 // as a call. | 913 // as a call. |
| 914 return true; | 914 return true; |
| 915 } | 915 } |
| 916 | 916 |
| 917 if ((recognized_kind == MethodRecognizer::kIntegerToInteger) && | |
| 918 (class_ids[0] == kSmiCid)) { | |
| 919 // TODO(srdjan): implement also for BigInt and Mint. | |
| 920 InsertBefore(call, | |
| 921 new CheckSmiInstr(call->ArgumentAt(0)->value()->Copy(), | |
| 922 call->deopt_id()), | |
| 923 call->env(), | |
| 924 Definition::kEffect); | |
| 925 IntegerToIntegerInstr* int2int_instr = | |
| 926 new IntegerToIntegerInstr(call->ArgumentAt(0)->value(), call, kSmiCid); | |
| 927 call->ReplaceWith(int2int_instr, current_iterator()); | |
|
Florian Schneider
2012/10/09 11:13:58
Since IntegerToInteger itself is a nop, I think yo
srdjan
2012/10/09 21:23:04
Done.
| |
| 928 RemovePushArguments(call); | |
| 929 return true; | |
| 930 } | |
| 931 | |
| 932 if ((recognized_kind == MethodRecognizer::kDoubleToInteger) && | |
| 933 (class_ids[0] == kDoubleCid)) { | |
| 934 AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); | |
| 935 DoubleToIntegerInstr* d2int_instr = new DoubleToIntegerInstr(call); | |
| 936 call->ReplaceWith(d2int_instr, current_iterator()); | |
| 937 // Pushed arguments are not removed because DoubleToInt is implemented | |
| 938 // as a call. | |
| 939 return true; | |
| 940 } | |
| 941 | |
| 917 if (recognized_kind == MethodRecognizer::kStringBaseIsEmpty) { | 942 if (recognized_kind == MethodRecognizer::kStringBaseIsEmpty) { |
| 918 if (!ic_data.HasOneTarget()) { | 943 if (!ic_data.HasOneTarget()) { |
| 919 // Target is not only StringBase_get_length. | 944 // Target is not only StringBase_get_length. |
| 920 return false; | 945 return false; |
| 921 } | 946 } |
| 922 InlineStringIsEmptyTester(call); | 947 InlineStringIsEmptyTester(call); |
| 923 return true; | 948 return true; |
| 924 } | 949 } |
| 925 | 950 |
| 926 return false; | 951 return false; |
| 927 } | 952 } |
| 928 | 953 |
| 929 | 954 |
| 955 // Tries to optimize instance call by replacing it with a faster instruction | |
| 956 // (e.g, binary op, field load, ..). | |
| 930 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 957 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 931 if (instr->HasICData() && (instr->ic_data()->NumberOfChecks() > 0)) { | 958 if (instr->HasICData() && (instr->ic_data()->NumberOfChecks() > 0)) { |
| 932 const Token::Kind op_kind = instr->token_kind(); | 959 const Token::Kind op_kind = instr->token_kind(); |
| 933 if (Token::IsIndexOperator(op_kind) && | 960 if (Token::IsIndexOperator(op_kind) && |
| 934 TryReplaceWithArrayOp(instr, op_kind)) { | 961 TryReplaceWithArrayOp(instr, op_kind)) { |
| 935 return; | 962 return; |
| 936 } | 963 } |
| 937 if (Token::IsBinaryToken(op_kind) && | 964 if (Token::IsBinaryToken(op_kind) && |
| 938 TryReplaceWithBinaryOp(instr, op_kind)) { | 965 TryReplaceWithBinaryOp(instr, op_kind)) { |
| 939 return; | 966 return; |
| (...skipping 2102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3042 } | 3069 } |
| 3043 } | 3070 } |
| 3044 | 3071 |
| 3045 | 3072 |
| 3046 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { | 3073 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { |
| 3047 // TODO(kmillikin): Handle conversion. | 3074 // TODO(kmillikin): Handle conversion. |
| 3048 SetValue(instr, non_constant_); | 3075 SetValue(instr, non_constant_); |
| 3049 } | 3076 } |
| 3050 | 3077 |
| 3051 | 3078 |
| 3079 void ConstantPropagator::VisitIntegerToInteger(IntegerToIntegerInstr* instr) { | |
| 3080 const Object& value = instr->value()->definition()->constant_value(); | |
| 3081 if (IsNonConstant(value)) { | |
| 3082 SetValue(instr, non_constant_); | |
| 3083 } else if (IsConstant(value)) { | |
| 3084 // TODO(kmillikin): Handle conversion. | |
| 3085 SetValue(instr, non_constant_); | |
| 3086 } | |
| 3087 } | |
| 3088 | |
| 3089 | |
| 3090 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { | |
| 3091 // TODO(kmillikin): Handle conversion. | |
| 3092 SetValue(instr, non_constant_); | |
| 3093 } | |
| 3094 | |
| 3095 | |
| 3052 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { | 3096 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { |
| 3053 SetValue(instr, instr->value()); | 3097 SetValue(instr, instr->value()); |
| 3054 } | 3098 } |
| 3055 | 3099 |
| 3056 | 3100 |
| 3057 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { | 3101 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { |
| 3058 // Should not be used outside of range analysis. | 3102 // Should not be used outside of range analysis. |
| 3059 UNREACHABLE(); | 3103 UNREACHABLE(); |
| 3060 } | 3104 } |
| 3061 | 3105 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3257 | 3301 |
| 3258 if (FLAG_trace_constant_propagation) { | 3302 if (FLAG_trace_constant_propagation) { |
| 3259 OS::Print("\n==== After constant propagation ====\n"); | 3303 OS::Print("\n==== After constant propagation ====\n"); |
| 3260 FlowGraphPrinter printer(*graph_); | 3304 FlowGraphPrinter printer(*graph_); |
| 3261 printer.PrintBlocks(); | 3305 printer.PrintBlocks(); |
| 3262 } | 3306 } |
| 3263 } | 3307 } |
| 3264 | 3308 |
| 3265 | 3309 |
| 3266 } // namespace dart | 3310 } // namespace dart |
| OLD | NEW |