Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/hydrogen.cc

Issue 11962041: Revert r13409 ("Make the array bounds check elimination phase optional (and set the foundation for … (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698