Index: src/arm64/lithium-codegen-arm64.cc |
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc |
index dce5a1a0cde89999c4d8aa492368bfdb1dde81ab..3b5aabfdf5e0776cf16c721f48242b4529663d55 100644 |
--- a/src/arm64/lithium-codegen-arm64.cc |
+++ b/src/arm64/lithium-codegen-arm64.cc |
@@ -3427,24 +3427,43 @@ void LCodeGen::DoLoadKeyedExternal(LLoadKeyedExternal* instr) { |
} |
-void LCodeGen::CalcKeyedArrayBaseRegister(Register base, |
- Register elements, |
- Register key, |
- bool key_is_tagged, |
- ElementsKind elements_kind) { |
+MemOperand LCodeGen::PrepareKeyedArrayOperand(Register base, |
+ Register elements, |
+ Register key, |
+ bool key_is_tagged, |
+ ElementsKind elements_kind, |
+ Representation representation, |
+ int additional_index) { |
+ STATIC_ASSERT((kSmiValueSize == 32) && (kSmiShift == 32) && (kSmiTag == 0)); |
int element_size_shift = ElementsKindToShiftSize(elements_kind); |
+ // Read or write only the most-significant 32 bits in the case of fast smi |
+ // arrays with integer inputs/outputs. |
+ bool int32_and_fast_smi = representation.IsInteger32() && |
ulan
2014/05/05 08:21:21
representation.IsInteger32() should imply (instr->
m.m.capewell
2014/05/06 13:20:45
Done.
|
+ (elements_kind == FAST_SMI_ELEMENTS); |
+ |
// Even though the HLoad/StoreKeyed instructions force the input |
// representation for the key to be an integer, the input gets replaced during |
// bounds check elimination with the index argument to the bounds check, which |
// can be tagged, so that case must be handled here, too. |
if (key_is_tagged) { |
__ Add(base, elements, Operand::UntagSmiAndScale(key, element_size_shift)); |
+ if (int32_and_fast_smi) { |
+ return UntagSmiFieldMemOperand(base, additional_index); |
+ } else { |
+ return FieldMemOperand(base, additional_index); |
+ } |
} else { |
// Sign extend key because it could be a 32-bit negative value or contain |
// garbage in the top 32-bits. The address computation happens in 64-bit. |
ASSERT((element_size_shift >= 0) && (element_size_shift <= 4)); |
- __ Add(base, elements, Operand(key, SXTW, element_size_shift)); |
+ if (int32_and_fast_smi) { |
+ __ Add(base, elements, Operand(key, SXTW, element_size_shift)); |
+ return UntagSmiFieldMemOperand(base, additional_index); |
+ } else { |
+ __ Add(base, elements, additional_index - kHeapObjectTag); |
+ return MemOperand(base, key, SXTW, element_size_shift); |
+ } |
} |
} |
@@ -3452,8 +3471,7 @@ void LCodeGen::CalcKeyedArrayBaseRegister(Register base, |
void LCodeGen::DoLoadKeyedFixedDouble(LLoadKeyedFixedDouble* instr) { |
Register elements = ToRegister(instr->elements()); |
DoubleRegister result = ToDoubleRegister(instr->result()); |
- Register load_base; |
- int offset = 0; |
+ MemOperand mem_op; |
if (instr->key()->IsConstantOperand()) { |
ASSERT(instr->hydrogen()->RequiresHoleCheck() || |
@@ -3463,27 +3481,30 @@ void LCodeGen::DoLoadKeyedFixedDouble(LLoadKeyedFixedDouble* instr) { |
if (constant_key & 0xf0000000) { |
Abort(kArrayIndexConstantValueTooBig); |
} |
- offset = FixedDoubleArray::OffsetOfElementAt(constant_key + |
- instr->additional_index()); |
- load_base = elements; |
+ int offset = FixedDoubleArray::OffsetOfElementAt(constant_key + |
+ instr->additional_index()); |
+ mem_op = FieldMemOperand(elements, offset); |
} else { |
- load_base = ToRegister(instr->temp()); |
+ Register load_base = ToRegister(instr->temp()); |
Register key = ToRegister(instr->key()); |
bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); |
- CalcKeyedArrayBaseRegister(load_base, elements, key, key_is_tagged, |
- instr->hydrogen()->elements_kind()); |
- offset = FixedDoubleArray::OffsetOfElementAt(instr->additional_index()); |
+ int offset = FixedDoubleArray::OffsetOfElementAt(instr->additional_index()); |
+ mem_op = PrepareKeyedArrayOperand(load_base, elements, key, key_is_tagged, |
+ instr->hydrogen()->elements_kind(), |
+ instr->hydrogen()->representation(), |
+ offset); |
} |
- __ Ldr(result, FieldMemOperand(load_base, offset)); |
+ |
+ __ Ldr(result, mem_op); |
if (instr->hydrogen()->RequiresHoleCheck()) { |
Register scratch = ToRegister(instr->temp()); |
- |
- // TODO(all): Is it faster to reload this value to an integer register, or |
- // move from fp to integer? |
- __ Fmov(scratch, result); |
- __ Cmp(scratch, kHoleNanInt64); |
- DeoptimizeIf(eq, instr->environment()); |
+ // Detect the hole NaN by adding one to the integer representation of the |
+ // result, and checking for overflow. |
+ STATIC_ASSERT(kHoleNanInt64 == 0x7fffffffffffffff); |
+ __ Ldr(scratch, mem_op); |
+ __ Cmn(scratch, 1); |
+ DeoptimizeIf(vs, instr->environment()); |
} |
} |
@@ -3491,35 +3512,35 @@ void LCodeGen::DoLoadKeyedFixedDouble(LLoadKeyedFixedDouble* instr) { |
void LCodeGen::DoLoadKeyedFixed(LLoadKeyedFixed* instr) { |
Register elements = ToRegister(instr->elements()); |
Register result = ToRegister(instr->result()); |
- Register load_base; |
- int offset = 0; |
+ MemOperand mem_op; |
+ Representation representation = instr->hydrogen()->representation(); |
if (instr->key()->IsConstantOperand()) { |
ASSERT(instr->temp() == NULL); |
LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
- offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
- instr->additional_index()); |
- load_base = elements; |
+ int offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
+ instr->additional_index()); |
+ if (representation.IsInteger32() && |
ulan
2014/05/05 08:21:21
representation.IsInteger32() should imply (instr->
m.m.capewell
2014/05/06 13:20:45
Done.
|
+ (instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS)) { |
+ STATIC_ASSERT((kSmiValueSize == 32) && (kSmiShift == 32) && |
+ (kSmiTag == 0)); |
+ mem_op = UntagSmiFieldMemOperand(elements, offset); |
+ } else { |
+ mem_op = FieldMemOperand(elements, offset); |
+ } |
} else { |
- load_base = ToRegister(instr->temp()); |
+ Register load_base = ToRegister(instr->temp()); |
Register key = ToRegister(instr->key()); |
bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); |
- CalcKeyedArrayBaseRegister(load_base, elements, key, key_is_tagged, |
- instr->hydrogen()->elements_kind()); |
- offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
- } |
- Representation representation = instr->hydrogen()->representation(); |
+ int offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
- if (representation.IsInteger32() && |
- instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS) { |
- STATIC_ASSERT(kSmiValueSize == 32 && kSmiShift == 32 && kSmiTag == 0); |
- __ Load(result, UntagSmiFieldMemOperand(load_base, offset), |
- Representation::Integer32()); |
- } else { |
- __ Load(result, FieldMemOperand(load_base, offset), |
- representation); |
+ mem_op = PrepareKeyedArrayOperand(load_base, elements, key, key_is_tagged, |
+ instr->hydrogen()->elements_kind(), |
+ representation, offset); |
} |
+ __ Load(result, mem_op, representation); |
+ |
if (instr->hydrogen()->RequiresHoleCheck()) { |
if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
DeoptimizeIfNotSmi(result, instr->environment()); |
@@ -5114,24 +5135,25 @@ void LCodeGen::DoStoreKeyedExternal(LStoreKeyedExternal* instr) { |
void LCodeGen::DoStoreKeyedFixedDouble(LStoreKeyedFixedDouble* instr) { |
Register elements = ToRegister(instr->elements()); |
DoubleRegister value = ToDoubleRegister(instr->value()); |
- Register store_base = no_reg; |
- int offset = 0; |
+ MemOperand mem_op; |
if (instr->key()->IsConstantOperand()) { |
int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
if (constant_key & 0xf0000000) { |
Abort(kArrayIndexConstantValueTooBig); |
} |
- offset = FixedDoubleArray::OffsetOfElementAt(constant_key + |
- instr->additional_index()); |
- store_base = elements; |
+ int offset = FixedDoubleArray::OffsetOfElementAt(constant_key + |
+ instr->additional_index()); |
+ mem_op = FieldMemOperand(elements, offset); |
} else { |
- store_base = ToRegister(instr->temp()); |
+ Register store_base = ToRegister(instr->temp()); |
Register key = ToRegister(instr->key()); |
bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); |
- CalcKeyedArrayBaseRegister(store_base, elements, key, key_is_tagged, |
- instr->hydrogen()->elements_kind()); |
- offset = FixedDoubleArray::OffsetOfElementAt(instr->additional_index()); |
+ int offset = FixedDoubleArray::OffsetOfElementAt(instr->additional_index()); |
+ mem_op = PrepareKeyedArrayOperand(store_base, elements, key, key_is_tagged, |
+ instr->hydrogen()->elements_kind(), |
+ instr->hydrogen()->representation(), |
+ offset); |
} |
if (instr->NeedsCanonicalization()) { |
@@ -5139,9 +5161,9 @@ void LCodeGen::DoStoreKeyedFixedDouble(LStoreKeyedFixedDouble* instr) { |
__ Fmov(dbl_scratch, |
FixedDoubleArray::canonical_not_the_hole_nan_as_double()); |
__ Fmaxnm(dbl_scratch, dbl_scratch, value); |
- __ Str(dbl_scratch, FieldMemOperand(store_base, offset)); |
+ __ Str(dbl_scratch, mem_op); |
} else { |
- __ Str(value, FieldMemOperand(store_base, offset)); |
+ __ Str(value, mem_op); |
} |
} |
@@ -5152,37 +5174,40 @@ void LCodeGen::DoStoreKeyedFixed(LStoreKeyedFixed* instr) { |
Register scratch = no_reg; |
Register store_base = no_reg; |
Register key = no_reg; |
- int offset = 0; |
+ MemOperand mem_op; |
if (!instr->key()->IsConstantOperand() || |
instr->hydrogen()->NeedsWriteBarrier()) { |
scratch = ToRegister(instr->temp()); |
} |
+ Representation representation = instr->hydrogen()->value()->representation(); |
if (instr->key()->IsConstantOperand()) { |
LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
- offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
- instr->additional_index()); |
+ int offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
+ instr->additional_index()); |
store_base = elements; |
+ if (representation.IsInteger32() && |
+ (instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS)) { |
ulan
2014/05/05 08:21:21
representation.IsInteger32() should imply (instr->
m.m.capewell
2014/05/06 13:20:45
Done.
|
+ STATIC_ASSERT((kSmiValueSize == 32) && (kSmiShift == 32) && |
+ (kSmiTag == 0)); |
+ mem_op = UntagSmiFieldMemOperand(store_base, offset); |
+ } else { |
+ mem_op = FieldMemOperand(store_base, offset); |
+ } |
} else { |
store_base = scratch; |
key = ToRegister(instr->key()); |
bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); |
- CalcKeyedArrayBaseRegister(store_base, elements, key, key_is_tagged, |
- instr->hydrogen()->elements_kind()); |
- offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
- } |
- Representation representation = instr->hydrogen()->value()->representation(); |
- if (representation.IsInteger32()) { |
- ASSERT(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
- ASSERT(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS); |
ulan
2014/05/05 08:21:21
Can we keep these two asserts?
m.m.capewell
2014/05/06 13:20:45
Done.
|
- STATIC_ASSERT(kSmiValueSize == 32 && kSmiShift == 32 && kSmiTag == 0); |
- __ Store(value, UntagSmiFieldMemOperand(store_base, offset), |
- Representation::Integer32()); |
- } else { |
- __ Store(value, FieldMemOperand(store_base, offset), representation); |
+ int offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
+ |
+ mem_op = PrepareKeyedArrayOperand(store_base, elements, key, key_is_tagged, |
+ instr->hydrogen()->elements_kind(), |
+ representation, offset); |
} |
+ __ Store(value, mem_op, representation); |
+ |
if (instr->hydrogen()->NeedsWriteBarrier()) { |
ASSERT(representation.IsTagged()); |
// This assignment may cause element_addr to alias store_base. |
@@ -5191,7 +5216,7 @@ void LCodeGen::DoStoreKeyedFixed(LStoreKeyedFixed* instr) { |
instr->hydrogen()->value()->IsHeapObject() |
? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
// Compute address of modified element and store it into key register. |
- __ Add(element_addr, store_base, offset - kHeapObjectTag); |
+ __ Add(element_addr, store_base, mem_op.OffsetAsOperand()); |
ulan
2014/05/05 08:21:21
Using mem_op.base() instead of store_base would be
m.m.capewell
2014/05/06 13:20:45
Done.
|
__ RecordWrite(elements, element_addr, value, GetLinkRegisterState(), |
kSaveFPRegs, EMIT_REMEMBERED_SET, check_needed); |
} |