| 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:
|
|
|