| Index: src/ia32/macro-assembler-ia32.cc
 | 
| diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
 | 
| index c31b0c24bef9e63fc15793c278349549ca4510dd..1b614867cd4a1bfa29efda6623fd41cc5bece440 100644
 | 
| --- a/src/ia32/macro-assembler-ia32.cc
 | 
| +++ b/src/ia32/macro-assembler-ia32.cc
 | 
| @@ -382,10 +382,12 @@ void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
 | 
|  void MacroAssembler::CheckFastElements(Register map,
 | 
|                                         Label* fail,
 | 
|                                         Label::Distance distance) {
 | 
| -  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
 | 
| -  STATIC_ASSERT(FAST_ELEMENTS == 1);
 | 
| +  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
 | 
| +  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
 | 
| +  STATIC_ASSERT(FAST_ELEMENTS == 2);
 | 
| +  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
 | 
|    cmpb(FieldOperand(map, Map::kBitField2Offset),
 | 
| -       Map::kMaximumBitField2FastElementValue);
 | 
| +       Map::kMaximumBitField2FastHoleyElementValue);
 | 
|    j(above, fail, distance);
 | 
|  }
 | 
|  
 | 
| @@ -393,23 +395,26 @@ void MacroAssembler::CheckFastElements(Register map,
 | 
|  void MacroAssembler::CheckFastObjectElements(Register map,
 | 
|                                               Label* fail,
 | 
|                                               Label::Distance distance) {
 | 
| -  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
 | 
| -  STATIC_ASSERT(FAST_ELEMENTS == 1);
 | 
| +  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
 | 
| +  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
 | 
| +  STATIC_ASSERT(FAST_ELEMENTS == 2);
 | 
| +  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
 | 
|    cmpb(FieldOperand(map, Map::kBitField2Offset),
 | 
| -       Map::kMaximumBitField2FastSmiOnlyElementValue);
 | 
| +       Map::kMaximumBitField2FastHoleySmiElementValue);
 | 
|    j(below_equal, fail, distance);
 | 
|    cmpb(FieldOperand(map, Map::kBitField2Offset),
 | 
| -       Map::kMaximumBitField2FastElementValue);
 | 
| +       Map::kMaximumBitField2FastHoleyElementValue);
 | 
|    j(above, fail, distance);
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void MacroAssembler::CheckFastSmiOnlyElements(Register map,
 | 
| -                                              Label* fail,
 | 
| -                                              Label::Distance distance) {
 | 
| -  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
 | 
| +void MacroAssembler::CheckFastSmiElements(Register map,
 | 
| +                                          Label* fail,
 | 
| +                                          Label::Distance distance) {
 | 
| +  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
 | 
| +  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
 | 
|    cmpb(FieldOperand(map, Map::kBitField2Offset),
 | 
| -       Map::kMaximumBitField2FastSmiOnlyElementValue);
 | 
| +       Map::kMaximumBitField2FastHoleySmiElementValue);
 | 
|    j(above, fail, distance);
 | 
|  }
 | 
|  
 | 
| @@ -493,24 +498,18 @@ void MacroAssembler::CompareMap(Register obj,
 | 
|                                  CompareMapMode mode) {
 | 
|    cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
 | 
|    if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
 | 
| -    Map* transitioned_fast_element_map(
 | 
| -        map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL));
 | 
| -    ASSERT(transitioned_fast_element_map == NULL ||
 | 
| -           map->elements_kind() != FAST_ELEMENTS);
 | 
| -    if (transitioned_fast_element_map != NULL) {
 | 
| -      j(equal, early_success, Label::kNear);
 | 
| -      cmp(FieldOperand(obj, HeapObject::kMapOffset),
 | 
| -          Handle<Map>(transitioned_fast_element_map));
 | 
| -    }
 | 
| -
 | 
| -    Map* transitioned_double_map(
 | 
| -        map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL));
 | 
| -    ASSERT(transitioned_double_map == NULL ||
 | 
| -           map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
 | 
| -    if (transitioned_double_map != NULL) {
 | 
| -      j(equal, early_success, Label::kNear);
 | 
| -      cmp(FieldOperand(obj, HeapObject::kMapOffset),
 | 
| -          Handle<Map>(transitioned_double_map));
 | 
| +    ElementsKind kind = map->elements_kind();
 | 
| +    if (IsFastElementsKind(kind)) {
 | 
| +      bool packed = IsFastPackedElementsKind(kind);
 | 
| +      Map* current_map = *map;
 | 
| +      while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
 | 
| +        kind = GetNextMoreGeneralFastElementsKind(kind, packed);
 | 
| +        current_map = current_map->LookupElementsTransitionMap(kind, NULL);
 | 
| +        if (!current_map) break;
 | 
| +        j(equal, early_success, Label::kNear);
 | 
| +        cmp(FieldOperand(obj, HeapObject::kMapOffset),
 | 
| +            Handle<Map>(current_map));
 | 
| +      }
 | 
|      }
 | 
|    }
 | 
|  }
 | 
| @@ -2161,27 +2160,38 @@ void MacroAssembler::LoadTransitionedArrayMapConditional(
 | 
|    mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
 | 
|  
 | 
|    // Check that the function's map is the same as the expected cached map.
 | 
| -  int expected_index =
 | 
| -      Context::GetContextMapIndexFromElementsKind(expected_kind);
 | 
| -  cmp(map_in_out, Operand(scratch, Context::SlotOffset(expected_index)));
 | 
| +  mov(scratch, Operand(scratch,
 | 
| +                       Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX)));
 | 
| +
 | 
| +  size_t offset = expected_kind * kPointerSize +
 | 
| +      FixedArrayBase::kHeaderSize;
 | 
| +  cmp(map_in_out, FieldOperand(scratch, offset));
 | 
|    j(not_equal, no_map_match);
 | 
|  
 | 
|    // Use the transitioned cached map.
 | 
| -  int trans_index =
 | 
| -      Context::GetContextMapIndexFromElementsKind(transitioned_kind);
 | 
| -  mov(map_in_out, Operand(scratch, Context::SlotOffset(trans_index)));
 | 
| +  offset = transitioned_kind * kPointerSize +
 | 
| +      FixedArrayBase::kHeaderSize;
 | 
| +  mov(map_in_out, FieldOperand(scratch, offset));
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void MacroAssembler::LoadInitialArrayMap(
 | 
| -    Register function_in, Register scratch, Register map_out) {
 | 
| +    Register function_in, Register scratch,
 | 
| +    Register map_out, bool can_have_holes) {
 | 
|    ASSERT(!function_in.is(map_out));
 | 
|    Label done;
 | 
|    mov(map_out, FieldOperand(function_in,
 | 
|                              JSFunction::kPrototypeOrInitialMapOffset));
 | 
|    if (!FLAG_smi_only_arrays) {
 | 
| -    LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
 | 
| -                                        FAST_ELEMENTS,
 | 
| +    ElementsKind kind = can_have_holes ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
 | 
| +    LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
 | 
| +                                        kind,
 | 
| +                                        map_out,
 | 
| +                                        scratch,
 | 
| +                                        &done);
 | 
| +  } else if (can_have_holes) {
 | 
| +    LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
 | 
| +                                        FAST_HOLEY_SMI_ELEMENTS,
 | 
|                                          map_out,
 | 
|                                          scratch,
 | 
|                                          &done);
 | 
| 
 |