| Index: src/x64/lithium-codegen-x64.cc
 | 
| diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
 | 
| index d1cf33899d5b307fd4571f9c3abf7378bcf0b0e0..f1c631bc5fd4ae905431c923c91bf4ee20c55614 100644
 | 
| --- a/src/x64/lithium-codegen-x64.cc
 | 
| +++ b/src/x64/lithium-codegen-x64.cc
 | 
| @@ -2324,8 +2324,10 @@ void LCodeGen::DoLoadElements(LLoadElements* instr) {
 | 
|      __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset));
 | 
|      __ and_(temp, Immediate(Map::kElementsKindMask));
 | 
|      __ shr(temp, Immediate(Map::kElementsKindShift));
 | 
| -    __ cmpl(temp, Immediate(FAST_ELEMENTS));
 | 
| -    __ j(equal, &ok, Label::kNear);
 | 
| +    __ cmpl(temp, Immediate(GetInitialFastElementsKind()));
 | 
| +    __ j(less, &fail, Label::kNear);
 | 
| +    __ cmpl(temp, Immediate(TERMINAL_FAST_ELEMENTS_KIND));
 | 
| +    __ j(less_equal, &ok, Label::kNear);
 | 
|      __ cmpl(temp, Immediate(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND));
 | 
|      __ j(less, &fail, Label::kNear);
 | 
|      __ cmpl(temp, Immediate(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND));
 | 
| @@ -2403,16 +2405,18 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
 | 
|      __ movsxlq(key_reg, key_reg);
 | 
|    }
 | 
|  
 | 
| -  int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
 | 
| -      sizeof(kHoleNanLower32);
 | 
| -  Operand hole_check_operand = BuildFastArrayOperand(
 | 
| -      instr->elements(),
 | 
| -      instr->key(),
 | 
| -      FAST_DOUBLE_ELEMENTS,
 | 
| -      offset,
 | 
| -      instr->additional_index());
 | 
| -  __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
 | 
| -  DeoptimizeIf(equal, instr->environment());
 | 
| +  if (instr->hydrogen()->RequiresHoleCheck()) {
 | 
| +    int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
 | 
| +        sizeof(kHoleNanLower32);
 | 
| +    Operand hole_check_operand = BuildFastArrayOperand(
 | 
| +        instr->elements(),
 | 
| +        instr->key(),
 | 
| +        FAST_DOUBLE_ELEMENTS,
 | 
| +        offset,
 | 
| +        instr->additional_index());
 | 
| +    __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
 | 
| +    DeoptimizeIf(equal, instr->environment());
 | 
| +  }
 | 
|  
 | 
|    Operand double_load_operand = BuildFastArrayOperand(
 | 
|        instr->elements(),
 | 
| @@ -2501,8 +2505,11 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
 | 
|        case EXTERNAL_FLOAT_ELEMENTS:
 | 
|        case EXTERNAL_DOUBLE_ELEMENTS:
 | 
|        case FAST_ELEMENTS:
 | 
| -      case FAST_SMI_ONLY_ELEMENTS:
 | 
| +      case FAST_SMI_ELEMENTS:
 | 
|        case FAST_DOUBLE_ELEMENTS:
 | 
| +      case FAST_HOLEY_ELEMENTS:
 | 
| +      case FAST_HOLEY_SMI_ELEMENTS:
 | 
| +      case FAST_HOLEY_DOUBLE_ELEMENTS:
 | 
|        case DICTIONARY_ELEMENTS:
 | 
|        case NON_STRICT_ARGUMENTS_ELEMENTS:
 | 
|          UNREACHABLE();
 | 
| @@ -3403,8 +3410,11 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
 | 
|        case EXTERNAL_FLOAT_ELEMENTS:
 | 
|        case EXTERNAL_DOUBLE_ELEMENTS:
 | 
|        case FAST_ELEMENTS:
 | 
| -      case FAST_SMI_ONLY_ELEMENTS:
 | 
| +      case FAST_SMI_ELEMENTS:
 | 
|        case FAST_DOUBLE_ELEMENTS:
 | 
| +      case FAST_HOLEY_ELEMENTS:
 | 
| +      case FAST_HOLEY_SMI_ELEMENTS:
 | 
| +      case FAST_HOLEY_DOUBLE_ELEMENTS:
 | 
|        case DICTIONARY_ELEMENTS:
 | 
|        case NON_STRICT_ARGUMENTS_ELEMENTS:
 | 
|          UNREACHABLE();
 | 
| @@ -3539,21 +3549,22 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
 | 
|    __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
 | 
|    __ j(not_equal, ¬_applicable);
 | 
|    __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT);
 | 
| -  if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) {
 | 
| +  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
 | 
|      __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg);
 | 
|      // Write barrier.
 | 
|      ASSERT_NE(instr->temp_reg(), NULL);
 | 
|      __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
 | 
|                          ToRegister(instr->temp_reg()), kDontSaveFPRegs);
 | 
| -  } else if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
 | 
| -      to_kind == FAST_DOUBLE_ELEMENTS) {
 | 
| +  } else if (IsFastSmiElementsKind(from_kind) &&
 | 
| +             IsFastDoubleElementsKind(to_kind)) {
 | 
|      Register fixed_object_reg = ToRegister(instr->temp_reg());
 | 
|      ASSERT(fixed_object_reg.is(rdx));
 | 
|      ASSERT(new_map_reg.is(rbx));
 | 
|      __ movq(fixed_object_reg, object_reg);
 | 
|      CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
 | 
|               RelocInfo::CODE_TARGET, instr);
 | 
| -  } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
 | 
| +  } else if (IsFastDoubleElementsKind(from_kind) &&
 | 
| +             IsFastObjectElementsKind(to_kind)) {
 | 
|      Register fixed_object_reg = ToRegister(instr->temp_reg());
 | 
|      ASSERT(fixed_object_reg.is(rdx));
 | 
|      ASSERT(new_map_reg.is(rbx));
 | 
| @@ -4227,8 +4238,9 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
 | 
|  
 | 
|    // Deopt if the array literal boilerplate ElementsKind is of a type different
 | 
|    // than the expected one. The check isn't necessary if the boilerplate has
 | 
| -  // already been converted to FAST_ELEMENTS.
 | 
| -  if (boilerplate_elements_kind != FAST_ELEMENTS) {
 | 
| +  // already been converted to TERMINAL_FAST_ELEMENTS_KIND.
 | 
| +  if (CanTransitionToMoreGeneralFastElementsKind(
 | 
| +          boilerplate_elements_kind, true)) {
 | 
|      __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object());
 | 
|      __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
 | 
|      // Load the map's "bit field 2".
 | 
| @@ -4374,10 +4386,11 @@ void LCodeGen::DoFastLiteral(LFastLiteral* instr) {
 | 
|    ElementsKind boilerplate_elements_kind =
 | 
|        instr->hydrogen()->boilerplate()->GetElementsKind();
 | 
|  
 | 
| -  // Deopt if the literal boilerplate ElementsKind is of a type different than
 | 
| -  // the expected one. The check isn't necessary if the boilerplate has already
 | 
| -  // been converted to FAST_ELEMENTS.
 | 
| -  if (boilerplate_elements_kind != FAST_ELEMENTS) {
 | 
| +  // Deopt if the array literal boilerplate ElementsKind is of a type different
 | 
| +  // than the expected one. The check isn't necessary if the boilerplate has
 | 
| +  // already been converted to TERMINAL_FAST_ELEMENTS_KIND.
 | 
| +  if (CanTransitionToMoreGeneralFastElementsKind(
 | 
| +          boilerplate_elements_kind, true)) {
 | 
|      __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate());
 | 
|      __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset));
 | 
|      // Load the map's "bit field 2".
 | 
| 
 |