Commit 99d541a4 authored by hpayer@chromium.org's avatar hpayer@chromium.org

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
parent e3676e91
...@@ -215,6 +215,7 @@ DEFINE_bool(use_gvn, true, "use hydrogen global value numbering") ...@@ -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_canonicalizing, true, "use hydrogen instruction canonicalizing")
DEFINE_bool(use_inlining, true, "use function inlining") DEFINE_bool(use_inlining, true, "use function inlining")
DEFINE_bool(use_escape_analysis, false, "use hydrogen escape analysis") 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, DEFINE_int(max_inlined_source_size, 600,
"maximum source size in bytes considered for a single inlining") "maximum source size in bytes considered for a single inlining")
DEFINE_int(max_inlined_nodes, 196, DEFINE_int(max_inlined_nodes, 196,
...@@ -236,6 +237,7 @@ DEFINE_bool(trace_range, false, "trace range analysis") ...@@ -236,6 +237,7 @@ DEFINE_bool(trace_range, false, "trace range analysis")
DEFINE_bool(trace_gvn, false, "trace global value numbering") DEFINE_bool(trace_gvn, false, "trace global value numbering")
DEFINE_bool(trace_representation, false, "trace representation types") DEFINE_bool(trace_representation, false, "trace representation types")
DEFINE_bool(trace_escape_analysis, false, "trace hydrogen escape analysis") 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, DEFINE_bool(trace_track_allocation_sites, false,
"trace the tracking of allocation sites") "trace the tracking of allocation sites")
DEFINE_bool(trace_migration, false, "trace object migration") DEFINE_bool(trace_migration, false, "trace object migration")
......
...@@ -776,9 +776,28 @@ void HGlobalValueNumberingPhase::AnalyzeGraph() { ...@@ -776,9 +776,28 @@ void HGlobalValueNumberingPhase::AnalyzeGraph() {
} }
// Go through all instructions of the current block. // Go through all instructions of the current block.
HInstruction* instr = block->first(); for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
while (instr != NULL) { HInstruction* instr = it.Current();
HInstruction* next = instr->next(); 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(); GVNFlagSet flags = instr->ChangesFlags();
if (!flags.IsEmpty()) { if (!flags.IsEmpty()) {
// Clear all instructions in the map that are affected by side effects. // Clear all instructions in the map that are affected by side effects.
...@@ -804,25 +823,6 @@ void HGlobalValueNumberingPhase::AnalyzeGraph() { ...@@ -804,25 +823,6 @@ void HGlobalValueNumberingPhase::AnalyzeGraph() {
map->Add(instr, zone()); 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; HBasicBlock* dominator_block;
......
...@@ -1654,8 +1654,8 @@ void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) { ...@@ -1654,8 +1654,8 @@ void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
} }
void HCheckMaps::SetSideEffectDominator(GVNFlag side_effect, void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) { HValue* dominator) {
ASSERT(side_effect == kChangesMaps); ASSERT(side_effect == kChangesMaps);
// TODO(mstarzinger): For now we specialize on HStoreNamedField, but once // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once
// type information is rich enough we should generalize this to any HType // type information is rich enough we should generalize this to any HType
...@@ -3183,6 +3183,84 @@ HType HAllocate::CalculateInferredType() { ...@@ -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) { void HAllocate::PrintDataTo(StringStream* stream) {
size()->PrintNameTo(stream); size()->PrintNameTo(stream);
if (!GuaranteedInNewSpace()) stream->Add(" (pretenure)"); if (!GuaranteedInNewSpace()) stream->Add(" (pretenure)");
......
...@@ -790,7 +790,7 @@ class HValue: public ZoneObject { ...@@ -790,7 +790,7 @@ class HValue: public ZoneObject {
// occurrences of the instruction are indeed the same. // occurrences of the instruction are indeed the same.
kUseGVN, kUseGVN,
// Track instructions that are dominating side effects. If an instruction // 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. // indicate which side effects to track by setting GVN flags.
kTrackSideEffectDominators, kTrackSideEffectDominators,
kCanOverflow, kCanOverflow,
...@@ -1109,7 +1109,8 @@ class HValue: public ZoneObject { ...@@ -1109,7 +1109,8 @@ class HValue: public ZoneObject {
// This function must be overridden for instructions which have the // This function must be overridden for instructions which have the
// kTrackSideEffectDominators flag set, to track instructions that are // kTrackSideEffectDominators flag set, to track instructions that are
// dominating side effects. // dominating side effects.
virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { virtual void HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) {
UNREACHABLE(); UNREACHABLE();
} }
...@@ -2774,7 +2775,8 @@ class HCheckMaps: public HTemplateInstruction<2> { ...@@ -2774,7 +2775,8 @@ class HCheckMaps: public HTemplateInstruction<2> {
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged(); 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 void PrintDataTo(StringStream* stream);
virtual HType CalculateInferredType(); virtual HType CalculateInferredType();
...@@ -4975,10 +4977,12 @@ class HAllocateObject: public HTemplateInstruction<1> { ...@@ -4975,10 +4977,12 @@ class HAllocateObject: public HTemplateInstruction<1> {
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged(); return Representation::Tagged();
} }
virtual Handle<Map> GetMonomorphicJSObjectMap() { virtual Handle<Map> GetMonomorphicJSObjectMap() {
ASSERT(!constructor_initial_map_.is_null()); ASSERT(!constructor_initial_map_.is_null());
return constructor_initial_map_; return constructor_initial_map_;
} }
virtual HType CalculateInferredType(); virtual HType CalculateInferredType();
DECLARE_CONCRETE_INSTRUCTION(AllocateObject) DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
...@@ -5007,7 +5011,9 @@ class HAllocate: public HTemplateInstruction<2> { ...@@ -5007,7 +5011,9 @@ class HAllocate: public HTemplateInstruction<2> {
SetOperandAt(0, context); SetOperandAt(0, context);
SetOperandAt(1, size); SetOperandAt(1, size);
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kTrackSideEffectDominators);
SetGVNFlag(kChangesNewSpacePromotion); SetGVNFlag(kChangesNewSpacePromotion);
SetGVNFlag(kDependsOnNewSpacePromotion);
} }
static Flags DefaultFlags() { static Flags DefaultFlags() {
...@@ -5025,6 +5031,7 @@ class HAllocate: public HTemplateInstruction<2> { ...@@ -5025,6 +5031,7 @@ class HAllocate: public HTemplateInstruction<2> {
HValue* context() { return OperandAt(0); } HValue* context() { return OperandAt(0); }
HValue* size() { return OperandAt(1); } HValue* size() { return OperandAt(1); }
HType type() { return type_; }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
if (index == 0) { if (index == 0) {
...@@ -5061,6 +5068,13 @@ class HAllocate: public HTemplateInstruction<2> { ...@@ -5061,6 +5068,13 @@ class HAllocate: public HTemplateInstruction<2> {
return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0; 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); virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(Allocate) DECLARE_CONCRETE_INSTRUCTION(Allocate)
...@@ -5073,8 +5087,9 @@ class HAllocate: public HTemplateInstruction<2> { ...@@ -5073,8 +5087,9 @@ class HAllocate: public HTemplateInstruction<2> {
class HInnerAllocatedObject: public HTemplateInstruction<1> { class HInnerAllocatedObject: public HTemplateInstruction<1> {
public: public:
HInnerAllocatedObject(HValue* value, int offset) HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged())
: offset_(offset) { : offset_(offset),
type_(type) {
ASSERT(value->IsAllocate()); ASSERT(value->IsAllocate());
SetOperandAt(0, value); SetOperandAt(0, value);
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
...@@ -5087,12 +5102,15 @@ class HInnerAllocatedObject: public HTemplateInstruction<1> { ...@@ -5087,12 +5102,15 @@ class HInnerAllocatedObject: public HTemplateInstruction<1> {
return Representation::Tagged(); return Representation::Tagged();
} }
virtual HType CalculateInferredType() { return type_; }
virtual void PrintDataTo(StringStream* stream); virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject) DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
private: private:
int offset_; int offset_;
HType type_;
}; };
...@@ -5815,7 +5833,8 @@ class HStoreNamedField: public HTemplateInstruction<2> { ...@@ -5815,7 +5833,8 @@ class HStoreNamedField: public HTemplateInstruction<2> {
} }
return Representation::Tagged(); return Representation::Tagged();
} }
virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { virtual void HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) {
ASSERT(side_effect == kChangesNewSpacePromotion); ASSERT(side_effect == kChangesNewSpacePromotion);
new_space_dominator_ = dominator; new_space_dominator_ = dominator;
} }
...@@ -6017,7 +6036,8 @@ class HStoreKeyed ...@@ -6017,7 +6036,8 @@ class HStoreKeyed
return value()->IsConstant() && HConstant::cast(value())->IsTheHole(); 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); ASSERT(side_effect == kChangesNewSpacePromotion);
new_space_dominator_ = dominator; new_space_dominator_ = dominator;
} }
......
...@@ -233,14 +233,21 @@ class HPredecessorIterator BASE_EMBEDDED { ...@@ -233,14 +233,21 @@ class HPredecessorIterator BASE_EMBEDDED {
class HInstructionIterator BASE_EMBEDDED { class HInstructionIterator BASE_EMBEDDED {
public: 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; } inline bool Done() const { return instr_ == NULL; }
HInstruction* Current() { return instr_; } inline HInstruction* Current() { return instr_; }
void Advance() { instr_ = instr_->next(); } inline void Advance() {
instr_ = next_;
next_ = Done() ? NULL : instr_->next();
}
private: private:
HInstruction* instr_; HInstruction* instr_;
HInstruction* next_;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment