Index: src/hydrogen-instructions.cc |
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc |
index 041ef8b37408f11fcb8cdc68e26abbf3c479966e..37a788b138a824d47e9d232f994e4d92b005653f 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 |
@@ -3197,6 +3197,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)"); |