| 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 // Value check not needed for Int32 and Uint32 arrays because they |
| 1427 // which can only deal unbox these values. | 1423 // implicitly contain unboxing instructions which check for right type. |
| 1428 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | 1424 ICData& value_check = ICData::Handle(); |
| 1429 if (!HasOnlySmiOrMint(value_check)) { | |
| 1430 return false; | |
| 1431 } | |
| 1432 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1425 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1433 value_check, entry, last); | 1426 value_check, entry, last); |
| 1427 } |
| 1434 case MethodRecognizer::kInt64ArraySetIndexed: | 1428 case MethodRecognizer::kInt64ArraySetIndexed: |
| 1435 if (!ShouldInlineInt64ArrayOps()) { | 1429 if (!ShouldInlineInt64ArrayOps()) { |
| 1436 return false; | 1430 return false; |
| 1437 } | 1431 } |
| 1438 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1432 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1439 value_check, entry, last); | 1433 value_check, entry, last); |
| 1440 case MethodRecognizer::kFloat32ArraySetIndexed: | 1434 case MethodRecognizer::kFloat32ArraySetIndexed: |
| 1441 case MethodRecognizer::kFloat64ArraySetIndexed: | 1435 case MethodRecognizer::kFloat64ArraySetIndexed: |
| 1442 if (!CanUnboxDouble()) { | 1436 if (!CanUnboxDouble()) { |
| 1443 return false; | 1437 return false; |
| 1444 } | 1438 } |
| 1445 // Check that value is always double. | 1439 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, | 1440 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1451 value_check, entry, last); | 1441 value_check, entry, last); |
| 1452 case MethodRecognizer::kFloat32x4ArraySetIndexed: | 1442 case MethodRecognizer::kFloat32x4ArraySetIndexed: |
| 1453 if (!ShouldInlineSimd()) { | 1443 if (!ShouldInlineSimd()) { |
| 1454 return false; | 1444 return false; |
| 1455 } | 1445 } |
| 1456 // Check that value is always a Float32x4. | 1446 value_check = ic_data.AsUnaryClassChecksForCid(kFloat32x4Cid, target); |
| 1457 if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) { | 1447 |
| 1458 return false; | |
| 1459 } | |
| 1460 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | |
| 1461 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1448 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1462 value_check, entry, last); | 1449 value_check, entry, last); |
| 1463 case MethodRecognizer::kFloat64x2ArraySetIndexed: | 1450 case MethodRecognizer::kFloat64x2ArraySetIndexed: |
| 1464 if (!ShouldInlineSimd()) { | 1451 if (!ShouldInlineSimd()) { |
| 1465 return false; | 1452 return false; |
| 1466 } | 1453 } |
| 1467 // Check that value is always a Float32x4. | 1454 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, | 1455 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1473 value_check, entry, last); | 1456 value_check, entry, last); |
| 1474 case MethodRecognizer::kByteArrayBaseGetInt8: | 1457 case MethodRecognizer::kByteArrayBaseGetInt8: |
| 1475 return InlineByteArrayBaseLoad(call, receiver, receiver_cid, | 1458 return InlineByteArrayBaseLoad(call, receiver, receiver_cid, |
| 1476 kTypedDataInt8ArrayCid, | 1459 kTypedDataInt8ArrayCid, |
| 1477 ic_data, entry, last); | 1460 ic_data, entry, last); |
| 1478 case MethodRecognizer::kByteArrayBaseGetUint8: | 1461 case MethodRecognizer::kByteArrayBaseGetUint8: |
| 1479 return InlineByteArrayBaseLoad(call, receiver, receiver_cid, | 1462 return InlineByteArrayBaseLoad(call, receiver, receiver_cid, |
| 1480 kTypedDataUint8ArrayCid, | 1463 kTypedDataUint8ArrayCid, |
| 1481 ic_data, entry, last); | 1464 ic_data, entry, last); |
| (...skipping 3045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4527 // Inline implicit instance setter. | 4510 // Inline implicit instance setter. |
| 4528 const String& field_name = | 4511 const String& field_name = |
| 4529 String::Handle(Z, Field::NameFromSetter(instr->function_name())); | 4512 String::Handle(Z, Field::NameFromSetter(instr->function_name())); |
| 4530 const Field& field = | 4513 const Field& field = |
| 4531 Field::ZoneHandle(Z, GetField(class_id, field_name)); | 4514 Field::ZoneHandle(Z, GetField(class_id, field_name)); |
| 4532 ASSERT(!field.IsNull()); | 4515 ASSERT(!field.IsNull()); |
| 4533 | 4516 |
| 4534 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) { | 4517 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) { |
| 4535 AddReceiverCheck(instr); | 4518 AddReceiverCheck(instr); |
| 4536 } | 4519 } |
| 4537 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) { | 4520 if (field.guarded_cid() != kDynamicCid) { |
| 4550 InsertBefore(instr, | 4521 InsertBefore(instr, |
| 4551 new(Z) GuardFieldClassInstr( | 4522 new(Z) GuardFieldClassInstr( |
| 4552 new(Z) Value(instr->ArgumentAt(1)), | 4523 new(Z) Value(instr->ArgumentAt(1)), |
| 4553 field, | 4524 field, |
| 4554 instr->deopt_id()), | 4525 instr->deopt_id()), |
| 4555 instr->env(), | 4526 instr->env(), |
| 4556 FlowGraph::kEffect); | 4527 FlowGraph::kEffect); |
| 4557 } | 4528 } |
| 4558 | 4529 |
| 4559 if (field.needs_length_check()) { | 4530 if (field.needs_length_check()) { |
| 4560 InsertBefore(instr, | 4531 InsertBefore(instr, |
| 4561 new(Z) GuardFieldLengthInstr( | 4532 new(Z) GuardFieldLengthInstr( |
| 4562 new(Z) Value(instr->ArgumentAt(1)), | 4533 new(Z) Value(instr->ArgumentAt(1)), |
| 4563 field, | 4534 field, |
| 4564 instr->deopt_id()), | 4535 instr->deopt_id()), |
| 4565 instr->env(), | 4536 instr->env(), |
| 4566 FlowGraph::kEffect); | 4537 FlowGraph::kEffect); |
| 4567 } | 4538 } |
| 4568 | 4539 |
| 4569 // Field guard was detached. | 4540 // Field guard was detached. |
| 4570 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( | 4541 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( |
| 4571 field, | 4542 field, |
| 4572 new(Z) Value(instr->ArgumentAt(0)), | 4543 new(Z) Value(instr->ArgumentAt(0)), |
| 4573 new(Z) Value(instr->ArgumentAt(1)), | 4544 new(Z) Value(instr->ArgumentAt(1)), |
| 4574 needs_store_barrier, | 4545 kEmitStoreBarrier, |
| 4575 instr->token_pos()); | 4546 instr->token_pos()); |
| 4576 | 4547 |
| 4577 if (store->IsUnboxedStore()) { | 4548 if (store->IsUnboxedStore()) { |
| 4578 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 4549 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
| 4579 } | 4550 } |
| 4580 | 4551 |
| 4581 // Discard the environment from the original instruction because the store | 4552 // Discard the environment from the original instruction because the store |
| 4582 // can't deoptimize. | 4553 // can't deoptimize. |
| 4583 instr->RemoveEnvironment(); | 4554 instr->RemoveEnvironment(); |
| 4584 ReplaceCall(instr, store); | 4555 ReplaceCall(instr, store); |
| (...skipping 4025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8610 | 8581 |
| 8611 // Insert materializations at environment uses. | 8582 // Insert materializations at environment uses. |
| 8612 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8583 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8613 CreateMaterializationAt( | 8584 CreateMaterializationAt( |
| 8614 exits_collector_.exits()[i], alloc, *slots); | 8585 exits_collector_.exits()[i], alloc, *slots); |
| 8615 } | 8586 } |
| 8616 } | 8587 } |
| 8617 | 8588 |
| 8618 | 8589 |
| 8619 } // namespace dart | 8590 } // namespace dart |
| OLD | NEW |