| 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 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1342 ASSERT(block() == NULL); | 1436 ASSERT(block() == NULL); |
| 1343 } | 1437 } |
| 1344 | 1438 |
| 1345 | 1439 |
| 1346 void HPhi::InitRealUses(int phi_id) { | 1440 void HPhi::InitRealUses(int phi_id) { |
| 1347 // Initialize real uses. | 1441 // Initialize real uses. |
| 1348 phi_id_ = phi_id; | 1442 phi_id_ = phi_id; |
| 1349 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 1443 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 1350 HValue* value = it.value(); | 1444 HValue* value = it.value(); |
| 1351 if (!value->IsPhi()) { | 1445 if (!value->IsPhi()) { |
| 1352 Representation rep = value->ObservedInputRepresentation(it.index()); | 1446 Representation rep = value->observed_input_representation(it.index()); |
| 1353 non_phi_uses_[rep.kind()] += value->LoopWeight(); | 1447 non_phi_uses_[rep.kind()] += value->LoopWeight(); |
| 1354 if (FLAG_trace_representation) { | 1448 if (FLAG_trace_representation) { |
| 1355 PrintF("%d %s is used by %d %s as %s\n", | 1449 PrintF("#%d Phi is used by real #%d %s as %s\n", |
| 1356 this->id(), | 1450 id(), value->id(), value->Mnemonic(), rep.Mnemonic()); |
| 1357 this->Mnemonic(), | |
| 1358 value->id(), | |
| 1359 value->Mnemonic(), | |
| 1360 rep.Mnemonic()); | |
| 1361 } | 1451 } |
| 1362 } | 1452 } |
| 1363 } | 1453 } |
| 1364 } | 1454 } |
| 1365 | 1455 |
| 1366 | 1456 |
| 1367 void HPhi::AddNonPhiUsesFrom(HPhi* other) { | 1457 void HPhi::AddNonPhiUsesFrom(HPhi* other) { |
| 1368 if (FLAG_trace_representation) { | 1458 if (FLAG_trace_representation) { |
| 1369 PrintF("adding to %d %s uses of %d %s: i%d d%d t%d\n", | 1459 PrintF("adding to #%d Phi uses of #%d Phi: i%d d%d t%d\n", |
| 1370 this->id(), | 1460 id(), other->id(), |
| 1371 this->Mnemonic(), | |
| 1372 other->id(), | |
| 1373 other->Mnemonic(), | |
| 1374 other->non_phi_uses_[Representation::kInteger32], | 1461 other->non_phi_uses_[Representation::kInteger32], |
| 1375 other->non_phi_uses_[Representation::kDouble], | 1462 other->non_phi_uses_[Representation::kDouble], |
| 1376 other->non_phi_uses_[Representation::kTagged]); | 1463 other->non_phi_uses_[Representation::kTagged]); |
| 1377 } | 1464 } |
| 1378 | 1465 |
| 1379 for (int i = 0; i < Representation::kNumRepresentations; i++) { | 1466 for (int i = 0; i < Representation::kNumRepresentations; i++) { |
| 1380 indirect_uses_[i] += other->non_phi_uses_[i]; | 1467 indirect_uses_[i] += other->non_phi_uses_[i]; |
| 1381 } | 1468 } |
| 1382 } | 1469 } |
| 1383 | 1470 |
| 1384 | 1471 |
| 1385 void HPhi::AddIndirectUsesTo(int* dest) { | 1472 void HPhi::AddIndirectUsesTo(int* dest) { |
| 1386 for (int i = 0; i < Representation::kNumRepresentations; i++) { | 1473 for (int i = 0; i < Representation::kNumRepresentations; i++) { |
| 1387 dest[i] += indirect_uses_[i]; | 1474 dest[i] += indirect_uses_[i]; |
| 1388 } | 1475 } |
| 1389 } | 1476 } |
| 1390 | 1477 |
| 1391 | 1478 |
| 1392 void HPhi::ResetInteger32Uses() { | 1479 void HSimulate::MergeInto(HSimulate* other) { |
| 1393 non_phi_uses_[Representation::kInteger32] = 0; | 1480 for (int i = 0; i < values_.length(); ++i) { |
| 1394 indirect_uses_[Representation::kInteger32] = 0; | 1481 HValue* value = values_[i]; |
| 1482 if (HasAssignedIndexAt(i)) { |
| 1483 other->AddAssignedValue(GetAssignedIndexAt(i), value); |
| 1484 } else { |
| 1485 if (other->pop_count_ > 0) { |
| 1486 other->pop_count_--; |
| 1487 } else { |
| 1488 other->AddPushedValue(value); |
| 1489 } |
| 1490 } |
| 1491 } |
| 1492 other->pop_count_ += pop_count(); |
| 1395 } | 1493 } |
| 1396 | 1494 |
| 1397 | 1495 |
| 1398 void HSimulate::PrintDataTo(StringStream* stream) { | 1496 void HSimulate::PrintDataTo(StringStream* stream) { |
| 1399 stream->Add("id=%d", ast_id().ToInt()); | 1497 stream->Add("id=%d", ast_id().ToInt()); |
| 1400 if (pop_count_ > 0) stream->Add(" pop %d", pop_count_); | 1498 if (pop_count_ > 0) stream->Add(" pop %d", pop_count_); |
| 1401 if (values_.length() > 0) { | 1499 if (values_.length() > 0) { |
| 1402 if (pop_count_ > 0) stream->Add(" /"); | 1500 if (pop_count_ > 0) stream->Add(" /"); |
| 1403 for (int i = 0; i < values_.length(); ++i) { | 1501 for (int i = values_.length() - 1; i >= 0; --i) { |
| 1404 if (i > 0) stream->Add(","); | 1502 if (i > 0) stream->Add(","); |
| 1405 if (HasAssignedIndexAt(i)) { | 1503 if (HasAssignedIndexAt(i)) { |
| 1406 stream->Add(" var[%d] = ", GetAssignedIndexAt(i)); | 1504 stream->Add(" var[%d] = ", GetAssignedIndexAt(i)); |
| 1407 } else { | 1505 } else { |
| 1408 stream->Add(" push "); | 1506 stream->Add(" push "); |
| 1409 } | 1507 } |
| 1410 values_[i]->PrintNameTo(stream); | 1508 values_[i]->PrintNameTo(stream); |
| 1411 } | 1509 } |
| 1412 } | 1510 } |
| 1413 } | 1511 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1432 static bool IsInteger32(double value) { | 1530 static bool IsInteger32(double value) { |
| 1433 double roundtrip_value = static_cast<double>(static_cast<int32_t>(value)); | 1531 double roundtrip_value = static_cast<double>(static_cast<int32_t>(value)); |
| 1434 return BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(value); | 1532 return BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(value); |
| 1435 } | 1533 } |
| 1436 | 1534 |
| 1437 | 1535 |
| 1438 HConstant::HConstant(Handle<Object> handle, Representation r) | 1536 HConstant::HConstant(Handle<Object> handle, Representation r) |
| 1439 : handle_(handle), | 1537 : handle_(handle), |
| 1440 has_int32_value_(false), | 1538 has_int32_value_(false), |
| 1441 has_double_value_(false) { | 1539 has_double_value_(false) { |
| 1442 set_representation(r); | |
| 1443 SetFlag(kUseGVN); | 1540 SetFlag(kUseGVN); |
| 1444 if (handle_->IsNumber()) { | 1541 if (handle_->IsNumber()) { |
| 1445 double n = handle_->Number(); | 1542 double n = handle_->Number(); |
| 1446 has_int32_value_ = IsInteger32(n); | 1543 has_int32_value_ = IsInteger32(n); |
| 1447 int32_value_ = DoubleToInt32(n); | 1544 int32_value_ = DoubleToInt32(n); |
| 1448 double_value_ = n; | 1545 double_value_ = n; |
| 1449 has_double_value_ = true; | 1546 has_double_value_ = true; |
| 1450 } | 1547 } |
| 1548 if (r.IsNone()) { |
| 1549 if (has_int32_value_) { |
| 1550 r = Representation::Integer32(); |
| 1551 } else if (has_double_value_) { |
| 1552 r = Representation::Double(); |
| 1553 } else { |
| 1554 r = Representation::Tagged(); |
| 1555 } |
| 1556 } |
| 1557 set_representation(r); |
| 1451 } | 1558 } |
| 1452 | 1559 |
| 1453 | 1560 |
| 1454 HConstant::HConstant(int32_t integer_value, Representation r) | 1561 HConstant::HConstant(int32_t integer_value, Representation r) |
| 1455 : has_int32_value_(true), | 1562 : has_int32_value_(true), |
| 1456 has_double_value_(true), | 1563 has_double_value_(true), |
| 1457 int32_value_(integer_value), | 1564 int32_value_(integer_value), |
| 1458 double_value_(FastI2D(integer_value)) { | 1565 double_value_(FastI2D(integer_value)) { |
| 1459 set_representation(r); | 1566 set_representation(r); |
| 1460 SetFlag(kUseGVN); | 1567 SetFlag(kUseGVN); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1539 | 1646 |
| 1540 void HBinaryOperation::PrintDataTo(StringStream* stream) { | 1647 void HBinaryOperation::PrintDataTo(StringStream* stream) { |
| 1541 left()->PrintNameTo(stream); | 1648 left()->PrintNameTo(stream); |
| 1542 stream->Add(" "); | 1649 stream->Add(" "); |
| 1543 right()->PrintNameTo(stream); | 1650 right()->PrintNameTo(stream); |
| 1544 if (CheckFlag(kCanOverflow)) stream->Add(" !"); | 1651 if (CheckFlag(kCanOverflow)) stream->Add(" !"); |
| 1545 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); | 1652 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); |
| 1546 } | 1653 } |
| 1547 | 1654 |
| 1548 | 1655 |
| 1656 Representation HBinaryOperation::RepresentationFromInputs() { |
| 1657 // Determine the worst case of observed input representations and |
| 1658 // the currently assumed output representation. |
| 1659 Representation rep = representation(); |
| 1660 if (observed_output_representation_.is_more_general_than(rep)) { |
| 1661 rep = observed_output_representation_; |
| 1662 } |
| 1663 for (int i = 1; i <= 2; ++i) { |
| 1664 Representation input_rep = observed_input_representation(i); |
| 1665 if (input_rep.is_more_general_than(rep)) rep = input_rep; |
| 1666 } |
| 1667 // If any of the actual input representation is more general than what we |
| 1668 // have so far but not Tagged, use that representation instead. |
| 1669 Representation left_rep = left()->representation(); |
| 1670 Representation right_rep = right()->representation(); |
| 1671 |
| 1672 if (left_rep.is_more_general_than(rep) && |
| 1673 left()->CheckFlag(kFlexibleRepresentation)) { |
| 1674 rep = left_rep; |
| 1675 } |
| 1676 if (right_rep.is_more_general_than(rep) && |
| 1677 right()->CheckFlag(kFlexibleRepresentation)) { |
| 1678 rep = right_rep; |
| 1679 } |
| 1680 return rep; |
| 1681 } |
| 1682 |
| 1683 |
| 1684 void HBinaryOperation::AssumeRepresentation(Representation r) { |
| 1685 set_observed_input_representation(r, r); |
| 1686 HValue::AssumeRepresentation(r); |
| 1687 } |
| 1688 |
| 1689 |
| 1549 Range* HBitwise::InferRange(Zone* zone) { | 1690 Range* HBitwise::InferRange(Zone* zone) { |
| 1550 if (op() == Token::BIT_XOR) return HValue::InferRange(zone); | 1691 if (op() == Token::BIT_XOR) return HValue::InferRange(zone); |
| 1551 const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff); | 1692 const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff); |
| 1552 int32_t left_mask = (left()->range() != NULL) | 1693 int32_t left_mask = (left()->range() != NULL) |
| 1553 ? left()->range()->Mask() | 1694 ? left()->range()->Mask() |
| 1554 : kDefaultMask; | 1695 : kDefaultMask; |
| 1555 int32_t right_mask = (right()->range() != NULL) | 1696 int32_t right_mask = (right()->range() != NULL) |
| 1556 ? right()->range()->Mask() | 1697 ? right()->range()->Mask() |
| 1557 : kDefaultMask; | 1698 : kDefaultMask; |
| 1558 int32_t result_mask = (op() == Token::BIT_AND) | 1699 int32_t result_mask = (op() == Token::BIT_AND) |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1670 right()->PrintNameTo(stream); | 1811 right()->PrintNameTo(stream); |
| 1671 HControlInstruction::PrintDataTo(stream); | 1812 HControlInstruction::PrintDataTo(stream); |
| 1672 } | 1813 } |
| 1673 | 1814 |
| 1674 | 1815 |
| 1675 void HGoto::PrintDataTo(StringStream* stream) { | 1816 void HGoto::PrintDataTo(StringStream* stream) { |
| 1676 stream->Add("B%d", SuccessorAt(0)->block_id()); | 1817 stream->Add("B%d", SuccessorAt(0)->block_id()); |
| 1677 } | 1818 } |
| 1678 | 1819 |
| 1679 | 1820 |
| 1680 void HCompareIDAndBranch::SetInputRepresentation(Representation r) { | 1821 void HCompareIDAndBranch::InferRepresentation(HInferRepresentation* h_infer) { |
| 1681 input_representation_ = r; | 1822 Representation rep = Representation::None(); |
| 1682 if (r.IsDouble()) { | 1823 if (observed_input_representation(0).IsInteger32() && |
| 1824 observed_input_representation(1).IsInteger32()) { |
| 1825 rep = Representation::Integer32(); |
| 1826 } else { |
| 1827 rep = Representation::Double(); |
| 1683 // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, === | 1828 // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, === |
| 1684 // and !=) have special handling of undefined, e.g. undefined == undefined | 1829 // and !=) have special handling of undefined, e.g. undefined == undefined |
| 1685 // is 'true'. Relational comparisons have a different semantic, first | 1830 // is 'true'. Relational comparisons have a different semantic, first |
| 1686 // calling ToPrimitive() on their arguments. The standard Crankshaft | 1831 // calling ToPrimitive() on their arguments. The standard Crankshaft |
| 1687 // tagged-to-double conversion to ensure the HCompareIDAndBranch's inputs | 1832 // tagged-to-double conversion to ensure the HCompareIDAndBranch's inputs |
| 1688 // are doubles caused 'undefined' to be converted to NaN. That's compatible | 1833 // are doubles caused 'undefined' to be converted to NaN. That's compatible |
| 1689 // out-of-the box with ordered relational comparisons (<, >, <=, | 1834 // out-of-the box with ordered relational comparisons (<, >, <=, |
| 1690 // >=). However, for equality comparisons (and for 'in' and 'instanceof'), | 1835 // >=). However, for equality comparisons (and for 'in' and 'instanceof'), |
| 1691 // it is not consistent with the spec. For example, it would cause undefined | 1836 // it is not consistent with the spec. For example, it would cause undefined |
| 1692 // == undefined (should be true) to be evaluated as NaN == NaN | 1837 // == undefined (should be true) to be evaluated as NaN == NaN |
| 1693 // (false). Therefore, any comparisons other than ordered relational | 1838 // (false). Therefore, any comparisons other than ordered relational |
| 1694 // comparisons must cause a deopt when one of their arguments is undefined. | 1839 // comparisons must cause a deopt when one of their arguments is undefined. |
| 1695 // See also v8:1434 | 1840 // See also v8:1434 |
| 1696 if (!Token::IsOrderedRelationalCompareOp(token_)) { | 1841 if (!Token::IsOrderedRelationalCompareOp(token_)) { |
| 1697 SetFlag(kDeoptimizeOnUndefined); | 1842 SetFlag(kDeoptimizeOnUndefined); |
| 1698 } | 1843 } |
| 1699 } else { | |
| 1700 ASSERT(r.IsInteger32()); | |
| 1701 } | 1844 } |
| 1845 AssumeRepresentation(rep); |
| 1702 } | 1846 } |
| 1703 | 1847 |
| 1704 | 1848 |
| 1705 void HParameter::PrintDataTo(StringStream* stream) { | 1849 void HParameter::PrintDataTo(StringStream* stream) { |
| 1706 stream->Add("%u", index()); | 1850 stream->Add("%u", index()); |
| 1707 } | 1851 } |
| 1708 | 1852 |
| 1709 | 1853 |
| 1710 void HLoadNamedField::PrintDataTo(StringStream* stream) { | 1854 void HLoadNamedField::PrintDataTo(StringStream* stream) { |
| 1711 object()->PrintNameTo(stream); | 1855 object()->PrintNameTo(stream); |
| (...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2454 } | 2598 } |
| 2455 | 2599 |
| 2456 | 2600 |
| 2457 void HBitwise::PrintDataTo(StringStream* stream) { | 2601 void HBitwise::PrintDataTo(StringStream* stream) { |
| 2458 stream->Add(Token::Name(op_)); | 2602 stream->Add(Token::Name(op_)); |
| 2459 stream->Add(" "); | 2603 stream->Add(" "); |
| 2460 HBitwiseBinaryOperation::PrintDataTo(stream); | 2604 HBitwiseBinaryOperation::PrintDataTo(stream); |
| 2461 } | 2605 } |
| 2462 | 2606 |
| 2463 | 2607 |
| 2464 Representation HPhi::InferredRepresentation() { | 2608 void HPhi::InferRepresentation(HInferRepresentation* h_infer) { |
| 2609 HValue::InferRepresentation(h_infer); |
| 2610 Representation new_rep = RepresentationFromUseRequirements(); |
| 2611 UpdateRepresentation(new_rep, h_infer, "use requirements"); |
| 2612 } |
| 2613 |
| 2614 |
| 2615 Representation HPhi::RepresentationFromInputs() { |
| 2465 bool double_occurred = false; | 2616 bool double_occurred = false; |
| 2466 bool int32_occurred = false; | 2617 bool int32_occurred = false; |
| 2467 for (int i = 0; i < OperandCount(); ++i) { | 2618 for (int i = 0; i < OperandCount(); ++i) { |
| 2468 HValue* value = OperandAt(i); | 2619 HValue* value = OperandAt(i); |
| 2469 if (value->IsUnknownOSRValue()) { | 2620 if (value->IsUnknownOSRValue()) { |
| 2470 HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value(); | 2621 HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value(); |
| 2471 if (hint_value != NULL) { | 2622 if (hint_value != NULL) { |
| 2472 Representation hint = hint_value->representation(); | 2623 Representation hint = hint_value->representation(); |
| 2624 if (hint.IsTagged()) return hint; |
| 2473 if (hint.IsDouble()) double_occurred = true; | 2625 if (hint.IsDouble()) double_occurred = true; |
| 2474 if (hint.IsInteger32()) int32_occurred = true; | 2626 if (hint.IsInteger32()) int32_occurred = true; |
| 2475 } | 2627 } |
| 2476 continue; | 2628 continue; |
| 2477 } | 2629 } |
| 2478 if (value->representation().IsDouble()) double_occurred = true; | 2630 if (value->representation().IsDouble()) double_occurred = true; |
| 2479 if (value->representation().IsInteger32()) int32_occurred = true; | 2631 if (value->representation().IsInteger32()) int32_occurred = true; |
| 2480 if (value->representation().IsTagged()) { | 2632 if (value->representation().IsTagged()) { |
| 2481 if (value->IsConstant()) { | 2633 if (value->IsConstant()) { |
| 2482 HConstant* constant = HConstant::cast(value); | 2634 HConstant* constant = HConstant::cast(value); |
| 2483 if (constant->IsConvertibleToInteger()) { | 2635 if (constant->IsConvertibleToInteger()) { |
| 2484 int32_occurred = true; | 2636 int32_occurred = true; |
| 2485 } else if (constant->HasNumberValue()) { | 2637 } else if (constant->HasNumberValue()) { |
| 2486 double_occurred = true; | 2638 double_occurred = true; |
| 2487 } else { | 2639 } else { |
| 2488 return Representation::Tagged(); | 2640 return Representation::Tagged(); |
| 2489 } | 2641 } |
| 2490 } else { | 2642 } else { |
| 2491 return Representation::Tagged(); | 2643 if (value->IsPhi() && !IsConvertibleToInteger()) { |
| 2644 return Representation::Tagged(); |
| 2645 } |
| 2492 } | 2646 } |
| 2493 } | 2647 } |
| 2494 } | 2648 } |
| 2495 | 2649 |
| 2496 if (double_occurred) return Representation::Double(); | 2650 if (double_occurred) return Representation::Double(); |
| 2497 | 2651 |
| 2498 if (int32_occurred) return Representation::Integer32(); | 2652 if (int32_occurred) return Representation::Integer32(); |
| 2499 | 2653 |
| 2500 return Representation::None(); | 2654 return Representation::None(); |
| 2501 } | 2655 } |
| 2502 | 2656 |
| 2503 | 2657 |
| 2658 Representation HPhi::RepresentationFromUseRequirements() { |
| 2659 Representation all_uses_require = Representation::None(); |
| 2660 bool all_uses_require_the_same = true; |
| 2661 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 2662 // We check for observed_input_representation elsewhere. |
| 2663 Representation use_rep = |
| 2664 it.value()->RequiredInputRepresentation(it.index()); |
| 2665 // No useful info from this use -> look at the next one. |
| 2666 if (use_rep.IsNone()) { |
| 2667 continue; |
| 2668 } |
| 2669 if (use_rep.Equals(all_uses_require)) { |
| 2670 continue; |
| 2671 } |
| 2672 // This use's representation contradicts what we've seen so far. |
| 2673 if (!all_uses_require.IsNone()) { |
| 2674 ASSERT(!use_rep.Equals(all_uses_require)); |
| 2675 all_uses_require_the_same = false; |
| 2676 break; |
| 2677 } |
| 2678 // Otherwise, initialize observed representation. |
| 2679 all_uses_require = use_rep; |
| 2680 } |
| 2681 if (all_uses_require_the_same) { |
| 2682 return all_uses_require; |
| 2683 } |
| 2684 |
| 2685 return Representation::None(); |
| 2686 } |
| 2687 |
| 2688 |
| 2504 // Node-specific verification code is only included in debug mode. | 2689 // Node-specific verification code is only included in debug mode. |
| 2505 #ifdef DEBUG | 2690 #ifdef DEBUG |
| 2506 | 2691 |
| 2507 void HPhi::Verify() { | 2692 void HPhi::Verify() { |
| 2508 ASSERT(OperandCount() == block()->predecessors()->length()); | 2693 ASSERT(OperandCount() == block()->predecessors()->length()); |
| 2509 for (int i = 0; i < OperandCount(); ++i) { | 2694 for (int i = 0; i < OperandCount(); ++i) { |
| 2510 HValue* value = OperandAt(i); | 2695 HValue* value = OperandAt(i); |
| 2511 HBasicBlock* defining_block = value->block(); | 2696 HBasicBlock* defining_block = value->block(); |
| 2512 HBasicBlock* predecessor_block = block()->predecessors()->at(i); | 2697 HBasicBlock* predecessor_block = block()->predecessors()->at(i); |
| 2513 ASSERT(defining_block == predecessor_block || | 2698 ASSERT(defining_block == predecessor_block || |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2535 | 2720 |
| 2536 | 2721 |
| 2537 void HCheckFunction::Verify() { | 2722 void HCheckFunction::Verify() { |
| 2538 HInstruction::Verify(); | 2723 HInstruction::Verify(); |
| 2539 ASSERT(HasNoUses()); | 2724 ASSERT(HasNoUses()); |
| 2540 } | 2725 } |
| 2541 | 2726 |
| 2542 #endif | 2727 #endif |
| 2543 | 2728 |
| 2544 } } // namespace v8::internal | 2729 } } // namespace v8::internal |
| OLD | NEW |