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

Side by Side Diff: src/hydrogen.cc

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

Powered by Google App Engine
This is Rietveld 408576698