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 |