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")
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")
......
......@@ -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;
......
......@@ -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)");
......
......@@ -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<Map> 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;
}
......
......@@ -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_;
};
......
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