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 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1396 return InlineGetIndexed(kind, call, receiver, entry, last); | 1396 return InlineGetIndexed(kind, call, receiver, entry, last); |
| 1397 | 1397 |
| 1398 case MethodRecognizer::kInt64ArrayGetIndexed: | 1398 case MethodRecognizer::kInt64ArrayGetIndexed: |
| 1399 if (!ShouldInlineInt64ArrayOps()) { | 1399 if (!ShouldInlineInt64ArrayOps()) { |
| 1400 return false; | 1400 return false; |
| 1401 } | 1401 } |
| 1402 return InlineGetIndexed(kind, call, receiver, entry, last); | 1402 return InlineGetIndexed(kind, call, receiver, entry, last); |
| 1403 // Recognized []= operators. | 1403 // Recognized []= operators. |
| 1404 case MethodRecognizer::kObjectArraySetIndexed: | 1404 case MethodRecognizer::kObjectArraySetIndexed: |
| 1405 case MethodRecognizer::kGrowableArraySetIndexed: | 1405 case MethodRecognizer::kGrowableArraySetIndexed: |
| 1406 if (ArgIsAlways(kSmiCid, ic_data, 2)) { | |
| 1407 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | |
| 1408 } | |
| 1409 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1406 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1410 value_check, entry, last); | 1407 value_check, entry, last); |
| 1411 case MethodRecognizer::kInt8ArraySetIndexed: | 1408 case MethodRecognizer::kInt8ArraySetIndexed: |
| 1412 case MethodRecognizer::kUint8ArraySetIndexed: | 1409 case MethodRecognizer::kUint8ArraySetIndexed: |
| 1413 case MethodRecognizer::kUint8ClampedArraySetIndexed: | 1410 case MethodRecognizer::kUint8ClampedArraySetIndexed: |
| 1414 case MethodRecognizer::kExternalUint8ArraySetIndexed: | 1411 case MethodRecognizer::kExternalUint8ArraySetIndexed: |
| 1415 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed: | 1412 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed: |
| 1416 case MethodRecognizer::kInt16ArraySetIndexed: | 1413 case MethodRecognizer::kInt16ArraySetIndexed: |
| 1417 case MethodRecognizer::kUint16ArraySetIndexed: | 1414 case MethodRecognizer::kUint16ArraySetIndexed: |
| 1418 if (!ArgIsAlways(kSmiCid, ic_data, 2)) { | 1415 // Optimistically assume Smi. |
| 1419 return false; | 1416 // TODO(srdjan): Check deopt reason to prevent repeated deoptimizations. |
| 1420 } | 1417 value_check = ic_data.AsUnaryClassChecksForCid(kSmiCid, target); |
| 1421 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | |
| 1422 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1418 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1423 value_check, entry, last); | 1419 value_check, entry, last); |
| 1424 case MethodRecognizer::kInt32ArraySetIndexed: | 1420 case MethodRecognizer::kInt32ArraySetIndexed: |
| 1425 case MethodRecognizer::kUint32ArraySetIndexed: | 1421 case MethodRecognizer::kUint32ArraySetIndexed: { |
| 1426 // Check that value is always smi or mint. We use Int32/Uint32 unboxing | 1422 // Check that value is always Smi or Mint. We use Int32/Uint32 unboxing |
| 1427 // which can only deal unbox these values. | 1423 // which can only deal unbox these values. |
| 1428 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | 1424 GrowableArray<intptr_t> smi_mint_cids; |
|
Vyacheslav Egorov (Google)
2015/05/27 15:06:34
same TODO as above
srdjan
2015/05/27 19:10:57
Done.
| |
| 1429 if (!HasOnlySmiOrMint(value_check)) { | 1425 smi_mint_cids.Add(kSmiCid); |
| 1430 return false; | 1426 smi_mint_cids.Add(kMintCid); |
| 1431 } | 1427 value_check = ic_data.AsUnaryClassChecksForCids(smi_mint_cids, target); |
| 1432 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1428 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
|
Vyacheslav Egorov (Google)
2015/05/27 15:06:34
InlineSetIndexed has an interesting code inside
srdjan
2015/05/27 19:10:57
Thanks! Also removed AsUnaryClassChecksForCids
| |
| 1433 value_check, entry, last); | 1429 value_check, entry, last); |
| 1430 } | |
| 1434 case MethodRecognizer::kInt64ArraySetIndexed: | 1431 case MethodRecognizer::kInt64ArraySetIndexed: |
| 1435 if (!ShouldInlineInt64ArrayOps()) { | 1432 if (!ShouldInlineInt64ArrayOps()) { |
| 1436 return false; | 1433 return false; |
| 1437 } | 1434 } |
| 1438 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1435 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1439 value_check, entry, last); | 1436 value_check, entry, last); |
| 1440 case MethodRecognizer::kFloat32ArraySetIndexed: | 1437 case MethodRecognizer::kFloat32ArraySetIndexed: |
| 1441 case MethodRecognizer::kFloat64ArraySetIndexed: | 1438 case MethodRecognizer::kFloat64ArraySetIndexed: |
| 1442 if (!CanUnboxDouble()) { | 1439 if (!CanUnboxDouble()) { |
| 1443 return false; | 1440 return false; |
| 1444 } | 1441 } |
| 1445 // Check that value is always double. | 1442 value_check = ic_data.AsUnaryClassChecksForCid(kDoubleCid, target); |
| 1446 if (!ArgIsAlways(kDoubleCid, ic_data, 2)) { | |
| 1447 return false; | |
| 1448 } | |
| 1449 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | |
| 1450 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1443 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1451 value_check, entry, last); | 1444 value_check, entry, last); |
| 1452 case MethodRecognizer::kFloat32x4ArraySetIndexed: | 1445 case MethodRecognizer::kFloat32x4ArraySetIndexed: |
| 1453 if (!ShouldInlineSimd()) { | 1446 if (!ShouldInlineSimd()) { |
| 1454 return false; | 1447 return false; |
| 1455 } | 1448 } |
| 1456 // Check that value is always a Float32x4. | 1449 value_check = ic_data.AsUnaryClassChecksForCid(kFloat32x4Cid, target); |
| 1457 if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) { | 1450 |
| 1458 return false; | |
| 1459 } | |
| 1460 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | |
| 1461 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1451 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1462 value_check, entry, last); | 1452 value_check, entry, last); |
| 1463 case MethodRecognizer::kFloat64x2ArraySetIndexed: | 1453 case MethodRecognizer::kFloat64x2ArraySetIndexed: |
| 1464 if (!ShouldInlineSimd()) { | 1454 if (!ShouldInlineSimd()) { |
| 1465 return false; | 1455 return false; |
| 1466 } | 1456 } |
| 1467 // Check that value is always a Float32x4. | 1457 value_check = ic_data.AsUnaryClassChecksForCid(kFloat64x2Cid, target); |
| 1468 if (!ArgIsAlways(kFloat64x2Cid, ic_data, 2)) { | |
| 1469 return false; | |
| 1470 } | |
| 1471 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | |
| 1472 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1458 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1473 value_check, entry, last); | 1459 value_check, entry, last); |
| 1474 case MethodRecognizer::kByteArrayBaseGetInt8: | 1460 case MethodRecognizer::kByteArrayBaseGetInt8: |
| 1475 return InlineByteArrayBaseLoad(call, receiver, receiver_cid, | 1461 return InlineByteArrayBaseLoad(call, receiver, receiver_cid, |
| 1476 kTypedDataInt8ArrayCid, | 1462 kTypedDataInt8ArrayCid, |
| 1477 ic_data, entry, last); | 1463 ic_data, entry, last); |
| 1478 case MethodRecognizer::kByteArrayBaseGetUint8: | 1464 case MethodRecognizer::kByteArrayBaseGetUint8: |
| 1479 return InlineByteArrayBaseLoad(call, receiver, receiver_cid, | 1465 return InlineByteArrayBaseLoad(call, receiver, receiver_cid, |
| 1480 kTypedDataUint8ArrayCid, | 1466 kTypedDataUint8ArrayCid, |
| 1481 ic_data, entry, last); | 1467 ic_data, entry, last); |
| (...skipping 3046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4528 const String& field_name = | 4514 const String& field_name = |
| 4529 String::Handle(Z, Field::NameFromSetter(instr->function_name())); | 4515 String::Handle(Z, Field::NameFromSetter(instr->function_name())); |
| 4530 const Field& field = | 4516 const Field& field = |
| 4531 Field::ZoneHandle(Z, GetField(class_id, field_name)); | 4517 Field::ZoneHandle(Z, GetField(class_id, field_name)); |
| 4532 ASSERT(!field.IsNull()); | 4518 ASSERT(!field.IsNull()); |
| 4533 | 4519 |
| 4534 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) { | 4520 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) { |
| 4535 AddReceiverCheck(instr); | 4521 AddReceiverCheck(instr); |
| 4536 } | 4522 } |
| 4537 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; | 4523 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; |
| 4538 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { | |
| 4539 InsertBefore(instr, | |
| 4540 new(Z) CheckSmiInstr( | |
| 4541 new(Z) Value(instr->ArgumentAt(1)), | |
| 4542 instr->deopt_id(), | |
| 4543 instr->token_pos()), | |
| 4544 instr->env(), | |
| 4545 FlowGraph::kEffect); | |
| 4546 needs_store_barrier = kNoStoreBarrier; | |
| 4547 } | |
| 4548 | |
| 4549 if (field.guarded_cid() != kDynamicCid) { | 4524 if (field.guarded_cid() != kDynamicCid) { |
| 4550 InsertBefore(instr, | 4525 InsertBefore(instr, |
| 4551 new(Z) GuardFieldClassInstr( | 4526 new(Z) GuardFieldClassInstr( |
| 4552 new(Z) Value(instr->ArgumentAt(1)), | 4527 new(Z) Value(instr->ArgumentAt(1)), |
| 4553 field, | 4528 field, |
| 4554 instr->deopt_id()), | 4529 instr->deopt_id()), |
| 4555 instr->env(), | 4530 instr->env(), |
| 4556 FlowGraph::kEffect); | 4531 FlowGraph::kEffect); |
| 4557 } | 4532 } |
| 4558 | 4533 |
| 4559 if (field.needs_length_check()) { | 4534 if (field.needs_length_check()) { |
| 4560 InsertBefore(instr, | 4535 InsertBefore(instr, |
| 4561 new(Z) GuardFieldLengthInstr( | 4536 new(Z) GuardFieldLengthInstr( |
| 4562 new(Z) Value(instr->ArgumentAt(1)), | 4537 new(Z) Value(instr->ArgumentAt(1)), |
| 4563 field, | 4538 field, |
| 4564 instr->deopt_id()), | 4539 instr->deopt_id()), |
| 4565 instr->env(), | 4540 instr->env(), |
| 4566 FlowGraph::kEffect); | 4541 FlowGraph::kEffect); |
| 4567 } | 4542 } |
| 4568 | 4543 |
| 4569 // Field guard was detached. | 4544 // Field guard was detached. |
| 4570 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( | 4545 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( |
| 4571 field, | 4546 field, |
| 4572 new(Z) Value(instr->ArgumentAt(0)), | 4547 new(Z) Value(instr->ArgumentAt(0)), |
| 4573 new(Z) Value(instr->ArgumentAt(1)), | 4548 new(Z) Value(instr->ArgumentAt(1)), |
| 4574 needs_store_barrier, | 4549 needs_store_barrier, |
|
Vyacheslav Egorov (Google)
2015/05/27 15:06:34
inline needs_store_barrier value here as it's alwa
srdjan
2015/05/27 19:10:57
Done.
| |
| 4575 instr->token_pos()); | 4550 instr->token_pos()); |
| 4576 | 4551 |
| 4577 if (store->IsUnboxedStore()) { | 4552 if (store->IsUnboxedStore()) { |
| 4578 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 4553 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
| 4579 } | 4554 } |
| 4580 | 4555 |
| 4581 // Discard the environment from the original instruction because the store | 4556 // Discard the environment from the original instruction because the store |
| 4582 // can't deoptimize. | 4557 // can't deoptimize. |
| 4583 instr->RemoveEnvironment(); | 4558 instr->RemoveEnvironment(); |
| 4584 ReplaceCall(instr, store); | 4559 ReplaceCall(instr, store); |
| (...skipping 4025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8610 | 8585 |
| 8611 // Insert materializations at environment uses. | 8586 // Insert materializations at environment uses. |
| 8612 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8587 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8613 CreateMaterializationAt( | 8588 CreateMaterializationAt( |
| 8614 exits_collector_.exits()[i], alloc, *slots); | 8589 exits_collector_.exits()[i], alloc, *slots); |
| 8615 } | 8590 } |
| 8616 } | 8591 } |
| 8617 | 8592 |
| 8618 | 8593 |
| 8619 } // namespace dart | 8594 } // namespace dart |
| OLD | NEW |