Chromium Code Reviews| Index: src/arm/lithium-codegen-arm.cc |
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc |
| index 6f5aa436a85b49913e437b78ffdc31c8d2c0c07a..88cde4d1f6b068d5349e5e4a6e8b3bf6b195686d 100644 |
| --- a/src/arm/lithium-codegen-arm.cc |
| +++ b/src/arm/lithium-codegen-arm.cc |
| @@ -2918,51 +2918,88 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| } |
| -void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
| - Register elements = ToRegister(instr->elements()); |
| - Register result = ToRegister(instr->result()); |
| - Register scratch = scratch0(); |
| - Register store_base = scratch; |
| - int offset = 0; |
| - |
| - if (instr->key()->IsConstantOperand()) { |
| - LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| - offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| - instr->additional_index()); |
| - store_base = elements; |
| - } else { |
| - Register key = EmitLoadRegister(instr->key(), scratch0()); |
| - // Even though the HLoadKeyedFastElement instruction forces 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. |
| - if (instr->hydrogen()->key()->representation().IsTagged()) { |
| - __ add(scratch, elements, |
| - Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| - } else { |
| - __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
| +void LCodeGen::DoLoadKeyedExternal(LLoadKeyed* instr) { |
| + Register external_pointer = ToRegister(instr->object()); |
| + Register key = no_reg; |
| + ElementsKind elements_kind = instr->elements_kind(); |
| + 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."); |
| } |
| - offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
| + } else { |
| + key = ToRegister(instr->key()); |
| } |
| - __ ldr(result, FieldMemOperand(store_base, offset)); |
| + int element_size_shift = ElementsKindToShiftSize(elements_kind); |
| + int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| + ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| + int additional_offset = instr->additional_index() << element_size_shift; |
| - // Check for the hole value. |
| - if (instr->hydrogen()->RequiresHoleCheck()) { |
| - if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
| - __ tst(result, Operand(kSmiTagMask)); |
| - DeoptimizeIf(ne, instr->environment()); |
| - } else { |
| - __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| - __ cmp(result, scratch); |
| - DeoptimizeIf(eq, instr->environment()); |
| + if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
| + elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| + CpuFeatures::Scope scope(VFP3); |
| + DwVfpRegister result = ToDoubleRegister(instr->result()); |
| + Operand operand = key_is_constant |
| + ? Operand(constant_key << element_size_shift) |
| + : Operand(key, LSL, shift_size); |
| + __ add(scratch0(), external_pointer, operand); |
| + if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
| + __ vldr(result.low(), scratch0(), additional_offset); |
| + __ vcvt_f64_f32(result, result.low()); |
| + } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
| + __ vldr(result, scratch0(), additional_offset); |
| + } |
| + } else { |
| + Register result = ToRegister(instr->result()); |
| + MemOperand mem_operand = PrepareKeyedOperand( |
| + key, external_pointer, key_is_constant, constant_key, |
| + element_size_shift, shift_size, |
| + instr->additional_index(), additional_offset); |
| + switch (elements_kind) { |
| + case EXTERNAL_BYTE_ELEMENTS: |
| + __ ldrsb(result, mem_operand); |
| + break; |
| + case EXTERNAL_PIXEL_ELEMENTS: |
| + case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| + __ ldrb(result, mem_operand); |
| + break; |
| + case EXTERNAL_SHORT_ELEMENTS: |
| + __ ldrsh(result, mem_operand); |
| + break; |
| + case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| + __ ldrh(result, mem_operand); |
| + break; |
| + case EXTERNAL_INT_ELEMENTS: |
| + __ ldr(result, mem_operand); |
| + break; |
| + case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| + __ ldr(result, mem_operand); |
| + if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| + __ cmp(result, Operand(0x80000000)); |
| + DeoptimizeIf(cs, instr->environment()); |
| + } |
| + break; |
| + case EXTERNAL_FLOAT_ELEMENTS: |
| + case EXTERNAL_DOUBLE_ELEMENTS: |
| + case FAST_HOLEY_DOUBLE_ELEMENTS: |
| + case FAST_HOLEY_ELEMENTS: |
| + case FAST_HOLEY_SMI_ELEMENTS: |
| + case FAST_DOUBLE_ELEMENTS: |
| + case FAST_ELEMENTS: |
| + case FAST_SMI_ELEMENTS: |
| + case DICTIONARY_ELEMENTS: |
| + case NON_STRICT_ARGUMENTS_ELEMENTS: |
| + UNREACHABLE(); |
| + break; |
| } |
| } |
| } |
| -void LCodeGen::DoLoadKeyedFastDoubleElement( |
| - LLoadKeyedFastDoubleElement* instr) { |
| - Register elements = ToRegister(instr->elements()); |
| +void LCodeGen::DoLoadKeyedDouble(LLoadKeyed* instr) { |
|
danno
2012/10/24 11:42:43
nit: Just to make searches easier, maybe call this
mvstanton
2012/10/24 18:24:21
Done.
|
| + Register elements = ToRegister(instr->object()); |
| bool key_is_constant = instr->key()->IsConstantOperand(); |
| Register key = no_reg; |
| DwVfpRegister result = ToDoubleRegister(instr->result()); |
| @@ -3003,6 +3040,59 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( |
| } |
| +void LCodeGen::DoLoadKeyedFixed(LLoadKeyed* instr) { |
| + Register elements = ToRegister(instr->object()); |
| + Register result = ToRegister(instr->result()); |
| + Register scratch = scratch0(); |
| + Register store_base = scratch; |
| + int offset = 0; |
| + |
| + if (instr->key()->IsConstantOperand()) { |
| + LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| + offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| + instr->additional_index()); |
| + store_base = elements; |
| + } else { |
| + Register key = EmitLoadRegister(instr->key(), scratch0()); |
| + // Even though the HLoadKeyed instruction forces 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. |
| + if (instr->hydrogen()->key()->representation().IsTagged()) { |
| + __ add(scratch, elements, |
| + Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| + } else { |
| + __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
| + } |
| + offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
| + } |
| + __ ldr(result, FieldMemOperand(store_base, offset)); |
| + |
| + // Check for the hole value. |
| + if (instr->hydrogen()->RequiresHoleCheck()) { |
| + if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
| + __ tst(result, Operand(kSmiTagMask)); |
| + DeoptimizeIf(ne, instr->environment()); |
| + } else { |
| + __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| + __ cmp(result, scratch); |
| + DeoptimizeIf(eq, instr->environment()); |
| + } |
| + } |
| +} |
| + |
| + |
| +void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| + if (instr->is_external()) { |
| + DoLoadKeyedExternal(instr); |
| + } else if (instr->hydrogen()->representation().IsDouble()) { |
| + DoLoadKeyedDouble(instr); |
| + } else { |
| + DoLoadKeyedFixed(instr); |
| + } |
| +} |
| + |
| + |
| MemOperand LCodeGen::PrepareKeyedOperand(Register key, |
| Register base, |
| bool key_is_constant, |
| @@ -3039,87 +3129,6 @@ MemOperand LCodeGen::PrepareKeyedOperand(Register key, |
| } |
| -void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
| - LLoadKeyedSpecializedArrayElement* instr) { |
| - Register external_pointer = ToRegister(instr->external_pointer()); |
| - Register key = no_reg; |
| - ElementsKind elements_kind = instr->elements_kind(); |
| - 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 element_size_shift = ElementsKindToShiftSize(elements_kind); |
| - int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| - ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| - int additional_offset = instr->additional_index() << element_size_shift; |
| - |
| - if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
| - elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| - CpuFeatures::Scope scope(VFP3); |
| - DwVfpRegister result = ToDoubleRegister(instr->result()); |
| - Operand operand = key_is_constant |
| - ? Operand(constant_key << element_size_shift) |
| - : Operand(key, LSL, shift_size); |
| - __ add(scratch0(), external_pointer, operand); |
| - if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
| - __ vldr(result.low(), scratch0(), additional_offset); |
| - __ vcvt_f64_f32(result, result.low()); |
| - } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
| - __ vldr(result, scratch0(), additional_offset); |
| - } |
| - } else { |
| - Register result = ToRegister(instr->result()); |
| - MemOperand mem_operand = PrepareKeyedOperand( |
| - key, external_pointer, key_is_constant, constant_key, |
| - element_size_shift, shift_size, |
| - instr->additional_index(), additional_offset); |
| - switch (elements_kind) { |
| - case EXTERNAL_BYTE_ELEMENTS: |
| - __ ldrsb(result, mem_operand); |
| - break; |
| - case EXTERNAL_PIXEL_ELEMENTS: |
| - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| - __ ldrb(result, mem_operand); |
| - break; |
| - case EXTERNAL_SHORT_ELEMENTS: |
| - __ ldrsh(result, mem_operand); |
| - break; |
| - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| - __ ldrh(result, mem_operand); |
| - break; |
| - case EXTERNAL_INT_ELEMENTS: |
| - __ ldr(result, mem_operand); |
| - break; |
| - case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| - __ ldr(result, mem_operand); |
| - if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| - __ cmp(result, Operand(0x80000000)); |
| - DeoptimizeIf(cs, instr->environment()); |
| - } |
| - break; |
| - case EXTERNAL_FLOAT_ELEMENTS: |
| - case EXTERNAL_DOUBLE_ELEMENTS: |
| - case FAST_HOLEY_DOUBLE_ELEMENTS: |
| - case FAST_HOLEY_ELEMENTS: |
| - case FAST_HOLEY_SMI_ELEMENTS: |
| - case FAST_DOUBLE_ELEMENTS: |
| - case FAST_ELEMENTS: |
| - case FAST_SMI_ELEMENTS: |
| - case DICTIONARY_ELEMENTS: |
| - case NON_STRICT_ARGUMENTS_ELEMENTS: |
| - UNREACHABLE(); |
| - break; |
| - } |
| - } |
| -} |
| - |
| - |
| void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| ASSERT(ToRegister(instr->object()).is(r1)); |
| ASSERT(ToRegister(instr->key()).is(r0)); |
| @@ -3999,103 +4008,8 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| DeoptimizeIf(hs, instr->environment()); |
| } |
| - |
| -void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
| - Register value = ToRegister(instr->value()); |
| - Register elements = ToRegister(instr->object()); |
| - Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; |
| - Register scratch = scratch0(); |
| - Register store_base = scratch; |
| - int offset = 0; |
| - |
| - // Do the store. |
| - if (instr->key()->IsConstantOperand()) { |
| - ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| - LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| - offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| - instr->additional_index()); |
| - store_base = elements; |
| - } else { |
| - // Even though the HLoadKeyedFastElement instruction forces 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. |
| - if (instr->hydrogen()->key()->representation().IsTagged()) { |
| - __ add(scratch, elements, |
| - Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| - } else { |
| - __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
| - } |
| - offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
| - } |
| - __ str(value, FieldMemOperand(store_base, offset)); |
| - |
| - if (instr->hydrogen()->NeedsWriteBarrier()) { |
| - HType type = instr->hydrogen()->value()->type(); |
| - SmiCheck check_needed = |
| - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| - // Compute address of modified element and store it into key register. |
| - __ add(key, store_base, Operand(offset - kHeapObjectTag)); |
| - __ RecordWrite(elements, |
| - key, |
| - value, |
| - kLRHasBeenSaved, |
| - kSaveFPRegs, |
| - EMIT_REMEMBERED_SET, |
| - check_needed); |
| - } |
| -} |
| - |
| - |
| -void LCodeGen::DoStoreKeyedFastDoubleElement( |
| - LStoreKeyedFastDoubleElement* instr) { |
| - DwVfpRegister value = ToDoubleRegister(instr->value()); |
| - Register elements = ToRegister(instr->elements()); |
| - Register key = no_reg; |
| - Register scratch = scratch0(); |
| - bool key_is_constant = instr->key()->IsConstantOperand(); |
| - int constant_key = 0; |
| - |
| - // Calculate the effective address of the slot in the array to store the |
| - // double value. |
| - 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 element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
| - int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| - ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| - Operand operand = key_is_constant |
| - ? Operand((constant_key << element_size_shift) + |
| - FixedDoubleArray::kHeaderSize - kHeapObjectTag) |
| - : Operand(key, LSL, shift_size); |
| - __ add(scratch, elements, operand); |
| - if (!key_is_constant) { |
| - __ add(scratch, scratch, |
| - Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| - } |
| - |
| - if (instr->NeedsCanonicalization()) { |
| - // Check for NaN. All NaNs must be canonicalized. |
| - __ VFPCompareAndSetFlags(value, value); |
| - // Only load canonical NaN if the comparison above set the overflow. |
| - __ Vmov(value, |
| - FixedDoubleArray::canonical_not_the_hole_nan_as_double(), |
| - no_reg, vs); |
| - } |
| - |
| - __ vstr(value, scratch, instr->additional_index() << element_size_shift); |
| -} |
| - |
| - |
| -void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
| - LStoreKeyedSpecializedArrayElement* instr) { |
| - |
| - Register external_pointer = ToRegister(instr->external_pointer()); |
| +void LCodeGen::DoStoreKeyedExternal(LStoreKeyed* instr) { |
| + Register external_pointer = ToRegister(instr->object()); |
| Register key = no_reg; |
| ElementsKind elements_kind = instr->elements_kind(); |
| bool key_is_constant = instr->key()->IsConstantOperand(); |
| @@ -4164,6 +4078,111 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
| } |
| +void LCodeGen::DoStoreKeyedDouble(LStoreKeyed* instr) { |
| + DwVfpRegister value = ToDoubleRegister(instr->value()); |
| + Register elements = ToRegister(instr->object()); |
| + Register key = no_reg; |
| + Register scratch = scratch0(); |
| + bool key_is_constant = instr->key()->IsConstantOperand(); |
| + int constant_key = 0; |
| + |
| + // Calculate the effective address of the slot in the array to store the |
| + // double value. |
| + 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 element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
| + int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| + ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| + Operand operand = key_is_constant |
| + ? Operand((constant_key << element_size_shift) + |
| + FixedDoubleArray::kHeaderSize - kHeapObjectTag) |
| + : Operand(key, LSL, shift_size); |
| + __ add(scratch, elements, operand); |
| + if (!key_is_constant) { |
| + __ add(scratch, scratch, |
| + Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| + } |
| + |
| + if (instr->NeedsCanonicalization()) { |
| + // Check for NaN. All NaNs must be canonicalized. |
| + __ VFPCompareAndSetFlags(value, value); |
| + // Only load canonical NaN if the comparison above set the overflow. |
| + __ Vmov(value, |
| + FixedDoubleArray::canonical_not_the_hole_nan_as_double(), |
| + no_reg, vs); |
| + } |
| + |
| + __ vstr(value, scratch, instr->additional_index() << element_size_shift); |
| +} |
| + |
| + |
| +void LCodeGen::DoStoreKeyedFixed(LStoreKeyed* instr) { |
| + Register value = ToRegister(instr->value()); |
| + Register elements = ToRegister(instr->object()); |
| + Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) |
| + : no_reg; |
| + Register scratch = scratch0(); |
| + Register store_base = scratch; |
| + int offset = 0; |
| + |
| + // Do the store. |
| + if (instr->key()->IsConstantOperand()) { |
| + ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| + LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| + offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| + instr->additional_index()); |
| + store_base = elements; |
| + } else { |
| + // Even though the HLoadKeyed instruction forces 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. |
| + if (instr->hydrogen()->key()->representation().IsTagged()) { |
| + __ add(scratch, elements, |
| + Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| + } else { |
| + __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
| + } |
| + offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
| + } |
| + __ str(value, FieldMemOperand(store_base, offset)); |
| + |
| + if (instr->hydrogen()->NeedsWriteBarrier()) { |
| + HType type = instr->hydrogen()->value()->type(); |
| + SmiCheck check_needed = |
| + type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| + // Compute address of modified element and store it into key register. |
| + __ add(key, store_base, Operand(offset - kHeapObjectTag)); |
| + __ RecordWrite(elements, |
| + key, |
| + value, |
| + kLRHasBeenSaved, |
| + kSaveFPRegs, |
| + EMIT_REMEMBERED_SET, |
| + check_needed); |
| + } |
| +} |
| + |
| + |
| + |
| +void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
| + // By cases: external, fast double |
| + if (instr->is_external()) { |
| + DoStoreKeyedExternal(instr); |
| + } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
| + DoStoreKeyedDouble(instr); |
| + } else { |
| + DoStoreKeyedFixed(instr); |
| + } |
| +} |
| + |
| + |
| void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| ASSERT(ToRegister(instr->object()).is(r2)); |
| ASSERT(ToRegister(instr->key()).is(r1)); |