| 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" | |
| 40 #elif V8_TARGET_ARCH_ARM | 38 #elif V8_TARGET_ARCH_ARM |
| 41 #include "arm/lithium-arm.h" | 39 #include "arm/lithium-arm.h" |
| 42 #elif V8_TARGET_ARCH_MIPS | 40 #elif V8_TARGET_ARCH_MIPS |
| 43 #include "mips/lithium-mips.h" | 41 #include "mips/lithium-mips.h" |
| 44 #else | 42 #else |
| 45 #error Unsupported target architecture. | 43 #error Unsupported target architecture. |
| 46 #endif | 44 #endif |
| 47 | 45 |
| 48 namespace v8 { | 46 namespace v8 { |
| 49 namespace internal { | 47 namespace internal { |
| (...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 | 597 |
| 600 | 598 |
| 601 void HValue::PrintChangesTo(StringStream* stream) { | 599 void HValue::PrintChangesTo(StringStream* stream) { |
| 602 GVNFlagSet changes_flags = ChangesFlags(); | 600 GVNFlagSet changes_flags = ChangesFlags(); |
| 603 if (changes_flags.IsEmpty()) return; | 601 if (changes_flags.IsEmpty()) return; |
| 604 stream->Add(" changes["); | 602 stream->Add(" changes["); |
| 605 if (changes_flags == AllSideEffectsFlagSet()) { | 603 if (changes_flags == AllSideEffectsFlagSet()) { |
| 606 stream->Add("*"); | 604 stream->Add("*"); |
| 607 } else { | 605 } else { |
| 608 bool add_comma = false; | 606 bool add_comma = false; |
| 609 #define PRINT_DO(Type) \ | 607 #define PRINT_DO(type) \ |
| 610 if (changes_flags.Contains(k##Type)) { \ | 608 if (changes_flags.Contains(kChanges##type)) { \ |
| 611 if (add_comma) stream->Add(","); \ | 609 if (add_comma) stream->Add(","); \ |
| 612 add_comma = true; \ | 610 add_comma = true; \ |
| 613 stream->Add(#Type); \ | 611 stream->Add(#type); \ |
| 614 } | 612 } |
| 615 GVN_TRACKED_FLAG_LIST(PRINT_DO); | 613 GVN_TRACKED_FLAG_LIST(PRINT_DO); |
| 616 GVN_UNTRACKED_FLAG_LIST(PRINT_DO); | 614 GVN_UNTRACKED_FLAG_LIST(PRINT_DO); |
| 617 #undef PRINT_DO | 615 #undef PRINT_DO |
| 618 } | 616 } |
| 619 stream->Add("]"); | 617 stream->Add("]"); |
| 620 } | 618 } |
| 621 | 619 |
| 622 | 620 |
| 623 void HValue::PrintNameTo(StringStream* stream) { | 621 void HValue::PrintNameTo(StringStream* stream) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 } | 673 } |
| 676 | 674 |
| 677 | 675 |
| 678 void HValue::ComputeInitialRange(Zone* zone) { | 676 void HValue::ComputeInitialRange(Zone* zone) { |
| 679 ASSERT(!HasRange()); | 677 ASSERT(!HasRange()); |
| 680 range_ = InferRange(zone); | 678 range_ = InferRange(zone); |
| 681 ASSERT(HasRange()); | 679 ASSERT(HasRange()); |
| 682 } | 680 } |
| 683 | 681 |
| 684 | 682 |
| 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 | |
| 698 void HInstruction::PrintTo(StringStream* stream) { | 683 void HInstruction::PrintTo(StringStream* stream) { |
| 699 PrintMnemonicTo(stream); | 684 PrintMnemonicTo(stream); |
| 700 PrintDataTo(stream); | 685 PrintDataTo(stream); |
| 701 PrintRangeTo(stream); | 686 PrintRangeTo(stream); |
| 702 PrintChangesTo(stream); | 687 PrintChangesTo(stream); |
| 703 PrintTypeTo(stream); | 688 PrintTypeTo(stream); |
| 704 if (CheckFlag(HValue::kHasNoObservableSideEffects)) { | 689 if (CheckFlag(HValue::kHasNoObservableSideEffects)) { |
| 705 stream->Add(" [noOSE]"); | 690 stream->Add(" [noOSE]"); |
| 706 } | 691 } |
| 707 if (CheckFlag(HValue::kIsDead)) { | 692 if (CheckFlag(HValue::kIsDead)) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 ASSERT(!next->IsBlockEntry()); | 729 ASSERT(!next->IsBlockEntry()); |
| 745 ASSERT(!IsControlInstruction()); | 730 ASSERT(!IsControlInstruction()); |
| 746 ASSERT(!next->block()->IsStartBlock()); | 731 ASSERT(!next->block()->IsStartBlock()); |
| 747 ASSERT(next->previous_ != NULL); | 732 ASSERT(next->previous_ != NULL); |
| 748 HInstruction* prev = next->previous(); | 733 HInstruction* prev = next->previous(); |
| 749 prev->next_ = this; | 734 prev->next_ = this; |
| 750 next->previous_ = this; | 735 next->previous_ = this; |
| 751 next_ = next; | 736 next_ = next; |
| 752 previous_ = prev; | 737 previous_ = prev; |
| 753 SetBlock(next->block()); | 738 SetBlock(next->block()); |
| 754 if (!has_position() && next->has_position()) { | 739 if (position() == RelocInfo::kNoPosition && |
| 740 next->position() != RelocInfo::kNoPosition) { |
| 755 set_position(next->position()); | 741 set_position(next->position()); |
| 756 } | 742 } |
| 757 } | 743 } |
| 758 | 744 |
| 759 | 745 |
| 760 void HInstruction::InsertAfter(HInstruction* previous) { | 746 void HInstruction::InsertAfter(HInstruction* previous) { |
| 761 ASSERT(!IsLinked()); | 747 ASSERT(!IsLinked()); |
| 762 ASSERT(!previous->IsControlInstruction()); | 748 ASSERT(!previous->IsControlInstruction()); |
| 763 ASSERT(!IsControlInstruction() || previous->next_ == NULL); | 749 ASSERT(!IsControlInstruction() || previous->next_ == NULL); |
| 764 HBasicBlock* block = previous->block(); | 750 HBasicBlock* block = previous->block(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 781 } | 767 } |
| 782 | 768 |
| 783 previous_ = previous; | 769 previous_ = previous; |
| 784 next_ = next; | 770 next_ = next; |
| 785 SetBlock(block); | 771 SetBlock(block); |
| 786 previous->next_ = this; | 772 previous->next_ = this; |
| 787 if (next != NULL) next->previous_ = this; | 773 if (next != NULL) next->previous_ = this; |
| 788 if (block->last() == previous) { | 774 if (block->last() == previous) { |
| 789 block->set_last(this); | 775 block->set_last(this); |
| 790 } | 776 } |
| 791 if (!has_position() && previous->has_position()) { | 777 if (position() == RelocInfo::kNoPosition && |
| 778 previous->position() != RelocInfo::kNoPosition) { |
| 792 set_position(previous->position()); | 779 set_position(previous->position()); |
| 793 } | 780 } |
| 794 } | 781 } |
| 795 | 782 |
| 796 | 783 |
| 797 #ifdef DEBUG | 784 #ifdef DEBUG |
| 798 void HInstruction::Verify() { | 785 void HInstruction::Verify() { |
| 799 // Verify that input operands are defined before use. | 786 // Verify that input operands are defined before use. |
| 800 HBasicBlock* cur_block = block(); | 787 HBasicBlock* cur_block = block(); |
| 801 for (int i = 0; i < OperandCount(); ++i) { | 788 for (int i = 0; i < OperandCount(); ++i) { |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1140 | 1127 |
| 1141 const char* HUnaryMathOperation::OpName() const { | 1128 const char* HUnaryMathOperation::OpName() const { |
| 1142 switch (op()) { | 1129 switch (op()) { |
| 1143 case kMathFloor: return "floor"; | 1130 case kMathFloor: return "floor"; |
| 1144 case kMathRound: return "round"; | 1131 case kMathRound: return "round"; |
| 1145 case kMathAbs: return "abs"; | 1132 case kMathAbs: return "abs"; |
| 1146 case kMathLog: return "log"; | 1133 case kMathLog: return "log"; |
| 1147 case kMathExp: return "exp"; | 1134 case kMathExp: return "exp"; |
| 1148 case kMathSqrt: return "sqrt"; | 1135 case kMathSqrt: return "sqrt"; |
| 1149 case kMathPowHalf: return "pow-half"; | 1136 case kMathPowHalf: return "pow-half"; |
| 1150 case kMathClz32: return "clz32"; | |
| 1151 default: | 1137 default: |
| 1152 UNREACHABLE(); | 1138 UNREACHABLE(); |
| 1153 return NULL; | 1139 return NULL; |
| 1154 } | 1140 } |
| 1155 } | 1141 } |
| 1156 | 1142 |
| 1157 | 1143 |
| 1158 Range* HUnaryMathOperation::InferRange(Zone* zone) { | 1144 Range* HUnaryMathOperation::InferRange(Zone* zone) { |
| 1159 Representation r = representation(); | 1145 Representation r = representation(); |
| 1160 if (op() == kMathClz32) return new(zone) Range(0, 32); | |
| 1161 if (r.IsSmiOrInteger32() && value()->HasRange()) { | 1146 if (r.IsSmiOrInteger32() && value()->HasRange()) { |
| 1162 if (op() == kMathAbs) { | 1147 if (op() == kMathAbs) { |
| 1163 int upper = value()->range()->upper(); | 1148 int upper = value()->range()->upper(); |
| 1164 int lower = value()->range()->lower(); | 1149 int lower = value()->range()->lower(); |
| 1165 bool spans_zero = value()->range()->CanBeZero(); | 1150 bool spans_zero = value()->range()->CanBeZero(); |
| 1166 // Math.abs(kMinInt) overflows its representation, on which the | 1151 // Math.abs(kMinInt) overflows its representation, on which the |
| 1167 // instruction deopts. Hence clamp it to kMaxInt. | 1152 // instruction deopts. Hence clamp it to kMaxInt. |
| 1168 int abs_upper = upper == kMinInt ? kMaxInt : abs(upper); | 1153 int abs_upper = upper == kMinInt ? kMaxInt : abs(upper); |
| 1169 int abs_lower = lower == kMinInt ? kMaxInt : abs(lower); | 1154 int abs_lower = lower == kMinInt ? kMaxInt : abs(lower); |
| 1170 Range* result = | 1155 Range* result = |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1524 *tag = kInternalizedTag; | 1509 *tag = kInternalizedTag; |
| 1525 return; | 1510 return; |
| 1526 default: | 1511 default: |
| 1527 UNREACHABLE(); | 1512 UNREACHABLE(); |
| 1528 } | 1513 } |
| 1529 } | 1514 } |
| 1530 | 1515 |
| 1531 | 1516 |
| 1532 bool HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect, | 1517 bool HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect, |
| 1533 HValue* dominator) { | 1518 HValue* dominator) { |
| 1534 ASSERT(side_effect == kMaps); | 1519 ASSERT(side_effect == kChangesMaps); |
| 1535 // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once | 1520 // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once |
| 1536 // type information is rich enough we should generalize this to any HType | 1521 // type information is rich enough we should generalize this to any HType |
| 1537 // for which the map is known. | 1522 // for which the map is known. |
| 1538 if (HasNoUses() && dominator->IsStoreNamedField()) { | 1523 if (HasNoUses() && dominator->IsStoreNamedField()) { |
| 1539 HStoreNamedField* store = HStoreNamedField::cast(dominator); | 1524 HStoreNamedField* store = HStoreNamedField::cast(dominator); |
| 1540 if (!store->has_transition() || store->object() != value()) return false; | 1525 if (!store->has_transition() || store->object() != value()) return false; |
| 1541 HConstant* transition = HConstant::cast(store->transition()); | 1526 HConstant* transition = HConstant::cast(store->transition()); |
| 1542 if (map_set_.Contains(transition->GetUnique())) { | 1527 if (map_set_.Contains(transition->GetUnique())) { |
| 1543 DeleteAndReplaceWith(NULL); | 1528 DeleteAndReplaceWith(NULL); |
| 1544 return true; | 1529 return true; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1632 | 1617 |
| 1633 | 1618 |
| 1634 Range* HChange::InferRange(Zone* zone) { | 1619 Range* HChange::InferRange(Zone* zone) { |
| 1635 Range* input_range = value()->range(); | 1620 Range* input_range = value()->range(); |
| 1636 if (from().IsInteger32() && !value()->CheckFlag(HInstruction::kUint32) && | 1621 if (from().IsInteger32() && !value()->CheckFlag(HInstruction::kUint32) && |
| 1637 (to().IsSmi() || | 1622 (to().IsSmi() || |
| 1638 (to().IsTagged() && | 1623 (to().IsTagged() && |
| 1639 input_range != NULL && | 1624 input_range != NULL && |
| 1640 input_range->IsInSmiRange()))) { | 1625 input_range->IsInSmiRange()))) { |
| 1641 set_type(HType::Smi()); | 1626 set_type(HType::Smi()); |
| 1642 ClearChangesFlag(kNewSpacePromotion); | 1627 ClearGVNFlag(kChangesNewSpacePromotion); |
| 1643 } | 1628 } |
| 1644 Range* result = (input_range != NULL) | 1629 Range* result = (input_range != NULL) |
| 1645 ? input_range->Copy(zone) | 1630 ? input_range->Copy(zone) |
| 1646 : HValue::InferRange(zone); | 1631 : HValue::InferRange(zone); |
| 1647 result->set_can_be_minus_zero(!to().IsSmiOrInteger32() || | 1632 result->set_can_be_minus_zero(!to().IsSmiOrInteger32() || |
| 1648 !(CheckFlag(kAllUsesTruncatingToInt32) || | 1633 !(CheckFlag(kAllUsesTruncatingToInt32) || |
| 1649 CheckFlag(kAllUsesTruncatingToSmi))); | 1634 CheckFlag(kAllUsesTruncatingToSmi))); |
| 1650 if (to().IsSmi()) result->ClampToSmi(); | 1635 if (to().IsSmi()) result->ClampToSmi(); |
| 1651 return result; | 1636 return result; |
| 1652 } | 1637 } |
| 1653 | 1638 |
| 1654 | 1639 |
| 1655 Range* HConstant::InferRange(Zone* zone) { | 1640 Range* HConstant::InferRange(Zone* zone) { |
| 1656 if (has_int32_value_) { | 1641 if (has_int32_value_) { |
| 1657 Range* result = new(zone) Range(int32_value_, int32_value_); | 1642 Range* result = new(zone) Range(int32_value_, int32_value_); |
| 1658 result->set_can_be_minus_zero(false); | 1643 result->set_can_be_minus_zero(false); |
| 1659 return result; | 1644 return result; |
| 1660 } | 1645 } |
| 1661 return HValue::InferRange(zone); | 1646 return HValue::InferRange(zone); |
| 1662 } | 1647 } |
| 1663 | 1648 |
| 1664 | 1649 |
| 1665 HSourcePosition HPhi::position() const { | 1650 int HPhi::position() const { |
| 1666 return block()->first()->position(); | 1651 return block()->first()->position(); |
| 1667 } | 1652 } |
| 1668 | 1653 |
| 1669 | 1654 |
| 1670 Range* HPhi::InferRange(Zone* zone) { | 1655 Range* HPhi::InferRange(Zone* zone) { |
| 1671 Representation r = representation(); | 1656 Representation r = representation(); |
| 1672 if (r.IsSmiOrInteger32()) { | 1657 if (r.IsSmiOrInteger32()) { |
| 1673 if (block()->IsLoopHeader()) { | 1658 if (block()->IsLoopHeader()) { |
| 1674 Range* range = r.IsSmi() | 1659 Range* range = r.IsSmi() |
| 1675 ? new(zone) Range(Smi::kMinValue, Smi::kMaxValue) | 1660 ? new(zone) Range(Smi::kMinValue, Smi::kMaxValue) |
| (...skipping 1437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3113 } | 3098 } |
| 3114 | 3099 |
| 3115 | 3100 |
| 3116 HCheckMaps* HCheckMaps::New(Zone* zone, | 3101 HCheckMaps* HCheckMaps::New(Zone* zone, |
| 3117 HValue* context, | 3102 HValue* context, |
| 3118 HValue* value, | 3103 HValue* value, |
| 3119 Handle<Map> map, | 3104 Handle<Map> map, |
| 3120 CompilationInfo* info, | 3105 CompilationInfo* info, |
| 3121 HValue* typecheck) { | 3106 HValue* typecheck) { |
| 3122 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); | 3107 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); |
| 3123 check_map->Add(map, info, zone); | 3108 check_map->Add(map, zone); |
| 3124 if (map->CanOmitMapChecks() && | 3109 if (map->CanOmitMapChecks() && |
| 3125 value->IsConstant() && | 3110 value->IsConstant() && |
| 3126 HConstant::cast(value)->HasMap(map)) { | 3111 HConstant::cast(value)->HasMap(map)) { |
| 3127 // TODO(titzer): collect dependent map checks into a list. | 3112 // TODO(titzer): collect dependent map checks into a list. |
| 3128 check_map->omit_ = true; | 3113 check_map->omit_ = true; |
| 3129 if (map->CanTransition()) { | 3114 if (map->CanTransition()) { |
| 3130 map->AddDependentCompilationInfo( | 3115 map->AddDependentCompilationInfo( |
| 3131 DependentCode::kPrototypeCheckGroup, info); | 3116 DependentCode::kPrototypeCheckGroup, info); |
| 3132 } | 3117 } |
| 3133 } | 3118 } |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3420 Representation input_rep = value()->representation(); | 3405 Representation input_rep = value()->representation(); |
| 3421 if (!input_rep.IsTagged()) { | 3406 if (!input_rep.IsTagged()) { |
| 3422 rep = rep.generalize(input_rep); | 3407 rep = rep.generalize(input_rep); |
| 3423 } | 3408 } |
| 3424 return rep; | 3409 return rep; |
| 3425 } | 3410 } |
| 3426 | 3411 |
| 3427 | 3412 |
| 3428 bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 3413 bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, |
| 3429 HValue* dominator) { | 3414 HValue* dominator) { |
| 3430 ASSERT(side_effect == kNewSpacePromotion); | 3415 ASSERT(side_effect == kChangesNewSpacePromotion); |
| 3431 Zone* zone = block()->zone(); | 3416 Zone* zone = block()->zone(); |
| 3432 if (!FLAG_use_allocation_folding) return false; | 3417 if (!FLAG_use_allocation_folding) return false; |
| 3433 | 3418 |
| 3434 // Try to fold allocations together with their dominating allocations. | 3419 // Try to fold allocations together with their dominating allocations. |
| 3435 if (!dominator->IsAllocate()) { | 3420 if (!dominator->IsAllocate()) { |
| 3436 if (FLAG_trace_allocation_folding) { | 3421 if (FLAG_trace_allocation_folding) { |
| 3437 PrintF("#%d (%s) cannot fold into #%d (%s)\n", | 3422 PrintF("#%d (%s) cannot fold into #%d (%s)\n", |
| 3438 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3423 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
| 3439 } | 3424 } |
| 3440 return false; | 3425 return false; |
| 3441 } | 3426 } |
| 3442 | 3427 |
| 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; | |
| 3450 } | |
| 3451 | |
| 3452 HAllocate* dominator_allocate = HAllocate::cast(dominator); | 3428 HAllocate* dominator_allocate = HAllocate::cast(dominator); |
| 3453 HValue* dominator_size = dominator_allocate->size(); | 3429 HValue* dominator_size = dominator_allocate->size(); |
| 3454 HValue* current_size = size(); | 3430 HValue* current_size = size(); |
| 3455 | 3431 |
| 3456 // TODO(hpayer): Add support for non-constant allocation in dominator. | 3432 // TODO(hpayer): Add support for non-constant allocation in dominator. |
| 3457 if (!current_size->IsInteger32Constant() || | 3433 if (!current_size->IsInteger32Constant() || |
| 3458 !dominator_size->IsInteger32Constant()) { | 3434 !dominator_size->IsInteger32Constant()) { |
| 3459 if (FLAG_trace_allocation_folding) { | 3435 if (FLAG_trace_allocation_folding) { |
| 3460 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n", | 3436 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n", |
| 3461 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3437 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
| (...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3920 return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0); | 3896 return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0); |
| 3921 case kMathLog: | 3897 case kMathLog: |
| 3922 case kMathSqrt: | 3898 case kMathSqrt: |
| 3923 return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value()); | 3899 return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value()); |
| 3924 case kMathPowHalf: | 3900 case kMathPowHalf: |
| 3925 case kMathAbs: | 3901 case kMathAbs: |
| 3926 return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d); | 3902 return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d); |
| 3927 case kMathRound: | 3903 case kMathRound: |
| 3928 case kMathFloor: | 3904 case kMathFloor: |
| 3929 return H_CONSTANT_DOUBLE(d); | 3905 return H_CONSTANT_DOUBLE(d); |
| 3930 case kMathClz32: | |
| 3931 return H_CONSTANT_INT(32); | |
| 3932 default: | 3906 default: |
| 3933 UNREACHABLE(); | 3907 UNREACHABLE(); |
| 3934 break; | 3908 break; |
| 3935 } | 3909 } |
| 3936 } | 3910 } |
| 3937 switch (op) { | 3911 switch (op) { |
| 3938 case kMathExp: | 3912 case kMathExp: |
| 3939 return H_CONSTANT_DOUBLE(fast_exp(d)); | 3913 return H_CONSTANT_DOUBLE(fast_exp(d)); |
| 3940 case kMathLog: | 3914 case kMathLog: |
| 3941 return H_CONSTANT_DOUBLE(std::log(d)); | 3915 return H_CONSTANT_DOUBLE(std::log(d)); |
| 3942 case kMathSqrt: | 3916 case kMathSqrt: |
| 3943 return H_CONSTANT_DOUBLE(fast_sqrt(d)); | 3917 return H_CONSTANT_DOUBLE(fast_sqrt(d)); |
| 3944 case kMathPowHalf: | 3918 case kMathPowHalf: |
| 3945 return H_CONSTANT_DOUBLE(power_double_double(d, 0.5)); | 3919 return H_CONSTANT_DOUBLE(power_double_double(d, 0.5)); |
| 3946 case kMathAbs: | 3920 case kMathAbs: |
| 3947 return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d); | 3921 return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d); |
| 3948 case kMathRound: | 3922 case kMathRound: |
| 3949 // -0.5 .. -0.0 round to -0.0. | 3923 // -0.5 .. -0.0 round to -0.0. |
| 3950 if ((d >= -0.5 && Double(d).Sign() < 0)) return H_CONSTANT_DOUBLE(-0.0); | 3924 if ((d >= -0.5 && Double(d).Sign() < 0)) return H_CONSTANT_DOUBLE(-0.0); |
| 3951 // Doubles are represented as Significant * 2 ^ Exponent. If the | 3925 // Doubles are represented as Significant * 2 ^ Exponent. If the |
| 3952 // Exponent is not negative, the double value is already an integer. | 3926 // Exponent is not negative, the double value is already an integer. |
| 3953 if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d); | 3927 if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d); |
| 3954 return H_CONSTANT_DOUBLE(std::floor(d + 0.5)); | 3928 return H_CONSTANT_DOUBLE(std::floor(d + 0.5)); |
| 3955 case kMathFloor: | 3929 case kMathFloor: |
| 3956 return H_CONSTANT_DOUBLE(std::floor(d)); | 3930 return H_CONSTANT_DOUBLE(std::floor(d)); |
| 3957 case kMathClz32: { | |
| 3958 uint32_t i = static_cast<uint32_t>(constant->Integer32Value()); | |
| 3959 return H_CONSTANT_INT( | |
| 3960 (i == 0) ? 32 : CompilerIntrinsics::CountLeadingZeros(i)); | |
| 3961 } | |
| 3962 default: | 3931 default: |
| 3963 UNREACHABLE(); | 3932 UNREACHABLE(); |
| 3964 break; | 3933 break; |
| 3965 } | 3934 } |
| 3966 } while (false); | 3935 } while (false); |
| 3967 return new(zone) HUnaryMathOperation(context, value, op); | 3936 return new(zone) HUnaryMathOperation(context, value, op); |
| 3968 } | 3937 } |
| 3969 | 3938 |
| 3970 | 3939 |
| 3971 HInstruction* HPower::New(Zone* zone, | 3940 HInstruction* HPower::New(Zone* zone, |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4414 } | 4383 } |
| 4415 | 4384 |
| 4416 | 4385 |
| 4417 HObjectAccess HObjectAccess::ForCellPayload(Isolate* isolate) { | 4386 HObjectAccess HObjectAccess::ForCellPayload(Isolate* isolate) { |
| 4418 return HObjectAccess( | 4387 return HObjectAccess( |
| 4419 kInobject, Cell::kValueOffset, Representation::Tagged(), | 4388 kInobject, Cell::kValueOffset, Representation::Tagged(), |
| 4420 Handle<String>(isolate->heap()->cell_value_string())); | 4389 Handle<String>(isolate->heap()->cell_value_string())); |
| 4421 } | 4390 } |
| 4422 | 4391 |
| 4423 | 4392 |
| 4424 void HObjectAccess::SetGVNFlags(HValue *instr, PropertyAccessType access_type) { | 4393 void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) { |
| 4425 // set the appropriate GVN flags for a given load or store instruction | 4394 // set the appropriate GVN flags for a given load or store instruction |
| 4426 if (access_type == STORE) { | 4395 if (is_store) { |
| 4427 // track dominating allocations in order to eliminate write barriers | 4396 // track dominating allocations in order to eliminate write barriers |
| 4428 instr->SetDependsOnFlag(::v8::internal::kNewSpacePromotion); | 4397 instr->SetGVNFlag(kDependsOnNewSpacePromotion); |
| 4429 instr->SetFlag(HValue::kTrackSideEffectDominators); | 4398 instr->SetFlag(HValue::kTrackSideEffectDominators); |
| 4430 } else { | 4399 } else { |
| 4431 // try to GVN loads, but don't hoist above map changes | 4400 // try to GVN loads, but don't hoist above map changes |
| 4432 instr->SetFlag(HValue::kUseGVN); | 4401 instr->SetFlag(HValue::kUseGVN); |
| 4433 instr->SetDependsOnFlag(::v8::internal::kMaps); | 4402 instr->SetGVNFlag(kDependsOnMaps); |
| 4434 } | 4403 } |
| 4435 | 4404 |
| 4436 switch (portion()) { | 4405 switch (portion()) { |
| 4437 case kArrayLengths: | 4406 case kArrayLengths: |
| 4438 if (access_type == STORE) { | 4407 instr->SetGVNFlag(is_store |
| 4439 instr->SetChangesFlag(::v8::internal::kArrayLengths); | 4408 ? kChangesArrayLengths : kDependsOnArrayLengths); |
| 4440 } else { | |
| 4441 instr->SetDependsOnFlag(::v8::internal::kArrayLengths); | |
| 4442 } | |
| 4443 break; | 4409 break; |
| 4444 case kStringLengths: | 4410 case kStringLengths: |
| 4445 if (access_type == STORE) { | 4411 instr->SetGVNFlag(is_store |
| 4446 instr->SetChangesFlag(::v8::internal::kStringLengths); | 4412 ? kChangesStringLengths : kDependsOnStringLengths); |
| 4447 } else { | |
| 4448 instr->SetDependsOnFlag(::v8::internal::kStringLengths); | |
| 4449 } | |
| 4450 break; | 4413 break; |
| 4451 case kInobject: | 4414 case kInobject: |
| 4452 if (access_type == STORE) { | 4415 instr->SetGVNFlag(is_store |
| 4453 instr->SetChangesFlag(::v8::internal::kInobjectFields); | 4416 ? kChangesInobjectFields : kDependsOnInobjectFields); |
| 4454 } else { | |
| 4455 instr->SetDependsOnFlag(::v8::internal::kInobjectFields); | |
| 4456 } | |
| 4457 break; | 4417 break; |
| 4458 case kDouble: | 4418 case kDouble: |
| 4459 if (access_type == STORE) { | 4419 instr->SetGVNFlag(is_store |
| 4460 instr->SetChangesFlag(::v8::internal::kDoubleFields); | 4420 ? kChangesDoubleFields : kDependsOnDoubleFields); |
| 4461 } else { | |
| 4462 instr->SetDependsOnFlag(::v8::internal::kDoubleFields); | |
| 4463 } | |
| 4464 break; | 4421 break; |
| 4465 case kBackingStore: | 4422 case kBackingStore: |
| 4466 if (access_type == STORE) { | 4423 instr->SetGVNFlag(is_store |
| 4467 instr->SetChangesFlag(::v8::internal::kBackingStoreFields); | 4424 ? kChangesBackingStoreFields : kDependsOnBackingStoreFields); |
| 4468 } else { | |
| 4469 instr->SetDependsOnFlag(::v8::internal::kBackingStoreFields); | |
| 4470 } | |
| 4471 break; | 4425 break; |
| 4472 case kElementsPointer: | 4426 case kElementsPointer: |
| 4473 if (access_type == STORE) { | 4427 instr->SetGVNFlag(is_store |
| 4474 instr->SetChangesFlag(::v8::internal::kElementsPointer); | 4428 ? kChangesElementsPointer : kDependsOnElementsPointer); |
| 4475 } else { | |
| 4476 instr->SetDependsOnFlag(::v8::internal::kElementsPointer); | |
| 4477 } | |
| 4478 break; | 4429 break; |
| 4479 case kMaps: | 4430 case kMaps: |
| 4480 if (access_type == STORE) { | 4431 instr->SetGVNFlag(is_store |
| 4481 instr->SetChangesFlag(::v8::internal::kMaps); | 4432 ? kChangesMaps : kDependsOnMaps); |
| 4482 } else { | |
| 4483 instr->SetDependsOnFlag(::v8::internal::kMaps); | |
| 4484 } | |
| 4485 break; | 4433 break; |
| 4486 case kExternalMemory: | 4434 case kExternalMemory: |
| 4487 if (access_type == STORE) { | 4435 instr->SetGVNFlag(is_store |
| 4488 instr->SetChangesFlag(::v8::internal::kExternalMemory); | 4436 ? kChangesExternalMemory : kDependsOnExternalMemory); |
| 4489 } else { | |
| 4490 instr->SetDependsOnFlag(::v8::internal::kExternalMemory); | |
| 4491 } | |
| 4492 break; | 4437 break; |
| 4493 } | 4438 } |
| 4494 } | 4439 } |
| 4495 | 4440 |
| 4496 | 4441 |
| 4497 void HObjectAccess::PrintTo(StringStream* stream) const { | 4442 void HObjectAccess::PrintTo(StringStream* stream) { |
| 4498 stream->Add("."); | 4443 stream->Add("."); |
| 4499 | 4444 |
| 4500 switch (portion()) { | 4445 switch (portion()) { |
| 4501 case kArrayLengths: | 4446 case kArrayLengths: |
| 4502 case kStringLengths: | 4447 case kStringLengths: |
| 4503 stream->Add("%length"); | 4448 stream->Add("%length"); |
| 4504 break; | 4449 break; |
| 4505 case kElementsPointer: | 4450 case kElementsPointer: |
| 4506 stream->Add("%elements"); | 4451 stream->Add("%elements"); |
| 4507 break; | 4452 break; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4523 break; | 4468 break; |
| 4524 case kExternalMemory: | 4469 case kExternalMemory: |
| 4525 stream->Add("[external-memory]"); | 4470 stream->Add("[external-memory]"); |
| 4526 break; | 4471 break; |
| 4527 } | 4472 } |
| 4528 | 4473 |
| 4529 stream->Add("@%d", offset()); | 4474 stream->Add("@%d", offset()); |
| 4530 } | 4475 } |
| 4531 | 4476 |
| 4532 } } // namespace v8::internal | 4477 } } // namespace v8::internal |
| OLD | NEW |