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/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/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 return true; | 68 return true; |
| 69 #else | 69 #else |
| 70 // ARM does not have a short instruction sequence for converting int64 to | 70 // ARM does not have a short instruction sequence for converting int64 to |
| 71 // double. | 71 // double. |
| 72 // TODO(johnmccutchan): Investigate possibility on MIPS once | 72 // TODO(johnmccutchan): Investigate possibility on MIPS once |
| 73 // mints are implemented there. | 73 // mints are implemented there. |
| 74 return false; | 74 return false; |
| 75 #endif | 75 #endif |
| 76 } | 76 } |
| 77 | 77 |
| 78 | |
| 79 static bool CanConvertUnboxedInt32ToDouble() { | |
| 80 #if defined(TARGET_ARCH_IA32) | |
| 81 return true; | |
| 82 #elif defined(TARGET_ARCH_ARM) | |
| 83 return true; | |
| 84 #elif defined(TARGET_ARCH_X64) | |
| 85 return true; | |
| 86 #else | |
| 87 return false; | |
|
Vyacheslav Egorov (Google)
2014/10/02 17:14:04
How hard it is to support Int32ToDouble() on MIPS
Cutch
2014/10/02 22:41:12
Done.
| |
| 88 #endif | |
| 89 } | |
| 90 | |
| 91 | |
| 78 // Optimize instance calls using ICData. | 92 // Optimize instance calls using ICData. |
| 79 void FlowGraphOptimizer::ApplyICData() { | 93 void FlowGraphOptimizer::ApplyICData() { |
| 80 VisitBlocks(); | 94 VisitBlocks(); |
| 81 } | 95 } |
| 82 | 96 |
| 83 | 97 |
| 84 // Optimize instance calls using cid. This is called after optimizer | 98 // Optimize instance calls using cid. This is called after optimizer |
| 85 // converted instance calls to instructions. Any remaining | 99 // converted instance calls to instructions. Any remaining |
| 86 // instance calls are either megamorphic calls, cannot be optimized or | 100 // instance calls are either megamorphic calls, cannot be optimized or |
| 87 // have no runtime type feedback collected. | 101 // have no runtime type feedback collected. |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 | 635 |
| 622 Definition* converted = NULL; | 636 Definition* converted = NULL; |
| 623 if ((from == kTagged) && (to == kUnboxedMint)) { | 637 if ((from == kTagged) && (to == kUnboxedMint)) { |
| 624 ASSERT((deopt_target != NULL) || | 638 ASSERT((deopt_target != NULL) || |
| 625 (use->Type()->ToCid() == kUnboxedMint)); | 639 (use->Type()->ToCid() == kUnboxedMint)); |
| 626 const intptr_t deopt_id = (deopt_target != NULL) ? | 640 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 627 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 641 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 628 converted = new(I) UnboxIntegerInstr(use->CopyWithType(), deopt_id); | 642 converted = new(I) UnboxIntegerInstr(use->CopyWithType(), deopt_id); |
| 629 } else if ((from == kUnboxedMint) && (to == kTagged)) { | 643 } else if ((from == kUnboxedMint) && (to == kTagged)) { |
| 630 converted = new(I) BoxIntegerInstr(use->CopyWithType()); | 644 converted = new(I) BoxIntegerInstr(use->CopyWithType()); |
| 645 } else if ((from == kUnboxedUint32) && (to == kTagged)) { | |
| 646 converted = new(I) BoxUint32Instr(use->CopyWithType()); | |
| 631 } else if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) { | 647 } else if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) { |
| 632 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) ? | 648 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) ? |
| 633 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 649 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 634 converted = new(I) UnboxedIntConverterInstr(from, | 650 converted = new(I) UnboxedIntConverterInstr(from, |
| 635 to, | 651 to, |
| 636 use->CopyWithType(), | 652 use->CopyWithType(), |
| 637 deopt_id); | 653 deopt_id); |
| 638 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) { | 654 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) { |
| 639 converted = new Int32ToDoubleInstr(use->CopyWithType()); | 655 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 656 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | |
| 657 if (CanConvertUnboxedInt32ToDouble()) { | |
| 658 converted = new Int32ToDoubleInstr(use->CopyWithType()); | |
| 659 } else { | |
| 660 BoxInt32Instr* boxed = new(I) BoxInt32Instr(use->CopyWithType()); | |
| 661 use->BindTo(boxed); | |
| 662 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); | |
| 663 converted = new(I) UnboxDoubleInstr(new(I) Value(boxed), deopt_id); | |
| 664 } | |
| 640 } else if ((from == kTagged) && (to == kUnboxedInt32)) { | 665 } else if ((from == kTagged) && (to == kUnboxedInt32)) { |
| 641 const intptr_t deopt_id = (deopt_target != NULL) ? | 666 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 642 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 667 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 643 converted = new UnboxInt32Instr(use->CopyWithType(), deopt_id); | 668 converted = new UnboxInt32Instr(use->CopyWithType(), deopt_id); |
| 644 } else if ((from == kUnboxedInt32) && (to == kTagged)) { | 669 } else if ((from == kUnboxedInt32) && (to == kTagged)) { |
| 645 converted = new BoxInt32Instr(use->CopyWithType()); | 670 converted = new BoxInt32Instr(use->CopyWithType()); |
| 646 } else if ((from == kTagged) && (to == kUnboxedUint32)) { | 671 } else if ((from == kTagged) && (to == kUnboxedUint32)) { |
| 647 const intptr_t deopt_id = (deopt_target != NULL) ? | 672 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 648 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 673 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 649 converted = new UnboxUint32Instr(use->CopyWithType(), deopt_id); | 674 converted = new UnboxUint32Instr(use->CopyWithType(), deopt_id); |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1348 &array, | 1373 &array, |
| 1349 index, | 1374 index, |
| 1350 &cursor); | 1375 &cursor); |
| 1351 | 1376 |
| 1352 // Check if store barrier is needed. Byte arrays don't need a store barrier. | 1377 // Check if store barrier is needed. Byte arrays don't need a store barrier. |
| 1353 StoreBarrierType needs_store_barrier = | 1378 StoreBarrierType needs_store_barrier = |
| 1354 (RawObject::IsTypedDataClassId(array_cid) || | 1379 (RawObject::IsTypedDataClassId(array_cid) || |
| 1355 RawObject::IsTypedDataViewClassId(array_cid) || | 1380 RawObject::IsTypedDataViewClassId(array_cid) || |
| 1356 RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier | 1381 RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier |
| 1357 : kEmitStoreBarrier; | 1382 : kEmitStoreBarrier; |
| 1358 if (!value_check.IsNull()) { | 1383 |
| 1384 // If the stored value is an integer that is already unboxed as | |
| 1385 // the StoreIndexedInstr expects, skip the class check. | |
| 1386 bool is_already_unboxed = | |
| 1387 ((array_cid == kTypedDataInt32ArrayCid) && | |
| 1388 (stored_value->representation() == kUnboxedInt32)) || | |
| 1389 ((array_cid == kTypedDataUint32ArrayCid) && | |
| 1390 (stored_value->representation() == kUnboxedUint32)); | |
| 1391 | |
| 1392 if (!is_already_unboxed && !value_check.IsNull()) { | |
|
Vyacheslav Egorov (Google)
2014/10/02 17:14:04
I am somewhat concerned about fragility of this.
Cutch
2014/10/02 22:41:12
Done.
| |
| 1359 // No store barrier needed because checked value is a smi, an unboxed mint, | 1393 // No store barrier needed because checked value is a smi, an unboxed mint, |
| 1360 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. | 1394 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. |
| 1361 needs_store_barrier = kNoStoreBarrier; | 1395 needs_store_barrier = kNoStoreBarrier; |
| 1362 Instruction* check = GetCheckClass( | 1396 Instruction* check = GetCheckClass( |
| 1363 stored_value, value_check, call->deopt_id(), call->token_pos()); | 1397 stored_value, value_check, call->deopt_id(), call->token_pos()); |
| 1364 cursor = flow_graph()->AppendTo(cursor, | 1398 cursor = flow_graph()->AppendTo(cursor, |
| 1365 check, | 1399 check, |
| 1366 call->env(), | 1400 call->env(), |
| 1367 FlowGraph::kEffect); | 1401 FlowGraph::kEffect); |
| 1368 } | 1402 } |
| 1369 | 1403 |
| 1370 if (array_cid == kTypedDataFloat32ArrayCid) { | 1404 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 1371 stored_value = | 1405 stored_value = |
| 1372 new(I) DoubleToFloatInstr( | 1406 new(I) DoubleToFloatInstr( |
| 1373 new(I) Value(stored_value), call->deopt_id()); | 1407 new(I) Value(stored_value), call->deopt_id()); |
| 1374 cursor = flow_graph()->AppendTo(cursor, | 1408 cursor = flow_graph()->AppendTo(cursor, |
| 1375 stored_value, | 1409 stored_value, |
| 1376 NULL, | 1410 NULL, |
| 1377 FlowGraph::kValue); | 1411 FlowGraph::kValue); |
| 1378 } else if (array_cid == kTypedDataInt32ArrayCid) { | 1412 } else if (!is_already_unboxed && (array_cid == kTypedDataInt32ArrayCid)) { |
| 1379 stored_value = new(I) UnboxInt32Instr( | 1413 stored_value = new(I) UnboxInt32Instr( |
| 1380 new(I) Value(stored_value), | 1414 new(I) Value(stored_value), |
| 1381 call->deopt_id()); | 1415 call->deopt_id()); |
| 1382 stored_value->AsUnboxIntN()->mark_truncating(); | 1416 stored_value->AsUnboxIntN()->mark_truncating(); |
| 1383 cursor = flow_graph()->AppendTo(cursor, | 1417 cursor = flow_graph()->AppendTo(cursor, |
| 1384 stored_value, | 1418 stored_value, |
| 1385 call->env(), | 1419 call->env(), |
| 1386 FlowGraph::kValue); | 1420 FlowGraph::kValue); |
| 1387 } else if (array_cid == kTypedDataUint32ArrayCid) { | 1421 } else if (!is_already_unboxed && (array_cid == kTypedDataUint32ArrayCid)) { |
| 1388 stored_value = new(I) UnboxUint32Instr( | 1422 stored_value = new(I) UnboxUint32Instr( |
| 1389 new(I) Value(stored_value), | 1423 new(I) Value(stored_value), |
| 1390 call->deopt_id()); | 1424 call->deopt_id()); |
| 1391 ASSERT(stored_value->AsUnboxIntN()->is_truncating()); | 1425 ASSERT(stored_value->AsUnboxIntN()->is_truncating()); |
| 1392 cursor = flow_graph()->AppendTo(cursor, | 1426 cursor = flow_graph()->AppendTo(cursor, |
| 1393 stored_value, | 1427 stored_value, |
| 1394 call->env(), | 1428 call->env(), |
| 1395 FlowGraph::kValue); | 1429 FlowGraph::kValue); |
| 1396 } | 1430 } |
| 1397 | 1431 |
| (...skipping 8722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10120 | 10154 |
| 10121 // Insert materializations at environment uses. | 10155 // Insert materializations at environment uses. |
| 10122 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10156 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 10123 CreateMaterializationAt( | 10157 CreateMaterializationAt( |
| 10124 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 10158 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
| 10125 } | 10159 } |
| 10126 } | 10160 } |
| 10127 | 10161 |
| 10128 | 10162 |
| 10129 } // namespace dart | 10163 } // namespace dart |
| OLD | NEW |