| Index: src/hydrogen-instructions.cc | 
| diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc | 
| index b0045b8751b06258f0a241416e54615924ea910f..8e0ed38921a2f6d1110b590e33a49ff6e0013f55 100644 | 
| --- a/src/hydrogen-instructions.cc | 
| +++ b/src/hydrogen-instructions.cc | 
| @@ -2366,6 +2366,24 @@ HConstant::HConstant(Handle<Object> handle, | 
| } | 
|  | 
|  | 
| +HConstant::HConstant(Handle<Map> handle, | 
| +                     UniqueValueId unique_id) | 
| +  : HTemplateInstruction<0>(HType::Tagged()), | 
| +    handle_(handle), | 
| +    unique_id_(unique_id), | 
| +    has_smi_value_(false), | 
| +    has_int32_value_(false), | 
| +    has_double_value_(false), | 
| +    has_external_reference_value_(false), | 
| +    is_internalized_string_(false), | 
| +    is_not_in_new_space_(true), | 
| +    is_cell_(false), | 
| +    boolean_value_(false) { | 
| +  ASSERT(!handle.is_null()); | 
| +  Initialize(Representation::Tagged()); | 
| +} | 
| + | 
| + | 
| HConstant::HConstant(int32_t integer_value, | 
| Representation r, | 
| bool is_not_in_new_space, | 
| @@ -3180,6 +3198,7 @@ Representation HUnaryMathOperation::RepresentationFromInputs() { | 
| void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 
| HValue* dominator) { | 
| ASSERT(side_effect == kChangesNewSpacePromotion); | 
| +  Zone* zone = block()->zone(); | 
| if (!FLAG_use_allocation_folding) return; | 
|  | 
| // Try to fold allocations together with their dominating allocations. | 
| @@ -3191,22 +3210,34 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 
| return; | 
| } | 
|  | 
| -  HAllocate* dominator_allocate_instr = HAllocate::cast(dominator); | 
| -  HValue* dominator_size = dominator_allocate_instr->size(); | 
| +  HAllocate* dominator_allocate = HAllocate::cast(dominator); | 
| +  HValue* dominator_size = dominator_allocate->size(); | 
| HValue* current_size = size(); | 
| -  // We can just fold allocations that are guaranteed in new space. | 
| + | 
| // TODO(hpayer): Add support for non-constant allocation in dominator. | 
| -  if (!IsNewSpaceAllocation() || !current_size->IsInteger32Constant() || | 
| -      !dominator_allocate_instr->IsNewSpaceAllocation() || | 
| +  if (!current_size->IsInteger32Constant() || | 
| !dominator_size->IsInteger32Constant()) { | 
| if (FLAG_trace_allocation_folding) { | 
| -      PrintF("#%d (%s) cannot fold into #%d (%s)\n", | 
| +      PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n", | 
| id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 
| } | 
| return; | 
| } | 
|  | 
| +  dominator_allocate = GetFoldableDominator(dominator_allocate); | 
| +  if (dominator_allocate == NULL) { | 
| +    return; | 
| +  } | 
| + | 
| +  ASSERT((IsNewSpaceAllocation() && | 
| +         dominator_allocate->IsNewSpaceAllocation()) || | 
| +         (IsOldDataSpaceAllocation() && | 
| +         dominator_allocate->IsOldDataSpaceAllocation()) || | 
| +         (IsOldPointerSpaceAllocation() && | 
| +         dominator_allocate->IsOldPointerSpaceAllocation())); | 
| + | 
| // First update the size of the dominator allocate instruction. | 
| +  dominator_size = dominator_allocate->size(); | 
| int32_t dominator_size_constant = | 
| HConstant::cast(dominator_size)->GetInteger32Constant(); | 
| int32_t current_size_constant = | 
| @@ -3214,8 +3245,8 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 
| int32_t new_dominator_size = dominator_size_constant + current_size_constant; | 
|  | 
| if (MustAllocateDoubleAligned()) { | 
| -    if (!dominator_allocate_instr->MustAllocateDoubleAligned()) { | 
| -      dominator_allocate_instr->MakeDoubleAligned(); | 
| +    if (!dominator_allocate->MustAllocateDoubleAligned()) { | 
| +      dominator_allocate->MakeDoubleAligned(); | 
| } | 
| if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { | 
| dominator_size_constant += kDoubleSize / 2; | 
| @@ -3226,21 +3257,19 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 
| if (new_dominator_size > Page::kMaxNonCodeHeapObjectSize) { | 
| if (FLAG_trace_allocation_folding) { | 
| PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", | 
| -          id(), Mnemonic(), dominator->id(), dominator->Mnemonic(), | 
| -          new_dominator_size); | 
| +          id(), Mnemonic(), dominator_allocate->id(), | 
| +          dominator_allocate->Mnemonic(), new_dominator_size); | 
| } | 
| return; | 
| } | 
| -  HBasicBlock* block = dominator->block(); | 
| -  Zone* zone = block->zone(); | 
| -  HInstruction* new_dominator_size_constant = | 
| -      HConstant::New(zone, context(), new_dominator_size); | 
| -  new_dominator_size_constant->InsertBefore(dominator_allocate_instr); | 
| -  dominator_allocate_instr->UpdateSize(new_dominator_size_constant); | 
| + | 
| +  HInstruction* new_dominator_size_constant = HConstant::CreateAndInsertBefore( | 
| +      zone, context(), new_dominator_size, dominator_allocate); | 
| +  dominator_allocate->UpdateSize(new_dominator_size_constant); | 
|  | 
| #ifdef VERIFY_HEAP | 
| -  if (FLAG_verify_heap) { | 
| -    dominator_allocate_instr->MakePrefillWithFiller(); | 
| +  if (FLAG_verify_heap && dominator_allocate->IsNewSpaceAllocation()) { | 
| +    dominator_allocate->MakePrefillWithFiller(); | 
| } | 
| #endif | 
|  | 
| @@ -3248,18 +3277,128 @@ void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 
| HInstruction* dominated_allocate_instr = | 
| HInnerAllocatedObject::New(zone, | 
| context(), | 
| -                                 dominator_allocate_instr, | 
| +                                 dominator_allocate, | 
| 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()); | 
| +        id(), Mnemonic(), dominator_allocate->id(), | 
| +        dominator_allocate->Mnemonic()); | 
| } | 
| } | 
|  | 
|  | 
| +HAllocate* HAllocate::GetFoldableDominator(HAllocate* dominator) { | 
| +  if (!IsFoldable(dominator)) { | 
| +    // We cannot hoist old space allocations over new space allocations. | 
| +    if (IsNewSpaceAllocation() || dominator->IsNewSpaceAllocation()) { | 
| +      if (FLAG_trace_allocation_folding) { | 
| +        PrintF("#%d (%s) cannot fold into #%d (%s), new space hoisting\n", | 
| +            id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 
| +      } | 
| +      return NULL; | 
| +    } | 
| + | 
| +    HAllocate* dominator_dominator = dominator->dominating_allocate_; | 
| + | 
| +    // We can hoist old data space allocations over an old pointer space | 
| +    // allocation and vice versa. For that we have to check the dominator | 
| +    // of the dominator allocate instruction. | 
| +    if (dominator_dominator == NULL) { | 
| +      dominating_allocate_ = dominator; | 
| +      if (FLAG_trace_allocation_folding) { | 
| +        PrintF("#%d (%s) cannot fold into #%d (%s), different spaces\n", | 
| +            id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 
| +      } | 
| +      return NULL; | 
| +    } | 
| + | 
| +    // We can just fold old space allocations that are in the same basic block, | 
| +    // since it is not guaranteed that we fill up the whole allocated old | 
| +    // space memory. | 
| +    // TODO(hpayer): Remove this limitation and add filler maps for each each | 
| +    // allocation as soon as we have store elimination. | 
| +    if (block()->block_id() != dominator_dominator->block()->block_id()) { | 
| +      if (FLAG_trace_allocation_folding) { | 
| +        PrintF("#%d (%s) cannot fold into #%d (%s), different basic blocks\n", | 
| +            id(), Mnemonic(), dominator_dominator->id(), | 
| +            dominator_dominator->Mnemonic()); | 
| +      } | 
| +      return NULL; | 
| +    } | 
| + | 
| +    ASSERT((IsOldDataSpaceAllocation() && | 
| +           dominator_dominator->IsOldDataSpaceAllocation()) || | 
| +           (IsOldPointerSpaceAllocation() && | 
| +           dominator_dominator->IsOldPointerSpaceAllocation())); | 
| + | 
| +    int32_t current_size = HConstant::cast(size())->GetInteger32Constant(); | 
| +    HStoreNamedField* dominator_free_space_size = | 
| +        dominator->filler_free_space_size_; | 
| +    if (dominator_free_space_size != NULL) { | 
| +      // We already hoisted one old space allocation, i.e., we already installed | 
| +      // a filler map. Hence, we just have to update the free space size. | 
| +      dominator->UpdateFreeSpaceFiller(current_size); | 
| +    } else { | 
| +      // This is the first old space allocation that gets hoisted. We have to | 
| +      // install a filler map since the follwing allocation may cause a GC. | 
| +      dominator->CreateFreeSpaceFiller(current_size); | 
| +    } | 
| + | 
| +    // We can hoist the old space allocation over the actual dominator. | 
| +    return dominator_dominator; | 
| +  } | 
| +  return dominator; | 
| +} | 
| + | 
| + | 
| +void HAllocate::UpdateFreeSpaceFiller(int32_t free_space_size) { | 
| +  ASSERT(filler_free_space_size_ != NULL); | 
| +  Zone* zone = block()->zone(); | 
| +  HConstant* new_free_space_size = HConstant::CreateAndInsertBefore( | 
| +      zone, | 
| +      context(), | 
| +      filler_free_space_size_->value()->GetInteger32Constant() + | 
| +          free_space_size, | 
| +      filler_free_space_size_); | 
| +  filler_free_space_size_->UpdateValue(new_free_space_size); | 
| +} | 
| + | 
| + | 
| +void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) { | 
| +  ASSERT(filler_free_space_size_ == NULL); | 
| +  Zone* zone = block()->zone(); | 
| +  int32_t dominator_size = | 
| +      HConstant::cast(dominating_allocate_->size())->GetInteger32Constant(); | 
| +  HInstruction* free_space_instr = | 
| +      HInnerAllocatedObject::New(zone, context(), dominating_allocate_, | 
| +      dominator_size, type()); | 
| +  free_space_instr->InsertBefore(this); | 
| +  HConstant* filler_map = HConstant::New( | 
| +      zone, | 
| +      context(), | 
| +      isolate()->factory()->free_space_map(), | 
| +      UniqueValueId(isolate()->heap()->free_space_map())); | 
| +  filler_map->InsertAfter(free_space_instr); | 
| +  HInstruction* store_map = HStoreNamedField::New(zone, context(), | 
| +      free_space_instr, HObjectAccess::ForMap(), filler_map); | 
| +  store_map->SetFlag(HValue::kHasNoObservableSideEffects); | 
| +  store_map->InsertAfter(filler_map); | 
| + | 
| +  HConstant* filler_size = HConstant::CreateAndInsertAfter( | 
| +      zone, context(), free_space_size, store_map); | 
| +  HObjectAccess access = | 
| +      HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); | 
| +  HStoreNamedField* store_size = HStoreNamedField::New(zone, context(), | 
| +      free_space_instr, access, filler_size); | 
| +  store_size->SetFlag(HValue::kHasNoObservableSideEffects); | 
| +  store_size->InsertAfter(filler_size); | 
| +  filler_free_space_size_ = store_size; | 
| +} | 
| + | 
| + | 
| void HAllocate::PrintDataTo(StringStream* stream) { | 
| size()->PrintNameTo(stream); | 
| stream->Add(" ("); | 
|  |