OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |