| 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 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 967 length_offset, | 967 length_offset, |
| 968 Type::ZoneHandle(Type::SmiType()), | 968 Type::ZoneHandle(Type::SmiType()), |
| 969 is_immutable); | 969 is_immutable); |
| 970 load->set_result_cid(kSmiCid); | 970 load->set_result_cid(kSmiCid); |
| 971 load->set_recognized_kind(kind); | 971 load->set_recognized_kind(kind); |
| 972 call->ReplaceWith(load, current_iterator()); | 972 call->ReplaceWith(load, current_iterator()); |
| 973 RemovePushArguments(call); | 973 RemovePushArguments(call); |
| 974 } | 974 } |
| 975 | 975 |
| 976 | 976 |
| 977 void FlowGraphOptimizer::InlineGArrayCapacityGetter(InstanceCallInstr* call) { | 977 void FlowGraphOptimizer::InlineGrowableArrayCapacityGetter( |
| 978 InstanceCallInstr* call) { |
| 978 // Check receiver class. | 979 // Check receiver class. |
| 979 AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); | 980 AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); |
| 980 | 981 |
| 981 // TODO(srdjan): type of load should be GrowableObjectArrayType. | 982 // TODO(srdjan): type of load should be GrowableObjectArrayType. |
| 982 LoadFieldInstr* data_load = new LoadFieldInstr( | 983 LoadFieldInstr* data_load = new LoadFieldInstr( |
| 983 call->ArgumentAt(0)->value(), | 984 call->ArgumentAt(0)->value(), |
| 984 Array::data_offset(), | 985 Array::data_offset(), |
| 985 Type::ZoneHandle(Type::DynamicType())); | 986 Type::ZoneHandle(Type::DynamicType())); |
| 986 data_load->set_result_cid(kArrayCid); | 987 data_load->set_result_cid(kArrayCid); |
| 987 InsertBefore(call, data_load, NULL, Definition::kValue); | 988 InsertBefore(call, data_load, NULL, Definition::kValue); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 | 1034 |
| 1034 StrictCompareInstr* compare = | 1035 StrictCompareInstr* compare = |
| 1035 new StrictCompareInstr(Token::kEQ_STRICT, | 1036 new StrictCompareInstr(Token::kEQ_STRICT, |
| 1036 new Value(load), | 1037 new Value(load), |
| 1037 new Value(zero)); | 1038 new Value(zero)); |
| 1038 call->ReplaceWith(compare, current_iterator()); | 1039 call->ReplaceWith(compare, current_iterator()); |
| 1039 RemovePushArguments(call); | 1040 RemovePushArguments(call); |
| 1040 } | 1041 } |
| 1041 | 1042 |
| 1042 | 1043 |
| 1044 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) { |
| 1045 switch (kind) { |
| 1046 case MethodRecognizer::kObjectArrayLength: |
| 1047 case MethodRecognizer::kImmutableArrayLength: |
| 1048 return Array::length_offset(); |
| 1049 case MethodRecognizer::kByteArrayBaseLength: |
| 1050 return ByteArray::length_offset(); |
| 1051 case MethodRecognizer::kGrowableArrayLength: |
| 1052 return GrowableObjectArray::length_offset(); |
| 1053 default: |
| 1054 UNREACHABLE(); |
| 1055 return 0; |
| 1056 } |
| 1057 } |
| 1058 |
| 1059 |
| 1043 // Only unique implicit instance getters can be currently handled. | 1060 // Only unique implicit instance getters can be currently handled. |
| 1044 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 1061 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
| 1045 ASSERT(call->HasICData()); | 1062 ASSERT(call->HasICData()); |
| 1046 const ICData& ic_data = *call->ic_data(); | 1063 const ICData& ic_data = *call->ic_data(); |
| 1047 if (ic_data.NumberOfChecks() == 0) { | 1064 if (ic_data.NumberOfChecks() == 0) { |
| 1048 // No type feedback collected. | 1065 // No type feedback collected. |
| 1049 return false; | 1066 return false; |
| 1050 } | 1067 } |
| 1051 Function& target = Function::Handle(ic_data.GetTargetAt(0)); | 1068 Function& target = Function::Handle(ic_data.GetTargetAt(0)); |
| 1052 if (target.kind() == RawFunction::kImplicitGetter) { | 1069 if (target.kind() == RawFunction::kImplicitGetter) { |
| 1053 if (!ic_data.HasOneTarget()) { | 1070 if (!ic_data.HasOneTarget()) { |
| 1054 // TODO(srdjan): Implement for mutiple targets. | 1071 // TODO(srdjan): Implement for mutiple targets. |
| 1055 return false; | 1072 return false; |
| 1056 } | 1073 } |
| 1057 InlineImplicitInstanceGetter(call); | 1074 InlineImplicitInstanceGetter(call); |
| 1058 return true; | 1075 return true; |
| 1059 } | 1076 } |
| 1060 | 1077 |
| 1061 // Not an implicit getter. | 1078 // Not an implicit getter. |
| 1062 MethodRecognizer::Kind recognized_kind = | 1079 MethodRecognizer::Kind recognized_kind = |
| 1063 MethodRecognizer::RecognizeKind(target); | 1080 MethodRecognizer::RecognizeKind(target); |
| 1064 | 1081 |
| 1065 // VM objects length getter. | 1082 // VM objects length getter. |
| 1066 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) || | 1083 switch (recognized_kind) { |
| 1067 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || | 1084 case MethodRecognizer::kObjectArrayLength: |
| 1068 (recognized_kind == MethodRecognizer::kGrowableArrayLength)) { | 1085 case MethodRecognizer::kImmutableArrayLength: |
| 1069 if (!ic_data.HasOneTarget()) { | 1086 case MethodRecognizer::kByteArrayBaseLength: |
| 1070 // TODO(srdjan): Implement for mutiple targets. | 1087 case MethodRecognizer::kGrowableArrayLength: { |
| 1071 return false; | 1088 if (!ic_data.HasOneTarget()) { |
| 1089 // TODO(srdjan): Implement for mutiple targets. |
| 1090 return false; |
| 1091 } |
| 1092 const bool is_immutable = |
| 1093 (recognized_kind != MethodRecognizer::kGrowableArrayLength); |
| 1094 InlineArrayLengthGetter(call, |
| 1095 OffsetForLengthGetter(recognized_kind), |
| 1096 is_immutable, |
| 1097 recognized_kind); |
| 1098 return true; |
| 1072 } | 1099 } |
| 1073 switch (recognized_kind) { | 1100 case MethodRecognizer::kGrowableArrayCapacity: |
| 1074 case MethodRecognizer::kObjectArrayLength: | 1101 InlineGrowableArrayCapacityGetter(call); |
| 1075 case MethodRecognizer::kImmutableArrayLength: | 1102 return true; |
| 1076 InlineArrayLengthGetter(call, | 1103 case MethodRecognizer::kStringBaseLength: |
| 1077 Array::length_offset(), | 1104 if (!ic_data.HasOneTarget()) { |
| 1078 true, | 1105 // Target is not only StringBase_get_length. |
| 1079 recognized_kind); | 1106 return false; |
| 1080 break; | 1107 } |
| 1081 case MethodRecognizer::kGrowableArrayLength: | 1108 InlineStringLengthGetter(call); |
| 1082 InlineArrayLengthGetter(call, | 1109 return true; |
| 1083 GrowableObjectArray::length_offset(), | 1110 case MethodRecognizer::kStringBaseIsEmpty: |
| 1084 false, | 1111 if (!ic_data.HasOneTarget()) { |
| 1085 recognized_kind); | 1112 // Target is not only StringBase_get_isEmpty. |
| 1086 break; | 1113 return false; |
| 1087 default: | 1114 } |
| 1088 UNREACHABLE(); | 1115 InlineStringIsEmptyGetter(call); |
| 1089 } | 1116 return true; |
| 1090 return true; | 1117 default: |
| 1118 ASSERT(recognized_kind == MethodRecognizer::kUnknown); |
| 1091 } | 1119 } |
| 1092 | |
| 1093 if (recognized_kind == MethodRecognizer::kGrowableArrayCapacity) { | |
| 1094 InlineGArrayCapacityGetter(call); | |
| 1095 return true; | |
| 1096 } | |
| 1097 | |
| 1098 if (recognized_kind == MethodRecognizer::kStringBaseLength) { | |
| 1099 if (!ic_data.HasOneTarget()) { | |
| 1100 // Target is not only StringBase_get_length. | |
| 1101 return false; | |
| 1102 } | |
| 1103 InlineStringLengthGetter(call); | |
| 1104 return true; | |
| 1105 } | |
| 1106 | |
| 1107 if (recognized_kind == MethodRecognizer::kStringBaseIsEmpty) { | |
| 1108 if (!ic_data.HasOneTarget()) { | |
| 1109 // Target is not only StringBase_get_isEmpty. | |
| 1110 return false; | |
| 1111 } | |
| 1112 InlineStringIsEmptyGetter(call); | |
| 1113 return true; | |
| 1114 } | |
| 1115 | |
| 1116 return false; | 1120 return false; |
| 1117 } | 1121 } |
| 1118 | 1122 |
| 1119 | 1123 |
| 1120 StringCharCodeAtInstr* FlowGraphOptimizer::BuildStringCharCodeAt( | 1124 StringCharCodeAtInstr* FlowGraphOptimizer::BuildStringCharCodeAt( |
| 1121 InstanceCallInstr* call, | 1125 InstanceCallInstr* call, |
| 1122 intptr_t cid) { | 1126 intptr_t cid) { |
| 1123 Value* str = call->ArgumentAt(0)->value(); | 1127 Value* str = call->ArgumentAt(0)->value(); |
| 1124 Value* index = call->ArgumentAt(1)->value(); | 1128 Value* index = call->ArgumentAt(1)->value(); |
| 1125 AddCheckClass(call, str->Copy()); | 1129 AddCheckClass(call, str->Copy()); |
| (...skipping 3143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4269 | 4273 |
| 4270 if (FLAG_trace_constant_propagation) { | 4274 if (FLAG_trace_constant_propagation) { |
| 4271 OS::Print("\n==== After constant propagation ====\n"); | 4275 OS::Print("\n==== After constant propagation ====\n"); |
| 4272 FlowGraphPrinter printer(*graph_); | 4276 FlowGraphPrinter printer(*graph_); |
| 4273 printer.PrintBlocks(); | 4277 printer.PrintBlocks(); |
| 4274 } | 4278 } |
| 4275 } | 4279 } |
| 4276 | 4280 |
| 4277 | 4281 |
| 4278 } // namespace dart | 4282 } // namespace dart |
| OLD | NEW |