| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), | 1296 *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(), |
| 1297 call->GetBlock()->try_index()); | 1297 call->GetBlock()->try_index()); |
| 1298 (*entry)->InheritDeoptTarget(Z, call); | 1298 (*entry)->InheritDeoptTarget(Z, call); |
| 1299 Instruction* cursor = *entry; | 1299 Instruction* cursor = *entry; |
| 1300 if (I->flags().type_checks()) { | 1300 if (I->flags().type_checks()) { |
| 1301 // Only type check for the value. A type check for the index is not | 1301 // Only type check for the value. A type check for the index is not |
| 1302 // needed here because we insert a deoptimizing smi-check for the case | 1302 // needed here because we insert a deoptimizing smi-check for the case |
| 1303 // the index is not a smi. | 1303 // the index is not a smi. |
| 1304 const AbstractType& value_type = | 1304 const AbstractType& value_type = |
| 1305 AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2)); | 1305 AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2)); |
| 1306 Definition* instantiator = NULL; | |
| 1307 Definition* type_args = NULL; | 1306 Definition* type_args = NULL; |
| 1308 switch (array_cid) { | 1307 switch (array_cid) { |
| 1309 case kArrayCid: | 1308 case kArrayCid: |
| 1310 case kGrowableObjectArrayCid: { | 1309 case kGrowableObjectArrayCid: { |
| 1311 const Class& instantiator_class = Class::Handle(Z, target.Owner()); | 1310 const Class& instantiator_class = Class::Handle(Z, target.Owner()); |
| 1312 intptr_t type_arguments_field_offset = | 1311 intptr_t type_arguments_field_offset = |
| 1313 instantiator_class.type_arguments_field_offset(); | 1312 instantiator_class.type_arguments_field_offset(); |
| 1314 LoadFieldInstr* load_type_args = | 1313 LoadFieldInstr* load_type_args = |
| 1315 new(Z) LoadFieldInstr(new(Z) Value(array), | 1314 new(Z) LoadFieldInstr(new(Z) Value(array), |
| 1316 type_arguments_field_offset, | 1315 type_arguments_field_offset, |
| 1317 Type::ZoneHandle(Z), // No type. | 1316 Type::ZoneHandle(Z), // No type. |
| 1318 call->token_pos()); | 1317 call->token_pos()); |
| 1319 cursor = flow_graph()->AppendTo(cursor, | 1318 cursor = flow_graph()->AppendTo(cursor, |
| 1320 load_type_args, | 1319 load_type_args, |
| 1321 NULL, | 1320 NULL, |
| 1322 FlowGraph::kValue); | 1321 FlowGraph::kValue); |
| 1323 | 1322 |
| 1324 instantiator = array; | |
| 1325 type_args = load_type_args; | 1323 type_args = load_type_args; |
| 1326 break; | 1324 break; |
| 1327 } | 1325 } |
| 1328 case kTypedDataInt8ArrayCid: | 1326 case kTypedDataInt8ArrayCid: |
| 1329 case kTypedDataUint8ArrayCid: | 1327 case kTypedDataUint8ArrayCid: |
| 1330 case kTypedDataUint8ClampedArrayCid: | 1328 case kTypedDataUint8ClampedArrayCid: |
| 1331 case kExternalTypedDataUint8ArrayCid: | 1329 case kExternalTypedDataUint8ArrayCid: |
| 1332 case kExternalTypedDataUint8ClampedArrayCid: | 1330 case kExternalTypedDataUint8ClampedArrayCid: |
| 1333 case kTypedDataInt16ArrayCid: | 1331 case kTypedDataInt16ArrayCid: |
| 1334 case kTypedDataUint16ArrayCid: | 1332 case kTypedDataUint16ArrayCid: |
| 1335 case kTypedDataInt32ArrayCid: | 1333 case kTypedDataInt32ArrayCid: |
| 1336 case kTypedDataUint32ArrayCid: | 1334 case kTypedDataUint32ArrayCid: |
| 1337 case kTypedDataInt64ArrayCid: | 1335 case kTypedDataInt64ArrayCid: |
| 1338 ASSERT(value_type.IsIntType()); | 1336 ASSERT(value_type.IsIntType()); |
| 1339 // Fall through. | 1337 // Fall through. |
| 1340 case kTypedDataFloat32ArrayCid: | 1338 case kTypedDataFloat32ArrayCid: |
| 1341 case kTypedDataFloat64ArrayCid: { | 1339 case kTypedDataFloat64ArrayCid: { |
| 1342 type_args = instantiator = flow_graph_->constant_null(); | 1340 type_args = flow_graph_->constant_null(); |
| 1343 ASSERT((array_cid != kTypedDataFloat32ArrayCid && | 1341 ASSERT((array_cid != kTypedDataFloat32ArrayCid && |
| 1344 array_cid != kTypedDataFloat64ArrayCid) || | 1342 array_cid != kTypedDataFloat64ArrayCid) || |
| 1345 value_type.IsDoubleType()); | 1343 value_type.IsDoubleType()); |
| 1346 ASSERT(value_type.IsInstantiated()); | 1344 ASSERT(value_type.IsInstantiated()); |
| 1347 break; | 1345 break; |
| 1348 } | 1346 } |
| 1349 case kTypedDataFloat32x4ArrayCid: { | 1347 case kTypedDataFloat32x4ArrayCid: { |
| 1350 type_args = instantiator = flow_graph_->constant_null(); | 1348 type_args = flow_graph_->constant_null(); |
| 1351 ASSERT((array_cid != kTypedDataFloat32x4ArrayCid) || | 1349 ASSERT((array_cid != kTypedDataFloat32x4ArrayCid) || |
| 1352 value_type.IsFloat32x4Type()); | 1350 value_type.IsFloat32x4Type()); |
| 1353 ASSERT(value_type.IsInstantiated()); | 1351 ASSERT(value_type.IsInstantiated()); |
| 1354 break; | 1352 break; |
| 1355 } | 1353 } |
| 1356 case kTypedDataFloat64x2ArrayCid: { | 1354 case kTypedDataFloat64x2ArrayCid: { |
| 1357 type_args = instantiator = flow_graph_->constant_null(); | 1355 type_args = flow_graph_->constant_null(); |
| 1358 ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) || | 1356 ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) || |
| 1359 value_type.IsFloat64x2Type()); | 1357 value_type.IsFloat64x2Type()); |
| 1360 ASSERT(value_type.IsInstantiated()); | 1358 ASSERT(value_type.IsInstantiated()); |
| 1361 break; | 1359 break; |
| 1362 } | 1360 } |
| 1363 default: | 1361 default: |
| 1364 // TODO(fschneider): Add support for other array types. | 1362 // TODO(fschneider): Add support for other array types. |
| 1365 UNREACHABLE(); | 1363 UNREACHABLE(); |
| 1366 } | 1364 } |
| 1367 AssertAssignableInstr* assert_value = | 1365 AssertAssignableInstr* assert_value = |
| 1368 new(Z) AssertAssignableInstr(token_pos, | 1366 new(Z) AssertAssignableInstr(token_pos, |
| 1369 new(Z) Value(stored_value), | 1367 new(Z) Value(stored_value), |
| 1370 new(Z) Value(instantiator), | |
| 1371 new(Z) Value(type_args), | 1368 new(Z) Value(type_args), |
| 1372 value_type, | 1369 value_type, |
| 1373 Symbols::Value(), | 1370 Symbols::Value(), |
| 1374 call->deopt_id()); | 1371 call->deopt_id()); |
| 1375 cursor = flow_graph()->AppendTo(cursor, | 1372 cursor = flow_graph()->AppendTo(cursor, |
| 1376 assert_value, | 1373 assert_value, |
| 1377 call->env(), | 1374 call->env(), |
| 1378 FlowGraph::kValue); | 1375 FlowGraph::kValue); |
| 1379 } | 1376 } |
| 1380 | 1377 |
| (...skipping 2663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4044 } | 4041 } |
| 4045 | 4042 |
| 4046 return true; // May deoptimize since we have not identified all 'true' tests. | 4043 return true; // May deoptimize since we have not identified all 'true' tests. |
| 4047 } | 4044 } |
| 4048 | 4045 |
| 4049 | 4046 |
| 4050 // TODO(srdjan): Use ICData to check if always true or false. | 4047 // TODO(srdjan): Use ICData to check if always true or false. |
| 4051 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 4048 void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
| 4052 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 4049 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
| 4053 Definition* left = call->ArgumentAt(0); | 4050 Definition* left = call->ArgumentAt(0); |
| 4054 Definition* instantiator = NULL; | |
| 4055 Definition* type_args = NULL; | 4051 Definition* type_args = NULL; |
| 4056 AbstractType& type = AbstractType::ZoneHandle(Z); | 4052 AbstractType& type = AbstractType::ZoneHandle(Z); |
| 4057 bool negate = false; | 4053 bool negate = false; |
| 4058 if (call->ArgumentCount() == 2) { | 4054 if (call->ArgumentCount() == 2) { |
| 4059 instantiator = flow_graph()->constant_null(); | |
| 4060 type_args = flow_graph()->constant_null(); | 4055 type_args = flow_graph()->constant_null(); |
| 4061 if (call->function_name().raw() == | 4056 if (call->function_name().raw() == |
| 4062 Library::PrivateCoreLibName(Symbols::_instanceOfNum()).raw()) { | 4057 Library::PrivateCoreLibName(Symbols::_instanceOfNum()).raw()) { |
| 4063 type = Type::Number(); | 4058 type = Type::Number(); |
| 4064 } else if (call->function_name().raw() == | 4059 } else if (call->function_name().raw() == |
| 4065 Library::PrivateCoreLibName(Symbols::_instanceOfInt()).raw()) { | 4060 Library::PrivateCoreLibName(Symbols::_instanceOfInt()).raw()) { |
| 4066 type = Type::IntType(); | 4061 type = Type::IntType(); |
| 4067 } else if (call->function_name().raw() == | 4062 } else if (call->function_name().raw() == |
| 4068 Library::PrivateCoreLibName(Symbols::_instanceOfSmi()).raw()) { | 4063 Library::PrivateCoreLibName(Symbols::_instanceOfSmi()).raw()) { |
| 4069 type = Type::SmiType(); | 4064 type = Type::SmiType(); |
| 4070 } else if (call->function_name().raw() == | 4065 } else if (call->function_name().raw() == |
| 4071 Library::PrivateCoreLibName(Symbols::_instanceOfDouble()).raw()) { | 4066 Library::PrivateCoreLibName(Symbols::_instanceOfDouble()).raw()) { |
| 4072 type = Type::Double(); | 4067 type = Type::Double(); |
| 4073 } else if (call->function_name().raw() == | 4068 } else if (call->function_name().raw() == |
| 4074 Library::PrivateCoreLibName(Symbols::_instanceOfString()).raw()) { | 4069 Library::PrivateCoreLibName(Symbols::_instanceOfString()).raw()) { |
| 4075 type = Type::StringType(); | 4070 type = Type::StringType(); |
| 4076 } else { | 4071 } else { |
| 4077 UNIMPLEMENTED(); | 4072 UNIMPLEMENTED(); |
| 4078 } | 4073 } |
| 4079 negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition() | 4074 negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition() |
| 4080 ->AsConstant()->value()).value(); | 4075 ->AsConstant()->value()).value(); |
| 4081 } else { | 4076 } else { |
| 4082 instantiator = call->ArgumentAt(1); | 4077 type_args = call->ArgumentAt(1); |
| 4083 type_args = call->ArgumentAt(2); | 4078 type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw(); |
| 4084 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw(); | 4079 negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition() |
| 4085 negate = Bool::Cast(call->ArgumentAt(4)->OriginalDefinition() | |
| 4086 ->AsConstant()->value()).value(); | 4080 ->AsConstant()->value()).value(); |
| 4087 } | 4081 } |
| 4088 const ICData& unary_checks = | 4082 const ICData& unary_checks = |
| 4089 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 4083 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 4090 if (FLAG_warn_on_javascript_compatibility && | 4084 if (FLAG_warn_on_javascript_compatibility && |
| 4091 !unary_checks.IssuedJSWarning() && | 4085 !unary_checks.IssuedJSWarning() && |
| 4092 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | 4086 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
| 4093 // No warning was reported yet for this type check, either because it has | 4087 // No warning was reported yet for this type check, either because it has |
| 4094 // not been executed yet, or because no problematic combinations of instance | 4088 // not been executed yet, or because no problematic combinations of instance |
| 4095 // type and test type have been encountered so far. A warning may still be | 4089 // type and test type have been encountered so far. A warning may still be |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4152 new(Z) Value(left_cid), | 4146 new(Z) Value(left_cid), |
| 4153 new(Z) Value(cid), | 4147 new(Z) Value(cid), |
| 4154 false); // No number check. | 4148 false); // No number check. |
| 4155 ReplaceCall(call, check_cid); | 4149 ReplaceCall(call, check_cid); |
| 4156 return; | 4150 return; |
| 4157 } | 4151 } |
| 4158 | 4152 |
| 4159 InstanceOfInstr* instance_of = | 4153 InstanceOfInstr* instance_of = |
| 4160 new(Z) InstanceOfInstr(call->token_pos(), | 4154 new(Z) InstanceOfInstr(call->token_pos(), |
| 4161 new(Z) Value(left), | 4155 new(Z) Value(left), |
| 4162 new(Z) Value(instantiator), | |
| 4163 new(Z) Value(type_args), | 4156 new(Z) Value(type_args), |
| 4164 type, | 4157 type, |
| 4165 negate, | 4158 negate, |
| 4166 call->deopt_id()); | 4159 call->deopt_id()); |
| 4167 ReplaceCall(call, instance_of); | 4160 ReplaceCall(call, instance_of); |
| 4168 } | 4161 } |
| 4169 | 4162 |
| 4170 | 4163 |
| 4171 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). | 4164 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). |
| 4172 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 4165 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
| 4173 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 4166 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
| 4174 Definition* left = call->ArgumentAt(0); | 4167 Definition* left = call->ArgumentAt(0); |
| 4175 Definition* instantiator = call->ArgumentAt(1); | 4168 Definition* type_args = call->ArgumentAt(1); |
| 4176 Definition* type_args = call->ArgumentAt(2); | |
| 4177 const AbstractType& type = | 4169 const AbstractType& type = |
| 4178 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); | 4170 AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()); |
| 4179 ASSERT(!type.IsMalformedOrMalbounded()); | 4171 ASSERT(!type.IsMalformedOrMalbounded()); |
| 4180 const ICData& unary_checks = | 4172 const ICData& unary_checks = |
| 4181 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 4173 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 4182 if (FLAG_warn_on_javascript_compatibility && | 4174 if (FLAG_warn_on_javascript_compatibility && |
| 4183 !unary_checks.IssuedJSWarning() && | 4175 !unary_checks.IssuedJSWarning() && |
| 4184 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | 4176 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
| 4185 // No warning was reported yet for this type check, either because it has | 4177 // No warning was reported yet for this type check, either because it has |
| 4186 // not been executed yet, or because no problematic combinations of instance | 4178 // not been executed yet, or because no problematic combinations of instance |
| 4187 // type and test type have been encountered so far. A warning may still be | 4179 // type and test type have been encountered so far. A warning may still be |
| 4188 // reported, so do not replace the instance call. | 4180 // reported, so do not replace the instance call. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4207 ASSERT(current_iterator()->Current() == call); | 4199 ASSERT(current_iterator()->Current() == call); |
| 4208 current_iterator()->RemoveCurrentFromGraph(); | 4200 current_iterator()->RemoveCurrentFromGraph(); |
| 4209 return; | 4201 return; |
| 4210 } | 4202 } |
| 4211 } | 4203 } |
| 4212 const String& dst_name = String::ZoneHandle(Z, | 4204 const String& dst_name = String::ZoneHandle(Z, |
| 4213 Symbols::New(Exceptions::kCastErrorDstName)); | 4205 Symbols::New(Exceptions::kCastErrorDstName)); |
| 4214 AssertAssignableInstr* assert_as = | 4206 AssertAssignableInstr* assert_as = |
| 4215 new(Z) AssertAssignableInstr(call->token_pos(), | 4207 new(Z) AssertAssignableInstr(call->token_pos(), |
| 4216 new(Z) Value(left), | 4208 new(Z) Value(left), |
| 4217 new(Z) Value(instantiator), | |
| 4218 new(Z) Value(type_args), | 4209 new(Z) Value(type_args), |
| 4219 type, | 4210 type, |
| 4220 dst_name, | 4211 dst_name, |
| 4221 call->deopt_id()); | 4212 call->deopt_id()); |
| 4222 ReplaceCall(call, assert_as); | 4213 ReplaceCall(call, assert_as); |
| 4223 } | 4214 } |
| 4224 | 4215 |
| 4225 | 4216 |
| 4226 bool FlowGraphOptimizer::IsBlackListedForInlining(intptr_t call_deopt_id) { | 4217 bool FlowGraphOptimizer::IsBlackListedForInlining(intptr_t call_deopt_id) { |
| 4227 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) { | 4218 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) { |
| (...skipping 4626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8854 | 8845 |
| 8855 // Insert materializations at environment uses. | 8846 // Insert materializations at environment uses. |
| 8856 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8847 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8857 CreateMaterializationAt( | 8848 CreateMaterializationAt( |
| 8858 exits_collector_.exits()[i], alloc, *slots); | 8849 exits_collector_.exits()[i], alloc, *slots); |
| 8859 } | 8850 } |
| 8860 } | 8851 } |
| 8861 | 8852 |
| 8862 | 8853 |
| 8863 } // namespace dart | 8854 } // namespace dart |
| OLD | NEW |