| 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 17 matching lines...) Expand all Loading... |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "double.h" | 30 #include "double.h" |
| 31 #include "factory.h" | 31 #include "factory.h" |
| 32 #include "hydrogen-infer-representation.h" | 32 #include "hydrogen-infer-representation.h" |
| 33 | 33 |
| 34 #if V8_TARGET_ARCH_IA32 | 34 #if V8_TARGET_ARCH_IA32 |
| 35 #include "ia32/lithium-ia32.h" | 35 #include "ia32/lithium-ia32.h" |
| 36 #elif V8_TARGET_ARCH_X64 | 36 #elif V8_TARGET_ARCH_X64 |
| 37 #include "x64/lithium-x64.h" | 37 #include "x64/lithium-x64.h" |
| 38 #elif V8_TARGET_ARCH_A64 |
| 39 #include "a64/lithium-a64.h" |
| 38 #elif V8_TARGET_ARCH_ARM | 40 #elif V8_TARGET_ARCH_ARM |
| 39 #include "arm/lithium-arm.h" | 41 #include "arm/lithium-arm.h" |
| 40 #elif V8_TARGET_ARCH_MIPS | 42 #elif V8_TARGET_ARCH_MIPS |
| 41 #include "mips/lithium-mips.h" | 43 #include "mips/lithium-mips.h" |
| 42 #else | 44 #else |
| 43 #error Unsupported target architecture. | 45 #error Unsupported target architecture. |
| 44 #endif | 46 #endif |
| 45 | 47 |
| 46 namespace v8 { | 48 namespace v8 { |
| 47 namespace internal { | 49 namespace internal { |
| (...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 | 599 |
| 598 | 600 |
| 599 void HValue::PrintChangesTo(StringStream* stream) { | 601 void HValue::PrintChangesTo(StringStream* stream) { |
| 600 GVNFlagSet changes_flags = ChangesFlags(); | 602 GVNFlagSet changes_flags = ChangesFlags(); |
| 601 if (changes_flags.IsEmpty()) return; | 603 if (changes_flags.IsEmpty()) return; |
| 602 stream->Add(" changes["); | 604 stream->Add(" changes["); |
| 603 if (changes_flags == AllSideEffectsFlagSet()) { | 605 if (changes_flags == AllSideEffectsFlagSet()) { |
| 604 stream->Add("*"); | 606 stream->Add("*"); |
| 605 } else { | 607 } else { |
| 606 bool add_comma = false; | 608 bool add_comma = false; |
| 607 #define PRINT_DO(type) \ | 609 #define PRINT_DO(Type) \ |
| 608 if (changes_flags.Contains(kChanges##type)) { \ | 610 if (changes_flags.Contains(k##Type)) { \ |
| 609 if (add_comma) stream->Add(","); \ | 611 if (add_comma) stream->Add(","); \ |
| 610 add_comma = true; \ | 612 add_comma = true; \ |
| 611 stream->Add(#type); \ | 613 stream->Add(#Type); \ |
| 612 } | 614 } |
| 613 GVN_TRACKED_FLAG_LIST(PRINT_DO); | 615 GVN_TRACKED_FLAG_LIST(PRINT_DO); |
| 614 GVN_UNTRACKED_FLAG_LIST(PRINT_DO); | 616 GVN_UNTRACKED_FLAG_LIST(PRINT_DO); |
| 615 #undef PRINT_DO | 617 #undef PRINT_DO |
| 616 } | 618 } |
| 617 stream->Add("]"); | 619 stream->Add("]"); |
| 618 } | 620 } |
| 619 | 621 |
| 620 | 622 |
| 621 void HValue::PrintNameTo(StringStream* stream) { | 623 void HValue::PrintNameTo(StringStream* stream) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 673 } | 675 } |
| 674 | 676 |
| 675 | 677 |
| 676 void HValue::ComputeInitialRange(Zone* zone) { | 678 void HValue::ComputeInitialRange(Zone* zone) { |
| 677 ASSERT(!HasRange()); | 679 ASSERT(!HasRange()); |
| 678 range_ = InferRange(zone); | 680 range_ = InferRange(zone); |
| 679 ASSERT(HasRange()); | 681 ASSERT(HasRange()); |
| 680 } | 682 } |
| 681 | 683 |
| 682 | 684 |
| 685 void HSourcePosition::PrintTo(FILE* out) { |
| 686 if (IsUnknown()) { |
| 687 PrintF(out, "<?>"); |
| 688 } else { |
| 689 if (FLAG_hydrogen_track_positions) { |
| 690 PrintF(out, "<%d:%d>", inlining_id(), position()); |
| 691 } else { |
| 692 PrintF(out, "<0:%d>", raw()); |
| 693 } |
| 694 } |
| 695 } |
| 696 |
| 697 |
| 683 void HInstruction::PrintTo(StringStream* stream) { | 698 void HInstruction::PrintTo(StringStream* stream) { |
| 684 PrintMnemonicTo(stream); | 699 PrintMnemonicTo(stream); |
| 685 PrintDataTo(stream); | 700 PrintDataTo(stream); |
| 686 PrintRangeTo(stream); | 701 PrintRangeTo(stream); |
| 687 PrintChangesTo(stream); | 702 PrintChangesTo(stream); |
| 688 PrintTypeTo(stream); | 703 PrintTypeTo(stream); |
| 689 if (CheckFlag(HValue::kHasNoObservableSideEffects)) { | 704 if (CheckFlag(HValue::kHasNoObservableSideEffects)) { |
| 690 stream->Add(" [noOSE]"); | 705 stream->Add(" [noOSE]"); |
| 691 } | 706 } |
| 707 if (CheckFlag(HValue::kIsDead)) { |
| 708 stream->Add(" [dead]"); |
| 709 } |
| 692 } | 710 } |
| 693 | 711 |
| 694 | 712 |
| 695 void HInstruction::PrintDataTo(StringStream *stream) { | 713 void HInstruction::PrintDataTo(StringStream *stream) { |
| 696 for (int i = 0; i < OperandCount(); ++i) { | 714 for (int i = 0; i < OperandCount(); ++i) { |
| 697 if (i > 0) stream->Add(" "); | 715 if (i > 0) stream->Add(" "); |
| 698 OperandAt(i)->PrintNameTo(stream); | 716 OperandAt(i)->PrintNameTo(stream); |
| 699 } | 717 } |
| 700 } | 718 } |
| 701 | 719 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 726 ASSERT(!next->IsBlockEntry()); | 744 ASSERT(!next->IsBlockEntry()); |
| 727 ASSERT(!IsControlInstruction()); | 745 ASSERT(!IsControlInstruction()); |
| 728 ASSERT(!next->block()->IsStartBlock()); | 746 ASSERT(!next->block()->IsStartBlock()); |
| 729 ASSERT(next->previous_ != NULL); | 747 ASSERT(next->previous_ != NULL); |
| 730 HInstruction* prev = next->previous(); | 748 HInstruction* prev = next->previous(); |
| 731 prev->next_ = this; | 749 prev->next_ = this; |
| 732 next->previous_ = this; | 750 next->previous_ = this; |
| 733 next_ = next; | 751 next_ = next; |
| 734 previous_ = prev; | 752 previous_ = prev; |
| 735 SetBlock(next->block()); | 753 SetBlock(next->block()); |
| 736 if (position() == RelocInfo::kNoPosition && | 754 if (!has_position() && next->has_position()) { |
| 737 next->position() != RelocInfo::kNoPosition) { | |
| 738 set_position(next->position()); | 755 set_position(next->position()); |
| 739 } | 756 } |
| 740 } | 757 } |
| 741 | 758 |
| 742 | 759 |
| 743 void HInstruction::InsertAfter(HInstruction* previous) { | 760 void HInstruction::InsertAfter(HInstruction* previous) { |
| 744 ASSERT(!IsLinked()); | 761 ASSERT(!IsLinked()); |
| 745 ASSERT(!previous->IsControlInstruction()); | 762 ASSERT(!previous->IsControlInstruction()); |
| 746 ASSERT(!IsControlInstruction() || previous->next_ == NULL); | 763 ASSERT(!IsControlInstruction() || previous->next_ == NULL); |
| 747 HBasicBlock* block = previous->block(); | 764 HBasicBlock* block = previous->block(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 764 } | 781 } |
| 765 | 782 |
| 766 previous_ = previous; | 783 previous_ = previous; |
| 767 next_ = next; | 784 next_ = next; |
| 768 SetBlock(block); | 785 SetBlock(block); |
| 769 previous->next_ = this; | 786 previous->next_ = this; |
| 770 if (next != NULL) next->previous_ = this; | 787 if (next != NULL) next->previous_ = this; |
| 771 if (block->last() == previous) { | 788 if (block->last() == previous) { |
| 772 block->set_last(this); | 789 block->set_last(this); |
| 773 } | 790 } |
| 774 if (position() == RelocInfo::kNoPosition && | 791 if (!has_position() && previous->has_position()) { |
| 775 previous->position() != RelocInfo::kNoPosition) { | |
| 776 set_position(previous->position()); | 792 set_position(previous->position()); |
| 777 } | 793 } |
| 778 } | 794 } |
| 779 | 795 |
| 780 | 796 |
| 781 #ifdef DEBUG | 797 #ifdef DEBUG |
| 782 void HInstruction::Verify() { | 798 void HInstruction::Verify() { |
| 783 // Verify that input operands are defined before use. | 799 // Verify that input operands are defined before use. |
| 784 HBasicBlock* cur_block = block(); | 800 HBasicBlock* cur_block = block(); |
| 785 for (int i = 0; i < OperandCount(); ++i) { | 801 for (int i = 0; i < OperandCount(); ++i) { |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1107 } | 1123 } |
| 1108 *block = NULL; | 1124 *block = NULL; |
| 1109 return false; | 1125 return false; |
| 1110 } | 1126 } |
| 1111 | 1127 |
| 1112 | 1128 |
| 1113 void HCompareMap::PrintDataTo(StringStream* stream) { | 1129 void HCompareMap::PrintDataTo(StringStream* stream) { |
| 1114 value()->PrintNameTo(stream); | 1130 value()->PrintNameTo(stream); |
| 1115 stream->Add(" (%p)", *map().handle()); | 1131 stream->Add(" (%p)", *map().handle()); |
| 1116 HControlInstruction::PrintDataTo(stream); | 1132 HControlInstruction::PrintDataTo(stream); |
| 1133 if (known_successor_index() == 0) { |
| 1134 stream->Add(" [true]"); |
| 1135 } else if (known_successor_index() == 1) { |
| 1136 stream->Add(" [false]"); |
| 1137 } |
| 1117 } | 1138 } |
| 1118 | 1139 |
| 1119 | 1140 |
| 1120 const char* HUnaryMathOperation::OpName() const { | 1141 const char* HUnaryMathOperation::OpName() const { |
| 1121 switch (op()) { | 1142 switch (op()) { |
| 1122 case kMathFloor: return "floor"; | 1143 case kMathFloor: return "floor"; |
| 1123 case kMathRound: return "round"; | 1144 case kMathRound: return "round"; |
| 1124 case kMathAbs: return "abs"; | 1145 case kMathAbs: return "abs"; |
| 1125 case kMathLog: return "log"; | 1146 case kMathLog: return "log"; |
| 1126 case kMathExp: return "exp"; | 1147 case kMathExp: return "exp"; |
| 1127 case kMathSqrt: return "sqrt"; | 1148 case kMathSqrt: return "sqrt"; |
| 1128 case kMathPowHalf: return "pow-half"; | 1149 case kMathPowHalf: return "pow-half"; |
| 1150 case kMathClz32: return "clz32"; |
| 1129 default: | 1151 default: |
| 1130 UNREACHABLE(); | 1152 UNREACHABLE(); |
| 1131 return NULL; | 1153 return NULL; |
| 1132 } | 1154 } |
| 1133 } | 1155 } |
| 1134 | 1156 |
| 1135 | 1157 |
| 1136 Range* HUnaryMathOperation::InferRange(Zone* zone) { | 1158 Range* HUnaryMathOperation::InferRange(Zone* zone) { |
| 1137 Representation r = representation(); | 1159 Representation r = representation(); |
| 1160 if (op() == kMathClz32) return new(zone) Range(0, 32); |
| 1138 if (r.IsSmiOrInteger32() && value()->HasRange()) { | 1161 if (r.IsSmiOrInteger32() && value()->HasRange()) { |
| 1139 if (op() == kMathAbs) { | 1162 if (op() == kMathAbs) { |
| 1140 int upper = value()->range()->upper(); | 1163 int upper = value()->range()->upper(); |
| 1141 int lower = value()->range()->lower(); | 1164 int lower = value()->range()->lower(); |
| 1142 bool spans_zero = value()->range()->CanBeZero(); | 1165 bool spans_zero = value()->range()->CanBeZero(); |
| 1143 // Math.abs(kMinInt) overflows its representation, on which the | 1166 // Math.abs(kMinInt) overflows its representation, on which the |
| 1144 // instruction deopts. Hence clamp it to kMaxInt. | 1167 // instruction deopts. Hence clamp it to kMaxInt. |
| 1145 int abs_upper = upper == kMinInt ? kMaxInt : abs(upper); | 1168 int abs_upper = upper == kMinInt ? kMaxInt : abs(upper); |
| 1146 int abs_lower = lower == kMinInt ? kMaxInt : abs(lower); | 1169 int abs_lower = lower == kMinInt ? kMaxInt : abs(lower); |
| 1147 Range* result = | 1170 Range* result = |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 void HChange::PrintDataTo(StringStream* stream) { | 1424 void HChange::PrintDataTo(StringStream* stream) { |
| 1402 HUnaryOperation::PrintDataTo(stream); | 1425 HUnaryOperation::PrintDataTo(stream); |
| 1403 stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic()); | 1426 stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic()); |
| 1404 | 1427 |
| 1405 if (CanTruncateToInt32()) stream->Add(" truncating-int32"); | 1428 if (CanTruncateToInt32()) stream->Add(" truncating-int32"); |
| 1406 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); | 1429 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); |
| 1407 if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan"); | 1430 if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan"); |
| 1408 } | 1431 } |
| 1409 | 1432 |
| 1410 | 1433 |
| 1411 static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* dividend) { | |
| 1412 // A value with an integer representation does not need to be transformed. | |
| 1413 if (dividend->representation().IsInteger32()) { | |
| 1414 return dividend; | |
| 1415 } | |
| 1416 // A change from an integer32 can be replaced by the integer32 value. | |
| 1417 if (dividend->IsChange() && | |
| 1418 HChange::cast(dividend)->from().IsInteger32()) { | |
| 1419 return HChange::cast(dividend)->value(); | |
| 1420 } | |
| 1421 return NULL; | |
| 1422 } | |
| 1423 | |
| 1424 | |
| 1425 HValue* HUnaryMathOperation::Canonicalize() { | 1434 HValue* HUnaryMathOperation::Canonicalize() { |
| 1426 if (op() == kMathRound || op() == kMathFloor) { | 1435 if (op() == kMathRound || op() == kMathFloor) { |
| 1427 HValue* val = value(); | 1436 HValue* val = value(); |
| 1428 if (val->IsChange()) val = HChange::cast(val)->value(); | 1437 if (val->IsChange()) val = HChange::cast(val)->value(); |
| 1429 | |
| 1430 // If the input is smi or integer32 then we replace the instruction with its | |
| 1431 // input. | |
| 1432 if (val->representation().IsSmiOrInteger32()) { | 1438 if (val->representation().IsSmiOrInteger32()) { |
| 1433 if (!val->representation().Equals(representation())) { | 1439 if (val->representation().Equals(representation())) return val; |
| 1434 HChange* result = new(block()->zone()) HChange( | 1440 return Prepend(new(block()->zone()) HChange( |
| 1435 val, representation(), false, false); | 1441 val, representation(), false, false)); |
| 1436 result->InsertBefore(this); | |
| 1437 return result; | |
| 1438 } | |
| 1439 return val; | |
| 1440 } | 1442 } |
| 1441 } | 1443 } |
| 1444 if (op() == kMathFloor && value()->IsDiv() && value()->UseCount() == 1) { |
| 1445 HDiv* hdiv = HDiv::cast(value()); |
| 1442 | 1446 |
| 1443 if (op() == kMathFloor) { | 1447 HValue* left = hdiv->left(); |
| 1444 HValue* val = value(); | 1448 if (left->representation().IsInteger32()) { |
| 1445 if (val->IsChange()) val = HChange::cast(val)->value(); | 1449 // A value with an integer representation does not need to be transformed. |
| 1446 if (val->IsDiv() && (val->UseCount() == 1)) { | 1450 } else if (left->IsChange() && HChange::cast(left)->from().IsInteger32()) { |
| 1447 HDiv* hdiv = HDiv::cast(val); | 1451 // A change from an integer32 can be replaced by the integer32 value. |
| 1448 HValue* left = hdiv->left(); | 1452 left = HChange::cast(left)->value(); |
| 1449 HValue* right = hdiv->right(); | 1453 } else if (hdiv->observed_input_representation(1).IsSmiOrInteger32()) { |
| 1450 // Try to simplify left and right values of the division. | 1454 left = Prepend(new(block()->zone()) HChange( |
| 1451 HValue* new_left = SimplifiedDividendForMathFloorOfDiv(left); | 1455 left, Representation::Integer32(), false, false)); |
| 1452 if (new_left == NULL && | 1456 } else { |
| 1453 hdiv->observed_input_representation(1).IsSmiOrInteger32()) { | 1457 return this; |
| 1454 new_left = new(block()->zone()) HChange( | 1458 } |
| 1455 left, Representation::Integer32(), false, false); | |
| 1456 HChange::cast(new_left)->InsertBefore(this); | |
| 1457 } | |
| 1458 HValue* new_right = | |
| 1459 LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right); | |
| 1460 if (new_right == NULL && | |
| 1461 #if V8_TARGET_ARCH_ARM | |
| 1462 CpuFeatures::IsSupported(SUDIV) && | |
| 1463 #endif | |
| 1464 hdiv->observed_input_representation(2).IsSmiOrInteger32()) { | |
| 1465 new_right = new(block()->zone()) HChange( | |
| 1466 right, Representation::Integer32(), false, false); | |
| 1467 HChange::cast(new_right)->InsertBefore(this); | |
| 1468 } | |
| 1469 | 1459 |
| 1470 // Return if left or right are not optimizable. | 1460 HValue* right = hdiv->right(); |
| 1471 if ((new_left == NULL) || (new_right == NULL)) return this; | 1461 if (right->IsInteger32Constant()) { |
| 1462 right = Prepend(HConstant::cast(right)->CopyToRepresentation( |
| 1463 Representation::Integer32(), right->block()->zone())); |
| 1464 } else if (right->representation().IsInteger32()) { |
| 1465 // A value with an integer representation does not need to be transformed. |
| 1466 } else if (right->IsChange() && |
| 1467 HChange::cast(right)->from().IsInteger32()) { |
| 1468 // A change from an integer32 can be replaced by the integer32 value. |
| 1469 right = HChange::cast(right)->value(); |
| 1470 } else if (hdiv->observed_input_representation(2).IsSmiOrInteger32()) { |
| 1471 right = Prepend(new(block()->zone()) HChange( |
| 1472 right, Representation::Integer32(), false, false)); |
| 1473 } else { |
| 1474 return this; |
| 1475 } |
| 1472 | 1476 |
| 1473 // Insert the new values in the graph. | 1477 return Prepend(HMathFloorOfDiv::New( |
| 1474 if (new_left->IsInstruction() && | 1478 block()->zone(), context(), left, right)); |
| 1475 !HInstruction::cast(new_left)->IsLinked()) { | |
| 1476 HInstruction::cast(new_left)->InsertBefore(this); | |
| 1477 } | |
| 1478 if (new_right->IsInstruction() && | |
| 1479 !HInstruction::cast(new_right)->IsLinked()) { | |
| 1480 HInstruction::cast(new_right)->InsertBefore(this); | |
| 1481 } | |
| 1482 HMathFloorOfDiv* instr = | |
| 1483 HMathFloorOfDiv::New(block()->zone(), context(), new_left, new_right); | |
| 1484 // Replace this HMathFloor instruction by the new HMathFloorOfDiv. | |
| 1485 instr->InsertBefore(this); | |
| 1486 ReplaceAllUsesWith(instr); | |
| 1487 Kill(); | |
| 1488 // We know the division had no other uses than this HMathFloor. Delete it. | |
| 1489 // Dead code elimination will deal with |left| and |right| if | |
| 1490 // appropriate. | |
| 1491 hdiv->DeleteAndReplaceWith(NULL); | |
| 1492 | |
| 1493 // Return NULL to remove this instruction from the graph. | |
| 1494 return NULL; | |
| 1495 } | |
| 1496 } | 1479 } |
| 1497 return this; | 1480 return this; |
| 1498 } | 1481 } |
| 1499 | 1482 |
| 1500 | 1483 |
| 1501 HValue* HCheckInstanceType::Canonicalize() { | 1484 HValue* HCheckInstanceType::Canonicalize() { |
| 1502 if (check_ == IS_STRING && value()->type().IsString()) { | 1485 if (check_ == IS_STRING && value()->type().IsString()) { |
| 1503 return value(); | 1486 return value(); |
| 1504 } | 1487 } |
| 1505 | 1488 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1539 case IS_INTERNALIZED_STRING: | 1522 case IS_INTERNALIZED_STRING: |
| 1540 *mask = kIsNotStringMask | kIsNotInternalizedMask; | 1523 *mask = kIsNotStringMask | kIsNotInternalizedMask; |
| 1541 *tag = kInternalizedTag; | 1524 *tag = kInternalizedTag; |
| 1542 return; | 1525 return; |
| 1543 default: | 1526 default: |
| 1544 UNREACHABLE(); | 1527 UNREACHABLE(); |
| 1545 } | 1528 } |
| 1546 } | 1529 } |
| 1547 | 1530 |
| 1548 | 1531 |
| 1549 void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect, | 1532 bool HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect, |
| 1550 HValue* dominator) { | 1533 HValue* dominator) { |
| 1551 ASSERT(side_effect == kChangesMaps); | 1534 ASSERT(side_effect == kMaps); |
| 1552 // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once | 1535 // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once |
| 1553 // type information is rich enough we should generalize this to any HType | 1536 // type information is rich enough we should generalize this to any HType |
| 1554 // for which the map is known. | 1537 // for which the map is known. |
| 1555 if (HasNoUses() && dominator->IsStoreNamedField()) { | 1538 if (HasNoUses() && dominator->IsStoreNamedField()) { |
| 1556 HStoreNamedField* store = HStoreNamedField::cast(dominator); | 1539 HStoreNamedField* store = HStoreNamedField::cast(dominator); |
| 1557 if (!store->has_transition() || store->object() != value()) return; | 1540 if (!store->has_transition() || store->object() != value()) return false; |
| 1558 HConstant* transition = HConstant::cast(store->transition()); | 1541 HConstant* transition = HConstant::cast(store->transition()); |
| 1559 if (map_set_.Contains(transition->GetUnique())) { | 1542 if (map_set_.Contains(transition->GetUnique())) { |
| 1560 DeleteAndReplaceWith(NULL); | 1543 DeleteAndReplaceWith(NULL); |
| 1561 return; | 1544 return true; |
| 1562 } | 1545 } |
| 1563 } | 1546 } |
| 1547 return false; |
| 1564 } | 1548 } |
| 1565 | 1549 |
| 1566 | 1550 |
| 1567 void HCheckMaps::PrintDataTo(StringStream* stream) { | 1551 void HCheckMaps::PrintDataTo(StringStream* stream) { |
| 1568 value()->PrintNameTo(stream); | 1552 value()->PrintNameTo(stream); |
| 1569 stream->Add(" [%p", *map_set_.at(0).handle()); | 1553 stream->Add(" [%p", *map_set_.at(0).handle()); |
| 1570 for (int i = 1; i < map_set_.size(); ++i) { | 1554 for (int i = 1; i < map_set_.size(); ++i) { |
| 1571 stream->Add(",%p", *map_set_.at(i).handle()); | 1555 stream->Add(",%p", *map_set_.at(i).handle()); |
| 1572 } | 1556 } |
| 1573 stream->Add("]%s", CanOmitMapChecks() ? "(omitted)" : ""); | 1557 stream->Add("]%s", CanOmitMapChecks() ? "(omitted)" : ""); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1648 | 1632 |
| 1649 | 1633 |
| 1650 Range* HChange::InferRange(Zone* zone) { | 1634 Range* HChange::InferRange(Zone* zone) { |
| 1651 Range* input_range = value()->range(); | 1635 Range* input_range = value()->range(); |
| 1652 if (from().IsInteger32() && !value()->CheckFlag(HInstruction::kUint32) && | 1636 if (from().IsInteger32() && !value()->CheckFlag(HInstruction::kUint32) && |
| 1653 (to().IsSmi() || | 1637 (to().IsSmi() || |
| 1654 (to().IsTagged() && | 1638 (to().IsTagged() && |
| 1655 input_range != NULL && | 1639 input_range != NULL && |
| 1656 input_range->IsInSmiRange()))) { | 1640 input_range->IsInSmiRange()))) { |
| 1657 set_type(HType::Smi()); | 1641 set_type(HType::Smi()); |
| 1658 ClearGVNFlag(kChangesNewSpacePromotion); | 1642 ClearChangesFlag(kNewSpacePromotion); |
| 1659 } | 1643 } |
| 1660 Range* result = (input_range != NULL) | 1644 Range* result = (input_range != NULL) |
| 1661 ? input_range->Copy(zone) | 1645 ? input_range->Copy(zone) |
| 1662 : HValue::InferRange(zone); | 1646 : HValue::InferRange(zone); |
| 1663 result->set_can_be_minus_zero(!to().IsSmiOrInteger32() || | 1647 result->set_can_be_minus_zero(!to().IsSmiOrInteger32() || |
| 1664 !(CheckFlag(kAllUsesTruncatingToInt32) || | 1648 !(CheckFlag(kAllUsesTruncatingToInt32) || |
| 1665 CheckFlag(kAllUsesTruncatingToSmi))); | 1649 CheckFlag(kAllUsesTruncatingToSmi))); |
| 1666 if (to().IsSmi()) result->ClampToSmi(); | 1650 if (to().IsSmi()) result->ClampToSmi(); |
| 1667 return result; | 1651 return result; |
| 1668 } | 1652 } |
| 1669 | 1653 |
| 1670 | 1654 |
| 1671 Range* HConstant::InferRange(Zone* zone) { | 1655 Range* HConstant::InferRange(Zone* zone) { |
| 1672 if (has_int32_value_) { | 1656 if (has_int32_value_) { |
| 1673 Range* result = new(zone) Range(int32_value_, int32_value_); | 1657 Range* result = new(zone) Range(int32_value_, int32_value_); |
| 1674 result->set_can_be_minus_zero(false); | 1658 result->set_can_be_minus_zero(false); |
| 1675 return result; | 1659 return result; |
| 1676 } | 1660 } |
| 1677 return HValue::InferRange(zone); | 1661 return HValue::InferRange(zone); |
| 1678 } | 1662 } |
| 1679 | 1663 |
| 1680 | 1664 |
| 1681 int HPhi::position() const { | 1665 HSourcePosition HPhi::position() const { |
| 1682 return block()->first()->position(); | 1666 return block()->first()->position(); |
| 1683 } | 1667 } |
| 1684 | 1668 |
| 1685 | 1669 |
| 1686 Range* HPhi::InferRange(Zone* zone) { | 1670 Range* HPhi::InferRange(Zone* zone) { |
| 1687 Representation r = representation(); | 1671 Representation r = representation(); |
| 1688 if (r.IsSmiOrInteger32()) { | 1672 if (r.IsSmiOrInteger32()) { |
| 1689 if (block()->IsLoopHeader()) { | 1673 if (block()->IsLoopHeader()) { |
| 1690 Range* range = r.IsSmi() | 1674 Range* range = r.IsSmi() |
| 1691 ? new(zone) Range(Smi::kMinValue, Smi::kMaxValue) | 1675 ? new(zone) Range(Smi::kMinValue, Smi::kMaxValue) |
| (...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2524 Heap* heap = Handle<HeapObject>::cast(handle)->GetHeap(); | 2508 Heap* heap = Handle<HeapObject>::cast(handle)->GetHeap(); |
| 2525 is_not_in_new_space_ = !heap->InNewSpace(*handle); | 2509 is_not_in_new_space_ = !heap->InNewSpace(*handle); |
| 2526 } | 2510 } |
| 2527 if (handle->IsNumber()) { | 2511 if (handle->IsNumber()) { |
| 2528 double n = handle->Number(); | 2512 double n = handle->Number(); |
| 2529 has_int32_value_ = IsInteger32(n); | 2513 has_int32_value_ = IsInteger32(n); |
| 2530 int32_value_ = DoubleToInt32(n); | 2514 int32_value_ = DoubleToInt32(n); |
| 2531 has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_); | 2515 has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_); |
| 2532 double_value_ = n; | 2516 double_value_ = n; |
| 2533 has_double_value_ = true; | 2517 has_double_value_ = true; |
| 2518 // TODO(titzer): if this heap number is new space, tenure a new one. |
| 2534 } else { | 2519 } else { |
| 2535 is_internalized_string_ = handle->IsInternalizedString(); | 2520 is_internalized_string_ = handle->IsInternalizedString(); |
| 2536 } | 2521 } |
| 2537 | 2522 |
| 2538 is_cell_ = !handle.is_null() && | 2523 is_cell_ = !handle.is_null() && |
| 2539 (handle->IsCell() || handle->IsPropertyCell()); | 2524 (handle->IsCell() || handle->IsPropertyCell()); |
| 2540 Initialize(r); | 2525 Initialize(r); |
| 2541 } | 2526 } |
| 2542 | 2527 |
| 2543 | 2528 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2640 } | 2625 } |
| 2641 } | 2626 } |
| 2642 r = Representation::Tagged(); | 2627 r = Representation::Tagged(); |
| 2643 } | 2628 } |
| 2644 } | 2629 } |
| 2645 set_representation(r); | 2630 set_representation(r); |
| 2646 SetFlag(kUseGVN); | 2631 SetFlag(kUseGVN); |
| 2647 } | 2632 } |
| 2648 | 2633 |
| 2649 | 2634 |
| 2635 bool HConstant::ImmortalImmovable() const { |
| 2636 if (has_int32_value_) { |
| 2637 return false; |
| 2638 } |
| 2639 if (has_double_value_) { |
| 2640 if (IsSpecialDouble()) { |
| 2641 return true; |
| 2642 } |
| 2643 return false; |
| 2644 } |
| 2645 if (has_external_reference_value_) { |
| 2646 return false; |
| 2647 } |
| 2648 |
| 2649 ASSERT(!object_.handle().is_null()); |
| 2650 Heap* heap = isolate()->heap(); |
| 2651 ASSERT(!object_.IsKnownGlobal(heap->minus_zero_value())); |
| 2652 ASSERT(!object_.IsKnownGlobal(heap->nan_value())); |
| 2653 return |
| 2654 #define IMMORTAL_IMMOVABLE_ROOT(name) \ |
| 2655 object_.IsKnownGlobal(heap->name()) || |
| 2656 IMMORTAL_IMMOVABLE_ROOT_LIST(IMMORTAL_IMMOVABLE_ROOT) |
| 2657 #undef IMMORTAL_IMMOVABLE_ROOT |
| 2658 #define INTERNALIZED_STRING(name, value) \ |
| 2659 object_.IsKnownGlobal(heap->name()) || |
| 2660 INTERNALIZED_STRING_LIST(INTERNALIZED_STRING) |
| 2661 #undef INTERNALIZED_STRING |
| 2662 #define STRING_TYPE(NAME, size, name, Name) \ |
| 2663 object_.IsKnownGlobal(heap->name##_map()) || |
| 2664 STRING_TYPE_LIST(STRING_TYPE) |
| 2665 #undef STRING_TYPE |
| 2666 false; |
| 2667 } |
| 2668 |
| 2669 |
| 2650 bool HConstant::EmitAtUses() { | 2670 bool HConstant::EmitAtUses() { |
| 2651 ASSERT(IsLinked()); | 2671 ASSERT(IsLinked()); |
| 2652 if (block()->graph()->has_osr() && | 2672 if (block()->graph()->has_osr() && |
| 2653 block()->graph()->IsStandardConstant(this)) { | 2673 block()->graph()->IsStandardConstant(this)) { |
| 2654 // TODO(titzer): this seems like a hack that should be fixed by custom OSR. | 2674 // TODO(titzer): this seems like a hack that should be fixed by custom OSR. |
| 2655 return true; | 2675 return true; |
| 2656 } | 2676 } |
| 2657 if (UseCount() == 0) return true; | 2677 if (UseCount() == 0) return true; |
| 2658 if (IsCell()) return false; | 2678 if (IsCell()) return false; |
| 2659 if (representation().IsDouble()) return false; | 2679 if (representation().IsDouble()) return false; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2722 if (has_int32_value_) { | 2742 if (has_int32_value_) { |
| 2723 stream->Add("%d ", int32_value_); | 2743 stream->Add("%d ", int32_value_); |
| 2724 } else if (has_double_value_) { | 2744 } else if (has_double_value_) { |
| 2725 stream->Add("%f ", FmtElm(double_value_)); | 2745 stream->Add("%f ", FmtElm(double_value_)); |
| 2726 } else if (has_external_reference_value_) { | 2746 } else if (has_external_reference_value_) { |
| 2727 stream->Add("%p ", reinterpret_cast<void*>( | 2747 stream->Add("%p ", reinterpret_cast<void*>( |
| 2728 external_reference_value_.address())); | 2748 external_reference_value_.address())); |
| 2729 } else { | 2749 } else { |
| 2730 handle(Isolate::Current())->ShortPrint(stream); | 2750 handle(Isolate::Current())->ShortPrint(stream); |
| 2731 } | 2751 } |
| 2752 if (!is_not_in_new_space_) { |
| 2753 stream->Add("[new space] "); |
| 2754 } |
| 2732 } | 2755 } |
| 2733 | 2756 |
| 2734 | 2757 |
| 2735 void HBinaryOperation::PrintDataTo(StringStream* stream) { | 2758 void HBinaryOperation::PrintDataTo(StringStream* stream) { |
| 2736 left()->PrintNameTo(stream); | 2759 left()->PrintNameTo(stream); |
| 2737 stream->Add(" "); | 2760 stream->Add(" "); |
| 2738 right()->PrintNameTo(stream); | 2761 right()->PrintNameTo(stream); |
| 2739 if (CheckFlag(kCanOverflow)) stream->Add(" !"); | 2762 if (CheckFlag(kCanOverflow)) stream->Add(" !"); |
| 2740 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); | 2763 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); |
| 2741 } | 2764 } |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2938 } | 2961 } |
| 2939 if (access().IsStringLength()) { | 2962 if (access().IsStringLength()) { |
| 2940 return new(zone) Range(0, String::kMaxLength); | 2963 return new(zone) Range(0, String::kMaxLength); |
| 2941 } | 2964 } |
| 2942 return HValue::InferRange(zone); | 2965 return HValue::InferRange(zone); |
| 2943 } | 2966 } |
| 2944 | 2967 |
| 2945 | 2968 |
| 2946 Range* HLoadKeyed::InferRange(Zone* zone) { | 2969 Range* HLoadKeyed::InferRange(Zone* zone) { |
| 2947 switch (elements_kind()) { | 2970 switch (elements_kind()) { |
| 2948 case EXTERNAL_BYTE_ELEMENTS: | 2971 case EXTERNAL_INT8_ELEMENTS: |
| 2949 return new(zone) Range(kMinInt8, kMaxInt8); | 2972 return new(zone) Range(kMinInt8, kMaxInt8); |
| 2950 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 2973 case EXTERNAL_UINT8_ELEMENTS: |
| 2951 case EXTERNAL_PIXEL_ELEMENTS: | 2974 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 2952 return new(zone) Range(kMinUInt8, kMaxUInt8); | 2975 return new(zone) Range(kMinUInt8, kMaxUInt8); |
| 2953 case EXTERNAL_SHORT_ELEMENTS: | 2976 case EXTERNAL_INT16_ELEMENTS: |
| 2954 return new(zone) Range(kMinInt16, kMaxInt16); | 2977 return new(zone) Range(kMinInt16, kMaxInt16); |
| 2955 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 2978 case EXTERNAL_UINT16_ELEMENTS: |
| 2956 return new(zone) Range(kMinUInt16, kMaxUInt16); | 2979 return new(zone) Range(kMinUInt16, kMaxUInt16); |
| 2957 default: | 2980 default: |
| 2958 return HValue::InferRange(zone); | 2981 return HValue::InferRange(zone); |
| 2959 } | 2982 } |
| 2960 } | 2983 } |
| 2961 | 2984 |
| 2962 | 2985 |
| 2963 void HCompareGeneric::PrintDataTo(StringStream* stream) { | 2986 void HCompareGeneric::PrintDataTo(StringStream* stream) { |
| 2964 stream->Add(Token::Name(token())); | 2987 stream->Add(Token::Name(token())); |
| 2965 stream->Add(" "); | 2988 stream->Add(" "); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3075 | 3098 |
| 3076 | 3099 |
| 3077 void HParameter::PrintDataTo(StringStream* stream) { | 3100 void HParameter::PrintDataTo(StringStream* stream) { |
| 3078 stream->Add("%u", index()); | 3101 stream->Add("%u", index()); |
| 3079 } | 3102 } |
| 3080 | 3103 |
| 3081 | 3104 |
| 3082 void HLoadNamedField::PrintDataTo(StringStream* stream) { | 3105 void HLoadNamedField::PrintDataTo(StringStream* stream) { |
| 3083 object()->PrintNameTo(stream); | 3106 object()->PrintNameTo(stream); |
| 3084 access_.PrintTo(stream); | 3107 access_.PrintTo(stream); |
| 3108 |
| 3109 if (HasDependency()) { |
| 3110 stream->Add(" "); |
| 3111 dependency()->PrintNameTo(stream); |
| 3112 } |
| 3085 } | 3113 } |
| 3086 | 3114 |
| 3087 | 3115 |
| 3088 HCheckMaps* HCheckMaps::New(Zone* zone, | 3116 HCheckMaps* HCheckMaps::New(Zone* zone, |
| 3089 HValue* context, | 3117 HValue* context, |
| 3090 HValue* value, | 3118 HValue* value, |
| 3091 Handle<Map> map, | 3119 Handle<Map> map, |
| 3092 CompilationInfo* info, | 3120 CompilationInfo* info, |
| 3093 HValue* typecheck) { | 3121 HValue* typecheck) { |
| 3094 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); | 3122 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3225 names_cache->map()); | 3253 names_cache->map()); |
| 3226 HInstruction* index = HLoadKeyed::New( | 3254 HInstruction* index = HLoadKeyed::New( |
| 3227 block()->graph()->zone(), | 3255 block()->graph()->zone(), |
| 3228 block()->graph()->GetInvalidContext(), | 3256 block()->graph()->GetInvalidContext(), |
| 3229 index_cache, | 3257 index_cache, |
| 3230 key_load->key(), | 3258 key_load->key(), |
| 3231 key_load->key(), | 3259 key_load->key(), |
| 3232 key_load->elements_kind()); | 3260 key_load->elements_kind()); |
| 3233 map_check->InsertBefore(this); | 3261 map_check->InsertBefore(this); |
| 3234 index->InsertBefore(this); | 3262 index->InsertBefore(this); |
| 3235 HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex( | 3263 return Prepend(new(block()->zone()) HLoadFieldByIndex( |
| 3236 object(), index); | 3264 object(), index)); |
| 3237 load->InsertBefore(this); | |
| 3238 return load; | |
| 3239 } | 3265 } |
| 3240 } | 3266 } |
| 3241 } | 3267 } |
| 3242 | 3268 |
| 3243 return this; | 3269 return this; |
| 3244 } | 3270 } |
| 3245 | 3271 |
| 3246 | 3272 |
| 3247 void HStoreNamedGeneric::PrintDataTo(StringStream* stream) { | 3273 void HStoreNamedGeneric::PrintDataTo(StringStream* stream) { |
| 3248 object()->PrintNameTo(stream); | 3274 object()->PrintNameTo(stream); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3392 // If any of the actual input representation is more general than what we | 3418 // If any of the actual input representation is more general than what we |
| 3393 // have so far but not Tagged, use that representation instead. | 3419 // have so far but not Tagged, use that representation instead. |
| 3394 Representation input_rep = value()->representation(); | 3420 Representation input_rep = value()->representation(); |
| 3395 if (!input_rep.IsTagged()) { | 3421 if (!input_rep.IsTagged()) { |
| 3396 rep = rep.generalize(input_rep); | 3422 rep = rep.generalize(input_rep); |
| 3397 } | 3423 } |
| 3398 return rep; | 3424 return rep; |
| 3399 } | 3425 } |
| 3400 | 3426 |
| 3401 | 3427 |
| 3402 void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 3428 bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, |
| 3403 HValue* dominator) { | 3429 HValue* dominator) { |
| 3404 ASSERT(side_effect == kChangesNewSpacePromotion); | 3430 ASSERT(side_effect == kNewSpacePromotion); |
| 3405 Zone* zone = block()->zone(); | 3431 Zone* zone = block()->zone(); |
| 3406 if (!FLAG_use_allocation_folding) return; | 3432 if (!FLAG_use_allocation_folding) return false; |
| 3407 | 3433 |
| 3408 // Try to fold allocations together with their dominating allocations. | 3434 // Try to fold allocations together with their dominating allocations. |
| 3409 if (!dominator->IsAllocate()) { | 3435 if (!dominator->IsAllocate()) { |
| 3410 if (FLAG_trace_allocation_folding) { | 3436 if (FLAG_trace_allocation_folding) { |
| 3411 PrintF("#%d (%s) cannot fold into #%d (%s)\n", | 3437 PrintF("#%d (%s) cannot fold into #%d (%s)\n", |
| 3412 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3438 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
| 3413 } | 3439 } |
| 3414 return; | 3440 return false; |
| 3441 } |
| 3442 |
| 3443 // Check whether we are folding within the same block for local folding. |
| 3444 if (FLAG_use_local_allocation_folding && dominator->block() != block()) { |
| 3445 if (FLAG_trace_allocation_folding) { |
| 3446 PrintF("#%d (%s) cannot fold into #%d (%s), crosses basic blocks\n", |
| 3447 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
| 3448 } |
| 3449 return false; |
| 3415 } | 3450 } |
| 3416 | 3451 |
| 3417 HAllocate* dominator_allocate = HAllocate::cast(dominator); | 3452 HAllocate* dominator_allocate = HAllocate::cast(dominator); |
| 3418 HValue* dominator_size = dominator_allocate->size(); | 3453 HValue* dominator_size = dominator_allocate->size(); |
| 3419 HValue* current_size = size(); | 3454 HValue* current_size = size(); |
| 3420 | 3455 |
| 3421 // TODO(hpayer): Add support for non-constant allocation in dominator. | 3456 // TODO(hpayer): Add support for non-constant allocation in dominator. |
| 3422 if (!current_size->IsInteger32Constant() || | 3457 if (!current_size->IsInteger32Constant() || |
| 3423 !dominator_size->IsInteger32Constant()) { | 3458 !dominator_size->IsInteger32Constant()) { |
| 3424 if (FLAG_trace_allocation_folding) { | 3459 if (FLAG_trace_allocation_folding) { |
| 3425 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n", | 3460 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n", |
| 3426 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3461 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
| 3427 } | 3462 } |
| 3428 return; | 3463 return false; |
| 3429 } | 3464 } |
| 3430 | 3465 |
| 3431 dominator_allocate = GetFoldableDominator(dominator_allocate); | 3466 dominator_allocate = GetFoldableDominator(dominator_allocate); |
| 3432 if (dominator_allocate == NULL) { | 3467 if (dominator_allocate == NULL) { |
| 3433 return; | 3468 return false; |
| 3434 } | 3469 } |
| 3435 | 3470 |
| 3436 ASSERT((IsNewSpaceAllocation() && | 3471 ASSERT((IsNewSpaceAllocation() && |
| 3437 dominator_allocate->IsNewSpaceAllocation()) || | 3472 dominator_allocate->IsNewSpaceAllocation()) || |
| 3438 (IsOldDataSpaceAllocation() && | 3473 (IsOldDataSpaceAllocation() && |
| 3439 dominator_allocate->IsOldDataSpaceAllocation()) || | 3474 dominator_allocate->IsOldDataSpaceAllocation()) || |
| 3440 (IsOldPointerSpaceAllocation() && | 3475 (IsOldPointerSpaceAllocation() && |
| 3441 dominator_allocate->IsOldPointerSpaceAllocation())); | 3476 dominator_allocate->IsOldPointerSpaceAllocation())); |
| 3442 | 3477 |
| 3443 // First update the size of the dominator allocate instruction. | 3478 // First update the size of the dominator allocate instruction. |
| 3444 dominator_size = dominator_allocate->size(); | 3479 dominator_size = dominator_allocate->size(); |
| 3445 int32_t original_object_size = | 3480 int32_t original_object_size = |
| 3446 HConstant::cast(dominator_size)->GetInteger32Constant(); | 3481 HConstant::cast(dominator_size)->GetInteger32Constant(); |
| 3447 int32_t dominator_size_constant = original_object_size; | 3482 int32_t dominator_size_constant = original_object_size; |
| 3448 int32_t current_size_constant = | 3483 int32_t current_size_constant = |
| 3449 HConstant::cast(current_size)->GetInteger32Constant(); | 3484 HConstant::cast(current_size)->GetInteger32Constant(); |
| 3450 int32_t new_dominator_size = dominator_size_constant + current_size_constant; | 3485 int32_t new_dominator_size = dominator_size_constant + current_size_constant; |
| 3451 | 3486 |
| 3452 if (MustAllocateDoubleAligned()) { | 3487 if (MustAllocateDoubleAligned()) { |
| 3453 if (!dominator_allocate->MustAllocateDoubleAligned()) { | 3488 if (!dominator_allocate->MustAllocateDoubleAligned()) { |
| 3454 dominator_allocate->MakeDoubleAligned(); | 3489 dominator_allocate->MakeDoubleAligned(); |
| 3455 } | 3490 } |
| 3456 if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { | 3491 if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { |
| 3457 dominator_size_constant += kDoubleSize / 2; | 3492 dominator_size_constant += kDoubleSize / 2; |
| 3458 new_dominator_size += kDoubleSize / 2; | 3493 new_dominator_size += kDoubleSize / 2; |
| 3459 } | 3494 } |
| 3460 } | 3495 } |
| 3461 | 3496 |
| 3462 if (new_dominator_size > isolate()->heap()->MaxRegularSpaceAllocationSize()) { | 3497 // Since we clear the first word after folded memory, we cannot use the |
| 3498 // whole Page::kMaxRegularHeapObjectSize memory. |
| 3499 if (new_dominator_size > Page::kMaxRegularHeapObjectSize - kPointerSize) { |
| 3463 if (FLAG_trace_allocation_folding) { | 3500 if (FLAG_trace_allocation_folding) { |
| 3464 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", | 3501 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", |
| 3465 id(), Mnemonic(), dominator_allocate->id(), | 3502 id(), Mnemonic(), dominator_allocate->id(), |
| 3466 dominator_allocate->Mnemonic(), new_dominator_size); | 3503 dominator_allocate->Mnemonic(), new_dominator_size); |
| 3467 } | 3504 } |
| 3468 return; | 3505 return false; |
| 3469 } | 3506 } |
| 3470 | 3507 |
| 3471 HInstruction* new_dominator_size_constant = HConstant::CreateAndInsertBefore( | 3508 HInstruction* new_dominator_size_constant = HConstant::CreateAndInsertBefore( |
| 3472 zone, | 3509 zone, |
| 3473 context(), | 3510 context(), |
| 3474 new_dominator_size, | 3511 new_dominator_size, |
| 3475 Representation::None(), | 3512 Representation::None(), |
| 3476 dominator_allocate); | 3513 dominator_allocate); |
| 3477 dominator_allocate->UpdateSize(new_dominator_size_constant); | 3514 dominator_allocate->UpdateSize(new_dominator_size_constant); |
| 3478 | 3515 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3506 dominator_allocate, | 3543 dominator_allocate, |
| 3507 inner_offset, | 3544 inner_offset, |
| 3508 type()); | 3545 type()); |
| 3509 dominated_allocate_instr->InsertBefore(this); | 3546 dominated_allocate_instr->InsertBefore(this); |
| 3510 DeleteAndReplaceWith(dominated_allocate_instr); | 3547 DeleteAndReplaceWith(dominated_allocate_instr); |
| 3511 if (FLAG_trace_allocation_folding) { | 3548 if (FLAG_trace_allocation_folding) { |
| 3512 PrintF("#%d (%s) folded into #%d (%s)\n", | 3549 PrintF("#%d (%s) folded into #%d (%s)\n", |
| 3513 id(), Mnemonic(), dominator_allocate->id(), | 3550 id(), Mnemonic(), dominator_allocate->id(), |
| 3514 dominator_allocate->Mnemonic()); | 3551 dominator_allocate->Mnemonic()); |
| 3515 } | 3552 } |
| 3553 return true; |
| 3516 } | 3554 } |
| 3517 | 3555 |
| 3518 | 3556 |
| 3519 HAllocate* HAllocate::GetFoldableDominator(HAllocate* dominator) { | 3557 HAllocate* HAllocate::GetFoldableDominator(HAllocate* dominator) { |
| 3520 if (!IsFoldable(dominator)) { | 3558 if (!IsFoldable(dominator)) { |
| 3521 // We cannot hoist old space allocations over new space allocations. | 3559 // We cannot hoist old space allocations over new space allocations. |
| 3522 if (IsNewSpaceAllocation() || dominator->IsNewSpaceAllocation()) { | 3560 if (IsNewSpaceAllocation() || dominator->IsNewSpaceAllocation()) { |
| 3523 if (FLAG_trace_allocation_folding) { | 3561 if (FLAG_trace_allocation_folding) { |
| 3524 PrintF("#%d (%s) cannot fold into #%d (%s), new space hoisting\n", | 3562 PrintF("#%d (%s) cannot fold into #%d (%s), new space hoisting\n", |
| 3525 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3563 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3615 store_map->SetFlag(HValue::kHasNoObservableSideEffects); | 3653 store_map->SetFlag(HValue::kHasNoObservableSideEffects); |
| 3616 store_map->InsertAfter(filler_map); | 3654 store_map->InsertAfter(filler_map); |
| 3617 | 3655 |
| 3618 // We must explicitly force Smi representation here because on x64 we | 3656 // We must explicitly force Smi representation here because on x64 we |
| 3619 // would otherwise automatically choose int32, but the actual store | 3657 // would otherwise automatically choose int32, but the actual store |
| 3620 // requires a Smi-tagged value. | 3658 // requires a Smi-tagged value. |
| 3621 HConstant* filler_size = HConstant::CreateAndInsertAfter( | 3659 HConstant* filler_size = HConstant::CreateAndInsertAfter( |
| 3622 zone, context(), free_space_size, Representation::Smi(), store_map); | 3660 zone, context(), free_space_size, Representation::Smi(), store_map); |
| 3623 // Must force Smi representation for x64 (see comment above). | 3661 // Must force Smi representation for x64 (see comment above). |
| 3624 HObjectAccess access = | 3662 HObjectAccess access = |
| 3625 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset, | 3663 HObjectAccess::ForMapAndOffset(isolate()->factory()->free_space_map(), |
| 3626 Representation::Smi()); | 3664 FreeSpace::kSizeOffset, |
| 3665 Representation::Smi()); |
| 3627 HStoreNamedField* store_size = HStoreNamedField::New(zone, context(), | 3666 HStoreNamedField* store_size = HStoreNamedField::New(zone, context(), |
| 3628 free_space_instr, access, filler_size); | 3667 free_space_instr, access, filler_size); |
| 3629 store_size->SetFlag(HValue::kHasNoObservableSideEffects); | 3668 store_size->SetFlag(HValue::kHasNoObservableSideEffects); |
| 3630 store_size->InsertAfter(filler_size); | 3669 store_size->InsertAfter(filler_size); |
| 3631 filler_free_space_size_ = store_size; | 3670 filler_free_space_size_ = store_size; |
| 3632 } | 3671 } |
| 3633 | 3672 |
| 3634 | 3673 |
| 3635 void HAllocate::ClearNextMapWord(int offset) { | 3674 void HAllocate::ClearNextMapWord(int offset) { |
| 3636 if (MustClearNextMapWord()) { | 3675 if (MustClearNextMapWord()) { |
| 3637 Zone* zone = block()->zone(); | 3676 Zone* zone = block()->zone(); |
| 3638 HObjectAccess access = HObjectAccess::ForJSObjectOffset(offset); | 3677 HObjectAccess access = |
| 3678 HObjectAccess::ForObservableJSObjectOffset(offset); |
| 3639 HStoreNamedField* clear_next_map = | 3679 HStoreNamedField* clear_next_map = |
| 3640 HStoreNamedField::New(zone, context(), this, access, | 3680 HStoreNamedField::New(zone, context(), this, access, |
| 3641 block()->graph()->GetConstant0()); | 3681 block()->graph()->GetConstant0()); |
| 3642 clear_next_map->ClearAllSideEffects(); | 3682 clear_next_map->ClearAllSideEffects(); |
| 3643 clear_next_map->InsertAfter(this); | 3683 clear_next_map->InsertAfter(this); |
| 3644 } | 3684 } |
| 3645 } | 3685 } |
| 3646 | 3686 |
| 3647 | 3687 |
| 3648 void HAllocate::PrintDataTo(StringStream* stream) { | 3688 void HAllocate::PrintDataTo(StringStream* stream) { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3880 return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0); | 3920 return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0); |
| 3881 case kMathLog: | 3921 case kMathLog: |
| 3882 case kMathSqrt: | 3922 case kMathSqrt: |
| 3883 return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value()); | 3923 return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value()); |
| 3884 case kMathPowHalf: | 3924 case kMathPowHalf: |
| 3885 case kMathAbs: | 3925 case kMathAbs: |
| 3886 return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d); | 3926 return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d); |
| 3887 case kMathRound: | 3927 case kMathRound: |
| 3888 case kMathFloor: | 3928 case kMathFloor: |
| 3889 return H_CONSTANT_DOUBLE(d); | 3929 return H_CONSTANT_DOUBLE(d); |
| 3930 case kMathClz32: |
| 3931 return H_CONSTANT_INT(32); |
| 3890 default: | 3932 default: |
| 3891 UNREACHABLE(); | 3933 UNREACHABLE(); |
| 3892 break; | 3934 break; |
| 3893 } | 3935 } |
| 3894 } | 3936 } |
| 3895 switch (op) { | 3937 switch (op) { |
| 3896 case kMathExp: | 3938 case kMathExp: |
| 3897 return H_CONSTANT_DOUBLE(fast_exp(d)); | 3939 return H_CONSTANT_DOUBLE(fast_exp(d)); |
| 3898 case kMathLog: | 3940 case kMathLog: |
| 3899 return H_CONSTANT_DOUBLE(std::log(d)); | 3941 return H_CONSTANT_DOUBLE(std::log(d)); |
| 3900 case kMathSqrt: | 3942 case kMathSqrt: |
| 3901 return H_CONSTANT_DOUBLE(fast_sqrt(d)); | 3943 return H_CONSTANT_DOUBLE(fast_sqrt(d)); |
| 3902 case kMathPowHalf: | 3944 case kMathPowHalf: |
| 3903 return H_CONSTANT_DOUBLE(power_double_double(d, 0.5)); | 3945 return H_CONSTANT_DOUBLE(power_double_double(d, 0.5)); |
| 3904 case kMathAbs: | 3946 case kMathAbs: |
| 3905 return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d); | 3947 return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d); |
| 3906 case kMathRound: | 3948 case kMathRound: |
| 3907 // -0.5 .. -0.0 round to -0.0. | 3949 // -0.5 .. -0.0 round to -0.0. |
| 3908 if ((d >= -0.5 && Double(d).Sign() < 0)) return H_CONSTANT_DOUBLE(-0.0); | 3950 if ((d >= -0.5 && Double(d).Sign() < 0)) return H_CONSTANT_DOUBLE(-0.0); |
| 3909 // Doubles are represented as Significant * 2 ^ Exponent. If the | 3951 // Doubles are represented as Significant * 2 ^ Exponent. If the |
| 3910 // Exponent is not negative, the double value is already an integer. | 3952 // Exponent is not negative, the double value is already an integer. |
| 3911 if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d); | 3953 if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d); |
| 3912 return H_CONSTANT_DOUBLE(std::floor(d + 0.5)); | 3954 return H_CONSTANT_DOUBLE(std::floor(d + 0.5)); |
| 3913 case kMathFloor: | 3955 case kMathFloor: |
| 3914 return H_CONSTANT_DOUBLE(std::floor(d)); | 3956 return H_CONSTANT_DOUBLE(std::floor(d)); |
| 3957 case kMathClz32: { |
| 3958 uint32_t i = DoubleToUint32(d); |
| 3959 return H_CONSTANT_INT( |
| 3960 (i == 0) ? 32 : CompilerIntrinsics::CountLeadingZeros(i)); |
| 3961 } |
| 3915 default: | 3962 default: |
| 3916 UNREACHABLE(); | 3963 UNREACHABLE(); |
| 3917 break; | 3964 break; |
| 3918 } | 3965 } |
| 3919 } while (false); | 3966 } while (false); |
| 3920 return new(zone) HUnaryMathOperation(context, value, op); | 3967 return new(zone) HUnaryMathOperation(context, value, op); |
| 3921 } | 3968 } |
| 3922 | 3969 |
| 3923 | 3970 |
| 3924 HInstruction* HPower::New(Zone* zone, | 3971 HInstruction* HPower::New(Zone* zone, |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4255 | 4302 |
| 4256 | 4303 |
| 4257 HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) { | 4304 HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) { |
| 4258 ASSERT(offset >= 0); | 4305 ASSERT(offset >= 0); |
| 4259 ASSERT(offset < FixedArray::kHeaderSize); | 4306 ASSERT(offset < FixedArray::kHeaderSize); |
| 4260 if (offset == FixedArray::kLengthOffset) return ForFixedArrayLength(); | 4307 if (offset == FixedArray::kLengthOffset) return ForFixedArrayLength(); |
| 4261 return HObjectAccess(kInobject, offset); | 4308 return HObjectAccess(kInobject, offset); |
| 4262 } | 4309 } |
| 4263 | 4310 |
| 4264 | 4311 |
| 4265 HObjectAccess HObjectAccess::ForJSObjectOffset(int offset, | 4312 HObjectAccess HObjectAccess::ForMapAndOffset(Handle<Map> map, int offset, |
| 4266 Representation representation) { | 4313 Representation representation) { |
| 4267 ASSERT(offset >= 0); | 4314 ASSERT(offset >= 0); |
| 4268 Portion portion = kInobject; | 4315 Portion portion = kInobject; |
| 4269 | 4316 |
| 4270 if (offset == JSObject::kElementsOffset) { | 4317 if (offset == JSObject::kElementsOffset) { |
| 4271 portion = kElementsPointer; | 4318 portion = kElementsPointer; |
| 4272 } else if (offset == JSObject::kMapOffset) { | 4319 } else if (offset == JSObject::kMapOffset) { |
| 4273 portion = kMaps; | 4320 portion = kMaps; |
| 4274 } | 4321 } |
| 4275 return HObjectAccess(portion, offset, representation); | 4322 bool existing_inobject_property = true; |
| 4323 if (!map.is_null()) { |
| 4324 existing_inobject_property = (offset < |
| 4325 map->instance_size() - map->unused_property_fields() * kPointerSize); |
| 4326 } |
| 4327 return HObjectAccess(portion, offset, representation, Handle<String>::null(), |
| 4328 false, existing_inobject_property); |
| 4276 } | 4329 } |
| 4277 | 4330 |
| 4278 | 4331 |
| 4279 HObjectAccess HObjectAccess::ForAllocationSiteOffset(int offset) { | 4332 HObjectAccess HObjectAccess::ForAllocationSiteOffset(int offset) { |
| 4280 switch (offset) { | 4333 switch (offset) { |
| 4281 case AllocationSite::kTransitionInfoOffset: | 4334 case AllocationSite::kTransitionInfoOffset: |
| 4282 return HObjectAccess(kInobject, offset, Representation::Tagged()); | 4335 return HObjectAccess(kInobject, offset, Representation::Tagged()); |
| 4283 case AllocationSite::kNestedSiteOffset: | 4336 case AllocationSite::kNestedSiteOffset: |
| 4284 return HObjectAccess(kInobject, offset, Representation::Tagged()); | 4337 return HObjectAccess(kInobject, offset, Representation::Tagged()); |
| 4285 case AllocationSite::kPretenureDataOffset: | 4338 case AllocationSite::kPretenureDataOffset: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4317 } else if (offset == JSObject::kMapOffset) { | 4370 } else if (offset == JSObject::kMapOffset) { |
| 4318 portion = kMaps; | 4371 portion = kMaps; |
| 4319 } | 4372 } |
| 4320 return HObjectAccess(portion, offset); | 4373 return HObjectAccess(portion, offset); |
| 4321 } | 4374 } |
| 4322 | 4375 |
| 4323 | 4376 |
| 4324 HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset, | 4377 HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset, |
| 4325 Representation representation) { | 4378 Representation representation) { |
| 4326 ASSERT(offset >= 0); | 4379 ASSERT(offset >= 0); |
| 4327 return HObjectAccess(kBackingStore, offset, representation); | 4380 return HObjectAccess(kBackingStore, offset, representation, |
| 4381 Handle<String>::null(), false, false); |
| 4328 } | 4382 } |
| 4329 | 4383 |
| 4330 | 4384 |
| 4331 HObjectAccess HObjectAccess::ForField(Handle<Map> map, | 4385 HObjectAccess HObjectAccess::ForField(Handle<Map> map, |
| 4332 LookupResult *lookup, Handle<String> name) { | 4386 LookupResult* lookup, |
| 4333 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*map)); | 4387 Handle<String> name) { |
| 4388 ASSERT(lookup->IsField() || lookup->IsTransitionToField()); |
| 4334 int index; | 4389 int index; |
| 4335 Representation representation; | 4390 Representation representation; |
| 4336 if (lookup->IsField()) { | 4391 if (lookup->IsField()) { |
| 4337 index = lookup->GetLocalFieldIndexFromMap(*map); | 4392 index = lookup->GetLocalFieldIndexFromMap(*map); |
| 4338 representation = lookup->representation(); | 4393 representation = lookup->representation(); |
| 4339 } else { | 4394 } else { |
| 4340 Map* transition = lookup->GetTransitionMapFromMap(*map); | 4395 Map* transition = lookup->GetTransitionTarget(); |
| 4341 int descriptor = transition->LastAdded(); | 4396 int descriptor = transition->LastAdded(); |
| 4342 index = transition->instance_descriptors()->GetFieldIndex(descriptor) - | 4397 index = transition->instance_descriptors()->GetFieldIndex(descriptor) - |
| 4343 map->inobject_properties(); | 4398 map->inobject_properties(); |
| 4344 PropertyDetails details = | 4399 PropertyDetails details = |
| 4345 transition->instance_descriptors()->GetDetails(descriptor); | 4400 transition->instance_descriptors()->GetDetails(descriptor); |
| 4346 representation = details.representation(); | 4401 representation = details.representation(); |
| 4347 } | 4402 } |
| 4348 if (index < 0) { | 4403 if (index < 0) { |
| 4349 // Negative property indices are in-object properties, indexed | 4404 // Negative property indices are in-object properties, indexed |
| 4350 // from the end of the fixed part of the object. | 4405 // from the end of the fixed part of the object. |
| 4351 int offset = (index * kPointerSize) + map->instance_size(); | 4406 int offset = (index * kPointerSize) + map->instance_size(); |
| 4352 return HObjectAccess(kInobject, offset, representation); | 4407 return HObjectAccess(kInobject, offset, representation, name, false, true); |
| 4353 } else { | 4408 } else { |
| 4354 // Non-negative property indices are in the properties array. | 4409 // Non-negative property indices are in the properties array. |
| 4355 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 4410 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
| 4356 return HObjectAccess(kBackingStore, offset, representation, name); | 4411 return HObjectAccess(kBackingStore, offset, representation, name, |
| 4412 false, false); |
| 4357 } | 4413 } |
| 4358 } | 4414 } |
| 4359 | 4415 |
| 4360 | 4416 |
| 4361 HObjectAccess HObjectAccess::ForCellPayload(Isolate* isolate) { | 4417 HObjectAccess HObjectAccess::ForCellPayload(Isolate* isolate) { |
| 4362 return HObjectAccess( | 4418 return HObjectAccess( |
| 4363 kInobject, Cell::kValueOffset, Representation::Tagged(), | 4419 kInobject, Cell::kValueOffset, Representation::Tagged(), |
| 4364 Handle<String>(isolate->heap()->cell_value_string())); | 4420 Handle<String>(isolate->heap()->cell_value_string())); |
| 4365 } | 4421 } |
| 4366 | 4422 |
| 4367 | 4423 |
| 4368 void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) { | 4424 void HObjectAccess::SetGVNFlags(HValue *instr, PropertyAccessType access_type) { |
| 4369 // set the appropriate GVN flags for a given load or store instruction | 4425 // set the appropriate GVN flags for a given load or store instruction |
| 4370 if (is_store) { | 4426 if (access_type == STORE) { |
| 4371 // track dominating allocations in order to eliminate write barriers | 4427 // track dominating allocations in order to eliminate write barriers |
| 4372 instr->SetGVNFlag(kDependsOnNewSpacePromotion); | 4428 instr->SetDependsOnFlag(::v8::internal::kNewSpacePromotion); |
| 4373 instr->SetFlag(HValue::kTrackSideEffectDominators); | 4429 instr->SetFlag(HValue::kTrackSideEffectDominators); |
| 4374 } else { | 4430 } else { |
| 4375 // try to GVN loads, but don't hoist above map changes | 4431 // try to GVN loads, but don't hoist above map changes |
| 4376 instr->SetFlag(HValue::kUseGVN); | 4432 instr->SetFlag(HValue::kUseGVN); |
| 4377 instr->SetGVNFlag(kDependsOnMaps); | 4433 instr->SetDependsOnFlag(::v8::internal::kMaps); |
| 4378 } | 4434 } |
| 4379 | 4435 |
| 4380 switch (portion()) { | 4436 switch (portion()) { |
| 4381 case kArrayLengths: | 4437 case kArrayLengths: |
| 4382 instr->SetGVNFlag(is_store | 4438 if (access_type == STORE) { |
| 4383 ? kChangesArrayLengths : kDependsOnArrayLengths); | 4439 instr->SetChangesFlag(::v8::internal::kArrayLengths); |
| 4440 } else { |
| 4441 instr->SetDependsOnFlag(::v8::internal::kArrayLengths); |
| 4442 } |
| 4384 break; | 4443 break; |
| 4385 case kStringLengths: | 4444 case kStringLengths: |
| 4386 instr->SetGVNFlag(is_store | 4445 if (access_type == STORE) { |
| 4387 ? kChangesStringLengths : kDependsOnStringLengths); | 4446 instr->SetChangesFlag(::v8::internal::kStringLengths); |
| 4447 } else { |
| 4448 instr->SetDependsOnFlag(::v8::internal::kStringLengths); |
| 4449 } |
| 4388 break; | 4450 break; |
| 4389 case kInobject: | 4451 case kInobject: |
| 4390 instr->SetGVNFlag(is_store | 4452 if (access_type == STORE) { |
| 4391 ? kChangesInobjectFields : kDependsOnInobjectFields); | 4453 instr->SetChangesFlag(::v8::internal::kInobjectFields); |
| 4454 } else { |
| 4455 instr->SetDependsOnFlag(::v8::internal::kInobjectFields); |
| 4456 } |
| 4392 break; | 4457 break; |
| 4393 case kDouble: | 4458 case kDouble: |
| 4394 instr->SetGVNFlag(is_store | 4459 if (access_type == STORE) { |
| 4395 ? kChangesDoubleFields : kDependsOnDoubleFields); | 4460 instr->SetChangesFlag(::v8::internal::kDoubleFields); |
| 4461 } else { |
| 4462 instr->SetDependsOnFlag(::v8::internal::kDoubleFields); |
| 4463 } |
| 4396 break; | 4464 break; |
| 4397 case kBackingStore: | 4465 case kBackingStore: |
| 4398 instr->SetGVNFlag(is_store | 4466 if (access_type == STORE) { |
| 4399 ? kChangesBackingStoreFields : kDependsOnBackingStoreFields); | 4467 instr->SetChangesFlag(::v8::internal::kBackingStoreFields); |
| 4468 } else { |
| 4469 instr->SetDependsOnFlag(::v8::internal::kBackingStoreFields); |
| 4470 } |
| 4400 break; | 4471 break; |
| 4401 case kElementsPointer: | 4472 case kElementsPointer: |
| 4402 instr->SetGVNFlag(is_store | 4473 if (access_type == STORE) { |
| 4403 ? kChangesElementsPointer : kDependsOnElementsPointer); | 4474 instr->SetChangesFlag(::v8::internal::kElementsPointer); |
| 4475 } else { |
| 4476 instr->SetDependsOnFlag(::v8::internal::kElementsPointer); |
| 4477 } |
| 4404 break; | 4478 break; |
| 4405 case kMaps: | 4479 case kMaps: |
| 4406 instr->SetGVNFlag(is_store | 4480 if (access_type == STORE) { |
| 4407 ? kChangesMaps : kDependsOnMaps); | 4481 instr->SetChangesFlag(::v8::internal::kMaps); |
| 4482 } else { |
| 4483 instr->SetDependsOnFlag(::v8::internal::kMaps); |
| 4484 } |
| 4408 break; | 4485 break; |
| 4409 case kExternalMemory: | 4486 case kExternalMemory: |
| 4410 instr->SetGVNFlag(is_store | 4487 if (access_type == STORE) { |
| 4411 ? kChangesExternalMemory : kDependsOnExternalMemory); | 4488 instr->SetChangesFlag(::v8::internal::kExternalMemory); |
| 4489 } else { |
| 4490 instr->SetDependsOnFlag(::v8::internal::kExternalMemory); |
| 4491 } |
| 4412 break; | 4492 break; |
| 4413 } | 4493 } |
| 4414 } | 4494 } |
| 4415 | 4495 |
| 4416 | 4496 |
| 4417 void HObjectAccess::PrintTo(StringStream* stream) { | 4497 void HObjectAccess::PrintTo(StringStream* stream) const { |
| 4418 stream->Add("."); | 4498 stream->Add("."); |
| 4419 | 4499 |
| 4420 switch (portion()) { | 4500 switch (portion()) { |
| 4421 case kArrayLengths: | 4501 case kArrayLengths: |
| 4422 case kStringLengths: | 4502 case kStringLengths: |
| 4423 stream->Add("%length"); | 4503 stream->Add("%length"); |
| 4424 break; | 4504 break; |
| 4425 case kElementsPointer: | 4505 case kElementsPointer: |
| 4426 stream->Add("%elements"); | 4506 stream->Add("%elements"); |
| 4427 break; | 4507 break; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4443 break; | 4523 break; |
| 4444 case kExternalMemory: | 4524 case kExternalMemory: |
| 4445 stream->Add("[external-memory]"); | 4525 stream->Add("[external-memory]"); |
| 4446 break; | 4526 break; |
| 4447 } | 4527 } |
| 4448 | 4528 |
| 4449 stream->Add("@%d", offset()); | 4529 stream->Add("@%d", offset()); |
| 4450 } | 4530 } |
| 4451 | 4531 |
| 4452 } } // namespace v8::internal | 4532 } } // namespace v8::internal |
| OLD | NEW |