Index: src/mips/lithium-codegen-mips.cc |
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc |
index 7ae33429b2bfdcfd067dba531c75f44a0e2ad56e..f79208ea25a9bb27b88468182248ea9f1047e8d1 100644 |
--- a/src/mips/lithium-codegen-mips.cc |
+++ b/src/mips/lithium-codegen-mips.cc |
@@ -2622,50 +2622,89 @@ 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(), scratch); |
- // 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()) { |
- __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
- __ addu(scratch, elements, scratch); |
- } else { |
- __ sll(scratch, key, kPointerSizeLog2); |
- __ addu(scratch, elements, scratch); |
+void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
+ Register external_pointer = ToRegister(instr->elements()); |
+ 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()); |
} |
- __ lw(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())) { |
- __ And(scratch, result, Operand(kSmiTagMask)); |
- DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); |
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
+ elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
+ FPURegister result = ToDoubleRegister(instr->result()); |
+ if (key_is_constant) { |
+ __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); |
} else { |
- __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
- DeoptimizeIf(eq, instr->environment(), result, Operand(scratch)); |
+ __ sll(scratch0(), key, shift_size); |
+ __ Addu(scratch0(), scratch0(), external_pointer); |
+ } |
+ |
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
+ __ lwc1(result, MemOperand(scratch0(), additional_offset)); |
+ __ cvt_d_s(result, result); |
+ } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
+ __ ldc1(result, MemOperand(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: |
+ __ lb(result, mem_operand); |
+ break; |
+ case EXTERNAL_PIXEL_ELEMENTS: |
+ case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
+ __ lbu(result, mem_operand); |
+ break; |
+ case EXTERNAL_SHORT_ELEMENTS: |
+ __ lh(result, mem_operand); |
+ break; |
+ case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
+ __ lhu(result, mem_operand); |
+ break; |
+ case EXTERNAL_INT_ELEMENTS: |
+ __ lw(result, mem_operand); |
+ break; |
+ case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
+ __ lw(result, mem_operand); |
+ if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
+ DeoptimizeIf(Ugreater_equal, instr->environment(), |
+ result, Operand(0x80000000)); |
+ } |
+ break; |
+ case EXTERNAL_FLOAT_ELEMENTS: |
+ case EXTERNAL_DOUBLE_ELEMENTS: |
+ case FAST_DOUBLE_ELEMENTS: |
+ case FAST_ELEMENTS: |
+ case FAST_SMI_ELEMENTS: |
+ case FAST_HOLEY_DOUBLE_ELEMENTS: |
+ case FAST_HOLEY_ELEMENTS: |
+ case FAST_HOLEY_SMI_ELEMENTS: |
+ case DICTIONARY_ELEMENTS: |
+ case NON_STRICT_ARGUMENTS_ELEMENTS: |
+ UNREACHABLE(); |
+ break; |
} |
} |
} |
-void LCodeGen::DoLoadKeyedFastDoubleElement( |
- LLoadKeyedFastDoubleElement* instr) { |
+void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
Register elements = ToRegister(instr->elements()); |
bool key_is_constant = instr->key()->IsConstantOperand(); |
Register key = no_reg; |
@@ -2707,6 +2746,59 @@ void LCodeGen::DoLoadKeyedFastDoubleElement( |
} |
+void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* 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 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()) { |
+ __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
+ __ addu(scratch, elements, scratch); |
+ } else { |
+ __ sll(scratch, key, kPointerSizeLog2); |
+ __ addu(scratch, elements, scratch); |
+ } |
+ offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
+ } |
+ __ lw(result, FieldMemOperand(store_base, offset)); |
+ |
+ // Check for the hole value. |
+ if (instr->hydrogen()->RequiresHoleCheck()) { |
+ if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
+ __ And(scratch, result, Operand(kSmiTagMask)); |
+ DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); |
+ } else { |
+ __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
+ DeoptimizeIf(eq, instr->environment(), result, Operand(scratch)); |
+ } |
+ } |
+} |
+ |
+ |
+void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
+ if (instr->is_external()) { |
+ DoLoadKeyedExternalArray(instr); |
+ } else if (instr->hydrogen()->representation().IsDouble()) { |
+ DoLoadKeyedFixedDoubleArray(instr); |
+ } else { |
+ DoLoadKeyedFixedArray(instr); |
+ } |
+} |
+ |
+ |
MemOperand LCodeGen::PrepareKeyedOperand(Register key, |
Register base, |
bool key_is_constant, |
@@ -2751,89 +2843,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) { |
- FPURegister result = ToDoubleRegister(instr->result()); |
- if (key_is_constant) { |
- __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); |
- } else { |
- __ sll(scratch0(), key, shift_size); |
- __ Addu(scratch0(), scratch0(), external_pointer); |
- } |
- |
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
- __ lwc1(result, MemOperand(scratch0(), additional_offset)); |
- __ cvt_d_s(result, result); |
- } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
- __ ldc1(result, MemOperand(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: |
- __ lb(result, mem_operand); |
- break; |
- case EXTERNAL_PIXEL_ELEMENTS: |
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
- __ lbu(result, mem_operand); |
- break; |
- case EXTERNAL_SHORT_ELEMENTS: |
- __ lh(result, mem_operand); |
- break; |
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
- __ lhu(result, mem_operand); |
- break; |
- case EXTERNAL_INT_ELEMENTS: |
- __ lw(result, mem_operand); |
- break; |
- case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
- __ lw(result, mem_operand); |
- if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
- DeoptimizeIf(Ugreater_equal, instr->environment(), |
- result, Operand(0x80000000)); |
- } |
- break; |
- case EXTERNAL_FLOAT_ELEMENTS: |
- case EXTERNAL_DOUBLE_ELEMENTS: |
- case FAST_DOUBLE_ELEMENTS: |
- case FAST_ELEMENTS: |
- case FAST_SMI_ELEMENTS: |
- case FAST_HOLEY_DOUBLE_ELEMENTS: |
- case FAST_HOLEY_ELEMENTS: |
- case FAST_HOLEY_SMI_ELEMENTS: |
- case DICTIONARY_ELEMENTS: |
- case NON_STRICT_ARGUMENTS_ELEMENTS: |
- UNREACHABLE(); |
- break; |
- } |
- } |
-} |
- |
- |
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
ASSERT(ToRegister(instr->object()).is(a1)); |
ASSERT(ToRegister(instr->key()).is(a0)); |
@@ -3737,108 +3746,8 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
} |
-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()) { |
- __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
- __ addu(scratch, elements, scratch); |
- } else { |
- __ sll(scratch, key, kPointerSizeLog2); |
- __ addu(scratch, elements, scratch); |
- } |
- offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
- } |
- __ sw(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. |
- __ Addu(key, store_base, Operand(offset - kHeapObjectTag)); |
- __ RecordWrite(elements, |
- key, |
- value, |
- kRAHasBeenSaved, |
- kSaveFPRegs, |
- EMIT_REMEMBERED_SET, |
- check_needed); |
- } |
-} |
- |
- |
-void LCodeGen::DoStoreKeyedFastDoubleElement( |
- LStoreKeyedFastDoubleElement* instr) { |
- DoubleRegister 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; |
- Label not_nan; |
- |
- // 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; |
- if (key_is_constant) { |
- __ Addu(scratch, elements, Operand((constant_key << element_size_shift) + |
- FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
- } else { |
- __ sll(scratch, key, shift_size); |
- __ Addu(scratch, elements, Operand(scratch)); |
- __ Addu(scratch, scratch, |
- Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
- } |
- |
- if (instr->NeedsCanonicalization()) { |
- Label is_nan; |
- // Check for NaN. All NaNs must be canonicalized. |
- __ BranchF(NULL, &is_nan, eq, value, value); |
- __ Branch(¬_nan); |
- |
- // Only load canonical NaN if the comparison above set the overflow. |
- __ bind(&is_nan); |
- __ Move(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double()); |
- } |
- |
- __ bind(¬_nan); |
- __ sdc1(value, MemOperand(scratch, instr->additional_index() << |
- element_size_shift)); |
-} |
- |
- |
-void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
- LStoreKeyedSpecializedArrayElement* instr) { |
- |
- Register external_pointer = ToRegister(instr->external_pointer()); |
+void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
+ Register external_pointer = ToRegister(instr->elements()); |
Register key = no_reg; |
ElementsKind elements_kind = instr->elements_kind(); |
bool key_is_constant = instr->key()->IsConstantOperand(); |
@@ -3909,6 +3818,117 @@ void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
} |
} |
+ |
+void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
+ DoubleRegister 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; |
+ Label not_nan; |
+ |
+ // 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; |
+ if (key_is_constant) { |
+ __ Addu(scratch, elements, Operand((constant_key << element_size_shift) + |
+ FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
+ } else { |
+ __ sll(scratch, key, shift_size); |
+ __ Addu(scratch, elements, Operand(scratch)); |
+ __ Addu(scratch, scratch, |
+ Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
+ } |
+ |
+ if (instr->NeedsCanonicalization()) { |
+ Label is_nan; |
+ // Check for NaN. All NaNs must be canonicalized. |
+ __ BranchF(NULL, &is_nan, eq, value, value); |
+ __ Branch(¬_nan); |
+ |
+ // Only load canonical NaN if the comparison above set the overflow. |
+ __ bind(&is_nan); |
+ __ Move(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double()); |
+ } |
+ |
+ __ bind(¬_nan); |
+ __ sdc1(value, MemOperand(scratch, instr->additional_index() << |
+ element_size_shift)); |
+} |
+ |
+ |
+void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
+ Register value = ToRegister(instr->value()); |
+ Register elements = ToRegister(instr->elements()); |
+ 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()) { |
+ __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
+ __ addu(scratch, elements, scratch); |
+ } else { |
+ __ sll(scratch, key, kPointerSizeLog2); |
+ __ addu(scratch, elements, scratch); |
+ } |
+ offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
+ } |
+ __ sw(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. |
+ __ Addu(key, store_base, Operand(offset - kHeapObjectTag)); |
+ __ RecordWrite(elements, |
+ key, |
+ value, |
+ kRAHasBeenSaved, |
+ kSaveFPRegs, |
+ EMIT_REMEMBERED_SET, |
+ check_needed); |
+ } |
+} |
+ |
+ |
+void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
+ // By cases: external, fast double |
+ if (instr->is_external()) { |
+ DoStoreKeyedExternalArray(instr); |
+ } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
+ DoStoreKeyedFixedDoubleArray(instr); |
+ } else { |
+ DoStoreKeyedFixedArray(instr); |
+ } |
+} |
+ |
+ |
void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
ASSERT(ToRegister(instr->object()).is(a2)); |
ASSERT(ToRegister(instr->key()).is(a1)); |