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

Side by Side Diff: runtime/vm/intermediate_language_ia32.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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 case kTypedDataFloat32x4ArrayCid: 1444 case kTypedDataFloat32x4ArrayCid:
1445 case kTypedDataFloat64x2ArrayCid: 1445 case kTypedDataFloat64x2ArrayCid:
1446 __ movups(element_address, locs()->in(2).fpu_reg()); 1446 __ movups(element_address, locs()->in(2).fpu_reg());
1447 break; 1447 break;
1448 default: 1448 default:
1449 UNREACHABLE(); 1449 UNREACHABLE();
1450 } 1450 }
1451 } 1451 }
1452 1452
1453 1453
1454 LocationSummary* GuardFieldInstr::MakeLocationSummary(Isolate* isolate, 1454 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Isolate* isolate,
1455 bool opt) const { 1455 bool opt) const {
1456 const intptr_t kNumInputs = 1; 1456 const intptr_t kNumInputs = 1;
1457 LocationSummary* summary = new(isolate) LocationSummary( 1457 LocationSummary* summary = new(isolate) LocationSummary(
1458 isolate, kNumInputs, 0, LocationSummary::kNoCall); 1458 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1459 summary->set_in(0, Location::RequiresRegister()); 1459 summary->set_in(0, Location::RequiresRegister());
1460 const bool field_has_length = field().needs_length_check(); 1460
1461 const bool need_value_temp_reg = 1461 const intptr_t value_cid = value()->Type()->ToCid();
1462 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) && 1462 const intptr_t field_cid = field().guarded_cid();
1463 (field().guarded_cid() != kSmiCid))); 1463
1464 if (need_value_temp_reg) { 1464 const bool emit_full_guard = !opt || (field_cid == kIllegalCid);
1465 const bool needs_value_cid_temp_reg =
1466 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1467 const bool needs_field_temp_reg = emit_full_guard;
1468
1469 if (needs_value_cid_temp_reg) {
1465 summary->AddTemp(Location::RequiresRegister()); 1470 summary->AddTemp(Location::RequiresRegister());
1466 } 1471 }
1467 const bool need_field_temp_reg = 1472
1468 field_has_length || (field().guarded_cid() == kIllegalCid); 1473 if (needs_field_temp_reg) {
1469 if (need_field_temp_reg) {
1470 summary->AddTemp(Location::RequiresRegister()); 1474 summary->AddTemp(Location::RequiresRegister());
1471 } 1475 }
1476
1472 return summary; 1477 return summary;
1473 } 1478 }
1474 1479
1475 1480
1476 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1481 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1482 const intptr_t value_cid = value()->Type()->ToCid();
1477 const intptr_t field_cid = field().guarded_cid(); 1483 const intptr_t field_cid = field().guarded_cid();
1478 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; 1484 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1479 const intptr_t field_length = field().guarded_list_length();
1480 const bool field_has_length = field().needs_length_check();
1481 const bool needs_value_temp_reg =
1482 (field_has_length || ((value()->Type()->ToCid() == kDynamicCid) &&
1483 (field().guarded_cid() != kSmiCid)));
1484 const bool needs_field_temp_reg =
1485 field_has_length || (field().guarded_cid() == kIllegalCid);
1486 if (field_has_length) {
1487 // Currently, we should only see final fields that remember length.
1488 ASSERT(field().is_final());
1489 }
1490 1485
1491 if (field_cid == kDynamicCid) { 1486 if (field_cid == kDynamicCid) {
1492 ASSERT(!compiler->is_optimizing()); 1487 ASSERT(!compiler->is_optimizing());
1493 return; // Nothing to emit. 1488 return; // Nothing to emit.
1494 } 1489 }
1495 const intptr_t value_cid = value()->Type()->ToCid();
1496 1490
1497 Register value_reg = locs()->in(0).reg(); 1491 const bool emit_full_guard =
1492 !compiler->is_optimizing() || (field_cid == kIllegalCid);
1498 1493
1499 Register value_cid_reg = needs_value_temp_reg ? 1494 const bool needs_value_cid_temp_reg =
1495 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1496
1497 const bool needs_field_temp_reg = emit_full_guard;
1498
1499 const Register value_reg = locs()->in(0).reg();
1500
1501 const Register value_cid_reg = needs_value_cid_temp_reg ?
1500 locs()->temp(0).reg() : kNoRegister; 1502 locs()->temp(0).reg() : kNoRegister;
1501 1503
1502 Register field_reg = needs_field_temp_reg ? 1504 const Register field_reg = needs_field_temp_reg ?
1503 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; 1505 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
1504 1506
1505 Label ok, fail_label; 1507 Label ok, fail_label;
1506 1508
1507 Label* deopt = compiler->is_optimizing() ? 1509 Label* deopt = compiler->is_optimizing() ?
1508 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; 1510 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
1509 1511
1510 Label* fail = (deopt != NULL) ? deopt : &fail_label; 1512 Label* fail = (deopt != NULL) ? deopt : &fail_label;
1511 1513
1512 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { 1514 if (emit_full_guard) {
1513 if (!compiler->is_optimizing() && (field_reg == kNoRegister)) {
1514 // Currently we can't have different location summaries for optimized
1515 // and non-optimized code. So instead we manually pick up a register
1516 // that is known to be free because we know how non-optimizing compiler
1517 // allocates registers.
1518 field_reg = EBX;
1519 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
1520 }
1521
1522 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); 1515 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1523 1516
1524 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); 1517 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
1525 FieldAddress field_nullability_operand( 1518 FieldAddress field_nullability_operand(
1526 field_reg, Field::is_nullable_offset()); 1519 field_reg, Field::is_nullable_offset());
1527 FieldAddress field_length_operand(
1528 field_reg, Field::guarded_list_length_offset());
1529 1520
1530 if (value_cid == kDynamicCid) { 1521 if (value_cid == kDynamicCid) {
1531 if (value_cid_reg == kNoRegister) {
1532 ASSERT(!compiler->is_optimizing());
1533 value_cid_reg = EDX;
1534 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1535 }
1536
1537 LoadValueCid(compiler, value_cid_reg, value_reg); 1522 LoadValueCid(compiler, value_cid_reg, value_reg);
1538 Label skip_length_check;
1539 __ cmpl(value_cid_reg, field_cid_operand); 1523 __ cmpl(value_cid_reg, field_cid_operand);
1540 // Value CID != Field guard CID, skip length check. 1524 __ j(EQUAL, &ok);
1541 __ j(NOT_EQUAL, &skip_length_check);
1542 if (field_has_length) {
1543 // Field guard may have remembered list length, check it.
1544 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1545 __ pushl(value_cid_reg);
1546 __ movl(value_cid_reg,
1547 FieldAddress(value_reg, Array::length_offset()));
1548 __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length)));
1549 __ popl(value_cid_reg);
1550 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1551 __ pushl(value_cid_reg);
1552 __ movl(value_cid_reg,
1553 FieldAddress(value_reg, TypedData::length_offset()));
1554 __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length)));
1555 __ popl(value_cid_reg);
1556 } else {
1557 ASSERT(field_cid == kIllegalCid);
1558 ASSERT(field_length == Field::kUnknownFixedLength);
1559 // At compile time we do not know the type of the field nor its
1560 // length. At execution time we may have set the class id and
1561 // list length so we compare the guarded length with the
1562 // list length here, without this check the list length could change
1563 // without triggering a deoptimization.
1564 Label check_array, length_compared, no_fixed_length;
1565 // If length is negative the length guard is either disabled or
1566 // has not been initialized, either way it is safe to skip the
1567 // length check.
1568 __ cmpl(field_length_operand, Immediate(Smi::RawValue(0)));
1569 __ j(LESS, &skip_length_check);
1570 __ cmpl(value_cid_reg, Immediate(kNullCid));
1571 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
1572 // Check for typed data array.
1573 __ cmpl(value_cid_reg, Immediate(kTypedDataInt32x4ArrayCid));
1574 // Not a typed array or a regular array.
1575 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1576 __ cmpl(value_cid_reg, Immediate(kTypedDataInt8ArrayCid));
1577 // Could still be a regular array.
1578 __ j(LESS, &check_array, Assembler::kNearJump);
1579 __ pushl(value_cid_reg);
1580 __ movl(value_cid_reg,
1581 FieldAddress(value_reg, TypedData::length_offset()));
1582 __ cmpl(field_length_operand, value_cid_reg);
1583 __ popl(value_cid_reg);
1584 __ jmp(&length_compared, Assembler::kNearJump);
1585 // Check for regular array.
1586 __ Bind(&check_array);
1587 __ cmpl(value_cid_reg, Immediate(kImmutableArrayCid));
1588 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1589 __ cmpl(value_cid_reg, Immediate(kArrayCid));
1590 __ j(LESS, &no_fixed_length, Assembler::kNearJump);
1591 __ pushl(value_cid_reg);
1592 __ movl(value_cid_reg,
1593 FieldAddress(value_reg, Array::length_offset()));
1594 __ cmpl(field_length_operand, value_cid_reg);
1595 __ popl(value_cid_reg);
1596 __ jmp(&length_compared, Assembler::kNearJump);
1597 __ Bind(&no_fixed_length);
1598 __ jmp(fail);
1599 __ Bind(&length_compared);
1600 }
1601 __ j(NOT_EQUAL, fail);
1602 }
1603 __ Bind(&skip_length_check);
1604 __ cmpl(value_cid_reg, field_nullability_operand); 1525 __ cmpl(value_cid_reg, field_nullability_operand);
1605 } else if (value_cid == kNullCid) { 1526 } else if (value_cid == kNullCid) {
1606 // Value in graph known to be null. 1527 // Value in graph known to be null.
1607 // Compare with null. 1528 // Compare with null.
1608 __ cmpl(field_nullability_operand, Immediate(value_cid)); 1529 __ cmpl(field_nullability_operand, Immediate(value_cid));
1609 } else { 1530 } else {
1610 // Value in graph known to be non-null. 1531 // Value in graph known to be non-null.
1611 Label skip_length_check;
1612 // Compare class id with guard field class id. 1532 // Compare class id with guard field class id.
1613 __ cmpl(field_cid_operand, Immediate(value_cid)); 1533 __ cmpl(field_cid_operand, Immediate(value_cid));
1614 // If not equal, skip over length check.
1615 __ j(NOT_EQUAL, &skip_length_check);
1616 // Insert length check.
1617 if (field_has_length) {
1618 ASSERT(value_cid_reg != kNoRegister);
1619 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1620 __ cmpl(FieldAddress(value_reg, Array::length_offset()),
1621 Immediate(Smi::RawValue(field_length)));
1622 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1623 __ cmpl(FieldAddress(value_reg, TypedData::length_offset()),
1624 Immediate(Smi::RawValue(field_length)));
1625 } else if (field_cid != kIllegalCid) {
1626 ASSERT(field_cid != value_cid);
1627 ASSERT(field_length >= 0);
1628 // Field has a known class id and length. At compile time it is
1629 // known that the value's class id is not a fixed length list.
1630 __ jmp(fail);
1631 } else {
1632 ASSERT(field_cid == kIllegalCid);
1633 ASSERT(field_length == Field::kUnknownFixedLength);
1634 // Following jump cannot not occur, fall through.
1635 }
1636 __ j(NOT_EQUAL, fail);
1637 }
1638 // Not identical, possibly null.
1639 __ Bind(&skip_length_check);
1640 } 1534 }
1641 // Jump when class id guard and list length guard are okay.
1642 __ j(EQUAL, &ok); 1535 __ j(EQUAL, &ok);
1643 1536
1644 // Check if guard field is uninitialized. 1537 // Check if the tracked state of the guarded field can be initialized
1645 __ cmpl(field_cid_operand, Immediate(kIllegalCid)); 1538 // inline. If the field needs length check we fall through to runtime
1646 // Jump to failure path when guard field has been initialized and 1539 // which is responsible for computing offset of the length field
1647 // the field and value class ids do not not match. 1540 // based on the class id.
1648 __ j(NOT_EQUAL, fail); 1541 // Length guard will be emitted separately when needed via GuardFieldLength
1542 // instruction after GuardFieldClass.
1543 if (!field().needs_length_check()) {
1544 // Uninitialized field can be handled inline. Check if the
1545 // field is still unitialized.
1546 __ cmpl(field_cid_operand, Immediate(kIllegalCid));
1547 // Jump to failure path when guard field has been initialized and
1548 // the field and value class ids do not not match.
1549 __ j(NOT_EQUAL, fail);
1649 1550
1650 // At this point the field guard is being initialized for the first time. 1551 if (value_cid == kDynamicCid) {
1651 if (value_cid == kDynamicCid) { 1552 // Do not know value's class id.
1652 // Do not know value's class id. 1553 __ movl(field_cid_operand, value_cid_reg);
1653 __ movl(field_cid_operand, value_cid_reg); 1554 __ movl(field_nullability_operand, value_cid_reg);
1654 __ movl(field_nullability_operand, value_cid_reg); 1555 } else {
1655 if (field_has_length) { 1556 ASSERT(field_reg != kNoRegister);
1656 Label check_array, length_set, no_fixed_length; 1557 __ movl(field_cid_operand, Immediate(value_cid));
1657 __ cmpl(value_cid_reg, Immediate(kNullCid)); 1558 __ movl(field_nullability_operand, Immediate(value_cid));
1658 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
1659 // Check for typed data array.
1660 __ cmpl(value_cid_reg, Immediate(kTypedDataInt32x4ArrayCid));
1661 // Not a typed array or a regular array.
1662 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1663 __ cmpl(value_cid_reg, Immediate(kTypedDataInt8ArrayCid));
1664 // Could still be a regular array.
1665 __ j(LESS, &check_array, Assembler::kNearJump);
1666 // Destroy value_cid_reg (safe because we are finished with it).
1667 __ movl(value_cid_reg,
1668 FieldAddress(value_reg, TypedData::length_offset()));
1669 __ movl(field_length_operand, value_cid_reg);
1670 // Updated field length typed data array.
1671 __ jmp(&length_set, Assembler::kNearJump);
1672 // Check for regular array.
1673 __ Bind(&check_array);
1674 __ cmpl(value_cid_reg, Immediate(kImmutableArrayCid));
1675 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1676 __ cmpl(value_cid_reg, Immediate(kArrayCid));
1677 __ j(LESS, &no_fixed_length, Assembler::kNearJump);
1678 // Destroy value_cid_reg (safe because we are finished with it).
1679 __ movl(value_cid_reg,
1680 FieldAddress(value_reg, Array::length_offset()));
1681 __ movl(field_length_operand, value_cid_reg);
1682 // Updated field length from regular array.
1683 __ jmp(&length_set, Assembler::kNearJump);
1684 __ Bind(&no_fixed_length);
1685 __ movl(field_length_operand,
1686 Immediate(Smi::RawValue(Field::kNoFixedLength)));
1687 __ Bind(&length_set);
1688 } 1559 }
1689 } else { 1560
1690 ASSERT(field_reg != kNoRegister); 1561 if (deopt == NULL) {
1691 __ movl(field_cid_operand, Immediate(value_cid)); 1562 ASSERT(!compiler->is_optimizing());
1692 __ movl(field_nullability_operand, Immediate(value_cid)); 1563 __ jmp(&ok);
1693 if (field_has_length) {
1694 ASSERT(value_cid_reg != kNoRegister);
1695 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1696 // Destroy value_cid_reg (safe because we are finished with it).
1697 __ movl(value_cid_reg,
1698 FieldAddress(value_reg, Array::length_offset()));
1699 __ movl(field_length_operand, value_cid_reg);
1700 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1701 // Destroy value_cid_reg (safe because we are finished with it).
1702 __ movl(value_cid_reg,
1703 FieldAddress(value_reg, TypedData::length_offset()));
1704 __ movl(field_length_operand, value_cid_reg);
1705 } else {
1706 __ movl(field_length_operand,
1707 Immediate(Smi::RawValue(Field::kNoFixedLength)));
1708 }
1709 } 1564 }
1710 } 1565 }
1711 1566
1712 if (deopt == NULL) { 1567 if (deopt == NULL) {
1713 ASSERT(!compiler->is_optimizing()); 1568 ASSERT(!compiler->is_optimizing());
1714 __ jmp(&ok);
1715 __ Bind(fail); 1569 __ Bind(fail);
1716 1570
1717 __ cmpl(FieldAddress(field_reg, Field::guarded_cid_offset()), 1571 __ cmpl(FieldAddress(field_reg, Field::guarded_cid_offset()),
1718 Immediate(kDynamicCid)); 1572 Immediate(kDynamicCid));
1719 __ j(EQUAL, &ok); 1573 __ j(EQUAL, &ok);
1720 1574
1721 __ pushl(field_reg); 1575 __ pushl(field_reg);
1722 __ pushl(value_reg); 1576 __ pushl(value_reg);
1723 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); 1577 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1724 __ Drop(2); // Drop the field and the value. 1578 __ Drop(2); // Drop the field and the value.
1725 } 1579 }
1726 } else { 1580 } else {
1727 ASSERT(compiler->is_optimizing()); 1581 ASSERT(compiler->is_optimizing());
1728 ASSERT(deopt != NULL); 1582 ASSERT(deopt != NULL);
1583 ASSERT(fail == deopt);
1584
1729 // Field guard class has been initialized and is known. 1585 // Field guard class has been initialized and is known.
1730 if (field_reg != kNoRegister) {
1731 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1732 }
1733
1734 if (value_cid == kDynamicCid) { 1586 if (value_cid == kDynamicCid) {
1735 // Value's class id is not known. 1587 // Value's class id is not known.
1736 __ testl(value_reg, Immediate(kSmiTagMask)); 1588 __ testl(value_reg, Immediate(kSmiTagMask));
1737 1589
1738 if (field_cid != kSmiCid) { 1590 if (field_cid != kSmiCid) {
1739 __ j(ZERO, fail); 1591 __ j(ZERO, fail);
1740 __ LoadClassId(value_cid_reg, value_reg); 1592 __ LoadClassId(value_cid_reg, value_reg);
1741 __ cmpl(value_cid_reg, Immediate(field_cid)); 1593 __ cmpl(value_cid_reg, Immediate(field_cid));
1742 } 1594 }
1743 1595
1744 if (field_has_length) {
1745 // Jump when Value CID != Field guard CID
1746 __ j(NOT_EQUAL, fail);
1747
1748 // Classes are same, perform guarded list length check.
1749 ASSERT(field_reg != kNoRegister);
1750 ASSERT(value_cid_reg != kNoRegister);
1751 FieldAddress field_length_operand(
1752 field_reg, Field::guarded_list_length_offset());
1753 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1754 // Destroy value_cid_reg (safe because we are finished with it).
1755 __ movl(value_cid_reg,
1756 FieldAddress(value_reg, Array::length_offset()));
1757 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1758 // Destroy value_cid_reg (safe because we are finished with it).
1759 __ movl(value_cid_reg,
1760 FieldAddress(value_reg, TypedData::length_offset()));
1761 }
1762 __ cmpl(value_cid_reg, field_length_operand);
1763 }
1764
1765 if (field().is_nullable() && (field_cid != kNullCid)) { 1596 if (field().is_nullable() && (field_cid != kNullCid)) {
1766 __ j(EQUAL, &ok); 1597 __ j(EQUAL, &ok);
1767 const Immediate& raw_null = 1598 if (field_cid != kSmiCid) {
1768 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1599 __ cmpl(value_cid_reg, Immediate(kNullCid));
1769 __ cmpl(value_reg, raw_null); 1600 } else {
1601 const Immediate& raw_null =
1602 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1603 __ cmpl(value_reg, raw_null);
1604 }
1770 } 1605 }
1771 __ j(NOT_EQUAL, fail); 1606 __ j(NOT_EQUAL, fail);
1772 } else { 1607 } else {
1773 // Both value's and field's class id is known. 1608 // Both value's and field's class id is known.
1774 if ((value_cid != field_cid) && (value_cid != nullability)) { 1609 ASSERT((value_cid != field_cid) && (value_cid != nullability));
1775 __ jmp(fail); 1610 __ jmp(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 __ movl(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 __ movl(value_cid_reg,
1785 FieldAddress(value_reg, TypedData::length_offset()));
1786 }
1787 __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length)));
1788 __ j(NOT_EQUAL, fail);
1789 } else {
1790 UNREACHABLE();
1791 }
1792 } 1611 }
1793 } 1612 }
1794 __ Bind(&ok); 1613 __ Bind(&ok);
1795 } 1614 }
1796 1615
1797 1616
1617 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Isolate* isolate,
1618 bool opt) const {
1619 const intptr_t kNumInputs = 1;
1620 LocationSummary* summary = new(isolate) LocationSummary(
1621 isolate, kNumInputs, 0, LocationSummary::kNoCall);
1622 summary->set_in(0, Location::RequiresRegister());
1623
1624 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1625 // We need temporaries for field object, length offset and expected length.
1626 summary->AddTemp(Location::RequiresRegister());
1627 summary->AddTemp(Location::RequiresRegister());
1628 summary->AddTemp(Location::RequiresRegister());
1629 }
1630
1631 return summary;
1632 }
1633
1634
1635 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1636 if (field().guarded_list_length() == Field::kNoFixedLength) {
1637 ASSERT(!compiler->is_optimizing());
1638 return; // Nothing to emit.
1639 }
1640
1641 Label* deopt = compiler->is_optimizing() ?
1642 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
1643
1644 const Register value_reg = locs()->in(0).reg();
1645
1646 if (!compiler->is_optimizing() ||
1647 (field().guarded_list_length() == Field::kUnknownFixedLength)) {
1648 const Register field_reg = locs()->temp(0).reg();
1649 const Register offset_reg = locs()->temp(1).reg();
1650 const Register length_reg = locs()->temp(2).reg();
1651
1652 Label ok;
1653
1654 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1655
1656 __ movsxb(offset_reg, FieldAddress(field_reg,
1657 Field::guarded_list_length_in_object_offset_offset()));
1658 __ movl(length_reg, FieldAddress(field_reg,
1659 Field::guarded_list_length_offset()));
1660
1661 __ cmpl(offset_reg, Immediate(0));
1662 __ j(NEGATIVE, &ok);
1663
1664 // Load the length from the value. GuardFieldClass already verified that
1665 // value's class matches guarded class id of the field.
1666 // offset_reg contains offset already corrected by -kHeapObjectTag that is
1667 // why we use Address instead of FieldAddress.
1668 __ cmpl(length_reg, Address(value_reg, offset_reg, TIMES_1, 0));
1669
1670 if (deopt == NULL) {
1671 __ j(EQUAL, &ok);
1672
1673 __ pushl(field_reg);
1674 __ pushl(value_reg);
1675 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1676 __ Drop(2); // Drop the field and the value.
1677 } else {
1678 __ j(NOT_EQUAL, deopt);
1679 }
1680
1681 __ Bind(&ok);
1682 } else {
1683 ASSERT(compiler->is_optimizing());
1684 ASSERT(field().guarded_list_length() >= 0);
1685 ASSERT(field().guarded_list_length_in_object_offset() !=
1686 Field::kUnknownLengthOffset);
1687
1688 __ cmpl(FieldAddress(value_reg,
1689 field().guarded_list_length_in_object_offset()),
1690 Immediate(Smi::RawValue(field().guarded_list_length())));
1691 __ j(NOT_EQUAL, deopt);
1692 }
1693 }
1694
1695
1798 class StoreInstanceFieldSlowPath : public SlowPathCode { 1696 class StoreInstanceFieldSlowPath : public SlowPathCode {
1799 public: 1697 public:
1800 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, 1698 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction,
1801 const Class& cls) 1699 const Class& cls)
1802 : instruction_(instruction), cls_(cls) { } 1700 : instruction_(instruction), cls_(cls) { }
1803 1701
1804 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 1702 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
1805 __ Comment("StoreInstanceFieldSlowPath"); 1703 __ Comment("StoreInstanceFieldSlowPath");
1806 __ Bind(entry_label()); 1704 __ Bind(entry_label());
1807 const Code& stub = 1705 const Code& stub =
(...skipping 4575 matching lines...) Expand 10 before | Expand all | Expand 10 after
6383 PcDescriptors::kOther, 6281 PcDescriptors::kOther,
6384 locs()); 6282 locs());
6385 __ Drop(ArgumentCount()); // Discard arguments. 6283 __ Drop(ArgumentCount()); // Discard arguments.
6386 } 6284 }
6387 6285
6388 } // namespace dart 6286 } // namespace dart
6389 6287
6390 #undef __ 6288 #undef __
6391 6289
6392 #endif // defined TARGET_ARCH_IA32 6290 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698