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

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: rewritten instruction pattern on ia32 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
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 (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, &not_smi, Assembler::kNearJump);
1534 __ movl(value_cid_reg, Immediate(kSmiCid));
1535 __ jmp(&cid_loaded);
1536 __ Bind(&not_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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698