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

Side by Side Diff: src/hydrogen-instructions.cc

Issue 10837165: Lattice-based representation inference, powered by left/right specific type feedback for BinaryOps … (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: review feedback; fixed tests Created 8 years, 1 month 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 | « src/hydrogen-instructions.h ('k') | src/ia32/code-stubs-ia32.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 void HValue::AssumeRepresentation(Representation r) { 78 void HValue::AssumeRepresentation(Representation r) {
79 if (CheckFlag(kFlexibleRepresentation)) { 79 if (CheckFlag(kFlexibleRepresentation)) {
80 ChangeRepresentation(r); 80 ChangeRepresentation(r);
81 // The representation of the value is dictated by type feedback and 81 // The representation of the value is dictated by type feedback and
82 // will not be changed later. 82 // will not be changed later.
83 ClearFlag(kFlexibleRepresentation); 83 ClearFlag(kFlexibleRepresentation);
84 } 84 }
85 } 85 }
86 86
87 87
88 void HValue::InferRepresentation(HInferRepresentation* h_infer) {
89 ASSERT(CheckFlag(kFlexibleRepresentation));
90 Representation new_rep = RepresentationFromInputs();
91 UpdateRepresentation(new_rep, h_infer, "inputs");
92 new_rep = RepresentationFromUses();
93 UpdateRepresentation(new_rep, h_infer, "uses");
94 }
95
96
97 Representation HValue::RepresentationFromUses() {
98 if (HasNoUses()) return Representation::None();
99
100 // Array of use counts for each representation.
101 int use_count[Representation::kNumRepresentations] = { 0 };
102
103 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
104 HValue* use = it.value();
105 Representation rep = use->observed_input_representation(it.index());
106 if (rep.IsNone()) continue;
107 if (FLAG_trace_representation) {
108 PrintF("#%d %s is used by #%d %s as %s%s\n",
109 id(), Mnemonic(), use->id(), use->Mnemonic(), rep.Mnemonic(),
110 (use->CheckFlag(kTruncatingToInt32) ? "-trunc" : ""));
111 }
112 use_count[rep.kind()] += use->LoopWeight();
113 }
114 if (IsPhi()) HPhi::cast(this)->AddIndirectUsesTo(&use_count[0]);
115 int tagged_count = use_count[Representation::kTagged];
116 int double_count = use_count[Representation::kDouble];
117 int int32_count = use_count[Representation::kInteger32];
118
119 if (tagged_count > 0) return Representation::Tagged();
120 if (double_count > 0) return Representation::Double();
121 if (int32_count > 0) return Representation::Integer32();
122
123 return Representation::None();
124 }
125
126
127 void HValue::UpdateRepresentation(Representation new_rep,
128 HInferRepresentation* h_infer,
129 const char* reason) {
130 Representation r = representation();
131 if (new_rep.is_more_general_than(r)) {
132 // When an HConstant is marked "not convertible to integer", then
133 // never try to represent it as an integer.
134 if (new_rep.IsInteger32() && !IsConvertibleToInteger()) {
135 new_rep = Representation::Tagged();
136 if (FLAG_trace_representation) {
137 PrintF("Changing #%d %s representation %s -> %s because it's NCTI"
138 " (%s want i)\n",
139 id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason);
140 }
141 } else {
142 if (FLAG_trace_representation) {
143 PrintF("Changing #%d %s representation %s -> %s based on %s\n",
144 id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason);
145 }
146 }
147 ChangeRepresentation(new_rep);
148 AddDependantsToWorklist(h_infer);
149 }
150 }
151
152
153 void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) {
154 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
155 h_infer->AddToWorklist(it.value());
156 }
157 for (int i = 0; i < OperandCount(); ++i) {
158 h_infer->AddToWorklist(OperandAt(i));
159 }
160 }
161
162
88 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) { 163 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
89 if (result > kMaxInt) { 164 if (result > kMaxInt) {
90 *overflow = true; 165 *overflow = true;
91 return kMaxInt; 166 return kMaxInt;
92 } 167 }
93 if (result < kMinInt) { 168 if (result < kMinInt) {
94 *overflow = true; 169 *overflow = true;
95 return kMinInt; 170 return kMinInt;
96 } 171 }
97 return static_cast<int32_t>(result); 172 return static_cast<int32_t>(result);
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 // Skip and remove dead items in the use list. 369 // Skip and remove dead items in the use list.
295 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) { 370 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) {
296 tail_ = tail_->tail_; 371 tail_ = tail_->tail_;
297 } 372 }
298 return tail_; 373 return tail_;
299 } 374 }
300 375
301 376
302 bool HValue::CheckUsesForFlag(Flag f) { 377 bool HValue::CheckUsesForFlag(Flag f) {
303 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { 378 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
379 if (it.value()->IsSimulate()) continue;
304 if (!it.value()->CheckFlag(f)) return false; 380 if (!it.value()->CheckFlag(f)) return false;
305 } 381 }
306 return true; 382 return true;
307 } 383 }
308 384
309 385
310 HUseIterator::HUseIterator(HUseListNode* head) : next_(head) { 386 HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
311 Advance(); 387 Advance();
312 } 388 }
313 389
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 stream->Add(nil() == kNullValue ? "null" : "undefined"); 833 stream->Add(nil() == kNullValue ? "null" : "undefined");
758 HControlInstruction::PrintDataTo(stream); 834 HControlInstruction::PrintDataTo(stream);
759 } 835 }
760 836
761 837
762 void HReturn::PrintDataTo(StringStream* stream) { 838 void HReturn::PrintDataTo(StringStream* stream) {
763 value()->PrintNameTo(stream); 839 value()->PrintNameTo(stream);
764 } 840 }
765 841
766 842
843 Representation HBranch::observed_input_representation(int index) {
844 static const ToBooleanStub::Types tagged_types(
845 ToBooleanStub::UNDEFINED |
846 ToBooleanStub::NULL_TYPE |
847 ToBooleanStub::SPEC_OBJECT |
848 ToBooleanStub::STRING);
849 if (expected_input_types_.ContainsAnyOf(tagged_types)) {
850 return Representation::Tagged();
851 } else if (expected_input_types_.Contains(ToBooleanStub::HEAP_NUMBER)) {
852 return Representation::Double();
853 } else if (expected_input_types_.Contains(ToBooleanStub::SMI)) {
854 return Representation::Integer32();
855 } else {
856 return Representation::None();
857 }
858 }
859
860
767 void HCompareMap::PrintDataTo(StringStream* stream) { 861 void HCompareMap::PrintDataTo(StringStream* stream) {
768 value()->PrintNameTo(stream); 862 value()->PrintNameTo(stream);
769 stream->Add(" (%p)", *map()); 863 stream->Add(" (%p)", *map());
770 HControlInstruction::PrintDataTo(stream); 864 HControlInstruction::PrintDataTo(stream);
771 } 865 }
772 866
773 867
774 const char* HUnaryMathOperation::OpName() const { 868 const char* HUnaryMathOperation::OpName() const {
775 switch (op()) { 869 switch (op()) {
776 case kMathFloor: return "floor"; 870 case kMathFloor: return "floor";
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 ASSERT(block() == NULL); 1426 ASSERT(block() == NULL);
1333 } 1427 }
1334 1428
1335 1429
1336 void HPhi::InitRealUses(int phi_id) { 1430 void HPhi::InitRealUses(int phi_id) {
1337 // Initialize real uses. 1431 // Initialize real uses.
1338 phi_id_ = phi_id; 1432 phi_id_ = phi_id;
1339 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { 1433 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1340 HValue* value = it.value(); 1434 HValue* value = it.value();
1341 if (!value->IsPhi()) { 1435 if (!value->IsPhi()) {
1342 Representation rep = value->ObservedInputRepresentation(it.index()); 1436 Representation rep = value->observed_input_representation(it.index());
1343 non_phi_uses_[rep.kind()] += value->LoopWeight(); 1437 non_phi_uses_[rep.kind()] += value->LoopWeight();
1344 if (FLAG_trace_representation) { 1438 if (FLAG_trace_representation) {
1345 PrintF("%d %s is used by %d %s as %s\n", 1439 PrintF("#%d Phi is used by real #%d %s as %s\n",
1346 this->id(), 1440 id(), value->id(), value->Mnemonic(), rep.Mnemonic());
1347 this->Mnemonic(),
1348 value->id(),
1349 value->Mnemonic(),
1350 rep.Mnemonic());
1351 } 1441 }
1352 } 1442 }
1353 } 1443 }
1354 } 1444 }
1355 1445
1356 1446
1357 void HPhi::AddNonPhiUsesFrom(HPhi* other) { 1447 void HPhi::AddNonPhiUsesFrom(HPhi* other) {
1358 if (FLAG_trace_representation) { 1448 if (FLAG_trace_representation) {
1359 PrintF("adding to %d %s uses of %d %s: i%d d%d t%d\n", 1449 PrintF("adding to #%d Phi uses of #%d Phi: i%d d%d t%d\n",
1360 this->id(), 1450 id(), other->id(),
1361 this->Mnemonic(),
1362 other->id(),
1363 other->Mnemonic(),
1364 other->non_phi_uses_[Representation::kInteger32], 1451 other->non_phi_uses_[Representation::kInteger32],
1365 other->non_phi_uses_[Representation::kDouble], 1452 other->non_phi_uses_[Representation::kDouble],
1366 other->non_phi_uses_[Representation::kTagged]); 1453 other->non_phi_uses_[Representation::kTagged]);
1367 } 1454 }
1368 1455
1369 for (int i = 0; i < Representation::kNumRepresentations; i++) { 1456 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1370 indirect_uses_[i] += other->non_phi_uses_[i]; 1457 indirect_uses_[i] += other->non_phi_uses_[i];
1371 } 1458 }
1372 } 1459 }
1373 1460
1374 1461
1375 void HPhi::AddIndirectUsesTo(int* dest) { 1462 void HPhi::AddIndirectUsesTo(int* dest) {
1376 for (int i = 0; i < Representation::kNumRepresentations; i++) { 1463 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1377 dest[i] += indirect_uses_[i]; 1464 dest[i] += indirect_uses_[i];
1378 } 1465 }
1379 } 1466 }
1380 1467
1381 1468
1382 void HPhi::ResetInteger32Uses() { 1469 void HSimulate::MergeInto(HSimulate* other) {
1383 non_phi_uses_[Representation::kInteger32] = 0; 1470 for (int i = 0; i < values_.length(); ++i) {
1384 indirect_uses_[Representation::kInteger32] = 0; 1471 HValue* value = values_[i];
1472 if (HasAssignedIndexAt(i)) {
1473 other->AddAssignedValue(GetAssignedIndexAt(i), value);
1474 } else {
1475 if (other->pop_count_ > 0) {
1476 other->pop_count_--;
1477 } else {
1478 other->AddPushedValue(value);
1479 }
1480 }
1481 }
1482 other->pop_count_ += pop_count();
1385 } 1483 }
1386 1484
1387 1485
1388 void HSimulate::PrintDataTo(StringStream* stream) { 1486 void HSimulate::PrintDataTo(StringStream* stream) {
1389 stream->Add("id=%d", ast_id().ToInt()); 1487 stream->Add("id=%d", ast_id().ToInt());
1390 if (pop_count_ > 0) stream->Add(" pop %d", pop_count_); 1488 if (pop_count_ > 0) stream->Add(" pop %d", pop_count_);
1391 if (values_.length() > 0) { 1489 if (values_.length() > 0) {
1392 if (pop_count_ > 0) stream->Add(" /"); 1490 if (pop_count_ > 0) stream->Add(" /");
1393 for (int i = 0; i < values_.length(); ++i) { 1491 for (int i = values_.length() - 1; i >= 0; --i) {
1394 if (i > 0) stream->Add(","); 1492 if (i > 0) stream->Add(",");
1395 if (HasAssignedIndexAt(i)) { 1493 if (HasAssignedIndexAt(i)) {
1396 stream->Add(" var[%d] = ", GetAssignedIndexAt(i)); 1494 stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
1397 } else { 1495 } else {
1398 stream->Add(" push "); 1496 stream->Add(" push ");
1399 } 1497 }
1400 values_[i]->PrintNameTo(stream); 1498 values_[i]->PrintNameTo(stream);
1401 } 1499 }
1402 } 1500 }
1403 } 1501 }
(...skipping 18 matching lines...) Expand all
1422 static bool IsInteger32(double value) { 1520 static bool IsInteger32(double value) {
1423 double roundtrip_value = static_cast<double>(static_cast<int32_t>(value)); 1521 double roundtrip_value = static_cast<double>(static_cast<int32_t>(value));
1424 return BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(value); 1522 return BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(value);
1425 } 1523 }
1426 1524
1427 1525
1428 HConstant::HConstant(Handle<Object> handle, Representation r) 1526 HConstant::HConstant(Handle<Object> handle, Representation r)
1429 : handle_(handle), 1527 : handle_(handle),
1430 has_int32_value_(false), 1528 has_int32_value_(false),
1431 has_double_value_(false) { 1529 has_double_value_(false) {
1432 set_representation(r);
1433 SetFlag(kUseGVN); 1530 SetFlag(kUseGVN);
1434 if (handle_->IsNumber()) { 1531 if (handle_->IsNumber()) {
1435 double n = handle_->Number(); 1532 double n = handle_->Number();
1436 has_int32_value_ = IsInteger32(n); 1533 has_int32_value_ = IsInteger32(n);
1437 int32_value_ = DoubleToInt32(n); 1534 int32_value_ = DoubleToInt32(n);
1438 double_value_ = n; 1535 double_value_ = n;
1439 has_double_value_ = true; 1536 has_double_value_ = true;
1440 } 1537 }
1538 if (r.IsNone()) {
1539 if (has_int32_value_) {
1540 r = Representation::Integer32();
1541 } else if (has_double_value_) {
1542 r = Representation::Double();
1543 } else {
1544 r = Representation::Tagged();
1545 }
1546 }
1547 set_representation(r);
1441 } 1548 }
1442 1549
1443 1550
1444 HConstant::HConstant(int32_t integer_value, Representation r) 1551 HConstant::HConstant(int32_t integer_value, Representation r)
1445 : has_int32_value_(true), 1552 : has_int32_value_(true),
1446 has_double_value_(true), 1553 has_double_value_(true),
1447 int32_value_(integer_value), 1554 int32_value_(integer_value),
1448 double_value_(FastI2D(integer_value)) { 1555 double_value_(FastI2D(integer_value)) {
1449 set_representation(r); 1556 set_representation(r);
1450 SetFlag(kUseGVN); 1557 SetFlag(kUseGVN);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1529 1636
1530 void HBinaryOperation::PrintDataTo(StringStream* stream) { 1637 void HBinaryOperation::PrintDataTo(StringStream* stream) {
1531 left()->PrintNameTo(stream); 1638 left()->PrintNameTo(stream);
1532 stream->Add(" "); 1639 stream->Add(" ");
1533 right()->PrintNameTo(stream); 1640 right()->PrintNameTo(stream);
1534 if (CheckFlag(kCanOverflow)) stream->Add(" !"); 1641 if (CheckFlag(kCanOverflow)) stream->Add(" !");
1535 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); 1642 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1536 } 1643 }
1537 1644
1538 1645
1646 void HBinaryOperation::InferRepresentation(HInferRepresentation* h_infer) {
1647 ASSERT(CheckFlag(kFlexibleRepresentation));
1648 Representation new_rep = RepresentationFromInputs();
1649 UpdateRepresentation(new_rep, h_infer, "inputs");
1650 // When the operation has information about its own output type, don't look
1651 // at uses.
1652 if (!observed_output_representation_.IsNone()) return;
1653 new_rep = RepresentationFromUses();
1654 UpdateRepresentation(new_rep, h_infer, "uses");
1655 }
1656
1657
1658 Representation HBinaryOperation::RepresentationFromInputs() {
1659 // Determine the worst case of observed input representations and
1660 // the currently assumed output representation.
1661 Representation rep = representation();
1662 if (observed_output_representation_.is_more_general_than(rep)) {
1663 rep = observed_output_representation_;
1664 }
1665 for (int i = 1; i <= 2; ++i) {
1666 Representation input_rep = observed_input_representation(i);
1667 if (input_rep.is_more_general_than(rep)) rep = input_rep;
1668 }
1669 // If any of the actual input representation is more general than what we
1670 // have so far but not Tagged, use that representation instead.
1671 Representation left_rep = left()->representation();
1672 Representation right_rep = right()->representation();
1673
1674 if (left_rep.is_more_general_than(rep) &&
1675 left()->CheckFlag(kFlexibleRepresentation)) {
1676 rep = left_rep;
1677 }
1678 if (right_rep.is_more_general_than(rep) &&
1679 right()->CheckFlag(kFlexibleRepresentation)) {
1680 rep = right_rep;
1681 }
1682 return rep;
1683 }
1684
1685
1686 void HBinaryOperation::AssumeRepresentation(Representation r) {
1687 set_observed_input_representation(r, r);
1688 HValue::AssumeRepresentation(r);
1689 }
1690
1691
1539 Range* HBitwise::InferRange(Zone* zone) { 1692 Range* HBitwise::InferRange(Zone* zone) {
1540 if (op() == Token::BIT_XOR) return HValue::InferRange(zone); 1693 if (op() == Token::BIT_XOR) return HValue::InferRange(zone);
1541 const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff); 1694 const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff);
1542 int32_t left_mask = (left()->range() != NULL) 1695 int32_t left_mask = (left()->range() != NULL)
1543 ? left()->range()->Mask() 1696 ? left()->range()->Mask()
1544 : kDefaultMask; 1697 : kDefaultMask;
1545 int32_t right_mask = (right()->range() != NULL) 1698 int32_t right_mask = (right()->range() != NULL)
1546 ? right()->range()->Mask() 1699 ? right()->range()->Mask()
1547 : kDefaultMask; 1700 : kDefaultMask;
1548 int32_t result_mask = (op() == Token::BIT_AND) 1701 int32_t result_mask = (op() == Token::BIT_AND)
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1660 right()->PrintNameTo(stream); 1813 right()->PrintNameTo(stream);
1661 HControlInstruction::PrintDataTo(stream); 1814 HControlInstruction::PrintDataTo(stream);
1662 } 1815 }
1663 1816
1664 1817
1665 void HGoto::PrintDataTo(StringStream* stream) { 1818 void HGoto::PrintDataTo(StringStream* stream) {
1666 stream->Add("B%d", SuccessorAt(0)->block_id()); 1819 stream->Add("B%d", SuccessorAt(0)->block_id());
1667 } 1820 }
1668 1821
1669 1822
1670 void HCompareIDAndBranch::SetInputRepresentation(Representation r) { 1823 void HCompareIDAndBranch::InferRepresentation(HInferRepresentation* h_infer) {
1671 input_representation_ = r; 1824 Representation rep = Representation::None();
1672 if (r.IsDouble()) { 1825 Representation left_rep = left()->representation();
1826 Representation right_rep = right()->representation();
1827 bool observed_integers =
1828 observed_input_representation(0).IsInteger32() &&
1829 observed_input_representation(1).IsInteger32();
1830 bool inputs_are_not_doubles =
1831 !left_rep.IsDouble() && !right_rep.IsDouble();
1832 if (observed_integers && inputs_are_not_doubles) {
1833 rep = Representation::Integer32();
1834 } else {
1835 rep = Representation::Double();
1673 // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, === 1836 // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, ===
1674 // and !=) have special handling of undefined, e.g. undefined == undefined 1837 // and !=) have special handling of undefined, e.g. undefined == undefined
1675 // is 'true'. Relational comparisons have a different semantic, first 1838 // is 'true'. Relational comparisons have a different semantic, first
1676 // calling ToPrimitive() on their arguments. The standard Crankshaft 1839 // calling ToPrimitive() on their arguments. The standard Crankshaft
1677 // tagged-to-double conversion to ensure the HCompareIDAndBranch's inputs 1840 // tagged-to-double conversion to ensure the HCompareIDAndBranch's inputs
1678 // are doubles caused 'undefined' to be converted to NaN. That's compatible 1841 // are doubles caused 'undefined' to be converted to NaN. That's compatible
1679 // out-of-the box with ordered relational comparisons (<, >, <=, 1842 // out-of-the box with ordered relational comparisons (<, >, <=,
1680 // >=). However, for equality comparisons (and for 'in' and 'instanceof'), 1843 // >=). However, for equality comparisons (and for 'in' and 'instanceof'),
1681 // it is not consistent with the spec. For example, it would cause undefined 1844 // it is not consistent with the spec. For example, it would cause undefined
1682 // == undefined (should be true) to be evaluated as NaN == NaN 1845 // == undefined (should be true) to be evaluated as NaN == NaN
1683 // (false). Therefore, any comparisons other than ordered relational 1846 // (false). Therefore, any comparisons other than ordered relational
1684 // comparisons must cause a deopt when one of their arguments is undefined. 1847 // comparisons must cause a deopt when one of their arguments is undefined.
1685 // See also v8:1434 1848 // See also v8:1434
1686 if (!Token::IsOrderedRelationalCompareOp(token_)) { 1849 if (!Token::IsOrderedRelationalCompareOp(token_)) {
1687 SetFlag(kDeoptimizeOnUndefined); 1850 SetFlag(kDeoptimizeOnUndefined);
1688 } 1851 }
1689 } else {
1690 ASSERT(r.IsInteger32());
1691 } 1852 }
1853 ChangeRepresentation(rep);
1692 } 1854 }
1693 1855
1694 1856
1695 void HParameter::PrintDataTo(StringStream* stream) { 1857 void HParameter::PrintDataTo(StringStream* stream) {
1696 stream->Add("%u", index()); 1858 stream->Add("%u", index());
1697 } 1859 }
1698 1860
1699 1861
1700 void HLoadNamedField::PrintDataTo(StringStream* stream) { 1862 void HLoadNamedField::PrintDataTo(StringStream* stream) {
1701 object()->PrintNameTo(stream); 1863 object()->PrintNameTo(stream);
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after
2444 } 2606 }
2445 2607
2446 2608
2447 void HBitwise::PrintDataTo(StringStream* stream) { 2609 void HBitwise::PrintDataTo(StringStream* stream) {
2448 stream->Add(Token::Name(op_)); 2610 stream->Add(Token::Name(op_));
2449 stream->Add(" "); 2611 stream->Add(" ");
2450 HBitwiseBinaryOperation::PrintDataTo(stream); 2612 HBitwiseBinaryOperation::PrintDataTo(stream);
2451 } 2613 }
2452 2614
2453 2615
2454 Representation HPhi::InferredRepresentation() { 2616 void HPhi::InferRepresentation(HInferRepresentation* h_infer) {
2617 ASSERT(CheckFlag(kFlexibleRepresentation));
2618 // If there are non-Phi uses, and all of them have observed the same
2619 // representation, than that's what this Phi is going to use.
2620 Representation new_rep = RepresentationObservedByAllNonPhiUses();
2621 if (!new_rep.IsNone()) {
2622 UpdateRepresentation(new_rep, h_infer, "unanimous use observations");
2623 return;
2624 }
2625 new_rep = RepresentationFromInputs();
2626 UpdateRepresentation(new_rep, h_infer, "inputs");
2627 new_rep = RepresentationFromUses();
2628 UpdateRepresentation(new_rep, h_infer, "uses");
2629 new_rep = RepresentationFromUseRequirements();
2630 UpdateRepresentation(new_rep, h_infer, "use requirements");
2631 }
2632
2633
2634 Representation HPhi::RepresentationObservedByAllNonPhiUses() {
2635 int non_phi_use_count = 0;
2636 for (int i = Representation::kInteger32;
2637 i < Representation::kNumRepresentations; ++i) {
2638 non_phi_use_count += non_phi_uses_[i];
2639 }
2640 if (non_phi_use_count <= 1) return Representation::None();
2641 for (int i = 0; i < Representation::kNumRepresentations; ++i) {
2642 if (non_phi_uses_[i] == non_phi_use_count) {
2643 return Representation::FromKind(static_cast<Representation::Kind>(i));
2644 }
2645 }
2646 return Representation::None();
2647 }
2648
2649
2650 Representation HPhi::RepresentationFromInputs() {
2455 bool double_occurred = false; 2651 bool double_occurred = false;
2456 bool int32_occurred = false; 2652 bool int32_occurred = false;
2457 for (int i = 0; i < OperandCount(); ++i) { 2653 for (int i = 0; i < OperandCount(); ++i) {
2458 HValue* value = OperandAt(i); 2654 HValue* value = OperandAt(i);
2459 if (value->IsUnknownOSRValue()) { 2655 if (value->IsUnknownOSRValue()) {
2460 HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value(); 2656 HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value();
2461 if (hint_value != NULL) { 2657 if (hint_value != NULL) {
2462 Representation hint = hint_value->representation(); 2658 Representation hint = hint_value->representation();
2659 if (hint.IsTagged()) return hint;
2463 if (hint.IsDouble()) double_occurred = true; 2660 if (hint.IsDouble()) double_occurred = true;
2464 if (hint.IsInteger32()) int32_occurred = true; 2661 if (hint.IsInteger32()) int32_occurred = true;
2465 } 2662 }
2466 continue; 2663 continue;
2467 } 2664 }
2468 if (value->representation().IsDouble()) double_occurred = true; 2665 if (value->representation().IsDouble()) double_occurred = true;
2469 if (value->representation().IsInteger32()) int32_occurred = true; 2666 if (value->representation().IsInteger32()) int32_occurred = true;
2470 if (value->representation().IsTagged()) { 2667 if (value->representation().IsTagged()) {
2471 if (value->IsConstant()) { 2668 if (value->IsConstant()) {
2472 HConstant* constant = HConstant::cast(value); 2669 HConstant* constant = HConstant::cast(value);
2473 if (constant->IsConvertibleToInteger()) { 2670 if (constant->IsConvertibleToInteger()) {
2474 int32_occurred = true; 2671 int32_occurred = true;
2475 } else if (constant->HasNumberValue()) { 2672 } else if (constant->HasNumberValue()) {
2476 double_occurred = true; 2673 double_occurred = true;
2477 } else { 2674 } else {
2478 return Representation::Tagged(); 2675 return Representation::Tagged();
2479 } 2676 }
2480 } else { 2677 } else {
2481 return Representation::Tagged(); 2678 if (value->IsPhi() && !IsConvertibleToInteger()) {
2679 return Representation::Tagged();
2680 }
2482 } 2681 }
2483 } 2682 }
2484 } 2683 }
2485 2684
2486 if (double_occurred) return Representation::Double(); 2685 if (double_occurred) return Representation::Double();
2487 2686
2488 if (int32_occurred) return Representation::Integer32(); 2687 if (int32_occurred) return Representation::Integer32();
2489 2688
2490 return Representation::None(); 2689 return Representation::None();
2491 } 2690 }
2492 2691
2493 2692
2693 Representation HPhi::RepresentationFromUseRequirements() {
2694 Representation all_uses_require = Representation::None();
2695 bool all_uses_require_the_same = true;
2696 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
2697 // We check for observed_input_representation elsewhere.
2698 Representation use_rep =
2699 it.value()->RequiredInputRepresentation(it.index());
2700 // No useful info from this use -> look at the next one.
2701 if (use_rep.IsNone()) {
2702 continue;
2703 }
2704 if (use_rep.Equals(all_uses_require)) {
2705 continue;
2706 }
2707 // This use's representation contradicts what we've seen so far.
2708 if (!all_uses_require.IsNone()) {
2709 ASSERT(!use_rep.Equals(all_uses_require));
2710 all_uses_require_the_same = false;
2711 break;
2712 }
2713 // Otherwise, initialize observed representation.
2714 all_uses_require = use_rep;
2715 }
2716 if (all_uses_require_the_same) {
2717 return all_uses_require;
2718 }
2719
2720 return Representation::None();
2721 }
2722
2723
2494 // Node-specific verification code is only included in debug mode. 2724 // Node-specific verification code is only included in debug mode.
2495 #ifdef DEBUG 2725 #ifdef DEBUG
2496 2726
2497 void HPhi::Verify() { 2727 void HPhi::Verify() {
2498 ASSERT(OperandCount() == block()->predecessors()->length()); 2728 ASSERT(OperandCount() == block()->predecessors()->length());
2499 for (int i = 0; i < OperandCount(); ++i) { 2729 for (int i = 0; i < OperandCount(); ++i) {
2500 HValue* value = OperandAt(i); 2730 HValue* value = OperandAt(i);
2501 HBasicBlock* defining_block = value->block(); 2731 HBasicBlock* defining_block = value->block();
2502 HBasicBlock* predecessor_block = block()->predecessors()->at(i); 2732 HBasicBlock* predecessor_block = block()->predecessors()->at(i);
2503 ASSERT(defining_block == predecessor_block || 2733 ASSERT(defining_block == predecessor_block ||
(...skipping 21 matching lines...) Expand all
2525 2755
2526 2756
2527 void HCheckFunction::Verify() { 2757 void HCheckFunction::Verify() {
2528 HInstruction::Verify(); 2758 HInstruction::Verify();
2529 ASSERT(HasNoUses()); 2759 ASSERT(HasNoUses());
2530 } 2760 }
2531 2761
2532 #endif 2762 #endif
2533 2763
2534 } } // namespace v8::internal 2764 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/code-stubs-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698