Chromium Code Reviews| 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/globals.h" // Needed here to get TARGET_ARCH_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
| 6 | 6 |
| 7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
| 8 | 8 |
| 9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
| 10 #include "vm/cha.h" | 10 #include "vm/cha.h" |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 exception_handlers_list_(NULL), | 91 exception_handlers_list_(NULL), |
| 92 pc_descriptors_list_(NULL), | 92 pc_descriptors_list_(NULL), |
| 93 stackmap_table_builder_( | 93 stackmap_table_builder_( |
| 94 is_optimizing ? new StackmapTableBuilder() : NULL), | 94 is_optimizing ? new StackmapTableBuilder() : NULL), |
| 95 block_info_(block_order_.length()), | 95 block_info_(block_order_.length()), |
| 96 deopt_infos_(), | 96 deopt_infos_(), |
| 97 static_calls_target_table_(GrowableObjectArray::ZoneHandle( | 97 static_calls_target_table_(GrowableObjectArray::ZoneHandle( |
| 98 GrowableObjectArray::New())), | 98 GrowableObjectArray::New())), |
| 99 is_optimizing_(is_optimizing), | 99 is_optimizing_(is_optimizing), |
| 100 may_reoptimize_(false), | 100 may_reoptimize_(false), |
| 101 intrinsic_mode_(false), | |
| 101 double_class_(Class::ZoneHandle( | 102 double_class_(Class::ZoneHandle( |
| 102 isolate_->object_store()->double_class())), | 103 isolate_->object_store()->double_class())), |
| 103 mint_class_(Class::ZoneHandle( | 104 mint_class_(Class::ZoneHandle( |
| 104 isolate_->object_store()->mint_class())), | 105 isolate_->object_store()->mint_class())), |
| 105 float32x4_class_(Class::ZoneHandle( | 106 float32x4_class_(Class::ZoneHandle( |
| 106 isolate_->object_store()->float32x4_class())), | 107 isolate_->object_store()->float32x4_class())), |
| 107 float64x2_class_(Class::ZoneHandle( | 108 float64x2_class_(Class::ZoneHandle( |
| 108 isolate_->object_store()->float64x2_class())), | 109 isolate_->object_store()->float64x2_class())), |
| 109 int32x4_class_(Class::ZoneHandle( | 110 int32x4_class_(Class::ZoneHandle( |
| 110 isolate_->object_store()->int32x4_class())), | 111 isolate_->object_store()->int32x4_class())), |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 540 ASSERT(Code::kSCallTableFunctionEntry == 1); | 541 ASSERT(Code::kSCallTableFunctionEntry == 1); |
| 541 static_calls_target_table_.Add(func); | 542 static_calls_target_table_.Add(func); |
| 542 ASSERT(Code::kSCallTableCodeEntry == 2); | 543 ASSERT(Code::kSCallTableCodeEntry == 2); |
| 543 static_calls_target_table_.Add(Code::Handle()); | 544 static_calls_target_table_.Add(Code::Handle()); |
| 544 } | 545 } |
| 545 | 546 |
| 546 | 547 |
| 547 void FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id, | 548 void FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id, |
| 548 intptr_t token_pos) { | 549 intptr_t token_pos) { |
| 549 ASSERT(is_optimizing()); | 550 ASSERT(is_optimizing()); |
| 551 ASSERT(!intrinsic_mode()); | |
| 550 CompilerDeoptInfo* info = | 552 CompilerDeoptInfo* info = |
| 551 new CompilerDeoptInfo(deopt_id, | 553 new CompilerDeoptInfo(deopt_id, |
| 552 ICData::kDeoptAtCall, | 554 ICData::kDeoptAtCall, |
| 553 pending_deoptimization_env_); | 555 pending_deoptimization_env_); |
| 554 info->set_pc_offset(assembler()->CodeSize()); | 556 info->set_pc_offset(assembler()->CodeSize()); |
| 555 deopt_infos_.Add(info); | 557 deopt_infos_.Add(info); |
| 556 } | 558 } |
| 557 | 559 |
| 558 | 560 |
| 559 // This function must be in sync with FlowGraphCompiler::SaveLiveRegisters | 561 // This function must be in sync with FlowGraphCompiler::SaveLiveRegisters |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 720 cpu_reg_slots); | 722 cpu_reg_slots); |
| 721 } | 723 } |
| 722 } | 724 } |
| 723 } | 725 } |
| 724 return env; | 726 return env; |
| 725 } | 727 } |
| 726 | 728 |
| 727 | 729 |
| 728 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, | 730 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, |
| 729 ICData::DeoptReasonId reason) { | 731 ICData::DeoptReasonId reason) { |
| 732 if (intrinsic_mode()) return &intrinsic_deopt_label_; | |
|
srdjan
2014/09/02 18:48:21
This feels fragile as we must guaranteed that the
Florian Schneider
2014/09/02 21:03:20
Can you elaborate? There is only one instance of F
srdjan
2014/09/08 17:34:06
I was mainly worried that the lifetime of a FlowGr
| |
| 733 | |
| 730 ASSERT(is_optimizing_); | 734 ASSERT(is_optimizing_); |
| 731 CompilerDeoptInfoWithStub* stub = | 735 CompilerDeoptInfoWithStub* stub = |
| 732 new CompilerDeoptInfoWithStub(deopt_id, | 736 new CompilerDeoptInfoWithStub(deopt_id, |
| 733 reason, | 737 reason, |
| 734 pending_deoptimization_env_); | 738 pending_deoptimization_env_); |
| 735 deopt_infos_.Add(stub); | 739 deopt_infos_.Add(stub); |
| 736 return stub->entry_label(); | 740 return stub->entry_label(); |
| 737 } | 741 } |
| 738 | 742 |
| 739 | 743 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 848 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); | 852 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); |
| 849 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); | 853 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); |
| 850 const StoreInstanceFieldNode& store_node = | 854 const StoreInstanceFieldNode& store_node = |
| 851 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); | 855 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); |
| 852 if (store_node.field().guarded_cid() == kDynamicCid) { | 856 if (store_node.field().guarded_cid() == kDynamicCid) { |
| 853 GenerateInlinedSetter(store_node.field().Offset()); | 857 GenerateInlinedSetter(store_node.field().Offset()); |
| 854 return; | 858 return; |
| 855 } | 859 } |
| 856 } | 860 } |
| 857 } | 861 } |
| 858 // Even if an intrinsified version of the function was successfully | 862 |
| 859 // generated, it may fall through to the non-intrinsified method body. | 863 EnterIntrinsicMode(); |
| 860 Intrinsifier::Intrinsify(parsed_function().function(), assembler()); | 864 |
| 865 Intrinsifier::Intrinsify(parsed_function(), this); | |
| 866 | |
| 867 ExitIntrinsicMode(); | |
| 868 // "Deoptimization" from intrinsic continues here. | |
|
srdjan
2014/09/02 18:48:21
We do not deoptimize, this is actually the slow-pa
Florian Schneider
2014/09/02 21:03:20
That's why it's in quotes. Intrinsic code uses the
| |
| 869 ASSERT(!intrinsic_deopt_label_.IsBound()); | |
| 870 assembler()->Bind(&intrinsic_deopt_label_); | |
| 861 } | 871 } |
| 862 | 872 |
| 863 | 873 |
| 864 void FlowGraphCompiler::GenerateInstanceCall( | 874 void FlowGraphCompiler::GenerateInstanceCall( |
| 865 intptr_t deopt_id, | 875 intptr_t deopt_id, |
| 866 intptr_t token_pos, | 876 intptr_t token_pos, |
| 867 intptr_t argument_count, | 877 intptr_t argument_count, |
| 868 LocationSummary* locs, | 878 LocationSummary* locs, |
| 869 const ICData& ic_data) { | 879 const ICData& ic_data) { |
| 870 ASSERT(!ic_data.IsNull()); | 880 ASSERT(!ic_data.IsNull()); |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1283 return true; | 1293 return true; |
| 1284 } | 1294 } |
| 1285 } | 1295 } |
| 1286 | 1296 |
| 1287 return false; | 1297 return false; |
| 1288 } | 1298 } |
| 1289 | 1299 |
| 1290 | 1300 |
| 1291 intptr_t ParallelMoveResolver::AllocateScratchRegister( | 1301 intptr_t ParallelMoveResolver::AllocateScratchRegister( |
| 1292 Location::Kind kind, | 1302 Location::Kind kind, |
| 1293 intptr_t blocked, | 1303 uword blocked_mask, |
| 1294 intptr_t first_free_register, | 1304 intptr_t first_free_register, |
| 1295 intptr_t last_free_register, | 1305 intptr_t last_free_register, |
| 1296 bool* spilled) { | 1306 bool* spilled) { |
| 1307 COMPILE_ASSERT(static_cast<intptr_t>(sizeof(blocked_mask)) * kBitsPerByte >= | |
| 1308 kNumberOfFpuRegisters); | |
| 1309 COMPILE_ASSERT(static_cast<intptr_t>(sizeof(blocked_mask)) * kBitsPerByte >= | |
| 1310 kNumberOfCpuRegisters); | |
| 1297 intptr_t scratch = -1; | 1311 intptr_t scratch = -1; |
| 1298 for (intptr_t reg = first_free_register; reg <= last_free_register; reg++) { | 1312 for (intptr_t reg = first_free_register; reg <= last_free_register; reg++) { |
| 1299 if ((blocked != reg) && | 1313 if ((((1u << reg) & blocked_mask) == 0) && |
| 1300 IsScratchLocation(Location::MachineRegisterLocation(kind, reg))) { | 1314 IsScratchLocation(Location::MachineRegisterLocation(kind, reg))) { |
| 1301 scratch = reg; | 1315 scratch = reg; |
| 1302 break; | 1316 break; |
| 1303 } | 1317 } |
| 1304 } | 1318 } |
| 1305 | 1319 |
| 1306 if (scratch == -1) { | 1320 if (scratch == -1) { |
| 1307 *spilled = true; | 1321 *spilled = true; |
| 1308 for (intptr_t reg = first_free_register; reg <= last_free_register; reg++) { | 1322 for (intptr_t reg = first_free_register; reg <= last_free_register; reg++) { |
| 1309 if (blocked != reg) { | 1323 if (((1u << reg) & blocked_mask) == 0) { |
| 1310 scratch = reg; | 1324 scratch = reg; |
| 1311 break; | 1325 break; |
| 1312 } | 1326 } |
| 1313 } | 1327 } |
| 1314 } else { | 1328 } else { |
| 1315 *spilled = false; | 1329 *spilled = false; |
| 1316 } | 1330 } |
| 1317 | 1331 |
| 1318 return scratch; | 1332 return scratch; |
| 1319 } | 1333 } |
| 1320 | 1334 |
| 1321 | 1335 |
| 1322 ParallelMoveResolver::ScratchFpuRegisterScope::ScratchFpuRegisterScope( | 1336 ParallelMoveResolver::ScratchFpuRegisterScope::ScratchFpuRegisterScope( |
| 1323 ParallelMoveResolver* resolver, FpuRegister blocked) | 1337 ParallelMoveResolver* resolver, FpuRegister blocked) |
| 1324 : resolver_(resolver), | 1338 : resolver_(resolver), |
| 1325 reg_(kNoFpuRegister), | 1339 reg_(kNoFpuRegister), |
| 1326 spilled_(false) { | 1340 spilled_(false) { |
| 1327 reg_ = static_cast<FpuRegister>( | 1341 reg_ = static_cast<FpuRegister>( |
| 1328 resolver_->AllocateScratchRegister(Location::kFpuRegister, | 1342 resolver_->AllocateScratchRegister(Location::kFpuRegister, |
| 1329 blocked, | 1343 1u << blocked, |
| 1330 0, | 1344 0, |
| 1331 kNumberOfFpuRegisters - 1, | 1345 kNumberOfFpuRegisters - 1, |
| 1332 &spilled_)); | 1346 &spilled_)); |
| 1333 | 1347 |
| 1334 if (spilled_) { | 1348 if (spilled_) { |
| 1335 resolver->SpillFpuScratch(reg_); | 1349 resolver->SpillFpuScratch(reg_); |
| 1336 } | 1350 } |
| 1337 } | 1351 } |
| 1338 | 1352 |
| 1339 | 1353 |
| 1340 ParallelMoveResolver::ScratchFpuRegisterScope::~ScratchFpuRegisterScope() { | 1354 ParallelMoveResolver::ScratchFpuRegisterScope::~ScratchFpuRegisterScope() { |
| 1341 if (spilled_) { | 1355 if (spilled_) { |
| 1342 resolver_->RestoreFpuScratch(reg_); | 1356 resolver_->RestoreFpuScratch(reg_); |
| 1343 } | 1357 } |
| 1344 } | 1358 } |
| 1345 | 1359 |
| 1346 | 1360 |
| 1347 ParallelMoveResolver::ScratchRegisterScope::ScratchRegisterScope( | 1361 ParallelMoveResolver::ScratchRegisterScope::ScratchRegisterScope( |
| 1348 ParallelMoveResolver* resolver, Register blocked) | 1362 ParallelMoveResolver* resolver, Register blocked) |
| 1349 : resolver_(resolver), | 1363 : resolver_(resolver), |
| 1350 reg_(kNoRegister), | 1364 reg_(kNoRegister), |
| 1351 spilled_(false) { | 1365 spilled_(false) { |
| 1366 uword blocked_mask = 1u << blocked; | |
| 1367 if (resolver->compiler_->intrinsic_mode()) { | |
| 1368 // Block additional registers that must be preserved for intrinsics. | |
| 1369 blocked_mask |= 1u << ICREG; | |
| 1370 blocked_mask |= 1u << ARGS_DESC_REG; | |
| 1371 } | |
| 1352 reg_ = static_cast<Register>( | 1372 reg_ = static_cast<Register>( |
| 1353 resolver_->AllocateScratchRegister(Location::kRegister, | 1373 resolver_->AllocateScratchRegister(Location::kRegister, |
| 1354 blocked, | 1374 1u << blocked, |
| 1355 kFirstFreeCpuRegister, | 1375 kFirstFreeCpuRegister, |
| 1356 kLastFreeCpuRegister, | 1376 kLastFreeCpuRegister, |
| 1357 &spilled_)); | 1377 &spilled_)); |
| 1358 | 1378 |
| 1359 if (spilled_) { | 1379 if (spilled_) { |
| 1360 resolver->SpillScratch(reg_); | 1380 resolver->SpillScratch(reg_); |
| 1361 } | 1381 } |
| 1362 } | 1382 } |
| 1363 | 1383 |
| 1364 | 1384 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1445 threshold = FLAG_optimization_counter_scale * basic_blocks + | 1465 threshold = FLAG_optimization_counter_scale * basic_blocks + |
| 1446 FLAG_min_optimization_counter_threshold; | 1466 FLAG_min_optimization_counter_threshold; |
| 1447 if (threshold > FLAG_optimization_counter_threshold) { | 1467 if (threshold > FLAG_optimization_counter_threshold) { |
| 1448 threshold = FLAG_optimization_counter_threshold; | 1468 threshold = FLAG_optimization_counter_threshold; |
| 1449 } | 1469 } |
| 1450 } | 1470 } |
| 1451 return threshold; | 1471 return threshold; |
| 1452 } | 1472 } |
| 1453 | 1473 |
| 1454 } // namespace dart | 1474 } // namespace dart |
| OLD | NEW |