From: hpayer@chromium.org Date: Thu, 11 Jul 2013 11:41:33 +0000 (+0000) Subject: Allocation folding integrated into the GVN phase. X-Git-Tag: upstream/4.7.83~13411 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=99d541a486ca568a45c311cf1ec22a877e0c6d0f;p=platform%2Fupstream%2Fv8.git Allocation folding integrated into the GVN phase. BUG= R=mstarzinger@chromium.org, titzer@chromium.org Review URL: https://codereview.chromium.org/18596005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15624 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/flag-definitions.h b/src/flag-definitions.h index 00d313f..a0185bd 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -215,6 +215,7 @@ DEFINE_bool(use_gvn, true, "use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true, "use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true, "use function inlining") DEFINE_bool(use_escape_analysis, false, "use hydrogen escape analysis") +DEFINE_bool(use_allocation_folding, false, "use allocation folding") DEFINE_int(max_inlined_source_size, 600, "maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196, @@ -236,6 +237,7 @@ DEFINE_bool(trace_range, false, "trace range analysis") DEFINE_bool(trace_gvn, false, "trace global value numbering") DEFINE_bool(trace_representation, false, "trace representation types") DEFINE_bool(trace_escape_analysis, false, "trace hydrogen escape analysis") +DEFINE_bool(trace_allocation_folding, false, "trace allocation folding") DEFINE_bool(trace_track_allocation_sites, false, "trace the tracking of allocation sites") DEFINE_bool(trace_migration, false, "trace object migration") diff --git a/src/hydrogen-gvn.cc b/src/hydrogen-gvn.cc index fd7430c..12c536a 100644 --- a/src/hydrogen-gvn.cc +++ b/src/hydrogen-gvn.cc @@ -776,9 +776,28 @@ void HGlobalValueNumberingPhase::AnalyzeGraph() { } // Go through all instructions of the current block. - HInstruction* instr = block->first(); - while (instr != NULL) { - HInstruction* next = instr->next(); + for (HInstructionIterator it(block); !it.Done(); it.Advance()) { + HInstruction* instr = it.Current(); + if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) { + for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { + HValue* other = dominators->at(i); + GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); + GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); + if (instr->DependsOnFlags().Contains(depends_on_flag) && + (other != NULL)) { + TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", + i, + instr->id(), + instr->Mnemonic(), + other->id(), + other->Mnemonic()); + instr->HandleSideEffectDominator(changes_flag, other); + } + } + } + // Instruction was unlinked during graph traversal. + if (!instr->IsLinked()) continue; + GVNFlagSet flags = instr->ChangesFlags(); if (!flags.IsEmpty()) { // Clear all instructions in the map that are affected by side effects. @@ -804,25 +823,6 @@ void HGlobalValueNumberingPhase::AnalyzeGraph() { map->Add(instr, zone()); } } - if (instr->IsLinked() && - instr->CheckFlag(HValue::kTrackSideEffectDominators)) { - for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { - HValue* other = dominators->at(i); - GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); - GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); - if (instr->DependsOnFlags().Contains(depends_on_flag) && - (other != NULL)) { - TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", - i, - instr->id(), - instr->Mnemonic(), - other->id(), - other->Mnemonic()); - instr->SetSideEffectDominator(changes_flag, other); - } - } - } - instr = next; } HBasicBlock* dominator_block; diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 0143baa..bdb2352 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -1654,8 +1654,8 @@ void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) { } -void HCheckMaps::SetSideEffectDominator(GVNFlag side_effect, - HValue* dominator) { +void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect, + HValue* dominator) { ASSERT(side_effect == kChangesMaps); // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once // type information is rich enough we should generalize this to any HType @@ -3183,6 +3183,84 @@ HType HAllocate::CalculateInferredType() { } +void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, + HValue* dominator) { + ASSERT(side_effect == kChangesNewSpacePromotion); + // Try to fold allocations together with their dominating allocations. + if (!FLAG_use_allocation_folding || !dominator->IsAllocate()) { + return; + } + HAllocate* dominator_allocate_instr = HAllocate::cast(dominator); + HValue* dominator_size = dominator_allocate_instr->size(); + HValue* current_size = size(); + // We can just fold allocations that are guaranteed in new space. + // TODO(hpayer): Support double aligned allocations. + // TODO(hpayer): Add support for non-constant allocation in dominator. + if (!GuaranteedInNewSpace() || MustAllocateDoubleAligned() || + !current_size->IsInteger32Constant() || + !dominator_allocate_instr->GuaranteedInNewSpace() || + dominator_allocate_instr->MustAllocateDoubleAligned() || + !dominator_size->IsInteger32Constant()) { + return; + } + + // First update the size of the dominator allocate instruction. + int32_t dominator_size_constant = + HConstant::cast(dominator_size)->GetInteger32Constant(); + int32_t current_size_constant = + HConstant::cast(current_size)->GetInteger32Constant(); + HBasicBlock* block = dominator->block(); + Zone* zone = block->zone(); + HInstruction* new_dominator_size = new(zone) HConstant( + dominator_size_constant + current_size_constant); + new_dominator_size->InsertBefore(dominator_allocate_instr); + dominator_allocate_instr->UpdateSize(new_dominator_size); + + // TODO(hpayer): Remove filler map but make sure new space is valid. + HInstruction* free_space_instr = + new(zone) HInnerAllocatedObject(dominator_allocate_instr, + dominator_size_constant, + type()); + free_space_instr->InsertAfter(dominator_allocate_instr); + HConstant* filler_map = new(zone) HConstant( + isolate()->factory()->free_space_map(), + UniqueValueId(isolate()->heap()->free_space_map()), + Representation::Tagged(), + HType::Tagged(), + false, + true, + false, + false); + filler_map->InsertAfter(free_space_instr); + + HInstruction* store_map = new(zone) HStoreNamedField( + free_space_instr, HObjectAccess::ForMap(), filler_map); + store_map->SetFlag(HValue::kHasNoObservableSideEffects); + store_map->InsertAfter(filler_map); + + HInstruction* free_space_size = new(zone) HConstant(current_size_constant); + free_space_size->InsertAfter(store_map); + HObjectAccess access = + HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); + HInstruction* store_size = new(zone) HStoreNamedField( + free_space_instr, access, free_space_size); + store_size->SetFlag(HValue::kHasNoObservableSideEffects); + store_size->InsertAfter(free_space_size); + + // After that replace the dominated allocate instruction. + HInstruction* dominated_allocate_instr = + new(zone) HInnerAllocatedObject(dominator_allocate_instr, + dominator_size_constant, + type()); + dominated_allocate_instr->InsertBefore(this); + DeleteAndReplaceWith(dominated_allocate_instr); + if (FLAG_trace_allocation_folding) { + PrintF("#%d (%s) folded into #%d (%s)\n", + id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); + } +} + + void HAllocate::PrintDataTo(StringStream* stream) { size()->PrintNameTo(stream); if (!GuaranteedInNewSpace()) stream->Add(" (pretenure)"); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 7bca40c..cb2225d 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -790,7 +790,7 @@ class HValue: public ZoneObject { // occurrences of the instruction are indeed the same. kUseGVN, // Track instructions that are dominating side effects. If an instruction - // sets this flag, it must implement SetSideEffectDominator() and should + // sets this flag, it must implement HandleSideEffectDominator() and should // indicate which side effects to track by setting GVN flags. kTrackSideEffectDominators, kCanOverflow, @@ -1109,7 +1109,8 @@ class HValue: public ZoneObject { // This function must be overridden for instructions which have the // kTrackSideEffectDominators flag set, to track instructions that are // dominating side effects. - virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { + virtual void HandleSideEffectDominator(GVNFlag side_effect, + HValue* dominator) { UNREACHABLE(); } @@ -2774,7 +2775,8 @@ class HCheckMaps: public HTemplateInstruction<2> { virtual Representation RequiredInputRepresentation(int index) { return Representation::Tagged(); } - virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator); + virtual void HandleSideEffectDominator(GVNFlag side_effect, + HValue* dominator); virtual void PrintDataTo(StringStream* stream); virtual HType CalculateInferredType(); @@ -4975,10 +4977,12 @@ class HAllocateObject: public HTemplateInstruction<1> { virtual Representation RequiredInputRepresentation(int index) { return Representation::Tagged(); } + virtual Handle GetMonomorphicJSObjectMap() { ASSERT(!constructor_initial_map_.is_null()); return constructor_initial_map_; } + virtual HType CalculateInferredType(); DECLARE_CONCRETE_INSTRUCTION(AllocateObject) @@ -5007,7 +5011,9 @@ class HAllocate: public HTemplateInstruction<2> { SetOperandAt(0, context); SetOperandAt(1, size); set_representation(Representation::Tagged()); + SetFlag(kTrackSideEffectDominators); SetGVNFlag(kChangesNewSpacePromotion); + SetGVNFlag(kDependsOnNewSpacePromotion); } static Flags DefaultFlags() { @@ -5025,6 +5031,7 @@ class HAllocate: public HTemplateInstruction<2> { HValue* context() { return OperandAt(0); } HValue* size() { return OperandAt(1); } + HType type() { return type_; } virtual Representation RequiredInputRepresentation(int index) { if (index == 0) { @@ -5061,6 +5068,13 @@ class HAllocate: public HTemplateInstruction<2> { return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0; } + void UpdateSize(HValue* size) { + SetOperandAt(1, size); + } + + virtual void HandleSideEffectDominator(GVNFlag side_effect, + HValue* dominator); + virtual void PrintDataTo(StringStream* stream); DECLARE_CONCRETE_INSTRUCTION(Allocate) @@ -5073,8 +5087,9 @@ class HAllocate: public HTemplateInstruction<2> { class HInnerAllocatedObject: public HTemplateInstruction<1> { public: - HInnerAllocatedObject(HValue* value, int offset) - : offset_(offset) { + HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged()) + : offset_(offset), + type_(type) { ASSERT(value->IsAllocate()); SetOperandAt(0, value); set_representation(Representation::Tagged()); @@ -5087,12 +5102,15 @@ class HInnerAllocatedObject: public HTemplateInstruction<1> { return Representation::Tagged(); } + virtual HType CalculateInferredType() { return type_; } + virtual void PrintDataTo(StringStream* stream); DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject) private: int offset_; + HType type_; }; @@ -5815,7 +5833,8 @@ class HStoreNamedField: public HTemplateInstruction<2> { } return Representation::Tagged(); } - virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { + virtual void HandleSideEffectDominator(GVNFlag side_effect, + HValue* dominator) { ASSERT(side_effect == kChangesNewSpacePromotion); new_space_dominator_ = dominator; } @@ -6017,7 +6036,8 @@ class HStoreKeyed return value()->IsConstant() && HConstant::cast(value())->IsTheHole(); } - virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { + virtual void HandleSideEffectDominator(GVNFlag side_effect, + HValue* dominator) { ASSERT(side_effect == kChangesNewSpacePromotion); new_space_dominator_ = dominator; } diff --git a/src/hydrogen.h b/src/hydrogen.h index 2db3d4b..7a76152 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -233,14 +233,21 @@ class HPredecessorIterator BASE_EMBEDDED { class HInstructionIterator BASE_EMBEDDED { public: - explicit HInstructionIterator(HBasicBlock* block) : instr_(block->first()) { } + explicit HInstructionIterator(HBasicBlock* block) + : instr_(block->first()) { + next_ = Done() ? NULL : instr_->next(); + } - bool Done() { return instr_ == NULL; } - HInstruction* Current() { return instr_; } - void Advance() { instr_ = instr_->next(); } + inline bool Done() const { return instr_ == NULL; } + inline HInstruction* Current() { return instr_; } + inline void Advance() { + instr_ = next_; + next_ = Done() ? NULL : instr_->next(); + } private: HInstruction* instr_; + HInstruction* next_; };