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

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

Issue 12529008: Collect type feedback for fields. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 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 "lib/error.h" 10 #include "lib/error.h"
11 #include "vm/dart_entry.h" 11 #include "vm/dart_entry.h"
12 #include "vm/flow_graph_compiler.h" 12 #include "vm/flow_graph_compiler.h"
13 #include "vm/locations.h" 13 #include "vm/locations.h"
14 #include "vm/object_store.h" 14 #include "vm/object_store.h"
15 #include "vm/parser.h" 15 #include "vm/parser.h"
16 #include "vm/stack_frame.h"
16 #include "vm/stub_code.h" 17 #include "vm/stub_code.h"
17 #include "vm/symbols.h" 18 #include "vm/symbols.h"
18 19
19 #define __ compiler->assembler()-> 20 #define __ compiler->assembler()->
20 21
21 namespace dart { 22 namespace dart {
22 23
23 DECLARE_FLAG(int, optimization_counter_threshold); 24 DECLARE_FLAG(int, optimization_counter_threshold);
24 DECLARE_FLAG(bool, propagate_ic_data); 25 DECLARE_FLAG(bool, propagate_ic_data);
25 26
(...skipping 1475 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 break; 1502 break;
1502 case kFloat64ArrayCid: 1503 case kFloat64ArrayCid:
1503 __ movsd(element_address, locs()->in(2).fpu_reg()); 1504 __ movsd(element_address, locs()->in(2).fpu_reg());
1504 break; 1505 break;
1505 default: 1506 default:
1506 UNREACHABLE(); 1507 UNREACHABLE();
1507 } 1508 }
1508 } 1509 }
1509 1510
1510 1511
1512 LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
1513 const intptr_t kNumInputs = 1;
1514 LocationSummary* summary =
1515 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
1516 summary->set_in(0, Location::RequiresRegister());
1517 if (value()->Type()->ToCid() == kDynamicCid) {
1518 summary->AddTemp(Location::RequiresRegister());
1519 }
1520 if (field().guarded_cid() == kIllegalCid) {
1521 summary->AddTemp(Location::RequiresRegister());
1522 }
1523 return summary;
1524 }
1525
1526
1527 static void PushCid(FlowGraphCompiler* compiler, const Immediate& imm) {
1528 __ pushl(Immediate(Smi::RawValue(imm.value())));
1529 }
1530
1531
1532 static void PushCid(FlowGraphCompiler* compiler, Register reg) {
1533 __ SmiTag(reg);
1534 __ pushl(reg);
1535 }
1536
1537
1538 template<typename ValueCidOperandType>
1539 static void EmitCidGuardInit(FlowGraphCompiler* compiler,
1540 ValueCidOperandType value_cid,
1541 const Immediate& field_cid,
1542 const Immediate& nullability,
1543 Label* deopt,
1544 Label* ok) {
1545 // nothing to do.
1546 }
1547
1548
1549 template<typename ValueCidOperandType>
1550 static void EmitCidGuardInit(FlowGraphCompiler* compiler,
1551 ValueCidOperandType value_cid,
1552 const FieldAddress& field_cid,
1553 const FieldAddress& nullability,
1554 Label* deopt,
1555 Label* ok) {
1556 // Check if field is initialized for the first time.
1557 Label fail;
1558 __ cmpl(field_cid, Immediate(kIllegalCid));
1559 __ j(NOT_EQUAL, (deopt != NULL) ? deopt : &fail);
1560 __ movl(field_cid, value_cid);
1561 __ movl(nullability, value_cid);
1562 __ jmp(ok);
1563 if (deopt == NULL) {
1564 __ Bind(&fail);
1565 }
1566 }
1567
1568
1569 static void CompareJump(FlowGraphCompiler* compiler,
1570 Condition cond,
1571 const Immediate& left,
1572 const Immediate& right,
1573 Label* target) {
1574 if ((left.value() == right.value()) && (cond == EQUAL)) {
1575 __ jmp(target);
1576 } else if ((left.value() != right.value()) && cond == NOT_EQUAL) {
1577 __ jmp(target);
1578 }
1579 }
1580
1581
1582 static void CompareJump(FlowGraphCompiler* compiler,
1583 Condition cond,
1584 Immediate left,
1585 Register right,
1586 Label* target) {
1587 ASSERT((cond == EQUAL) || (cond == NOT_EQUAL));
1588 __ cmpl(right, left);
1589 __ j(cond, target);
1590 }
1591
1592
1593 template<typename LeftT, typename RightT>
Kevin Millikin (Google) 2013/03/12 12:14:56 Spell out Type like below, or at least be uniform.
Vyacheslav Egorov (Google) 2013/03/12 16:54:40 Done.
1594 static void CompareJump(FlowGraphCompiler* compiler,
1595 Condition cond,
1596 LeftT left,
1597 RightT right,
1598 Label* target) {
1599 __ cmpl(left, right);
1600 __ j(cond, target);
1601 }
1602
1603
1604 template<typename ValueCidOperandType,
1605 typename FieldCidOperandType,
1606 typename FieldNullabilityOperandType>
1607 static void EmitCidGuard(FlowGraphCompiler* compiler,
1608 const Field& field,
Kevin Millikin (Google) 2013/03/12 12:14:56 The templates are kind of messy because you have t
Vyacheslav Egorov (Google) 2013/03/12 16:54:40 Done.
1609 ValueCidOperandType value_cid,
1610 FieldCidOperandType field_cid,
1611 FieldNullabilityOperandType nullability,
1612 Label* deopt) {
1613 Label ok, update;
1614 CompareJump(compiler, EQUAL, field_cid, value_cid, &ok);
1615 if ((deopt != NULL) && (field.guarded_cid() != kIllegalCid)) {
1616 CompareJump(compiler, NOT_EQUAL, nullability, value_cid, deopt);
1617 } else {
1618 CompareJump(compiler, EQUAL, nullability, value_cid, &ok);
1619 }
1620
1621 EmitCidGuardInit(compiler, value_cid, field_cid, nullability, deopt, &ok);
1622
1623 if (deopt == NULL) {
1624 // Switch field's cid to dynamic and notify runtime.
1625 CompareJump(compiler, EQUAL, field_cid, Immediate(kDynamicCid), &ok);
1626 __ PushObject(field);
1627 PushCid(compiler, value_cid);
1628 __ CallRuntime(kUpdateFieldCidRuntimeEntry);
1629 __ Drop(2);
1630 }
1631
1632 __ Bind(&ok);
1633 }
1634
1635
1636 template<typename FieldCidOperandType, typename FieldNullabilityOperandType>
1637 static void EmitCidGuard(FlowGraphCompiler* compiler,
1638 const Field& field,
1639 intptr_t value_cid,
1640 Register value_cid_reg,
1641 FieldCidOperandType field_cid,
1642 FieldNullabilityOperandType nullability,
1643 Label* deopt) {
1644 if (value_cid == kDynamicCid) {
1645 EmitCidGuard(compiler, field, value_cid_reg, field_cid, nullability, deopt);
1646 } else {
1647 EmitCidGuard(compiler,
1648 field,
1649 Immediate(value_cid),
1650 field_cid,
1651 nullability,
1652 deopt);
1653 }
1654 }
1655
1656
1657 static void EmitFieldGuard(FlowGraphCompiler* compiler,
1658 Register value_reg,
1659 const Field& field,
1660 intptr_t value_cid,
1661 Register value_cid_reg,
1662 intptr_t field_cid,
1663 intptr_t nullability,
1664 Register field_reg,
1665 Label* deopt) {
1666 if (value_cid == kDynamicCid) {
1667 Label not_smi, cid_loaded;
1668 __ testl(value_reg, Immediate(kSmiTagMask));
1669 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
1670 __ movl(value_cid_reg, Immediate(kSmiCid));
1671 __ jmp(&cid_loaded);
1672 __ Bind(&not_smi);
1673 __ LoadClassId(value_cid_reg, value_reg);
1674 __ Bind(&cid_loaded);
1675 }
1676
1677 if (field_cid == kIllegalCid) {
1678 __ LoadObject(field_reg, Field::ZoneHandle(field.raw()));
1679 EmitCidGuard(compiler,
1680 field,
1681 value_cid,
1682 value_cid_reg,
1683 FieldAddress(field_reg, Field::guarded_cid_offset()),
1684 FieldAddress(field_reg, Field::is_nullable_offset()),
1685 deopt);
1686 } else {
1687 EmitCidGuard(compiler,
1688 field,
1689 value_cid,
1690 value_cid_reg,
1691 Immediate(field_cid),
1692 Immediate(nullability),
1693 deopt);
1694 }
1695 }
1696
1697
1698 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1699 const intptr_t value_cid = value()->Type()->ToCid();
1700 const intptr_t field_cid = field().guarded_cid();
1701 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1702
1703 Register value_reg = locs()->in(0).reg();
1704
1705 Register value_cid_reg = (value_cid == kDynamicCid) ?
1706 locs()->temp(0).reg() : kNoRegister;
1707
1708 Label* deopt = compiler->is_optimizing() && CanDeoptimize() ?
1709 compiler->AddDeoptStub(deopt_id(), kDeoptStoreInstanceField) : NULL;
1710
1711 if ((deopt != NULL) && (field_cid != kIllegalCid)) {
1712 if (value_cid != kDynamicCid) {
1713 ASSERT(field_cid != value_cid);
1714 __ jmp(deopt);
1715 return;
1716 }
1717
1718 if (field_cid == kSmiCid) {
1719 __ testl(value_reg, Immediate(kSmiTagMask));
1720 } else {
1721 ASSERT(value_cid_reg != kNoRegister);
1722 __ testl(value_reg, Immediate(kSmiTagMask));
1723 __ j(ZERO, deopt);
1724 __ LoadClassId(value_cid_reg, value_reg);
1725 __ cmpl(value_cid_reg, Immediate(field_cid));
1726 }
1727
1728 if (field().is_nullable()) {
1729 Label ok;
1730 __ j(EQUAL, &ok);
1731 const Immediate& raw_null =
1732 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1733 __ cmpl(value_reg, raw_null);
1734 __ j(NOT_EQUAL, deopt);
1735 __ Bind(&ok);
1736 } else {
1737 __ j(NOT_EQUAL, deopt);
1738 }
1739
1740 return;
1741 }
1742
1743 Register field_reg = (field_cid == kIllegalCid) ?
1744 locs()->temp(1).reg() : kNoRegister;
1745
1746 EmitFieldGuard(compiler,
1747 value_reg,
1748 field(),
1749 value_cid, value_cid_reg,
1750 field_cid, nullability, field_reg,
1751 deopt);
1752 }
1753
1754
1511 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { 1755 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
1512 const intptr_t kNumInputs = 2; 1756 const intptr_t kNumInputs = 2;
1513 const intptr_t num_temps = 0; 1757 const intptr_t num_temps = 0;
1514 LocationSummary* summary = 1758 LocationSummary* summary =
1515 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); 1759 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall);
1516 summary->set_in(0, Location::RequiresRegister()); 1760 summary->set_in(0, Location::RequiresRegister());
1517 summary->set_in(1, ShouldEmitStoreBarrier() 1761 if (ShouldEmitStoreBarrier() || should_emit_field_guard()) {
1518 ? Location::WritableRegister() 1762 summary->set_in(1, Location::WritableRegister());
1519 : Location::RegisterOrConstant(value())); 1763 } else {
1764 summary->set_in(1, Location::RegisterOrConstant(value()));
1765 }
1766
1767 if (should_emit_field_guard()) {
1768 summary->AddTemp(Location::RequiresRegister());
1769 summary->AddTemp(Location::RequiresRegister());
1770 }
1771
1520 return summary; 1772 return summary;
1521 } 1773 }
1522 1774
1523 1775
1524 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1776 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1525 Register instance_reg = locs()->in(0).reg(); 1777 Register instance_reg = locs()->in(0).reg();
1778
1779 if (should_emit_field_guard()) {
1780 ASSERT(!compiler->is_optimizing());
1781 Register value_reg = locs()->in(1).reg();
1782 Register value_cid_reg = locs()->temp(0).reg();
1783 Register field_reg = locs()->temp(1).reg();
1784
1785 __ pushl(instance_reg);
1786 __ pushl(value_reg);
1787 EmitFieldGuard(compiler,
1788 value_reg,
1789 field(),
1790 kDynamicCid,
1791 value_cid_reg,
1792 kIllegalCid,
1793 kIllegalCid,
1794 field_reg,
1795 NULL);
1796 __ popl(value_reg);
1797 __ popl(instance_reg);
1798 }
1799
1526 if (ShouldEmitStoreBarrier()) { 1800 if (ShouldEmitStoreBarrier()) {
1527 Register value_reg = locs()->in(1).reg(); 1801 Register value_reg = locs()->in(1).reg();
1528 __ StoreIntoObject(instance_reg, 1802 __ StoreIntoObject(instance_reg,
1529 FieldAddress(instance_reg, field().Offset()), value_reg); 1803 FieldAddress(instance_reg, field().Offset()), value_reg);
1530 } else { 1804 } else {
1531 if (locs()->in(1).IsConstant()) { 1805 if (locs()->in(1).IsConstant()) {
1532 __ StoreIntoObjectNoBarrier( 1806 __ StoreIntoObjectNoBarrier(
1533 instance_reg, 1807 instance_reg,
1534 FieldAddress(instance_reg, field().Offset()), 1808 FieldAddress(instance_reg, field().Offset()),
1535 locs()->in(1).constant()); 1809 locs()->in(1).constant());
(...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after
2821 } 3095 }
2822 3096
2823 3097
2824 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3098 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2825 comparison()->EmitBranchCode(compiler, this); 3099 comparison()->EmitBranchCode(compiler, this);
2826 } 3100 }
2827 3101
2828 3102
2829 LocationSummary* CheckClassInstr::MakeLocationSummary() const { 3103 LocationSummary* CheckClassInstr::MakeLocationSummary() const {
2830 const intptr_t kNumInputs = 1; 3104 const intptr_t kNumInputs = 1;
2831 const intptr_t kNumTemps = 1; 3105 const intptr_t kNumTemps = 0;
2832 LocationSummary* summary = 3106 LocationSummary* summary =
2833 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 3107 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2834 summary->set_in(0, Location::RequiresRegister()); 3108 summary->set_in(0, Location::RequiresRegister());
2835 summary->set_temp(0, Location::RequiresRegister()); 3109 if (!null_check()) {
3110 summary->AddTemp(Location::RequiresRegister());
3111 }
2836 return summary; 3112 return summary;
2837 } 3113 }
2838 3114
2839 3115
2840 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3116 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3117 if (null_check()) {
3118 Label* deopt = compiler->AddDeoptStub(deopt_id(),
3119 kDeoptCheckClass);
3120 const Immediate& raw_null =
3121 Immediate(reinterpret_cast<intptr_t>(Object::null()));
3122 __ cmpl(locs()->in(0).reg(), raw_null);
3123 __ j(EQUAL, deopt);
3124 return;
3125 }
3126
2841 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || 3127 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) ||
2842 (unary_checks().NumberOfChecks() > 1)); 3128 (unary_checks().NumberOfChecks() > 1));
2843 Register value = locs()->in(0).reg(); 3129 Register value = locs()->in(0).reg();
2844 Register temp = locs()->temp(0).reg(); 3130 Register temp = locs()->temp(0).reg();
2845 Label* deopt = compiler->AddDeoptStub(deopt_id(), 3131 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2846 kDeoptCheckClass); 3132 kDeoptCheckClass);
2847 Label is_ok; 3133 Label is_ok;
2848 intptr_t cix = 0; 3134 intptr_t cix = 0;
2849 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { 3135 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
2850 __ testl(value, Immediate(kSmiTagMask)); 3136 __ testl(value, Immediate(kSmiTagMask));
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
3554 PcDescriptors::kOther, 3840 PcDescriptors::kOther,
3555 locs()); 3841 locs());
3556 __ Drop(2); // Discard type arguments and receiver. 3842 __ Drop(2); // Discard type arguments and receiver.
3557 } 3843 }
3558 3844
3559 } // namespace dart 3845 } // namespace dart
3560 3846
3561 #undef __ 3847 #undef __
3562 3848
3563 #endif // defined TARGET_ARCH_IA32 3849 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698