| Index: src/arm/lithium-codegen-arm.cc | 
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc | 
| index 4b045385a40a9bd5eb809510db8825d21393847d..33143b462bffcef4fbcb2f60e0dece22b0a98378 100644 | 
| --- a/src/arm/lithium-codegen-arm.cc | 
| +++ b/src/arm/lithium-codegen-arm.cc | 
| @@ -2482,40 +2482,56 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 
| void LCodeGen::DoLoadKeyedSpecializedArrayElement( | 
| LLoadKeyedSpecializedArrayElement* instr) { | 
| Register external_pointer = ToRegister(instr->external_pointer()); | 
| -  Register key = ToRegister(instr->key()); | 
| +  Register key = no_reg; | 
| ExternalArrayType array_type = instr->array_type(); | 
| -  if (array_type == kExternalFloatArray) { | 
| -    CpuFeatures::Scope scope(VFP3); | 
| -    DwVfpRegister result(ToDoubleRegister(instr->result())); | 
| -    __ add(scratch0(), external_pointer, Operand(key, LSL, 2)); | 
| -    __ vldr(result.low(), scratch0(), 0); | 
| -    __ vcvt_f64_f32(result, result.low()); | 
| -  } else if (array_type == kExternalDoubleArray) { | 
| +  bool key_is_constant = instr->key()->IsConstantOperand(); | 
| +  int constant_key = 0; | 
| +  if (key_is_constant) { | 
| +    constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 
| +    if (constant_key & 0xF0000000) { | 
| +      Abort("array index constant value too big."); | 
| +    } | 
| +  } else { | 
| +    key = ToRegister(instr->key()); | 
| +  } | 
| +  int shift_size = ExternalArrayTypeToShiftSize(array_type); | 
| + | 
| +  if (array_type == kExternalFloatArray || array_type == kExternalDoubleArray) { | 
| CpuFeatures::Scope scope(VFP3); | 
| DwVfpRegister result(ToDoubleRegister(instr->result())); | 
| -    __ add(scratch0(), external_pointer, Operand(key, LSL, 3)); | 
| -    __ vldr(result, scratch0(), 0); | 
| +    Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size)) | 
| +                                    : Operand(key, LSL, shift_size)); | 
| +    __ add(scratch0(), external_pointer, operand); | 
| +    if (array_type == kExternalFloatArray) { | 
| +      __ vldr(result.low(), scratch0(), 0); | 
| +      __ vcvt_f64_f32(result, result.low()); | 
| +    } else  {  // i.e. array_type == kExternalDoubleArray | 
| +      __ vldr(result, scratch0(), 0); | 
| +    } | 
| } else { | 
| Register result(ToRegister(instr->result())); | 
| +    MemOperand mem_operand(key_is_constant | 
| +        ? MemOperand(external_pointer, constant_key * (1 << shift_size)) | 
| +        : MemOperand(external_pointer, key, LSL, shift_size)); | 
| switch (array_type) { | 
| case kExternalByteArray: | 
| -        __ ldrsb(result, MemOperand(external_pointer, key)); | 
| +        __ ldrsb(result, mem_operand); | 
| break; | 
| case kExternalUnsignedByteArray: | 
| case kExternalPixelArray: | 
| -        __ ldrb(result, MemOperand(external_pointer, key)); | 
| +        __ ldrb(result, mem_operand); | 
| break; | 
| case kExternalShortArray: | 
| -        __ ldrsh(result, MemOperand(external_pointer, key, LSL, 1)); | 
| +        __ ldrsh(result, mem_operand); | 
| break; | 
| case kExternalUnsignedShortArray: | 
| -        __ ldrh(result, MemOperand(external_pointer, key, LSL, 1)); | 
| +        __ ldrh(result, mem_operand); | 
| break; | 
| case kExternalIntArray: | 
| -        __ ldr(result, MemOperand(external_pointer, key, LSL, 2)); | 
| +        __ ldr(result, mem_operand); | 
| break; | 
| case kExternalUnsignedIntArray: | 
| -        __ ldr(result, MemOperand(external_pointer, key, LSL, 2)); | 
| +        __ ldr(result, mem_operand); | 
| __ cmp(result, Operand(0x80000000)); | 
| // TODO(danno): we could be more clever here, perhaps having a special | 
| // version of the stub that detects if the overflow case actually | 
| @@ -3245,39 +3261,53 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement( | 
| LStoreKeyedSpecializedArrayElement* instr) { | 
|  | 
| Register external_pointer = ToRegister(instr->external_pointer()); | 
| -  Register key = ToRegister(instr->key()); | 
| +  Register key = no_reg; | 
| ExternalArrayType array_type = instr->array_type(); | 
| +  bool key_is_constant = instr->key()->IsConstantOperand(); | 
| +  int constant_key = 0; | 
| +  if (key_is_constant) { | 
| +    constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 
| +    if (constant_key & 0xF0000000) { | 
| +      Abort("array index constant value too big."); | 
| +    } | 
| +  } else { | 
| +    key = ToRegister(instr->key()); | 
| +  } | 
| +  int shift_size = ExternalArrayTypeToShiftSize(array_type); | 
|  | 
| -  if (array_type == kExternalFloatArray) { | 
| +  if (array_type == kExternalFloatArray || array_type == kExternalDoubleArray) { | 
| CpuFeatures::Scope scope(VFP3); | 
| DwVfpRegister value(ToDoubleRegister(instr->value())); | 
| -    __ add(scratch0(), external_pointer, Operand(key, LSL, 2)); | 
| -    __ vcvt_f32_f64(double_scratch0().low(), value); | 
| -    __ vstr(double_scratch0().low(), scratch0(), 0); | 
| -  } else if (array_type == kExternalDoubleArray) { | 
| -    CpuFeatures::Scope scope(VFP3); | 
| -    DwVfpRegister value(ToDoubleRegister(instr->value())); | 
| -    __ add(scratch0(), external_pointer, Operand(key, LSL, 3)); | 
| -    __ vstr(value, scratch0(), 0); | 
| +    Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size)) | 
| +                                    : Operand(key, LSL, shift_size)); | 
| +    __ add(scratch0(), external_pointer, operand); | 
| +    if (array_type == kExternalFloatArray) { | 
| +      __ vcvt_f32_f64(double_scratch0().low(), value); | 
| +      __ vstr(double_scratch0().low(), scratch0(), 0); | 
| +    } else {  // i.e. array_type == kExternalDoubleArray | 
| +      __ vstr(value, scratch0(), 0); | 
| +    } | 
| } else { | 
| Register value(ToRegister(instr->value())); | 
| +    MemOperand mem_operand(key_is_constant | 
| +        ? MemOperand(external_pointer, constant_key * (1 << shift_size)) | 
| +        : MemOperand(external_pointer, key, LSL, shift_size)); | 
| switch (array_type) { | 
| case kExternalPixelArray: | 
| // Clamp the value to [0..255]. | 
| __ Usat(value, 8, Operand(value)); | 
| -        __ strb(value, MemOperand(external_pointer, key)); | 
| -        break; | 
| +        // Fall through to the next case for the store instruction: | 
| case kExternalByteArray: | 
| case kExternalUnsignedByteArray: | 
| -        __ strb(value, MemOperand(external_pointer, key)); | 
| +        __ strb(value, mem_operand); | 
| break; | 
| case kExternalShortArray: | 
| case kExternalUnsignedShortArray: | 
| -        __ strh(value, MemOperand(external_pointer, key, LSL, 1)); | 
| +        __ strh(value, mem_operand); | 
| break; | 
| case kExternalIntArray: | 
| case kExternalUnsignedIntArray: | 
| -        __ str(value, MemOperand(external_pointer, key, LSL, 2)); | 
| +        __ str(value, mem_operand); | 
| break; | 
| case kExternalFloatArray: | 
| case kExternalDoubleArray: | 
|  |