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/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 Loading... | |
| 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 (field().guarded_cid() != kSmiCid)) { | |
| 1519 summary->AddTemp(Location::RequiresRegister()); | |
| 1520 } | |
| 1521 if (field().guarded_cid() == kIllegalCid) { | |
| 1522 summary->AddTemp(Location::RequiresRegister()); | |
| 1523 } | |
| 1524 return summary; | |
| 1525 } | |
| 1526 | |
| 1527 | |
| 1528 static void LoadValueCid(FlowGraphCompiler* compiler, | |
|
Kevin Millikin (Google)
2013/03/15 12:17:21
I think we have this pattern in a few places. Emit
Vyacheslav Egorov (Google)
2013/03/15 13:01:10
Done.
| |
| 1529 Register value_reg, | |
| 1530 Register value_cid_reg) { | |
|
Kevin Millikin (Google)
2013/03/15 12:17:21
I guess the order of these registers should be swa
Vyacheslav Egorov (Google)
2013/03/15 13:01:10
Done.
| |
| 1531 Label not_smi, cid_loaded; | |
| 1532 __ testl(value_reg, Immediate(kSmiTagMask)); | |
| 1533 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | |
| 1534 __ movl(value_cid_reg, Immediate(kSmiCid)); | |
| 1535 __ jmp(&cid_loaded); | |
| 1536 __ Bind(¬_smi); | |
| 1537 __ LoadClassId(value_cid_reg, value_reg); | |
| 1538 __ Bind(&cid_loaded); | |
| 1539 } | |
| 1540 | |
| 1541 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1542 const intptr_t field_cid = field().guarded_cid(); | |
| 1543 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | |
| 1544 | |
| 1545 if (field_cid == kDynamicCid) { | |
| 1546 ASSERT(!compiler->is_optimizing()); | |
| 1547 return; // Nothing to emit. | |
| 1548 } | |
| 1549 | |
| 1550 const intptr_t value_cid = value()->Type()->ToCid(); | |
| 1551 | |
| 1552 Register value_reg = locs()->in(0).reg(); | |
| 1553 | |
| 1554 Register value_cid_reg = ((value_cid == kDynamicCid) && | |
| 1555 (field_cid != kSmiCid)) ? locs()->temp(0).reg() : kNoRegister; | |
| 1556 | |
| 1557 Register field_reg = (field_cid == kIllegalCid) ? | |
| 1558 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | |
| 1559 | |
| 1560 Label ok, fail_label; | |
| 1561 | |
| 1562 Label* deopt = compiler->is_optimizing() ? | |
| 1563 compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL; | |
| 1564 | |
| 1565 Label* fail = (deopt != NULL) ? deopt : &fail_label; | |
| 1566 | |
| 1567 const bool ok_is_fall_through = (deopt != NULL); | |
| 1568 | |
| 1569 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { | |
| 1570 if (field_reg == kNoRegister) { | |
|
Kevin Millikin (Google)
2013/03/15 12:17:21
It seems to me that
(field_reg == kNoRegister) if
Vyacheslav Egorov (Google)
2013/03/15 13:01:10
Done.
| |
| 1571 field_reg = EBX; | |
| 1572 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg)); | |
| 1573 } | |
| 1574 | |
| 1575 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); | |
| 1576 | |
| 1577 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | |
| 1578 FieldAddress field_nullability_operand( | |
| 1579 field_reg, Field::is_nullable_offset()); | |
| 1580 | |
| 1581 if (value_cid == kDynamicCid) { | |
| 1582 if (value_cid_reg == kNoRegister) { | |
| 1583 ASSERT(!compiler->is_optimizing()); | |
| 1584 value_cid_reg = EDX; | |
| 1585 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); | |
| 1586 } | |
| 1587 | |
| 1588 LoadValueCid(compiler, value_reg, value_cid_reg); | |
| 1589 | |
| 1590 __ cmpl(value_cid_reg, field_cid_operand); | |
| 1591 __ j(EQUAL, &ok); | |
| 1592 __ cmpl(value_cid_reg, field_nullability_operand); | |
| 1593 } else if (value_cid == kNullCid) { | |
| 1594 __ cmpl(field_nullability_operand, Immediate(value_cid)); | |
| 1595 } else { | |
| 1596 __ cmpl(field_cid_operand, Immediate(value_cid)); | |
| 1597 } | |
| 1598 __ j(EQUAL, &ok); | |
| 1599 | |
| 1600 __ cmpl(field_cid_operand, Immediate(kIllegalCid)); | |
| 1601 __ j(NOT_EQUAL, fail); | |
| 1602 | |
| 1603 if (value_cid == kDynamicCid) { | |
| 1604 __ movl(field_cid_operand, value_cid_reg); | |
| 1605 __ movl(field_nullability_operand, value_cid_reg); | |
| 1606 } else { | |
| 1607 __ movl(field_cid_operand, Immediate(value_cid)); | |
| 1608 __ movl(field_nullability_operand, Immediate(value_cid)); | |
| 1609 } | |
| 1610 | |
| 1611 if (!ok_is_fall_through) { | |
| 1612 __ jmp(&ok); | |
| 1613 } | |
| 1614 } else { | |
| 1615 if (value_cid == kDynamicCid) { | |
| 1616 // Field's guarded class id is fixed by value's class id is not known. | |
|
Kevin Millikin (Google)
2013/03/15 12:17:21
by ==> but
Vyacheslav Egorov (Google)
2013/03/15 13:01:10
Done.
| |
| 1617 __ testl(value_reg, Immediate(kSmiTagMask)); | |
| 1618 | |
| 1619 if (field_cid != kSmiCid) { | |
| 1620 __ j(ZERO, fail); | |
| 1621 __ LoadClassId(value_cid_reg, value_reg); | |
| 1622 __ cmpl(value_cid_reg, Immediate(field_cid)); | |
| 1623 } | |
| 1624 | |
| 1625 if (field().is_nullable() && (field_cid != kNullCid)) { | |
| 1626 __ j(EQUAL, &ok); | |
| 1627 const Immediate& raw_null = | |
| 1628 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 1629 __ cmpl(value_reg, raw_null); | |
| 1630 } | |
| 1631 | |
| 1632 if (ok_is_fall_through) { | |
| 1633 __ j(NOT_EQUAL, fail); | |
| 1634 } else { | |
| 1635 __ j(EQUAL, &ok); | |
| 1636 } | |
| 1637 } else { | |
| 1638 // Both value's and field's class id is known. | |
| 1639 if ((value_cid != field_cid) && (value_cid != nullability)) { | |
| 1640 if (ok_is_fall_through) { | |
| 1641 __ jmp(fail); | |
| 1642 } | |
| 1643 } else { | |
| 1644 // Nothing to emit. | |
| 1645 ASSERT(!compiler->is_optimizing()); | |
| 1646 return; | |
| 1647 } | |
| 1648 } | |
| 1649 } | |
| 1650 | |
| 1651 if (deopt == NULL) { | |
| 1652 ASSERT(!compiler->is_optimizing()); | |
| 1653 __ Bind(fail); | |
| 1654 | |
| 1655 __ cmpl(FieldAddress(field_reg, Field::guarded_cid_offset()), | |
| 1656 Immediate(kDynamicCid)); | |
| 1657 __ j(EQUAL, &ok); | |
| 1658 | |
| 1659 __ pushl(field_reg); | |
| 1660 __ pushl(value_reg); | |
| 1661 __ CallRuntime(kUpdateFieldCidRuntimeEntry); | |
| 1662 __ Drop(2); // Drop the field and the value. | |
|
Kevin Millikin (Google)
2013/03/15 12:17:21
You're right, it's still spaghetti. But now it's
| |
| 1663 } | |
| 1664 | |
| 1665 __ Bind(&ok); | |
| 1666 } | |
| 1667 | |
| 1668 | |
| 1511 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1669 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
| 1512 const intptr_t kNumInputs = 2; | 1670 const intptr_t kNumInputs = 2; |
| 1513 const intptr_t num_temps = 0; | 1671 const intptr_t num_temps = 0; |
| 1514 LocationSummary* summary = | 1672 LocationSummary* summary = |
| 1515 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); | 1673 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1516 summary->set_in(0, Location::RequiresRegister()); | 1674 summary->set_in(0, Location::RequiresRegister()); |
| 1517 summary->set_in(1, ShouldEmitStoreBarrier() | 1675 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1518 ? Location::WritableRegister() | 1676 ? Location::WritableRegister() |
| 1519 : Location::RegisterOrConstant(value())); | 1677 : Location::RegisterOrConstant(value())); |
| 1520 return summary; | 1678 return summary; |
| (...skipping 1300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2821 } | 2979 } |
| 2822 | 2980 |
| 2823 | 2981 |
| 2824 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2982 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2825 comparison()->EmitBranchCode(compiler, this); | 2983 comparison()->EmitBranchCode(compiler, this); |
| 2826 } | 2984 } |
| 2827 | 2985 |
| 2828 | 2986 |
| 2829 LocationSummary* CheckClassInstr::MakeLocationSummary() const { | 2987 LocationSummary* CheckClassInstr::MakeLocationSummary() const { |
| 2830 const intptr_t kNumInputs = 1; | 2988 const intptr_t kNumInputs = 1; |
| 2831 const intptr_t kNumTemps = 1; | 2989 const intptr_t kNumTemps = 0; |
| 2832 LocationSummary* summary = | 2990 LocationSummary* summary = |
| 2833 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2991 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2834 summary->set_in(0, Location::RequiresRegister()); | 2992 summary->set_in(0, Location::RequiresRegister()); |
| 2835 summary->set_temp(0, Location::RequiresRegister()); | 2993 if (!null_check()) { |
| 2994 summary->AddTemp(Location::RequiresRegister()); | |
| 2995 } | |
| 2836 return summary; | 2996 return summary; |
| 2837 } | 2997 } |
| 2838 | 2998 |
| 2839 | 2999 |
| 2840 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3000 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3001 if (null_check()) { | |
| 3002 Label* deopt = compiler->AddDeoptStub(deopt_id(), | |
| 3003 kDeoptCheckClass); | |
| 3004 const Immediate& raw_null = | |
| 3005 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 3006 __ cmpl(locs()->in(0).reg(), raw_null); | |
| 3007 __ j(EQUAL, deopt); | |
| 3008 return; | |
| 3009 } | |
| 3010 | |
| 2841 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 3011 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| 2842 (unary_checks().NumberOfChecks() > 1)); | 3012 (unary_checks().NumberOfChecks() > 1)); |
| 2843 Register value = locs()->in(0).reg(); | 3013 Register value = locs()->in(0).reg(); |
| 2844 Register temp = locs()->temp(0).reg(); | 3014 Register temp = locs()->temp(0).reg(); |
| 2845 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3015 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2846 kDeoptCheckClass); | 3016 kDeoptCheckClass); |
| 2847 Label is_ok; | 3017 Label is_ok; |
| 2848 intptr_t cix = 0; | 3018 intptr_t cix = 0; |
| 2849 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { | 3019 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { |
| 2850 __ testl(value, Immediate(kSmiTagMask)); | 3020 __ testl(value, Immediate(kSmiTagMask)); |
| (...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3554 PcDescriptors::kOther, | 3724 PcDescriptors::kOther, |
| 3555 locs()); | 3725 locs()); |
| 3556 __ Drop(2); // Discard type arguments and receiver. | 3726 __ Drop(2); // Discard type arguments and receiver. |
| 3557 } | 3727 } |
| 3558 | 3728 |
| 3559 } // namespace dart | 3729 } // namespace dart |
| 3560 | 3730 |
| 3561 #undef __ | 3731 #undef __ |
| 3562 | 3732 |
| 3563 #endif // defined TARGET_ARCH_IA32 | 3733 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |