| Index: src/ia32/lithium-codegen-ia32.cc
 | 
| diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
 | 
| index 32c66a05f509df7df7d7314401f628dfbdcf4e87..7468d310a3d7721b01495aa16294a3aa79ff7ee3 100644
 | 
| --- a/src/ia32/lithium-codegen-ia32.cc
 | 
| +++ b/src/ia32/lithium-codegen-ia32.cc
 | 
| @@ -2749,33 +2749,71 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
 | 
| -  Register result = ToRegister(instr->result());
 | 
| -
 | 
| -  // Load the result.
 | 
| -  __ mov(result,
 | 
| -         BuildFastArrayOperand(instr->elements(),
 | 
| -                               instr->key(),
 | 
| -                               instr->hydrogen()->key()->representation(),
 | 
| -                               FAST_ELEMENTS,
 | 
| -                               FixedArray::kHeaderSize - kHeapObjectTag,
 | 
| -                               instr->additional_index()));
 | 
| -
 | 
| -  // Check for the hole value.
 | 
| -  if (instr->hydrogen()->RequiresHoleCheck()) {
 | 
| -    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
 | 
| -      __ test(result, Immediate(kSmiTagMask));
 | 
| -      DeoptimizeIf(not_equal, instr->environment());
 | 
| -    } else {
 | 
| -      __ cmp(result, factory()->the_hole_value());
 | 
| -      DeoptimizeIf(equal, instr->environment());
 | 
| +void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
 | 
| +  ElementsKind elements_kind = instr->elements_kind();
 | 
| +  LOperand* key = instr->key();
 | 
| +  if (!key->IsConstantOperand() &&
 | 
| +      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
 | 
| +                                  elements_kind)) {
 | 
| +    __ SmiUntag(ToRegister(key));
 | 
| +  }
 | 
| +  Operand operand(BuildFastArrayOperand(
 | 
| +      instr->elements(),
 | 
| +      key,
 | 
| +      instr->hydrogen()->key()->representation(),
 | 
| +      elements_kind,
 | 
| +      0,
 | 
| +      instr->additional_index()));
 | 
| +  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
 | 
| +    XMMRegister result(ToDoubleRegister(instr->result()));
 | 
| +    __ movss(result, operand);
 | 
| +    __ cvtss2sd(result, result);
 | 
| +  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
 | 
| +    __ movdbl(ToDoubleRegister(instr->result()), operand);
 | 
| +  } else {
 | 
| +    Register result(ToRegister(instr->result()));
 | 
| +    switch (elements_kind) {
 | 
| +      case EXTERNAL_BYTE_ELEMENTS:
 | 
| +        __ movsx_b(result, operand);
 | 
| +        break;
 | 
| +      case EXTERNAL_PIXEL_ELEMENTS:
 | 
| +      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
 | 
| +        __ movzx_b(result, operand);
 | 
| +        break;
 | 
| +      case EXTERNAL_SHORT_ELEMENTS:
 | 
| +        __ movsx_w(result, operand);
 | 
| +        break;
 | 
| +      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
| +        __ movzx_w(result, operand);
 | 
| +        break;
 | 
| +      case EXTERNAL_INT_ELEMENTS:
 | 
| +        __ mov(result, operand);
 | 
| +        break;
 | 
| +      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| +        __ mov(result, operand);
 | 
| +        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
 | 
| +          __ test(result, Operand(result));
 | 
| +          DeoptimizeIf(negative, instr->environment());
 | 
| +        }
 | 
| +        break;
 | 
| +      case EXTERNAL_FLOAT_ELEMENTS:
 | 
| +      case EXTERNAL_DOUBLE_ELEMENTS:
 | 
| +      case FAST_SMI_ELEMENTS:
 | 
| +      case FAST_ELEMENTS:
 | 
| +      case FAST_DOUBLE_ELEMENTS:
 | 
| +      case FAST_HOLEY_SMI_ELEMENTS:
 | 
| +      case FAST_HOLEY_ELEMENTS:
 | 
| +      case FAST_HOLEY_DOUBLE_ELEMENTS:
 | 
| +      case DICTIONARY_ELEMENTS:
 | 
| +      case NON_STRICT_ARGUMENTS_ELEMENTS:
 | 
| +        UNREACHABLE();
 | 
| +        break;
 | 
|      }
 | 
|    }
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void LCodeGen::DoLoadKeyedFastDoubleElement(
 | 
| -    LLoadKeyedFastDoubleElement* instr) {
 | 
| +void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
 | 
|    XMMRegister result = ToDoubleRegister(instr->result());
 | 
|  
 | 
|    if (instr->hydrogen()->RequiresHoleCheck()) {
 | 
| @@ -2802,6 +2840,42 @@ void LCodeGen::DoLoadKeyedFastDoubleElement(
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
 | 
| +  Register result = ToRegister(instr->result());
 | 
| +
 | 
| +  // Load the result.
 | 
| +  __ mov(result,
 | 
| +         BuildFastArrayOperand(instr->elements(),
 | 
| +                               instr->key(),
 | 
| +                               instr->hydrogen()->key()->representation(),
 | 
| +                               FAST_ELEMENTS,
 | 
| +                               FixedArray::kHeaderSize - kHeapObjectTag,
 | 
| +                               instr->additional_index()));
 | 
| +
 | 
| +  // Check for the hole value.
 | 
| +  if (instr->hydrogen()->RequiresHoleCheck()) {
 | 
| +    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
 | 
| +      __ test(result, Immediate(kSmiTagMask));
 | 
| +      DeoptimizeIf(not_equal, instr->environment());
 | 
| +    } else {
 | 
| +      __ cmp(result, factory()->the_hole_value());
 | 
| +      DeoptimizeIf(equal, instr->environment());
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
 | 
| +  if (instr->is_external()) {
 | 
| +    DoLoadKeyedExternalArray(instr);
 | 
| +  } else if (instr->hydrogen()->representation().IsDouble()) {
 | 
| +    DoLoadKeyedFixedDoubleArray(instr);
 | 
| +  } else {
 | 
| +    DoLoadKeyedFixedArray(instr);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
|  Operand LCodeGen::BuildFastArrayOperand(
 | 
|      LOperand* elements_pointer,
 | 
|      LOperand* key,
 | 
| @@ -2811,7 +2885,7 @@ Operand LCodeGen::BuildFastArrayOperand(
 | 
|      uint32_t additional_index) {
 | 
|    Register elements_pointer_reg = ToRegister(elements_pointer);
 | 
|    int shift_size = ElementsKindToShiftSize(elements_kind);
 | 
| -  // Even though the HLoad/StoreKeyedFastElement instructions force the input
 | 
| +  // Even though the HLoad/StoreKeyed instructions force the input
 | 
|    // representation for the key to be an integer, the input gets replaced during
 | 
|    // bound check elimination with the index argument to the bounds check, which
 | 
|    // can be tagged, so that case must be handled here, too.
 | 
| @@ -2836,71 +2910,6 @@ Operand LCodeGen::BuildFastArrayOperand(
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void LCodeGen::DoLoadKeyedSpecializedArrayElement(
 | 
| -    LLoadKeyedSpecializedArrayElement* instr) {
 | 
| -  ElementsKind elements_kind = instr->elements_kind();
 | 
| -  LOperand* key = instr->key();
 | 
| -  if (!key->IsConstantOperand() &&
 | 
| -      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
 | 
| -                                  elements_kind)) {
 | 
| -    __ SmiUntag(ToRegister(key));
 | 
| -  }
 | 
| -  Operand operand(BuildFastArrayOperand(
 | 
| -      instr->external_pointer(),
 | 
| -      key,
 | 
| -      instr->hydrogen()->key()->representation(),
 | 
| -      elements_kind,
 | 
| -      0,
 | 
| -      instr->additional_index()));
 | 
| -  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
 | 
| -    XMMRegister result(ToDoubleRegister(instr->result()));
 | 
| -    __ movss(result, operand);
 | 
| -    __ cvtss2sd(result, result);
 | 
| -  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
 | 
| -    __ movdbl(ToDoubleRegister(instr->result()), operand);
 | 
| -  } else {
 | 
| -    Register result(ToRegister(instr->result()));
 | 
| -    switch (elements_kind) {
 | 
| -      case EXTERNAL_BYTE_ELEMENTS:
 | 
| -        __ movsx_b(result, operand);
 | 
| -        break;
 | 
| -      case EXTERNAL_PIXEL_ELEMENTS:
 | 
| -      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
 | 
| -        __ movzx_b(result, operand);
 | 
| -        break;
 | 
| -      case EXTERNAL_SHORT_ELEMENTS:
 | 
| -        __ movsx_w(result, operand);
 | 
| -        break;
 | 
| -      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
 | 
| -        __ movzx_w(result, operand);
 | 
| -        break;
 | 
| -      case EXTERNAL_INT_ELEMENTS:
 | 
| -        __ mov(result, operand);
 | 
| -        break;
 | 
| -      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
 | 
| -        __ mov(result, operand);
 | 
| -        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
 | 
| -          __ test(result, Operand(result));
 | 
| -          DeoptimizeIf(negative, instr->environment());
 | 
| -        }
 | 
| -        break;
 | 
| -      case EXTERNAL_FLOAT_ELEMENTS:
 | 
| -      case EXTERNAL_DOUBLE_ELEMENTS:
 | 
| -      case FAST_SMI_ELEMENTS:
 | 
| -      case FAST_ELEMENTS:
 | 
| -      case FAST_DOUBLE_ELEMENTS:
 | 
| -      case FAST_HOLEY_SMI_ELEMENTS:
 | 
| -      case FAST_HOLEY_ELEMENTS:
 | 
| -      case FAST_HOLEY_DOUBLE_ELEMENTS:
 | 
| -      case DICTIONARY_ELEMENTS:
 | 
| -      case NON_STRICT_ARGUMENTS_ELEMENTS:
 | 
| -        UNREACHABLE();
 | 
| -        break;
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
|  void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
 | 
|    ASSERT(ToRegister(instr->context()).is(esi));
 | 
|    ASSERT(ToRegister(instr->object()).is(edx));
 | 
| @@ -3818,8 +3827,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void LCodeGen::DoStoreKeyedSpecializedArrayElement(
 | 
| -    LStoreKeyedSpecializedArrayElement* instr) {
 | 
| +void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
 | 
|    ElementsKind elements_kind = instr->elements_kind();
 | 
|    LOperand* key = instr->key();
 | 
|    if (!key->IsConstantOperand() &&
 | 
| @@ -3828,7 +3836,7 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
 | 
|      __ SmiUntag(ToRegister(key));
 | 
|    }
 | 
|    Operand operand(BuildFastArrayOperand(
 | 
| -      instr->external_pointer(),
 | 
| +      instr->elements(),
 | 
|        key,
 | 
|        instr->hydrogen()->key()->representation(),
 | 
|        elements_kind,
 | 
| @@ -3872,13 +3880,39 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement(
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
 | 
| +void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
 | 
| +  XMMRegister value = ToDoubleRegister(instr->value());
 | 
| +
 | 
| +  if (instr->NeedsCanonicalization()) {
 | 
| +    Label have_value;
 | 
| +
 | 
| +    __ ucomisd(value, value);
 | 
| +    __ j(parity_odd, &have_value);  // NaN.
 | 
| +
 | 
| +    ExternalReference canonical_nan_reference =
 | 
| +        ExternalReference::address_of_canonical_non_hole_nan();
 | 
| +    __ movdbl(value, Operand::StaticVariable(canonical_nan_reference));
 | 
| +    __ bind(&have_value);
 | 
| +  }
 | 
| +
 | 
| +  Operand double_store_operand = BuildFastArrayOperand(
 | 
| +      instr->elements(),
 | 
| +      instr->key(),
 | 
| +      instr->hydrogen()->key()->representation(),
 | 
| +      FAST_DOUBLE_ELEMENTS,
 | 
| +      FixedDoubleArray::kHeaderSize - kHeapObjectTag,
 | 
| +      instr->additional_index());
 | 
| +  __ movdbl(double_store_operand, value);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
 | 
|    Register value = ToRegister(instr->value());
 | 
| -  Register elements = ToRegister(instr->object());
 | 
| +  Register elements = ToRegister(instr->elements());
 | 
|    Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
 | 
|  
 | 
|    Operand operand = BuildFastArrayOperand(
 | 
| -      instr->object(),
 | 
| +      instr->elements(),
 | 
|        instr->key(),
 | 
|        instr->hydrogen()->key()->representation(),
 | 
|        FAST_ELEMENTS,
 | 
| @@ -3903,30 +3937,15 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void LCodeGen::DoStoreKeyedFastDoubleElement(
 | 
| -    LStoreKeyedFastDoubleElement* instr) {
 | 
| -  XMMRegister value = ToDoubleRegister(instr->value());
 | 
| -
 | 
| -  if (instr->NeedsCanonicalization()) {
 | 
| -    Label have_value;
 | 
| -
 | 
| -    __ ucomisd(value, value);
 | 
| -    __ j(parity_odd, &have_value);  // NaN.
 | 
| -
 | 
| -    ExternalReference canonical_nan_reference =
 | 
| -        ExternalReference::address_of_canonical_non_hole_nan();
 | 
| -    __ movdbl(value, Operand::StaticVariable(canonical_nan_reference));
 | 
| -    __ bind(&have_value);
 | 
| +void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
 | 
| +  // By cases...external, fast-double, fast
 | 
| +  if (instr->is_external()) {
 | 
| +    DoStoreKeyedExternalArray(instr);
 | 
| +  } else if (instr->hydrogen()->value()->representation().IsDouble()) {
 | 
| +    DoStoreKeyedFixedDoubleArray(instr);
 | 
| +  } else {
 | 
| +    DoStoreKeyedFixedArray(instr);
 | 
|    }
 | 
| -
 | 
| -  Operand double_store_operand = BuildFastArrayOperand(
 | 
| -      instr->elements(),
 | 
| -      instr->key(),
 | 
| -      instr->hydrogen()->key()->representation(),
 | 
| -      FAST_DOUBLE_ELEMENTS,
 | 
| -      FixedDoubleArray::kHeaderSize - kHeapObjectTag,
 | 
| -      instr->additional_index());
 | 
| -  __ movdbl(double_store_operand, value);
 | 
|  }
 | 
|  
 | 
|  
 | 
| 
 |