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

Side by Side Diff: src/hydrogen.cc

Issue 12090021: Foundation for the use of informative definitions in Crankshaft. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased on bleeding edge. Created 7 years, 10 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 727 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 } 738 }
739 739
740 740
741 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 741 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
742 HValue* object, 742 HValue* object,
743 HValue* key, 743 HValue* key,
744 HValue* val, 744 HValue* val,
745 HCheckMaps* mapcheck, 745 HCheckMaps* mapcheck,
746 bool is_js_array, 746 bool is_js_array,
747 ElementsKind elements_kind, 747 ElementsKind elements_kind,
748 bool is_store) { 748 bool is_store,
749 Representation checked_index_representation) {
749 Zone* zone = this->zone(); 750 Zone* zone = this->zone();
750 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 751 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
751 // on a HElementsTransition instruction. The flag can also be removed if the 752 // on a HElementsTransition instruction. The flag can also be removed if the
752 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further 753 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
753 // ElementsKind transitions. Finally, the dependency can be removed for stores 754 // ElementsKind transitions. Finally, the dependency can be removed for stores
754 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the 755 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
755 // generated store code. 756 // generated store code.
756 if ((elements_kind == FAST_HOLEY_ELEMENTS) || 757 if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
757 (elements_kind == FAST_ELEMENTS && is_store)) { 758 (elements_kind == FAST_ELEMENTS && is_store)) {
758 if (mapcheck != NULL) { 759 if (mapcheck != NULL) {
759 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 760 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
760 } 761 }
761 } 762 }
762 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); 763 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
763 bool fast_elements = IsFastObjectElementsKind(elements_kind); 764 bool fast_elements = IsFastObjectElementsKind(elements_kind);
764 HInstruction* elements = 765 HInstruction* elements =
765 AddInstruction(new(zone) HLoadElements(object, mapcheck)); 766 AddInstruction(new(zone) HLoadElements(object, mapcheck));
766 if (is_store && (fast_elements || fast_smi_only_elements)) { 767 if (is_store && (fast_elements || fast_smi_only_elements)) {
767 HCheckMaps* check_cow_map = new(zone) HCheckMaps( 768 HCheckMaps* check_cow_map = new(zone) HCheckMaps(
768 elements, Isolate::Current()->factory()->fixed_array_map(), zone); 769 elements, Isolate::Current()->factory()->fixed_array_map(), zone);
769 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 770 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
770 AddInstruction(check_cow_map); 771 AddInstruction(check_cow_map);
771 } 772 }
772 HInstruction* length = NULL; 773 HInstruction* length = NULL;
773 HInstruction* checked_key = NULL; 774 HInstruction* checked_key = NULL;
774 if (IsExternalArrayElementsKind(elements_kind)) { 775 if (IsExternalArrayElementsKind(elements_kind)) {
775 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); 776 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
776 checked_key = AddInstruction(new(zone) HBoundsCheck(key, length, 777 checked_key = AddInstruction(new(zone) HBoundsCheck(
777 ALLOW_SMI_KEY)); 778 key, length, ALLOW_SMI_KEY, checked_index_representation));
778 HLoadExternalArrayPointer* external_elements = 779 HLoadExternalArrayPointer* external_elements =
779 new(zone) HLoadExternalArrayPointer(elements); 780 new(zone) HLoadExternalArrayPointer(elements);
780 AddInstruction(external_elements); 781 AddInstruction(external_elements);
781 return BuildExternalArrayElementAccess( 782 return BuildExternalArrayElementAccess(
782 external_elements, checked_key, val, mapcheck, 783 external_elements, checked_key, val, mapcheck,
783 elements_kind, is_store); 784 elements_kind, is_store);
784 } 785 }
785 ASSERT(fast_smi_only_elements || 786 ASSERT(fast_smi_only_elements ||
786 fast_elements || 787 fast_elements ||
787 IsFastDoubleElementsKind(elements_kind)); 788 IsFastDoubleElementsKind(elements_kind));
788 if (is_js_array) { 789 if (is_js_array) {
789 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, 790 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck,
790 HType::Smi())); 791 HType::Smi()));
791 } else { 792 } else {
792 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); 793 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
793 } 794 }
794 checked_key = AddInstruction(new(zone) HBoundsCheck(key, length, 795 checked_key = AddInstruction(new(zone) HBoundsCheck(
795 ALLOW_SMI_KEY)); 796 key, length, ALLOW_SMI_KEY, checked_index_representation));
796 return BuildFastElementAccess(elements, checked_key, val, mapcheck, 797 return BuildFastElementAccess(elements, checked_key, val, mapcheck,
797 elements_kind, is_store); 798 elements_kind, is_store);
798 } 799 }
799 800
800 801
801 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, 802 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info,
802 TypeFeedbackOracle* oracle) 803 TypeFeedbackOracle* oracle)
803 : HGraphBuilder(info), 804 : HGraphBuilder(info),
804 function_state_(NULL), 805 function_state_(NULL),
805 initial_function_state_(this, info, oracle, NORMAL_RETURN), 806 initial_function_state_(this, info, oracle, NORMAL_RETURN),
(...skipping 2773 matching lines...) Expand 10 before | Expand all | Expand 10 after
3579 if (FLAG_use_range) { 3580 if (FLAG_use_range) {
3580 HRangeAnalysis rangeAnalysis(this); 3581 HRangeAnalysis rangeAnalysis(this);
3581 rangeAnalysis.Analyze(); 3582 rangeAnalysis.Analyze();
3582 } 3583 }
3583 ComputeMinusZeroChecks(); 3584 ComputeMinusZeroChecks();
3584 3585
3585 // Eliminate redundant stack checks on backwards branches. 3586 // Eliminate redundant stack checks on backwards branches.
3586 HStackCheckEliminator sce(this); 3587 HStackCheckEliminator sce(this);
3587 sce.Process(); 3588 sce.Process();
3588 3589
3589 EliminateRedundantBoundsChecks(); 3590 if (FLAG_array_bounds_checks_elimination) EliminateRedundantBoundsChecks();
3590 DehoistSimpleArrayIndexComputations(); 3591 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations();
3591 if (FLAG_dead_code_elimination) DeadCodeElimination(); 3592 if (FLAG_dead_code_elimination) DeadCodeElimination();
3592 3593
3594 RestoreActualValues();
3595
3593 return true; 3596 return true;
3594 } 3597 }
3595 3598
3596 3599
3597 // We try to "factor up" HBoundsCheck instructions towards the root of the 3600 // We try to "factor up" HBoundsCheck instructions towards the root of the
3598 // dominator tree. 3601 // dominator tree.
3599 // For now we handle checks where the index is like "exp + int32value". 3602 // For now we handle checks where the index is like "exp + int32value".
3600 // If in the dominator tree we check "exp + v1" and later (dominated) 3603 // If in the dominator tree we check "exp + v1" and later (dominated)
3601 // "exp + v2", if v2 <= v1 we can safely remove the second check, and if 3604 // "exp + v2", if v2 <= v1 we can safely remove the second check, and if
3602 // v2 > v1 we can use v2 in the 1st check and again remove the second. 3605 // v2 > v1 we can use v2 in the 1st check and again remove the second.
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
3720 keep_new_check = true; 3723 keep_new_check = true;
3721 upper_check_ = new_check; 3724 upper_check_ = new_check;
3722 } else { 3725 } else {
3723 bool result = BuildOffsetAdd(upper_check_, 3726 bool result = BuildOffsetAdd(upper_check_,
3724 &added_upper_index_, 3727 &added_upper_index_,
3725 &added_upper_offset_, 3728 &added_upper_offset_,
3726 Key()->IndexBase(), 3729 Key()->IndexBase(),
3727 new_check->index()->representation(), 3730 new_check->index()->representation(),
3728 new_offset); 3731 new_offset);
3729 if (!result) return false; 3732 if (!result) return false;
3733 upper_check_->ReplaceAllUsesWith(upper_check_->index());
3730 upper_check_->SetOperandAt(0, added_upper_index_); 3734 upper_check_->SetOperandAt(0, added_upper_index_);
3731 } 3735 }
3732 } else if (new_offset < lower_offset_) { 3736 } else if (new_offset < lower_offset_) {
3733 lower_offset_ = new_offset; 3737 lower_offset_ = new_offset;
3734 if (HasSingleCheck()) { 3738 if (HasSingleCheck()) {
3735 keep_new_check = true; 3739 keep_new_check = true;
3736 lower_check_ = new_check; 3740 lower_check_ = new_check;
3737 } else { 3741 } else {
3738 bool result = BuildOffsetAdd(lower_check_, 3742 bool result = BuildOffsetAdd(lower_check_,
3739 &added_lower_index_, 3743 &added_lower_index_,
3740 &added_lower_offset_, 3744 &added_lower_offset_,
3741 Key()->IndexBase(), 3745 Key()->IndexBase(),
3742 new_check->index()->representation(), 3746 new_check->index()->representation(),
3743 new_offset); 3747 new_offset);
3744 if (!result) return false; 3748 if (!result) return false;
3749 lower_check_->ReplaceAllUsesWith(lower_check_->index());
3745 lower_check_->SetOperandAt(0, added_lower_index_); 3750 lower_check_->SetOperandAt(0, added_lower_index_);
3746 } 3751 }
3747 } else { 3752 } else {
3748 ASSERT(false); 3753 ASSERT(false);
3749 } 3754 }
3750 3755
3751 if (!keep_new_check) { 3756 if (!keep_new_check) {
3752 new_check->DeleteAndReplaceWith(NULL); 3757 new_check->DeleteAndReplaceWith(new_check->ActualValue());
3753 } 3758 }
3754 3759
3755 return true; 3760 return true;
3756 } 3761 }
3757 3762
3758 void RemoveZeroOperations() { 3763 void RemoveZeroOperations() {
3759 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_); 3764 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_);
3760 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_); 3765 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_);
3761 } 3766 }
3762 3767
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
3878 // this point. It enables better register allocation since the value produced 3883 // this point. It enables better register allocation since the value produced
3879 // by check instructions is really a copy of the original value. 3884 // by check instructions is really a copy of the original value.
3880 void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb, 3885 void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
3881 BoundsCheckTable* table) { 3886 BoundsCheckTable* table) {
3882 BoundsCheckBbData* bb_data_list = NULL; 3887 BoundsCheckBbData* bb_data_list = NULL;
3883 3888
3884 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) { 3889 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) {
3885 if (!i->IsBoundsCheck()) continue; 3890 if (!i->IsBoundsCheck()) continue;
3886 3891
3887 HBoundsCheck* check = HBoundsCheck::cast(i); 3892 HBoundsCheck* check = HBoundsCheck::cast(i);
3888 check->ReplaceAllUsesWith(check->index());
3889
3890 if (!FLAG_array_bounds_checks_elimination) continue;
3891
3892 int32_t offset; 3893 int32_t offset;
3893 BoundsCheckKey* key = 3894 BoundsCheckKey* key =
3894 BoundsCheckKey::Create(zone(), check, &offset); 3895 BoundsCheckKey::Create(zone(), check, &offset);
3895 if (key == NULL) continue; 3896 if (key == NULL) continue;
3896 BoundsCheckBbData** data_p = table->LookupOrInsert(key, zone()); 3897 BoundsCheckBbData** data_p = table->LookupOrInsert(key, zone());
3897 BoundsCheckBbData* data = *data_p; 3898 BoundsCheckBbData* data = *data_p;
3898 if (data == NULL) { 3899 if (data == NULL) {
3899 bb_data_list = new(zone()) BoundsCheckBbData(key, 3900 bb_data_list = new(zone()) BoundsCheckBbData(key,
3900 offset, 3901 offset,
3901 offset, 3902 offset,
3902 bb, 3903 bb,
3903 check, 3904 check,
3904 check, 3905 check,
3905 bb_data_list, 3906 bb_data_list,
3906 NULL); 3907 NULL);
3907 *data_p = bb_data_list; 3908 *data_p = bb_data_list;
3908 } else if (data->OffsetIsCovered(offset)) { 3909 } else if (data->OffsetIsCovered(offset)) {
3909 check->DeleteAndReplaceWith(NULL); 3910 check->DeleteAndReplaceWith(check->ActualValue());
3910 } else if (data->BasicBlock() != bb || 3911 } else if (data->BasicBlock() != bb ||
3911 !data->CoverCheck(check, offset)) { 3912 !data->CoverCheck(check, offset)) {
3912 // If the check is in the current BB we try to modify it by calling 3913 // If the check is in the current BB we try to modify it by calling
3913 // "CoverCheck", but if also that fails we record the current offsets 3914 // "CoverCheck", but if also that fails we record the current offsets
3914 // in a new data instance because from now on they are covered. 3915 // in a new data instance because from now on they are covered.
3915 int32_t new_lower_offset = offset < data->LowerOffset() 3916 int32_t new_lower_offset = offset < data->LowerOffset()
3916 ? offset 3917 ? offset
3917 : data->LowerOffset(); 3918 : data->LowerOffset();
3918 int32_t new_upper_offset = offset > data->UpperOffset() 3919 int32_t new_upper_offset = offset > data->UpperOffset()
3919 ? offset 3920 ? offset
(...skipping 28 matching lines...) Expand all
3948 3949
3949 3950
3950 void HGraph::EliminateRedundantBoundsChecks() { 3951 void HGraph::EliminateRedundantBoundsChecks() {
3951 HPhase phase("H_Eliminate bounds checks", this); 3952 HPhase phase("H_Eliminate bounds checks", this);
3952 BoundsCheckTable checks_table(zone()); 3953 BoundsCheckTable checks_table(zone());
3953 EliminateRedundantBoundsChecks(entry_block(), &checks_table); 3954 EliminateRedundantBoundsChecks(entry_block(), &checks_table);
3954 } 3955 }
3955 3956
3956 3957
3957 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) { 3958 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
3958 HValue* index = array_operation->GetKey(); 3959 HValue* index = array_operation->GetKey()->ActualValue();
3959 if (!index->representation().IsInteger32()) return; 3960 if (!index->representation().IsInteger32()) return;
3960 3961
3961 HConstant* constant; 3962 HConstant* constant;
3962 HValue* subexpression; 3963 HValue* subexpression;
3963 int32_t sign; 3964 int32_t sign;
3964 if (index->IsAdd()) { 3965 if (index->IsAdd()) {
3965 sign = 1; 3966 sign = 1;
3966 HAdd* add = HAdd::cast(index); 3967 HAdd* add = HAdd::cast(index);
3967 if (add->left()->IsConstant()) { 3968 if (add->left()->IsConstant()) {
3968 subexpression = add->right(); 3969 subexpression = add->right();
(...skipping 27 matching lines...) Expand all
3996 if (index->HasNoUses()) { 3997 if (index->HasNoUses()) {
3997 index->DeleteAndReplaceWith(NULL); 3998 index->DeleteAndReplaceWith(NULL);
3998 } 3999 }
3999 ASSERT(value >= 0); 4000 ASSERT(value >= 0);
4000 array_operation->SetIndexOffset(static_cast<uint32_t>(value)); 4001 array_operation->SetIndexOffset(static_cast<uint32_t>(value));
4001 array_operation->SetDehoisted(true); 4002 array_operation->SetDehoisted(true);
4002 } 4003 }
4003 4004
4004 4005
4005 void HGraph::DehoistSimpleArrayIndexComputations() { 4006 void HGraph::DehoistSimpleArrayIndexComputations() {
4006 if (!FLAG_array_index_dehoisting) return;
4007
4008 HPhase phase("H_Dehoist index computations", this); 4007 HPhase phase("H_Dehoist index computations", this);
4009 for (int i = 0; i < blocks()->length(); ++i) { 4008 for (int i = 0; i < blocks()->length(); ++i) {
4010 for (HInstruction* instr = blocks()->at(i)->first(); 4009 for (HInstruction* instr = blocks()->at(i)->first();
4011 instr != NULL; 4010 instr != NULL;
4012 instr = instr->next()) { 4011 instr = instr->next()) {
4013 ArrayInstructionInterface* array_instruction = NULL; 4012 ArrayInstructionInterface* array_instruction = NULL;
4014 if (instr->IsLoadKeyed()) { 4013 if (instr->IsLoadKeyed()) {
4015 HLoadKeyed* op = HLoadKeyed::cast(instr); 4014 HLoadKeyed* op = HLoadKeyed::cast(instr);
4016 array_instruction = static_cast<ArrayInstructionInterface*>(op); 4015 array_instruction = static_cast<ArrayInstructionInterface*>(op);
4017 } else if (instr->IsStoreKeyed()) { 4016 } else if (instr->IsStoreKeyed()) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4049 } 4048 }
4050 instr->DeleteAndReplaceWith(NULL); 4049 instr->DeleteAndReplaceWith(NULL);
4051 for (int i = 0; i < instr->OperandCount(); ++i) { 4050 for (int i = 0; i < instr->OperandCount(); ++i) {
4052 HValue* operand = instr->OperandAt(i); 4051 HValue* operand = instr->OperandAt(i);
4053 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); 4052 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone());
4054 } 4053 }
4055 } 4054 }
4056 } 4055 }
4057 4056
4058 4057
4058 void HGraph::RestoreActualValues() {
4059 HPhase phase("H_Restore actual values", this);
4060
4061 for (int block_index = 0; block_index < blocks()->length(); block_index++) {
4062 HBasicBlock* block = blocks()->at(block_index);
4063
4064 #ifdef DEBUG
4065 for (int i = 0; i < block->phis()->length(); i++) {
4066 HPhi* phi = block->phis()->at(i);
4067 ASSERT(phi->ActualValue() == phi);
4068 }
4069 #endif
4070
4071 for (HInstruction* instruction = block->first();
4072 instruction != NULL;
4073 instruction = instruction->next()) {
4074 if (instruction->ActualValue() != instruction) {
4075 instruction->ReplaceAllUsesWith(instruction->ActualValue());
4076 }
4077 }
4078 }
4079 }
4080
4081
4059 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) { 4082 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) {
4060 ASSERT(current_block() != NULL); 4083 ASSERT(current_block() != NULL);
4061 current_block()->AddPhi(instr); 4084 current_block()->AddPhi(instr);
4062 } 4085 }
4063 4086
4064 4087
4065 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { 4088 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) {
4066 Push(instr); 4089 Push(instr);
4067 AddInstruction(instr); 4090 AddInstruction(instr);
4068 } 4091 }
(...skipping 6256 matching lines...) Expand 10 before | Expand all | Expand 10 after
10325 } 10348 }
10326 } 10349 }
10327 10350
10328 #ifdef DEBUG 10351 #ifdef DEBUG
10329 if (graph_ != NULL) graph_->Verify(false); // No full verify. 10352 if (graph_ != NULL) graph_->Verify(false); // No full verify.
10330 if (allocator_ != NULL) allocator_->Verify(); 10353 if (allocator_ != NULL) allocator_->Verify();
10331 #endif 10354 #endif
10332 } 10355 }
10333 10356
10334 } } // namespace v8::internal 10357 } } // 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