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 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 } | 736 } |
737 | 737 |
738 | 738 |
739 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 739 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
740 HValue* object, | 740 HValue* object, |
741 HValue* key, | 741 HValue* key, |
742 HValue* val, | 742 HValue* val, |
743 HCheckMaps* mapcheck, | 743 HCheckMaps* mapcheck, |
744 bool is_js_array, | 744 bool is_js_array, |
745 ElementsKind elements_kind, | 745 ElementsKind elements_kind, |
746 bool is_store, | 746 bool is_store) { |
747 Representation checked_index_representation) { | |
748 Zone* zone = this->zone(); | 747 Zone* zone = this->zone(); |
749 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 748 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
750 // on a HElementsTransition instruction. The flag can also be removed if the | 749 // on a HElementsTransition instruction. The flag can also be removed if the |
751 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 750 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
752 // ElementsKind transitions. Finally, the dependency can be removed for stores | 751 // ElementsKind transitions. Finally, the dependency can be removed for stores |
753 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 752 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
754 // generated store code. | 753 // generated store code. |
755 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 754 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
756 (elements_kind == FAST_ELEMENTS && is_store)) { | 755 (elements_kind == FAST_ELEMENTS && is_store)) { |
757 if (mapcheck != NULL) { | 756 if (mapcheck != NULL) { |
758 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 757 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
759 } | 758 } |
760 } | 759 } |
761 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 760 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
762 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 761 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
763 HInstruction* elements = | 762 HInstruction* elements = |
764 AddInstruction(new(zone) HLoadElements(object, mapcheck)); | 763 AddInstruction(new(zone) HLoadElements(object, mapcheck)); |
765 if (is_store && (fast_elements || fast_smi_only_elements)) { | 764 if (is_store && (fast_elements || fast_smi_only_elements)) { |
766 HCheckMaps* check_cow_map = new(zone) HCheckMaps( | 765 HCheckMaps* check_cow_map = new(zone) HCheckMaps( |
767 elements, Isolate::Current()->factory()->fixed_array_map(), zone); | 766 elements, Isolate::Current()->factory()->fixed_array_map(), zone); |
768 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 767 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
769 AddInstruction(check_cow_map); | 768 AddInstruction(check_cow_map); |
770 } | 769 } |
771 HInstruction* length = NULL; | 770 HInstruction* length = NULL; |
772 HInstruction* checked_key = NULL; | 771 HInstruction* checked_key = NULL; |
773 if (IsExternalArrayElementsKind(elements_kind)) { | 772 if (IsExternalArrayElementsKind(elements_kind)) { |
774 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 773 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
775 checked_key = AddInstruction(new(zone) HBoundsCheck( | 774 checked_key = AddInstruction(new(zone) HBoundsCheck(key, length, |
776 key, length, ALLOW_SMI_KEY, checked_index_representation)); | 775 ALLOW_SMI_KEY)); |
777 HLoadExternalArrayPointer* external_elements = | 776 HLoadExternalArrayPointer* external_elements = |
778 new(zone) HLoadExternalArrayPointer(elements); | 777 new(zone) HLoadExternalArrayPointer(elements); |
779 AddInstruction(external_elements); | 778 AddInstruction(external_elements); |
780 return BuildExternalArrayElementAccess( | 779 return BuildExternalArrayElementAccess( |
781 external_elements, checked_key, val, mapcheck, | 780 external_elements, checked_key, val, mapcheck, |
782 elements_kind, is_store); | 781 elements_kind, is_store); |
783 } | 782 } |
784 ASSERT(fast_smi_only_elements || | 783 ASSERT(fast_smi_only_elements || |
785 fast_elements || | 784 fast_elements || |
786 IsFastDoubleElementsKind(elements_kind)); | 785 IsFastDoubleElementsKind(elements_kind)); |
787 if (is_js_array) { | 786 if (is_js_array) { |
788 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, | 787 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, |
789 HType::Smi())); | 788 HType::Smi())); |
790 } else { | 789 } else { |
791 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 790 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
792 } | 791 } |
793 checked_key = AddInstruction(new(zone) HBoundsCheck( | 792 checked_key = AddInstruction(new(zone) HBoundsCheck(key, length, |
794 key, length, ALLOW_SMI_KEY, checked_index_representation)); | 793 ALLOW_SMI_KEY)); |
795 return BuildFastElementAccess(elements, checked_key, val, mapcheck, | 794 return BuildFastElementAccess(elements, checked_key, val, mapcheck, |
796 elements_kind, is_store); | 795 elements_kind, is_store); |
797 } | 796 } |
798 | 797 |
799 | 798 |
800 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 799 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, |
801 TypeFeedbackOracle* oracle) | 800 TypeFeedbackOracle* oracle) |
802 : HGraphBuilder(info), | 801 : HGraphBuilder(info), |
803 function_state_(NULL), | 802 function_state_(NULL), |
804 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 803 initial_function_state_(this, info, oracle, NORMAL_RETURN), |
(...skipping 2692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3497 if (FLAG_use_range) { | 3496 if (FLAG_use_range) { |
3498 HRangeAnalysis rangeAnalysis(this); | 3497 HRangeAnalysis rangeAnalysis(this); |
3499 rangeAnalysis.Analyze(); | 3498 rangeAnalysis.Analyze(); |
3500 } | 3499 } |
3501 ComputeMinusZeroChecks(); | 3500 ComputeMinusZeroChecks(); |
3502 | 3501 |
3503 // Eliminate redundant stack checks on backwards branches. | 3502 // Eliminate redundant stack checks on backwards branches. |
3504 HStackCheckEliminator sce(this); | 3503 HStackCheckEliminator sce(this); |
3505 sce.Process(); | 3504 sce.Process(); |
3506 | 3505 |
3507 if (FLAG_array_bounds_checks_elimination) EliminateRedundantBoundsChecks(); | 3506 EliminateRedundantBoundsChecks(); |
3508 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); | 3507 DehoistSimpleArrayIndexComputations(); |
3509 if (FLAG_dead_code_elimination) DeadCodeElimination(); | 3508 if (FLAG_dead_code_elimination) DeadCodeElimination(); |
3510 | 3509 |
3511 ApplyActualValues(); | |
3512 | |
3513 return true; | 3510 return true; |
3514 } | 3511 } |
3515 | 3512 |
3516 | 3513 |
3517 // We try to "factor up" HBoundsCheck instructions towards the root of the | 3514 // We try to "factor up" HBoundsCheck instructions towards the root of the |
3518 // dominator tree. | 3515 // dominator tree. |
3519 // For now we handle checks where the index is like "exp + int32value". | 3516 // For now we handle checks where the index is like "exp + int32value". |
3520 // If in the dominator tree we check "exp + v1" and later (dominated) | 3517 // If in the dominator tree we check "exp + v1" and later (dominated) |
3521 // "exp + v2", if v2 <= v1 we can safely remove the second check, and if | 3518 // "exp + v2", if v2 <= v1 we can safely remove the second check, and if |
3522 // v2 > v1 we can use v2 in the 1st check and again remove the second. | 3519 // v2 > v1 we can use v2 in the 1st check and again remove the second. |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3662 new_check->index()->representation(), | 3659 new_check->index()->representation(), |
3663 new_offset); | 3660 new_offset); |
3664 if (!result) return false; | 3661 if (!result) return false; |
3665 lower_check_->SetOperandAt(0, added_lower_index_); | 3662 lower_check_->SetOperandAt(0, added_lower_index_); |
3666 } | 3663 } |
3667 } else { | 3664 } else { |
3668 ASSERT(false); | 3665 ASSERT(false); |
3669 } | 3666 } |
3670 | 3667 |
3671 if (!keep_new_check) { | 3668 if (!keep_new_check) { |
3672 new_check->DeleteAndReplaceWith(new_check->ActualValue()); | 3669 new_check->DeleteAndReplaceWith(NULL); |
3673 } | 3670 } |
3674 | 3671 |
3675 return true; | 3672 return true; |
3676 } | 3673 } |
3677 | 3674 |
3678 void RemoveZeroOperations() { | 3675 void RemoveZeroOperations() { |
3679 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_); | 3676 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_); |
3680 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_); | 3677 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_); |
3681 } | 3678 } |
3682 | 3679 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3798 // this point. It enables better register allocation since the value produced | 3795 // this point. It enables better register allocation since the value produced |
3799 // by check instructions is really a copy of the original value. | 3796 // by check instructions is really a copy of the original value. |
3800 void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb, | 3797 void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb, |
3801 BoundsCheckTable* table) { | 3798 BoundsCheckTable* table) { |
3802 BoundsCheckBbData* bb_data_list = NULL; | 3799 BoundsCheckBbData* bb_data_list = NULL; |
3803 | 3800 |
3804 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) { | 3801 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) { |
3805 if (!i->IsBoundsCheck()) continue; | 3802 if (!i->IsBoundsCheck()) continue; |
3806 | 3803 |
3807 HBoundsCheck* check = HBoundsCheck::cast(i); | 3804 HBoundsCheck* check = HBoundsCheck::cast(i); |
| 3805 check->ReplaceAllUsesWith(check->index()); |
| 3806 |
| 3807 if (!FLAG_array_bounds_checks_elimination) continue; |
| 3808 |
3808 int32_t offset; | 3809 int32_t offset; |
3809 BoundsCheckKey* key = | 3810 BoundsCheckKey* key = |
3810 BoundsCheckKey::Create(zone(), check, &offset); | 3811 BoundsCheckKey::Create(zone(), check, &offset); |
3811 if (key == NULL) continue; | 3812 if (key == NULL) continue; |
3812 BoundsCheckBbData** data_p = table->LookupOrInsert(key, zone()); | 3813 BoundsCheckBbData** data_p = table->LookupOrInsert(key, zone()); |
3813 BoundsCheckBbData* data = *data_p; | 3814 BoundsCheckBbData* data = *data_p; |
3814 if (data == NULL) { | 3815 if (data == NULL) { |
3815 bb_data_list = new(zone()) BoundsCheckBbData(key, | 3816 bb_data_list = new(zone()) BoundsCheckBbData(key, |
3816 offset, | 3817 offset, |
3817 offset, | 3818 offset, |
3818 bb, | 3819 bb, |
3819 check, | 3820 check, |
3820 check, | 3821 check, |
3821 bb_data_list, | 3822 bb_data_list, |
3822 NULL); | 3823 NULL); |
3823 *data_p = bb_data_list; | 3824 *data_p = bb_data_list; |
3824 } else if (data->OffsetIsCovered(offset)) { | 3825 } else if (data->OffsetIsCovered(offset)) { |
3825 check->DeleteAndReplaceWith(check->ActualValue()); | 3826 check->DeleteAndReplaceWith(NULL); |
3826 } else if (data->BasicBlock() != bb || | 3827 } else if (data->BasicBlock() != bb || |
3827 !data->CoverCheck(check, offset)) { | 3828 !data->CoverCheck(check, offset)) { |
3828 // If the check is in the current BB we try to modify it by calling | 3829 // If the check is in the current BB we try to modify it by calling |
3829 // "CoverCheck", but if also that fails we record the current offsets | 3830 // "CoverCheck", but if also that fails we record the current offsets |
3830 // in a new data instance because from now on they are covered. | 3831 // in a new data instance because from now on they are covered. |
3831 int32_t new_lower_offset = offset < data->LowerOffset() | 3832 int32_t new_lower_offset = offset < data->LowerOffset() |
3832 ? offset | 3833 ? offset |
3833 : data->LowerOffset(); | 3834 : data->LowerOffset(); |
3834 int32_t new_upper_offset = offset > data->UpperOffset() | 3835 int32_t new_upper_offset = offset > data->UpperOffset() |
3835 ? offset | 3836 ? offset |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3912 if (index->HasNoUses()) { | 3913 if (index->HasNoUses()) { |
3913 index->DeleteAndReplaceWith(NULL); | 3914 index->DeleteAndReplaceWith(NULL); |
3914 } | 3915 } |
3915 ASSERT(value >= 0); | 3916 ASSERT(value >= 0); |
3916 array_operation->SetIndexOffset(static_cast<uint32_t>(value)); | 3917 array_operation->SetIndexOffset(static_cast<uint32_t>(value)); |
3917 array_operation->SetDehoisted(true); | 3918 array_operation->SetDehoisted(true); |
3918 } | 3919 } |
3919 | 3920 |
3920 | 3921 |
3921 void HGraph::DehoistSimpleArrayIndexComputations() { | 3922 void HGraph::DehoistSimpleArrayIndexComputations() { |
| 3923 if (!FLAG_array_index_dehoisting) return; |
| 3924 |
3922 HPhase phase("H_Dehoist index computations", this); | 3925 HPhase phase("H_Dehoist index computations", this); |
3923 for (int i = 0; i < blocks()->length(); ++i) { | 3926 for (int i = 0; i < blocks()->length(); ++i) { |
3924 for (HInstruction* instr = blocks()->at(i)->first(); | 3927 for (HInstruction* instr = blocks()->at(i)->first(); |
3925 instr != NULL; | 3928 instr != NULL; |
3926 instr = instr->next()) { | 3929 instr = instr->next()) { |
3927 ArrayInstructionInterface* array_instruction = NULL; | 3930 ArrayInstructionInterface* array_instruction = NULL; |
3928 if (instr->IsLoadKeyed()) { | 3931 if (instr->IsLoadKeyed()) { |
3929 HLoadKeyed* op = HLoadKeyed::cast(instr); | 3932 HLoadKeyed* op = HLoadKeyed::cast(instr); |
3930 array_instruction = static_cast<ArrayInstructionInterface*>(op); | 3933 array_instruction = static_cast<ArrayInstructionInterface*>(op); |
3931 } else if (instr->IsStoreKeyed()) { | 3934 } else if (instr->IsStoreKeyed()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3963 } | 3966 } |
3964 instr->DeleteAndReplaceWith(NULL); | 3967 instr->DeleteAndReplaceWith(NULL); |
3965 for (int i = 0; i < instr->OperandCount(); ++i) { | 3968 for (int i = 0; i < instr->OperandCount(); ++i) { |
3966 HValue* operand = instr->OperandAt(i); | 3969 HValue* operand = instr->OperandAt(i); |
3967 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); | 3970 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); |
3968 } | 3971 } |
3969 } | 3972 } |
3970 } | 3973 } |
3971 | 3974 |
3972 | 3975 |
3973 void HGraph::ApplyActualValues() { | |
3974 HPhase phase("H_Apply actual values", this); | |
3975 | |
3976 for (int block_index = 0; block_index < blocks()->length(); block_index++) { | |
3977 HBasicBlock* block = blocks()->at(block_index); | |
3978 | |
3979 #ifdef DEBUG | |
3980 for (int i = 0; i < block->phis()->length(); i++) { | |
3981 HPhi* phi = block->phis()->at(i); | |
3982 ASSERT(phi->ActualValue() == phi); | |
3983 } | |
3984 #endif | |
3985 | |
3986 for (HInstruction* instruction = block->first(); | |
3987 instruction != NULL; | |
3988 instruction = instruction->next()) { | |
3989 if (instruction->ActualValue() != instruction) { | |
3990 instruction->ReplaceAllUsesWith(instruction->ActualValue()); | |
3991 } | |
3992 } | |
3993 } | |
3994 } | |
3995 | |
3996 | |
3997 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) { | 3976 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) { |
3998 ASSERT(current_block() != NULL); | 3977 ASSERT(current_block() != NULL); |
3999 current_block()->AddPhi(instr); | 3978 current_block()->AddPhi(instr); |
4000 } | 3979 } |
4001 | 3980 |
4002 | 3981 |
4003 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { | 3982 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { |
4004 Push(instr); | 3983 Push(instr); |
4005 AddInstruction(instr); | 3984 AddInstruction(instr); |
4006 } | 3985 } |
(...skipping 6229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10236 } | 10215 } |
10237 } | 10216 } |
10238 | 10217 |
10239 #ifdef DEBUG | 10218 #ifdef DEBUG |
10240 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10219 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10241 if (allocator_ != NULL) allocator_->Verify(); | 10220 if (allocator_ != NULL) allocator_->Verify(); |
10242 #endif | 10221 #endif |
10243 } | 10222 } |
10244 | 10223 |
10245 } } // namespace v8::internal | 10224 } } // namespace v8::internal |
OLD | NEW |