MIPS: Consolidated all the key store/load classes in the Hydrogen and Lithium space into just two: HLoadKeyed/HLoadKeyedGeneric and HStoreKeyed/HStoreKeyedGeneric LLoadKeyed/LLoadKeyedGeneric and LStoreKeyed/LStoreKeyedGeneric
Port r12839 (b8b7faa3) BUG= TEST= Review URL: https://codereview.chromium.org/11369110 Patch from palfia <palfia@homejinni.com>. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12876 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e405ff84b4
commit
85ac311a6e
@ -2622,138 +2622,8 @@ 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);
|
||||
}
|
||||
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::DoLoadKeyedFastDoubleElement(
|
||||
LLoadKeyedFastDoubleElement* instr) {
|
||||
Register elements = ToRegister(instr->elements());
|
||||
bool key_is_constant = instr->key()->IsConstantOperand();
|
||||
Register key = no_reg;
|
||||
DoubleRegister result = ToDoubleRegister(instr->result());
|
||||
Register scratch = scratch0();
|
||||
|
||||
int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
|
||||
int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
|
||||
? (element_size_shift - kSmiTagSize) : element_size_shift;
|
||||
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());
|
||||
}
|
||||
|
||||
if (key_is_constant) {
|
||||
__ Addu(elements, elements,
|
||||
Operand(((constant_key + instr->additional_index()) <<
|
||||
element_size_shift) +
|
||||
FixedDoubleArray::kHeaderSize - kHeapObjectTag));
|
||||
} else {
|
||||
__ sll(scratch, key, shift_size);
|
||||
__ Addu(elements, elements, Operand(scratch));
|
||||
__ Addu(elements, elements,
|
||||
Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
|
||||
(instr->additional_index() << element_size_shift)));
|
||||
}
|
||||
|
||||
if (instr->hydrogen()->RequiresHoleCheck()) {
|
||||
__ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
|
||||
DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32));
|
||||
}
|
||||
|
||||
__ ldc1(result, MemOperand(elements));
|
||||
}
|
||||
|
||||
|
||||
MemOperand LCodeGen::PrepareKeyedOperand(Register key,
|
||||
Register base,
|
||||
bool key_is_constant,
|
||||
int constant_key,
|
||||
int element_size,
|
||||
int shift_size,
|
||||
int additional_index,
|
||||
int additional_offset) {
|
||||
if (additional_index != 0 && !key_is_constant) {
|
||||
additional_index *= 1 << (element_size - shift_size);
|
||||
__ Addu(scratch0(), key, Operand(additional_index));
|
||||
}
|
||||
|
||||
if (key_is_constant) {
|
||||
return MemOperand(base,
|
||||
(constant_key << element_size) + additional_offset);
|
||||
}
|
||||
|
||||
if (additional_index == 0) {
|
||||
if (shift_size >= 0) {
|
||||
__ sll(scratch0(), key, shift_size);
|
||||
__ Addu(scratch0(), base, scratch0());
|
||||
return MemOperand(scratch0());
|
||||
} else {
|
||||
ASSERT_EQ(-1, shift_size);
|
||||
__ srl(scratch0(), key, 1);
|
||||
__ Addu(scratch0(), base, scratch0());
|
||||
return MemOperand(scratch0());
|
||||
}
|
||||
}
|
||||
|
||||
if (shift_size >= 0) {
|
||||
__ sll(scratch0(), scratch0(), shift_size);
|
||||
__ Addu(scratch0(), base, scratch0());
|
||||
return MemOperand(scratch0());
|
||||
} else {
|
||||
ASSERT_EQ(-1, shift_size);
|
||||
__ srl(scratch0(), scratch0(), 1);
|
||||
__ Addu(scratch0(), base, scratch0());
|
||||
return MemOperand(scratch0());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
LLoadKeyedSpecializedArrayElement* instr) {
|
||||
Register external_pointer = ToRegister(instr->external_pointer());
|
||||
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();
|
||||
@ -2834,6 +2704,145 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
|
||||
Register elements = ToRegister(instr->elements());
|
||||
bool key_is_constant = instr->key()->IsConstantOperand();
|
||||
Register key = no_reg;
|
||||
DoubleRegister result = ToDoubleRegister(instr->result());
|
||||
Register scratch = scratch0();
|
||||
|
||||
int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
|
||||
int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
|
||||
? (element_size_shift - kSmiTagSize) : element_size_shift;
|
||||
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());
|
||||
}
|
||||
|
||||
if (key_is_constant) {
|
||||
__ Addu(elements, elements,
|
||||
Operand(((constant_key + instr->additional_index()) <<
|
||||
element_size_shift) +
|
||||
FixedDoubleArray::kHeaderSize - kHeapObjectTag));
|
||||
} else {
|
||||
__ sll(scratch, key, shift_size);
|
||||
__ Addu(elements, elements, Operand(scratch));
|
||||
__ Addu(elements, elements,
|
||||
Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
|
||||
(instr->additional_index() << element_size_shift)));
|
||||
}
|
||||
|
||||
if (instr->hydrogen()->RequiresHoleCheck()) {
|
||||
__ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
|
||||
DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32));
|
||||
}
|
||||
|
||||
__ ldc1(result, MemOperand(elements));
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
int constant_key,
|
||||
int element_size,
|
||||
int shift_size,
|
||||
int additional_index,
|
||||
int additional_offset) {
|
||||
if (additional_index != 0 && !key_is_constant) {
|
||||
additional_index *= 1 << (element_size - shift_size);
|
||||
__ Addu(scratch0(), key, Operand(additional_index));
|
||||
}
|
||||
|
||||
if (key_is_constant) {
|
||||
return MemOperand(base,
|
||||
(constant_key << element_size) + additional_offset);
|
||||
}
|
||||
|
||||
if (additional_index == 0) {
|
||||
if (shift_size >= 0) {
|
||||
__ sll(scratch0(), key, shift_size);
|
||||
__ Addu(scratch0(), base, scratch0());
|
||||
return MemOperand(scratch0());
|
||||
} else {
|
||||
ASSERT_EQ(-1, shift_size);
|
||||
__ srl(scratch0(), key, 1);
|
||||
__ Addu(scratch0(), base, scratch0());
|
||||
return MemOperand(scratch0());
|
||||
}
|
||||
}
|
||||
|
||||
if (shift_size >= 0) {
|
||||
__ sll(scratch0(), scratch0(), shift_size);
|
||||
__ Addu(scratch0(), base, scratch0());
|
||||
return MemOperand(scratch0());
|
||||
} else {
|
||||
ASSERT_EQ(-1, shift_size);
|
||||
__ srl(scratch0(), scratch0(), 1);
|
||||
__ Addu(scratch0(), base, scratch0());
|
||||
return MemOperand(scratch0());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
|
@ -376,6 +376,12 @@ class LCodeGen BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
void EnsureSpaceForLazyDeopt();
|
||||
void DoLoadKeyedExternalArray(LLoadKeyed* instr);
|
||||
void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
|
||||
void DoLoadKeyedFixedArray(LLoadKeyed* instr);
|
||||
void DoStoreKeyedExternalArray(LStoreKeyed* instr);
|
||||
void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
|
||||
void DoStoreKeyedFixedArray(LStoreKeyed* instr);
|
||||
|
||||
Zone* zone_;
|
||||
LPlatformChunk* const chunk_;
|
||||
|
@ -372,16 +372,7 @@ void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
|
||||
}
|
||||
|
||||
|
||||
void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
|
||||
object()->PrintTo(stream);
|
||||
stream->Add("[");
|
||||
key()->PrintTo(stream);
|
||||
stream->Add("] <- ");
|
||||
value()->PrintTo(stream);
|
||||
}
|
||||
|
||||
|
||||
void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
|
||||
void LStoreKeyed::PrintDataTo(StringStream* stream) {
|
||||
elements()->PrintTo(stream);
|
||||
stream->Add("[");
|
||||
key()->PrintTo(stream);
|
||||
@ -1798,53 +1789,40 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
||||
HLoadKeyedFastElement* instr) {
|
||||
ASSERT(instr->representation().IsTagged());
|
||||
LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
LOperand* obj = UseRegisterAtStart(instr->object());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
|
||||
if (instr->RequiresHoleCheck()) AssignEnvironment(result);
|
||||
return DefineAsRegister(result);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
|
||||
HLoadKeyedFastDoubleElement* instr) {
|
||||
ASSERT(instr->representation().IsDouble());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
LOperand* elements = UseTempRegister(instr->elements());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LLoadKeyedFastDoubleElement* result =
|
||||
new(zone()) LLoadKeyedFastDoubleElement(elements, key);
|
||||
return AssignEnvironment(DefineAsRegister(result));
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
|
||||
HLoadKeyedSpecializedArrayElement* instr) {
|
||||
ElementsKind elements_kind = instr->elements_kind();
|
||||
ASSERT(
|
||||
(instr->representation().IsInteger32() &&
|
||||
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(instr->representation().IsDouble() &&
|
||||
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
LLoadKeyedSpecializedArrayElement* result =
|
||||
new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
|
||||
LInstruction* load_instr = DefineAsRegister(result);
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
LLoadKeyed* result = NULL;
|
||||
|
||||
if (!instr->is_external()) {
|
||||
LOperand* obj = NULL;
|
||||
if (instr->representation().IsDouble()) {
|
||||
obj = UseTempRegister(instr->elements());
|
||||
} else {
|
||||
ASSERT(instr->representation().IsTagged());
|
||||
obj = UseRegisterAtStart(instr->elements());
|
||||
}
|
||||
result = new(zone()) LLoadKeyed(obj, key);
|
||||
} else {
|
||||
ASSERT(
|
||||
(instr->representation().IsInteger32() &&
|
||||
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(instr->representation().IsDouble() &&
|
||||
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
LOperand* external_pointer = UseRegister(instr->elements());
|
||||
result = new(zone()) LLoadKeyed(external_pointer, key);
|
||||
}
|
||||
|
||||
DefineAsRegister(result);
|
||||
// An unsigned int array load might overflow and cause a deopt, make sure it
|
||||
// has an environment.
|
||||
return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) ?
|
||||
AssignEnvironment(load_instr) : load_instr;
|
||||
bool can_deoptimize = instr->RequiresHoleCheck() ||
|
||||
(elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
|
||||
return can_deoptimize ? AssignEnvironment(result) : result;
|
||||
}
|
||||
|
||||
|
||||
@ -1858,66 +1836,47 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
|
||||
HStoreKeyedFastElement* instr) {
|
||||
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
|
||||
ElementsKind elements_kind = instr->elements_kind();
|
||||
bool needs_write_barrier = instr->NeedsWriteBarrier();
|
||||
ASSERT(instr->value()->representation().IsTagged());
|
||||
ASSERT(instr->object()->representation().IsTagged());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
|
||||
LOperand* obj = UseTempRegister(instr->object());
|
||||
LOperand* val = needs_write_barrier
|
||||
? UseTempRegister(instr->value())
|
||||
: UseRegisterAtStart(instr->value());
|
||||
LOperand* key = needs_write_barrier
|
||||
? UseTempRegister(instr->key())
|
||||
: UseRegisterOrConstantAtStart(instr->key());
|
||||
return new(zone()) LStoreKeyedFastElement(obj, key, val);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
|
||||
HStoreKeyedFastDoubleElement* instr) {
|
||||
ASSERT(instr->value()->representation().IsDouble());
|
||||
ASSERT(instr->elements()->representation().IsTagged());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
|
||||
LOperand* elements = UseRegisterAtStart(instr->elements());
|
||||
LOperand* val = UseTempRegister(instr->value());
|
||||
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
|
||||
|
||||
return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
|
||||
HStoreKeyedSpecializedArrayElement* instr) {
|
||||
ElementsKind elements_kind = instr->elements_kind();
|
||||
ASSERT(
|
||||
(instr->value()->representation().IsInteger32() &&
|
||||
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(instr->value()->representation().IsDouble() &&
|
||||
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
ASSERT(instr->external_pointer()->representation().IsExternal());
|
||||
ASSERT(instr->key()->representation().IsInteger32() ||
|
||||
instr->key()->representation().IsTagged());
|
||||
|
||||
LOperand* external_pointer = UseRegister(instr->external_pointer());
|
||||
bool val_is_temp_register =
|
||||
elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
|
||||
elements_kind == EXTERNAL_FLOAT_ELEMENTS;
|
||||
LOperand* val = val_is_temp_register
|
||||
LOperand* val = val_is_temp_register || needs_write_barrier
|
||||
? UseTempRegister(instr->value())
|
||||
: UseRegister(instr->value());
|
||||
LOperand* key = UseRegisterOrConstant(instr->key());
|
||||
LStoreKeyed* result = NULL;
|
||||
if (!instr->is_external()) {
|
||||
ASSERT(instr->elements()->representation().IsTagged());
|
||||
|
||||
return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
|
||||
key,
|
||||
val);
|
||||
LOperand* object = NULL;
|
||||
if (instr->value()->representation().IsDouble()) {
|
||||
object = UseRegisterAtStart(instr->elements());
|
||||
} else {
|
||||
ASSERT(instr->value()->representation().IsTagged());
|
||||
object = UseTempRegister(instr->elements());
|
||||
}
|
||||
|
||||
result = new(zone()) LStoreKeyed(object, key, val);
|
||||
} else {
|
||||
ASSERT(
|
||||
(instr->value()->representation().IsInteger32() &&
|
||||
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
|
||||
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
|
||||
(instr->value()->representation().IsDouble() &&
|
||||
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
|
||||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
|
||||
ASSERT(instr->elements()->representation().IsExternal());
|
||||
|
||||
LOperand* external_pointer = UseRegister(instr->elements());
|
||||
result = new(zone()) LStoreKeyed(external_pointer, key, val);
|
||||
}
|
||||
|
||||
ASSERT(result != NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -125,10 +125,8 @@ class LCodeGen;
|
||||
V(LoadFunctionPrototype) \
|
||||
V(LoadGlobalCell) \
|
||||
V(LoadGlobalGeneric) \
|
||||
V(LoadKeyedFastDoubleElement) \
|
||||
V(LoadKeyedFastElement) \
|
||||
V(LoadKeyed) \
|
||||
V(LoadKeyedGeneric) \
|
||||
V(LoadKeyedSpecializedArrayElement) \
|
||||
V(LoadNamedField) \
|
||||
V(LoadNamedFieldPolymorphic) \
|
||||
V(LoadNamedGeneric) \
|
||||
@ -156,10 +154,8 @@ class LCodeGen;
|
||||
V(StoreContextSlot) \
|
||||
V(StoreGlobalCell) \
|
||||
V(StoreGlobalGeneric) \
|
||||
V(StoreKeyedFastDoubleElement) \
|
||||
V(StoreKeyedFastElement) \
|
||||
V(StoreKeyed) \
|
||||
V(StoreKeyedGeneric) \
|
||||
V(StoreKeyedSpecializedArrayElement) \
|
||||
V(StoreNamedField) \
|
||||
V(StoreNamedGeneric) \
|
||||
V(StringAdd) \
|
||||
@ -1337,59 +1333,25 @@ class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
|
||||
class LLoadKeyed: public LTemplateInstruction<1, 2, 0> {
|
||||
public:
|
||||
LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
|
||||
LLoadKeyed(LOperand* elements, LOperand* key) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
}
|
||||
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element")
|
||||
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement)
|
||||
|
||||
uint32_t additional_index() const { return hydrogen()->index_offset(); }
|
||||
};
|
||||
|
||||
|
||||
class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
|
||||
public:
|
||||
LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
}
|
||||
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
|
||||
"load-keyed-fast-double-element")
|
||||
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
|
||||
|
||||
uint32_t additional_index() const { return hydrogen()->index_offset(); }
|
||||
};
|
||||
|
||||
|
||||
class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
|
||||
public:
|
||||
LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
|
||||
LOperand* key) {
|
||||
inputs_[0] = external_pointer;
|
||||
inputs_[1] = key;
|
||||
}
|
||||
|
||||
LOperand* external_pointer() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
|
||||
"load-keyed-specialized-array-element")
|
||||
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
|
||||
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
bool is_external() const {
|
||||
return hydrogen()->is_external();
|
||||
}
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
|
||||
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
|
||||
|
||||
uint32_t additional_index() const { return hydrogen()->index_offset(); }
|
||||
};
|
||||
|
||||
@ -1903,51 +1865,28 @@ class LStoreNamedGeneric: public LTemplateInstruction<0, 2, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
|
||||
class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
|
||||
public:
|
||||
LStoreKeyedFastElement(LOperand* object, LOperand* key, LOperand* value) {
|
||||
LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
|
||||
inputs_[0] = object;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = value;
|
||||
}
|
||||
|
||||
LOperand* object() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
|
||||
"store-keyed-fast-element")
|
||||
DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
uint32_t additional_index() const { return hydrogen()->index_offset(); }
|
||||
};
|
||||
|
||||
|
||||
class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
|
||||
public:
|
||||
LStoreKeyedFastDoubleElement(LOperand* elements,
|
||||
LOperand* key,
|
||||
LOperand* value) {
|
||||
inputs_[0] = elements;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = value;
|
||||
}
|
||||
|
||||
bool is_external() const { return hydrogen()->is_external(); }
|
||||
LOperand* elements() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
ElementsKind elements_kind() const {
|
||||
return hydrogen()->elements_kind();
|
||||
}
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
|
||||
"store-keyed-fast-double-element")
|
||||
DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
|
||||
DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
|
||||
DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
uint32_t additional_index() const { return hydrogen()->index_offset(); }
|
||||
|
||||
bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
|
||||
uint32_t additional_index() const { return hydrogen()->index_offset(); }
|
||||
};
|
||||
|
||||
|
||||
@ -1971,28 +1910,6 @@ class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
|
||||
StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
|
||||
};
|
||||
|
||||
class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
|
||||
public:
|
||||
LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
|
||||
LOperand* key,
|
||||
LOperand* value) {
|
||||
inputs_[0] = external_pointer;
|
||||
inputs_[1] = key;
|
||||
inputs_[2] = value;
|
||||
}
|
||||
|
||||
LOperand* external_pointer() { return inputs_[0]; }
|
||||
LOperand* key() { return inputs_[1]; }
|
||||
LOperand* value() { return inputs_[2]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
|
||||
"store-keyed-specialized-array-element")
|
||||
DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement)
|
||||
|
||||
ElementsKind elements_kind() const { return hydrogen()->elements_kind(); }
|
||||
uint32_t additional_index() const { return hydrogen()->index_offset(); }
|
||||
};
|
||||
|
||||
|
||||
class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user