Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Side by Side Diff: runtime/vm/intermediate_language_mips.cc

Issue 304703002: Split GuardField into GuardFieldType and GuardFieldLength instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address comments Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after
1460 case kTypedDataInt32x4ArrayCid: 1460 case kTypedDataInt32x4ArrayCid:
1461 case kTypedDataFloat32x4ArrayCid: 1461 case kTypedDataFloat32x4ArrayCid:
1462 UNIMPLEMENTED(); 1462 UNIMPLEMENTED();
1463 break; 1463 break;
1464 default: 1464 default:
1465 UNREACHABLE(); 1465 UNREACHABLE();
1466 } 1466 }
1467 } 1467 }
1468 1468
1469 1469
1470 LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate, 1470 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
1471 bool opt) const { 1471 bool opt) const {
1472 const intptr_t kNumInputs = 1; 1472 const intptr_t kNumInputs = 1;
1473 LocationSummary* summary = new(isolate) LocationSummary( 1473 LocationSummary* summary = new(isolate) LocationSummary(
1474 isolate, kNumInputs, 0, LocationSummary::kNoCall); 1474 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1475 summary->set_in(0, Location::RequiresRegister()); 1475 summary->set_in(0, Location::RequiresRegister());
1476 const bool field_has_length = field().needs_length_check(); 1476
1477 const bool need_value_temp_reg = 1477 const intptr_t value_cid = value()->Type()->ToCid();
1478 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) && 1478 const intptr_t field_cid = field().guarded_cid();
1479 (field().guarded_cid() != kSmiCid))); 1479
1480 if (need_value_temp_reg) { 1480 const bool emit_full_guard = !opt || (field_cid == kIllegalCid);
1481 const bool needs_value_cid_temp_reg =
1482 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1483 const bool needs_field_temp_reg = emit_full_guard;
1484
1485 if (needs_value_cid_temp_reg) {
1481 summary->AddTemp(Location::RequiresRegister()); 1486 summary->AddTemp(Location::RequiresRegister());
1482 } 1487 }
1483 const bool need_field_temp_reg = 1488
1484 field_has_length || (field().guarded_cid() == kIllegalCid); 1489 if (needs_field_temp_reg) {
1485 if (need_field_temp_reg) {
1486 summary->AddTemp(Location::RequiresRegister()); 1490 summary->AddTemp(Location::RequiresRegister());
1487 } 1491 }
1492
1488 return summary; 1493 return summary;
1489 } 1494 }
1490 1495
1491 1496
1492 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1497 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1493 __ TraceSimMsg("GuardFieldInstr"); 1498 __ TraceSimMsg("GuardFieldClassInstr");
1499
1500 const intptr_t value_cid = value()->Type()->ToCid();
1494 const intptr_t field_cid = field().guarded_cid(); 1501 const intptr_t field_cid = field().guarded_cid();
1495 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; 1502 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1496 const intptr_t field_length = field().guarded_list_length();
1497 const bool field_has_length = field().needs_length_check();
1498 const bool needs_value_temp_reg =
1499 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
1500 (field().guarded_cid() != kSmiCid)));
1501 const bool needs_field_temp_reg =
1502 field_has_length || (field().guarded_cid() == kIllegalCid);
1503 if (field_has_length) {
1504 // Currently, we should only see final fields that remember length.
1505 ASSERT(field().is_final());
1506 }
1507 1503
1508 if (field_cid == kDynamicCid) { 1504 if (field_cid == kDynamicCid) {
1509 ASSERT(!compiler->is_optimizing()); 1505 ASSERT(!compiler->is_optimizing());
1510 return; // Nothing to emit. 1506 return; // Nothing to emit.
1511 } 1507 }
1512 1508
1513 const intptr_t value_cid = value()->Type()->ToCid(); 1509 const bool emit_full_guard =
1510 !compiler->is_optimizing() || (field_cid == kIllegalCid);
1514 1511
1515 Register value_reg = locs()->in(0).reg(); 1512 const bool needs_value_cid_temp_reg =
1513 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1516 1514
1517 Register value_cid_reg = needs_value_temp_reg ? 1515 const bool needs_field_temp_reg = emit_full_guard;
1516
1517 const Register value_reg = locs()->in(0).reg();
1518
1519 const Register value_cid_reg = needs_value_cid_temp_reg ?
1518 locs()->temp(0).reg() : kNoRegister; 1520 locs()->temp(0).reg() : kNoRegister;
1519 1521
1520 Register field_reg = needs_field_temp_reg ? 1522 const Register field_reg = needs_field_temp_reg ?
1521 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; 1523 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
1522 1524
1523 Label ok, fail_label; 1525 Label ok, fail_label;
1524 1526
1525 Label* deopt = compiler->is_optimizing() ? 1527 Label* deopt = compiler->is_optimizing() ?
1526 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; 1528 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
1527 1529
1528 Label* fail = (deopt != NULL) ? deopt : &fail_label; 1530 Label* fail = (deopt != NULL) ? deopt : &fail_label;
1529 1531
1530 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { 1532 if (emit_full_guard) {
1531 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
1532 // Currently we can't have different location summaries for optimized
1533 // and non-optimized code. So instead we manually pick up a register
1534 // that is known to be free because we know how non-optimizing compiler
1535 // allocates registers.
1536 field_reg = A0;
1537 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
1538 }
1539
1540 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); 1533 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1541 1534
1542 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); 1535 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
1543 FieldAddress field_nullability_operand( 1536 FieldAddress field_nullability_operand(
1544 field_reg, Field::is_nullable_offset()); 1537 field_reg, Field::is_nullable_offset());
1545 FieldAddress field_length_operand(
1546 field_reg, Field::guarded_list_length_offset());
1547 1538
1548 if (value_cid == kDynamicCid) { 1539 if (value_cid == kDynamicCid) {
1549 if (value_cid_reg == kNoRegister) {
1550 ASSERT(!compiler->is_optimizing());
1551 value_cid_reg = A1;
1552 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1553 }
1554
1555 LoadValueCid(compiler, value_cid_reg, value_reg); 1540 LoadValueCid(compiler, value_cid_reg, value_reg);
1556 1541
1557 Label skip_length_check;
1558
1559 __ lw(CMPRES1, field_cid_operand); 1542 __ lw(CMPRES1, field_cid_operand);
1560 __ bne(value_cid_reg, CMPRES1, &skip_length_check); 1543 __ beq(value_cid_reg, CMPRES1, &ok);
1561 if (field_has_length) {
1562 // Field guard may have remembered list length, check it.
1563 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1564 __ lw(TMP, FieldAddress(value_reg, Array::length_offset()));
1565 __ LoadImmediate(CMPRES1, Smi::RawValue(field_length));
1566 __ subu(CMPRES1, TMP, CMPRES1);
1567 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1568 __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset()));
1569 __ LoadImmediate(CMPRES1, Smi::RawValue(field_length));
1570 __ subu(CMPRES1, TMP, CMPRES1);
1571 } else {
1572 ASSERT(field_cid == kIllegalCid);
1573 ASSERT(field_length == Field::kUnknownFixedLength);
1574 // At compile time we do not know the type of the field nor its
1575 // length. At execution time we may have set the class id and
1576 // list length so we compare the guarded length with the
1577 // list length here, without this check the list length could change
1578 // without triggering a deoptimization.
1579 Label check_array, length_compared, no_fixed_length;
1580 // If length is negative the length guard is either disabled or
1581 // has not been initialized, either way it is safe to skip the
1582 // length check.
1583 __ lw(CMPRES1, field_length_operand);
1584 __ BranchSignedLess(CMPRES1, 0, &skip_length_check);
1585 __ BranchEqual(value_cid_reg, kNullCid, &no_fixed_length);
1586 // Check for typed data array.
1587 __ BranchSignedGreater(value_cid_reg, kTypedDataInt32x4ArrayCid,
1588 &no_fixed_length);
1589 __ BranchSignedLess(value_cid_reg, kTypedDataInt8ArrayCid,
1590 &check_array);
1591 __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset()));
1592 __ lw(CMPRES1, field_length_operand);
1593 __ subu(CMPRES1, TMP, CMPRES1);
1594 __ b(&length_compared);
1595 // Check for regular array.
1596 __ Bind(&check_array);
1597 __ BranchSignedGreater(value_cid_reg, kImmutableArrayCid,
1598 &no_fixed_length);
1599 __ BranchSignedLess(value_cid_reg, kArrayCid, &no_fixed_length);
1600 __ lw(TMP, FieldAddress(value_reg, Array::length_offset()));
1601 __ lw(CMPRES1, field_length_operand);
1602 __ subu(CMPRES1, TMP, CMPRES1);
1603 __ b(&length_compared);
1604 __ Bind(&no_fixed_length);
1605 __ b(fail);
1606 __ Bind(&length_compared);
1607 }
1608 __ bne(CMPRES1, ZR, fail);
1609 }
1610 __ Bind(&skip_length_check);
1611 __ lw(TMP, field_nullability_operand); 1544 __ lw(TMP, field_nullability_operand);
1612 __ subu(CMPRES1, value_cid_reg, TMP); 1545 __ subu(CMPRES1, value_cid_reg, TMP);
1613 } else if (value_cid == kNullCid) { 1546 } else if (value_cid == kNullCid) {
1614 __ lw(TMP, field_nullability_operand); 1547 __ lw(TMP, field_nullability_operand);
1615 __ LoadImmediate(CMPRES1, value_cid); 1548 __ LoadImmediate(CMPRES1, value_cid);
1616 __ subu(CMPRES1, TMP, CMPRES1); 1549 __ subu(CMPRES1, TMP, CMPRES1);
1617 } else { 1550 } else {
1618 Label skip_length_check;
1619 __ lw(TMP, field_cid_operand); 1551 __ lw(TMP, field_cid_operand);
1620 __ LoadImmediate(CMPRES1, value_cid); 1552 __ LoadImmediate(CMPRES1, value_cid);
1621 __ subu(CMPRES1, TMP, CMPRES1); 1553 __ subu(CMPRES1, TMP, CMPRES1);
1622 __ bne(CMPRES1, ZR, &skip_length_check);
1623 // Insert length check.
1624 if (field_has_length) {
1625 ASSERT(value_cid_reg != kNoRegister);
1626 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1627 __ lw(TMP, FieldAddress(value_reg, Array::length_offset()));
1628 __ LoadImmediate(CMPRES1, Smi::RawValue(field_length));
1629 __ subu(CMPRES1, TMP, CMPRES1);
1630 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1631 __ lw(TMP, FieldAddress(value_reg, TypedData::length_offset()));
1632 __ LoadImmediate(CMPRES1, Smi::RawValue(field_length));
1633 __ subu(CMPRES1, TMP, CMPRES1);
1634 } else if (field_cid != kIllegalCid) {
1635 ASSERT(field_cid != value_cid);
1636 ASSERT(field_length >= 0);
1637 // Field has a known class id and length. At compile time it is
1638 // known that the value's class id is not a fixed length list.
1639 __ b(fail);
1640 } else {
1641 ASSERT(field_cid == kIllegalCid);
1642 ASSERT(field_length == Field::kUnknownFixedLength);
1643 // Following jump cannot not occur, fall through.
1644 }
1645 __ bne(CMPRES1, ZR, fail);
1646 }
1647 __ Bind(&skip_length_check);
1648 } 1554 }
1649 __ beq(CMPRES1, ZR, &ok); 1555 __ beq(CMPRES1, ZR, &ok);
1650 1556
1651 __ lw(CMPRES1, field_cid_operand); 1557 // Check if the tracked state of the guarded field can be initialized
1652 __ BranchNotEqual(CMPRES1, kIllegalCid, fail); 1558 // inline. If the field needs length check we fall through to runtime
1559 // which is responsible for computing offset of the length field
1560 // based on the class id.
1561 // Length guard will be emitted separately when needed via GuardFieldLength
1562 // instruction after GuardFieldClass.
1563 if (!field().needs_length_check()) {
1564 // Uninitialized field can be handled inline. Check if the
1565 // field is still unitialized.
1566 __ lw(CMPRES1, field_cid_operand);
1567 __ BranchNotEqual(CMPRES1, kIllegalCid, fail);
1653 1568
1654 if (value_cid == kDynamicCid) { 1569 if (value_cid == kDynamicCid) {
1655 __ sw(value_cid_reg, field_cid_operand); 1570 __ sw(value_cid_reg, field_cid_operand);
1656 __ sw(value_cid_reg, field_nullability_operand); 1571 __ sw(value_cid_reg, field_nullability_operand);
1657 if (field_has_length) { 1572 } else {
1658 Label check_array, length_set, no_fixed_length; 1573 __ LoadImmediate(TMP, value_cid);
1659 __ BranchEqual(value_cid_reg, kNullCid, &no_fixed_length); 1574 __ sw(TMP, field_cid_operand);
1660 // Check for typed data array. 1575 __ sw(TMP, field_nullability_operand);
1661 __ BranchSignedGreater(value_cid_reg, kTypedDataInt32x4ArrayCid,
1662 &no_fixed_length);
1663 __ BranchSignedLess(value_cid_reg, kTypedDataInt8ArrayCid,
1664 &check_array);
1665 // Destroy value_cid_reg (safe because we are finished with it).
1666 __ lw(value_cid_reg,
1667 FieldAddress(value_reg, TypedData::length_offset()));
1668 __ sw(value_cid_reg, field_length_operand);
1669 // Updated field length typed data array.
1670 __ b(&length_set);
1671 // Check for regular array.
1672 __ Bind(&check_array);
1673 __ BranchSignedGreater(value_cid_reg, kImmutableArrayCid,
1674 &no_fixed_length);
1675 __ BranchSignedLess(value_cid_reg, kArrayCid, &no_fixed_length);
1676 // Destroy value_cid_reg (safe because we are finished with it).
1677 __ lw(value_cid_reg,
1678 FieldAddress(value_reg, Array::length_offset()));
1679 __ sw(value_cid_reg, field_length_operand);
1680 // Updated field length from regular array.
1681 __ b(&length_set);
1682 __ Bind(&no_fixed_length);
1683 __ LoadImmediate(TMP, Smi::RawValue(Field::kNoFixedLength));
1684 __ sw(TMP, field_length_operand);
1685 __ Bind(&length_set);
1686 } 1576 }
1687 } else { 1577
1688 ASSERT(field_reg != kNoRegister); 1578 if (deopt == NULL) {
1689 __ LoadImmediate(TMP, value_cid); 1579 ASSERT(!compiler->is_optimizing());
1690 __ sw(TMP, field_cid_operand); 1580 __ b(&ok);
1691 __ sw(TMP, field_nullability_operand);
1692 if (field_has_length) {
1693 ASSERT(value_cid_reg != kNoRegister);
1694 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1695 // Destroy value_cid_reg (safe because we are finished with it).
1696 __ lw(value_cid_reg,
1697 FieldAddress(value_reg, Array::length_offset()));
1698 __ sw(value_cid_reg, field_length_operand);
1699 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1700 // Destroy value_cid_reg (safe because we are finished with it).
1701 __ lw(value_cid_reg,
1702 FieldAddress(value_reg, TypedData::length_offset()));
1703 __ sw(value_cid_reg, field_length_operand);
1704 } else {
1705 // Destroy value_cid_reg (safe because we are finished with it).
1706 __ LoadImmediate(value_cid_reg, Smi::RawValue(Field::kNoFixedLength));
1707 __ sw(value_cid_reg, field_length_operand);
1708 }
1709 } 1581 }
1710 } 1582 }
1711 1583
1712 if (deopt == NULL) { 1584 if (deopt == NULL) {
1713 ASSERT(!compiler->is_optimizing()); 1585 ASSERT(!compiler->is_optimizing());
1714 __ b(&ok);
1715 __ Bind(fail); 1586 __ Bind(fail);
1716 1587
1717 __ lw(CMPRES1, FieldAddress(field_reg, Field::guarded_cid_offset())); 1588 __ lw(CMPRES1, FieldAddress(field_reg, Field::guarded_cid_offset()));
1718 __ BranchEqual(CMPRES1, kDynamicCid, &ok); 1589 __ BranchEqual(CMPRES1, kDynamicCid, &ok);
1719 1590
1720 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1591 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1721 __ sw(field_reg, Address(SP, 1 * kWordSize)); 1592 __ sw(field_reg, Address(SP, 1 * kWordSize));
1722 __ sw(value_reg, Address(SP, 0 * kWordSize)); 1593 __ sw(value_reg, Address(SP, 0 * kWordSize));
1723 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); 1594 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1724 __ Drop(2); // Drop the field and the value. 1595 __ Drop(2); // Drop the field and the value.
1725 } 1596 }
1726 } else { 1597 } else {
1727 ASSERT(compiler->is_optimizing()); 1598 ASSERT(compiler->is_optimizing());
1728 ASSERT(deopt != NULL); 1599 ASSERT(deopt != NULL);
1600
1729 // Field guard class has been initialized and is known. 1601 // Field guard class has been initialized and is known.
1730 if (field_reg != kNoRegister) {
1731 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1732 }
1733 if (value_cid == kDynamicCid) { 1602 if (value_cid == kDynamicCid) {
1734 // Field's guarded class id is fixed by value's class id is not known. 1603 // Value's class id is not known.
1735 __ andi(CMPRES1, value_reg, Immediate(kSmiTagMask)); 1604 __ andi(CMPRES1, value_reg, Immediate(kSmiTagMask));
1736 1605
1737 if (field_cid != kSmiCid) { 1606 if (field_cid != kSmiCid) {
1738 __ beq(CMPRES1, ZR, fail); 1607 __ beq(CMPRES1, ZR, fail);
1739 __ LoadClassId(value_cid_reg, value_reg); 1608 __ LoadClassId(value_cid_reg, value_reg);
1740 __ LoadImmediate(TMP, field_cid); 1609 __ LoadImmediate(TMP, field_cid);
1741 __ subu(CMPRES1, value_cid_reg, TMP); 1610 __ subu(CMPRES1, value_cid_reg, TMP);
1742 } 1611 }
1743 1612
1744 if (field_has_length) {
1745 // Jump when Value CID != Field guard CID
1746 __ bne(CMPRES1, ZR, fail);
1747 // Classes are same, perform guarded list length check.
1748 ASSERT(field_reg != kNoRegister);
1749 ASSERT(value_cid_reg != kNoRegister);
1750 FieldAddress field_length_operand(
1751 field_reg, Field::guarded_list_length_offset());
1752 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1753 // Destroy value_cid_reg (safe because we are finished with it).
1754 __ lw(value_cid_reg,
1755 FieldAddress(value_reg, Array::length_offset()));
1756 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1757 // Destroy value_cid_reg (safe because we are finished with it).
1758 __ lw(value_cid_reg,
1759 FieldAddress(value_reg, TypedData::length_offset()));
1760 }
1761 __ lw(TMP, field_length_operand);
1762 __ subu(CMPRES1, value_cid_reg, TMP);
1763 }
1764
1765 if (field().is_nullable() && (field_cid != kNullCid)) { 1613 if (field().is_nullable() && (field_cid != kNullCid)) {
1766 __ beq(CMPRES1, ZR, &ok); 1614 __ beq(CMPRES1, ZR, &ok);
1767 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null())); 1615 if (field_cid != kSmiCid) {
1768 __ subu(CMPRES1, value_reg, TMP); 1616 __ LoadImmediate(TMP, kNullCid);
1617 __ subu(CMPRES1, value_cid_reg, TMP);
1618 } else {
1619 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
1620 __ subu(CMPRES1, value_reg, TMP);
1621 }
1769 } 1622 }
1770 1623
1771 __ bne(CMPRES1, ZR, fail); 1624 __ bne(CMPRES1, ZR, fail);
1772 } else { 1625 } else {
1773 // Both value's and field's class id is known. 1626 // Both value's and field's class id is known.
1774 if ((value_cid != field_cid) && (value_cid != nullability)) { 1627 ASSERT((value_cid != field_cid) && (value_cid != nullability));
1775 __ b(fail); 1628 __ b(fail);
1776 } else if (field_has_length && (value_cid == field_cid)) {
1777 ASSERT(value_cid_reg != kNoRegister);
1778 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1779 // Destroy value_cid_reg (safe because we are finished with it).
1780 __ lw(value_cid_reg,
1781 FieldAddress(value_reg, Array::length_offset()));
1782 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1783 // Destroy value_cid_reg (safe because we are finished with it).
1784 __ lw(value_cid_reg,
1785 FieldAddress(value_reg, TypedData::length_offset()));
1786 }
1787 __ LoadImmediate(TMP, Smi::RawValue(field_length));
1788 __ subu(CMPRES1, value_cid_reg, TMP);
1789 __ bne(CMPRES1, ZR, fail);
1790 } else {
1791 UNREACHABLE();
1792 }
1793 } 1629 }
1794 } 1630 }
1795 __ Bind(&ok); 1631 __ Bind(&ok);
1796 } 1632 }
1797 1633
1798 1634
1635 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
1636 bool opt) const {
1637 const intptr_t kNumInputs = 1;
1638 LocationSummary* summary = new(isolate) LocationSummary(
1639 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1640 summary->set_in(0, Location::RequiresRegister());
1641
1642 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1643 // We need temporary for field object.
1644 summary->AddTemp(Location::RequiresRegister());
1645 }
1646
1647 return summary;
1648 }
1649
1650
1651 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1652 if (field().guarded_list_length() == Field::kNoFixedLength) {
1653 ASSERT(!compiler->is_optimizing());
1654 return; // Nothing to emit.
1655 }
1656
1657 Label* deopt = compiler->is_optimizing() ?
1658 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
1659
1660 const Register value_reg = locs()->in(0).reg();
1661
1662 if (!compiler->is_optimizing() ||
1663 (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1664 const Register field_reg = locs()->temp(0).reg();
1665
1666 Label ok;
1667
1668 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1669
1670 __ lb(CMPRES1, FieldAddress(field_reg,
1671 Field::guarded_list_length_in_object_offset_offset()));
1672 __ blez(CMPRES1, &ok);
1673
1674 __ lw(CMPRES2, FieldAddress(field_reg,
1675 Field::guarded_list_length_offset()));
1676
1677 // Load the length from the value. GuardFieldClass already verified that
1678 // value's class matches guarded class id of the field.
1679 // CMPRES1 contains offset already corrected by -kHeapObjectTag that is
1680 // why we can use Address instead of FieldAddress.
1681 __ addu(TMP, value_reg, CMPRES1);
1682 __ lw(TMP, Address(TMP));
1683
1684 if (deopt == NULL) {
1685 __ beq(CMPRES2, TMP, &ok);
1686
1687 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1688 __ sw(field_reg, Address(SP, 1 * kWordSize));
1689 __ sw(value_reg, Address(SP, 0 * kWordSize));
1690 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1691 __ Drop(2); // Drop the field and the value.
1692 } else {
1693 __ bne(CMPRES2, TMP, deopt);
1694 }
1695
1696 __ Bind(&ok);
1697 } else {
1698 ASSERT(compiler->is_optimizing());
1699 ASSERT(field().guarded_list_length() >= 0);
1700 ASSERT(field().guarded_list_length_in_object_offset() !=
1701 Field::kUnknownLengthOffset);
1702
1703 __ lw(CMPRES1,
1704 FieldAddress(value_reg,
1705 field().guarded_list_length_in_object_offset()));
1706 __ LoadImmediate(TMP, Smi::RawValue(field().guarded_list_length()));
1707 __ bne(CMPRES1, TMP, deopt);
1708 }
1709 }
1710
1711
1799 class StoreInstanceFieldSlowPath : public SlowPathCode { 1712 class StoreInstanceFieldSlowPath : public SlowPathCode {
1800 public: 1713 public:
1801 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, 1714 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
1802 const Class& cls) 1715 const Class& cls)
1803 : instruction_(instruction), cls_(cls) { } 1716 : instruction_(instruction), cls_(cls) { }
1804 1717
1805 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 1718 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
1806 __ Comment("StoreInstanceFieldSlowPath"); 1719 __ Comment("StoreInstanceFieldSlowPath");
1807 __ Bind(entry_label()); 1720 __ Bind(entry_label());
1808 const Code& stub = 1721 const Code& stub =
(...skipping 2948 matching lines...) Expand 10 before | Expand all | Expand 10 after
4757 compiler->GenerateCall(token_pos(), 4670 compiler->GenerateCall(token_pos(),
4758 &label, 4671 &label,
4759 PcDescriptors::kOther, 4672 PcDescriptors::kOther,
4760 locs()); 4673 locs());
4761 __ Drop(ArgumentCount()); // Discard arguments. 4674 __ Drop(ArgumentCount()); // Discard arguments.
4762 } 4675 }
4763 4676
4764 } // namespace dart 4677 } // namespace dart
4765 4678
4766 #endif // defined TARGET_ARCH_MIPS 4679 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698