Some improvements in register usage in lithium compilation of LoadKeyed/StoreKeyed operations.

BUG=

Review URL: https://codereview.chromium.org/11365084

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12912 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 09666b60
...@@ -1881,6 +1881,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { ...@@ -1881,6 +1881,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
(instr->representation().IsDouble() && (instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
LOperand* external_pointer = UseRegister(instr->elements()); LOperand* external_pointer = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(external_pointer, key); result = new(zone()) LLoadKeyed(external_pointer, key);
} }
...@@ -1905,32 +1906,22 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { ...@@ -1905,32 +1906,22 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind(); LOperand* elements = UseRegisterAtStart(instr->elements());
bool needs_write_barrier = instr->NeedsWriteBarrier(); LOperand* key;
LOperand* key = needs_write_barrier LOperand* val;
? UseTempRegister(instr->key()) if (instr->NeedsWriteBarrier()) {
: UseRegisterOrConstantAtStart(instr->key()); key = UseTempRegister(instr->key());
bool val_is_temp_register = val = UseTempRegister(instr->value());
elements_kind == EXTERNAL_PIXEL_ELEMENTS || } else {
elements_kind == EXTERNAL_FLOAT_ELEMENTS; key = UseRegisterOrConstantAtStart(instr->key());
LOperand* val = val_is_temp_register || needs_write_barrier val = UseRegisterAtStart(instr->value());
? UseTempRegister(instr->value()) }
: UseRegister(instr->value());
LStoreKeyed* result = NULL; #ifdef DEBUG
if (!instr->is_external()) { if (!instr->is_external()) {
ASSERT(instr->elements()->representation().IsTagged()); ASSERT(instr->elements()->representation().IsTagged());
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 { } else {
ElementsKind elements_kind = instr->elements_kind();
ASSERT( ASSERT(
(instr->value()->representation().IsInteger32() && (instr->value()->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
...@@ -1939,11 +1930,10 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { ...@@ -1939,11 +1930,10 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->elements()->representation().IsExternal()); ASSERT(instr->elements()->representation().IsExternal());
LOperand* external_pointer = UseRegister(instr->elements());
result = new(zone()) LStoreKeyed(external_pointer, key, val);
} }
#endif
LStoreKeyed* result = new(zone()) LStoreKeyed(elements, key, val);
ASSERT(result != NULL); ASSERT(result != NULL);
return result; return result;
} }
......
...@@ -2773,15 +2773,12 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { ...@@ -2773,15 +2773,12 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key(); if (ExternalArrayOpRequiresTemp<HLoadKeyed>(instr->hydrogen())) {
if (!key->IsConstantOperand() && __ SmiUntag(ToRegister(instr->key()));
ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
elements_kind)) {
__ SmiUntag(ToRegister(key));
} }
Operand operand(BuildFastArrayOperand( Operand operand(BuildFastArrayOperand(
instr->elements(), instr->elements(),
key, instr->key(),
instr->hydrogen()->key()->representation(), instr->hydrogen()->key()->representation(),
elements_kind, elements_kind,
0, 0,
...@@ -3851,15 +3848,12 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { ...@@ -3851,15 +3848,12 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key(); if (ExternalArrayOpRequiresTemp<HStoreKeyed>(instr->hydrogen())) {
if (!key->IsConstantOperand() && __ SmiUntag(ToRegister(instr->key()));
ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
elements_kind)) {
__ SmiUntag(ToRegister(key));
} }
Operand operand(BuildFastArrayOperand( Operand operand(BuildFastArrayOperand(
instr->elements(), instr->elements(),
key, instr->key(),
instr->hydrogen()->key()->representation(), instr->hydrogen()->key()->representation(),
elements_kind, elements_kind,
0, 0,
......
...@@ -1933,17 +1933,14 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { ...@@ -1933,17 +1933,14 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
ASSERT(instr->key()->representation().IsInteger32() || ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged()); instr->key()->representation().IsTagged());
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
bool clobbers_key = ExternalArrayOpRequiresTemp( LOperand* elements = UseRegisterAtStart(instr->elements());
instr->key()->representation(), elements_kind); LOperand* key = instr->is_external() &&
LOperand* key = clobbers_key ExternalArrayOpRequiresTemp<HLoadKeyed>(instr)
? UseTempRegister(instr->key()) ? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key()); : UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
if (!instr->is_external()) { #ifdef DEBUG
LOperand* obj = UseRegisterAtStart(instr->elements()); if (instr->is_external()) {
result = new(zone()) LLoadKeyed(obj, key);
} else {
ASSERT( ASSERT(
(instr->representation().IsInteger32() && (instr->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
...@@ -1951,10 +1948,10 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { ...@@ -1951,10 +1948,10 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
(instr->representation().IsDouble() && (instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
LOperand* external_pointer = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(external_pointer, key);
} }
#endif
LLoadKeyed* result = new(zone()) LLoadKeyed(elements, key);
DefineAsRegister(result); DefineAsRegister(result);
bool can_deoptimize = instr->RequiresHoleCheck() || bool can_deoptimize = instr->RequiresHoleCheck() ||
(elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS); (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
...@@ -1976,34 +1973,27 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { ...@@ -1976,34 +1973,27 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
LStoreKeyed* result = NULL; ElementsKind elements_kind = instr->elements_kind();
LOperand* elements;
LOperand* val;
LOperand* key;
if (!instr->is_external()) { if (!instr->is_external()) {
ASSERT(instr->elements()->representation().IsTagged()); ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32() || ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged()); instr->key()->representation().IsTagged());
if (instr->value()->representation().IsDouble()) { if (instr->NeedsWriteBarrier() &&
LOperand* object = UseRegisterAtStart(instr->elements()); !IsFastDoubleElementsKind(elements_kind)) {
LOperand* val = UseTempRegister(instr->value()); val = UseTempRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key()); key = UseTempRegister(instr->key());
elements = UseRegister(instr->elements());
result = new(zone()) LStoreKeyed(object, key, val);
} else { } else {
ASSERT(instr->value()->representation().IsTagged()); val = UseRegisterAtStart(instr->value());
bool needs_write_barrier = instr->NeedsWriteBarrier(); key = UseRegisterOrConstantAtStart(instr->key());
elements = UseRegisterAtStart(instr->elements());
LOperand* obj = UseRegister(instr->elements());
LOperand* val = needs_write_barrier
? UseTempRegister(instr->value())
: UseRegisterAtStart(instr->value());
LOperand* key = needs_write_barrier
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
result = new(zone()) LStoreKeyed(obj, key, val);
} }
} else { } else {
ElementsKind elements_kind = instr->elements_kind();
ASSERT( ASSERT(
(instr->value()->representation().IsInteger32() && (instr->value()->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
...@@ -2013,26 +2003,25 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { ...@@ -2013,26 +2003,25 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->elements()->representation().IsExternal()); ASSERT(instr->elements()->representation().IsExternal());
LOperand* external_pointer = UseRegister(instr->elements()); if (ExternalArrayOpRequiresTemp<HStoreKeyed>(instr)) {
key = UseTempRegister(instr->key());
elements = UseRegister(instr->elements());
} else {
key = UseRegisterOrConstantAtStart(instr->key());
elements = UseRegisterAtStart(instr->elements());
}
// Determine if we need a byte register in this case for the value. // Determine if we need a byte register in this case for the value.
bool val_is_fixed_register = bool val_is_fixed_register =
elements_kind == EXTERNAL_BYTE_ELEMENTS || elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS || elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_PIXEL_ELEMENTS; elements_kind == EXTERNAL_PIXEL_ELEMENTS;
val = val_is_fixed_register
LOperand* val = val_is_fixed_register
? UseFixed(instr->value(), eax) ? UseFixed(instr->value(), eax)
: UseRegister(instr->value()); : UseRegister(instr->value());
bool clobbers_key = ExternalArrayOpRequiresTemp(
instr->key()->representation(), elements_kind);
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
result = new(zone()) LStoreKeyed(external_pointer,
key,
val);
} }
LStoreKeyed* result = new(zone()) LStoreKeyed(elements, key, val);
ASSERT(result != NULL); ASSERT(result != NULL);
return result; return result;
} }
......
...@@ -1408,13 +1408,16 @@ class LLoadKeyed: public LTemplateInstruction<1, 2, 0> { ...@@ -1408,13 +1408,16 @@ class LLoadKeyed: public LTemplateInstruction<1, 2, 0> {
}; };
inline static bool ExternalArrayOpRequiresTemp( template <class T>
Representation key_representation, inline static bool ExternalArrayOpRequiresTemp(T* value) {
ElementsKind elements_kind) { CHECK(value->IsLoadKeyed() || value->IsStoreKeyed());
Representation key_representation = value->key()->representation();
ElementsKind elements_kind = value->elements_kind();
// Operations that require the key to be divided by two to be converted into // Operations that require the key to be divided by two to be converted into
// an index cannot fold the scale operation into a load and need an extra // an index cannot fold the scale operation into a load and need an extra
// temp register to do the work. // temp register to do the work.
return key_representation.IsTagged() && return !value->IsConstant() && key_representation.IsTagged() &&
(elements_kind == EXTERNAL_BYTE_ELEMENTS || (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS || elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_PIXEL_ELEMENTS); elements_kind == EXTERNAL_PIXEL_ELEMENTS);
......
...@@ -2623,24 +2623,30 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { ...@@ -2623,24 +2623,30 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
} }
void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { template <class T>
ElementsKind elements_kind = instr->elements_kind(); inline void LCodeGen::PrepareKeyForKeyedOp(T* hydrogen_instr, LOperand* key) {
LOperand* key = instr->key(); if (ArrayOpClobbersKey<T>(hydrogen_instr)) {
if (!key->IsConstantOperand()) {
Register key_reg = ToRegister(key);
// Even though the HLoad/StoreKeyed (in this case) instructions force // Even though the HLoad/StoreKeyed (in this case) instructions force
// the input representation for the key to be an integer, the input // the input representation for the key to be an integer, the input
// gets replaced during bound check elimination with the index argument // gets replaced during bound check elimination with the index argument
// to the bounds check, which can be tagged, so that case must be // to the bounds check, which can be tagged, so that case must be
// handled here, too. // handled here, too.
if (instr->hydrogen()->key()->representation().IsTagged()) { Register key_reg = ToRegister(key);
if (hydrogen_instr->key()->representation().IsTagged()) {
__ SmiToInteger64(key_reg, key_reg); __ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) { } else if (hydrogen_instr->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value // Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits // and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg); __ movsxlq(key_reg, key_reg);
} }
} }
}
void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key();
PrepareKeyForKeyedOp(instr->hydrogen(), key);
Operand operand(BuildFastArrayOperand( Operand operand(BuildFastArrayOperand(
instr->elements(), instr->elements(),
key, key,
...@@ -2700,21 +2706,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { ...@@ -2700,21 +2706,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
XMMRegister result(ToDoubleRegister(instr->result())); XMMRegister result(ToDoubleRegister(instr->result()));
LOperand* key = instr->key(); LOperand* key = instr->key();
if (!key->IsConstantOperand()) { PrepareKeyForKeyedOp<HLoadKeyed>(instr->hydrogen(), key);
Register key_reg = ToRegister(key);
// Even though the HLoad/StoreKeyed instructions force 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()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
}
}
if (instr->hydrogen()->RequiresHoleCheck()) { if (instr->hydrogen()->RequiresHoleCheck()) {
int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
sizeof(kHoleNanLower32); sizeof(kHoleNanLower32);
...@@ -2741,21 +2733,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { ...@@ -2741,21 +2733,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
Register result = ToRegister(instr->result()); Register result = ToRegister(instr->result());
LOperand* key = instr->key(); LOperand* key = instr->key();
if (!key->IsConstantOperand()) { PrepareKeyForKeyedOp<HLoadKeyed>(instr->hydrogen(), key);
Register key_reg = ToRegister(key);
// Even though the HLoad/StoreKeyedFastElement instructions force
// 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()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
}
}
// Load the result. // Load the result.
__ movq(result, __ movq(result,
...@@ -3750,21 +3728,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { ...@@ -3750,21 +3728,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key(); LOperand* key = instr->key();
if (!key->IsConstantOperand()) { PrepareKeyForKeyedOp<HStoreKeyed>(instr->hydrogen(), key);
Register key_reg = ToRegister(key);
// Even though the HLoad/StoreKeyedFastElement instructions force
// 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()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
}
}
Operand operand(BuildFastArrayOperand( Operand operand(BuildFastArrayOperand(
instr->elements(), instr->elements(),
key, key,
...@@ -3814,22 +3778,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { ...@@ -3814,22 +3778,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
XMMRegister value = ToDoubleRegister(instr->value()); XMMRegister value = ToDoubleRegister(instr->value());
LOperand* key = instr->key(); LOperand* key = instr->key();
if (!key->IsConstantOperand()) { PrepareKeyForKeyedOp<HStoreKeyed>(instr->hydrogen(), key);
Register key_reg = ToRegister(key);
// Even though the HLoad/StoreKeyedFastElement instructions force
// 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()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
}
}
if (instr->NeedsCanonicalization()) { if (instr->NeedsCanonicalization()) {
Label have_value; Label have_value;
...@@ -3858,21 +3807,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { ...@@ -3858,21 +3807,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
Register value = ToRegister(instr->value()); Register value = ToRegister(instr->value());
Register elements = ToRegister(instr->elements()); Register elements = ToRegister(instr->elements());
LOperand* key = instr->key(); LOperand* key = instr->key();
if (!key->IsConstantOperand()) { PrepareKeyForKeyedOp<HStoreKeyed>(instr->hydrogen(), key);
Register key_reg = ToRegister(key);
// Even though the HLoad/StoreKeyedFastElement instructions force
// 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()) {
__ SmiToInteger64(key_reg, key_reg);
} else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
}
}
Operand operand = Operand operand =
BuildFastArrayOperand(instr->elements(), BuildFastArrayOperand(instr->elements(),
......
...@@ -341,6 +341,8 @@ class LCodeGen BASE_EMBEDDED { ...@@ -341,6 +341,8 @@ class LCodeGen BASE_EMBEDDED {
void DoStoreKeyedExternalArray(LStoreKeyed* instr); void DoStoreKeyedExternalArray(LStoreKeyed* instr);
void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr); void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
void DoStoreKeyedFixedArray(LStoreKeyed* instr); void DoStoreKeyedFixedArray(LStoreKeyed* instr);
template <class T>
void PrepareKeyForKeyedOp(T* hydrogen_instr, LOperand* key);
Zone* zone_; Zone* zone_;
LPlatformChunk* const chunk_; LPlatformChunk* const chunk_;
......
...@@ -1844,16 +1844,15 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { ...@@ -1844,16 +1844,15 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
ASSERT(instr->key()->representation().IsInteger32() || ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged()); instr->key()->representation().IsTagged());
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
bool clobbers_key = instr->key()->representation().IsTagged(); bool clobbers_key = ArrayOpClobbersKey<HLoadKeyed>(instr);
LOperand* key = clobbers_key LOperand* key = clobbers_key
? UseTempRegister(instr->key()) ? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key()); : UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL; LOperand* elements = UseRegisterAtStart(instr->elements());
LLoadKeyed* result = new(zone()) LLoadKeyed(elements, key);
if (!instr->is_external()) { #ifdef DEBUG
LOperand* obj = UseRegisterAtStart(instr->elements()); if (instr->is_external()) {
result = new(zone()) LLoadKeyed(obj, key);
} else {
ASSERT( ASSERT(
(instr->representation().IsInteger32() && (instr->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
...@@ -1861,9 +1860,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { ...@@ -1861,9 +1860,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
(instr->representation().IsDouble() && (instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
LOperand* external_pointer = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(external_pointer, key);
} }
#endif
DefineAsRegister(result); DefineAsRegister(result);
bool can_deoptimize = instr->RequiresHoleCheck() || bool can_deoptimize = instr->RequiresHoleCheck() ||
...@@ -1884,33 +1882,21 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { ...@@ -1884,33 +1882,21 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
bool needs_write_barrier = instr->NeedsWriteBarrier(); bool needs_write_barrier = instr->NeedsWriteBarrier();
bool clobbers_key = instr->key()->representation().IsTagged(); bool clobbers_key = ArrayOpClobbersKey<HStoreKeyed>(instr);
LOperand* key = (clobbers_key || needs_write_barrier) LOperand* key = (clobbers_key || needs_write_barrier)
? UseTempRegister(instr->key()) ? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key()); : UseRegisterOrConstantAtStart(instr->key());
bool val_is_temp_register = LOperand* val = needs_write_barrier
elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
elements_kind == EXTERNAL_FLOAT_ELEMENTS;
LOperand* val = (needs_write_barrier || val_is_temp_register)
? UseTempRegister(instr->value()) ? UseTempRegister(instr->value())
: UseRegisterAtStart(instr->value()); : UseRegisterAtStart(instr->value());
LStoreKeyed* result = NULL; LOperand* elements = UseRegisterAtStart(instr->elements());
#ifdef DEBUG
if (!instr->is_external()) { if (!instr->is_external()) {
ASSERT(instr->elements()->representation().IsTagged()); ASSERT(instr->elements()->representation().IsTagged());
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 { } else {
ElementsKind elements_kind = instr->elements_kind();
ASSERT( ASSERT(
(instr->value()->representation().IsInteger32() && (instr->value()->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
...@@ -1919,11 +1905,10 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { ...@@ -1919,11 +1905,10 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->elements()->representation().IsExternal()); ASSERT(instr->elements()->representation().IsExternal());
LOperand* external_pointer = UseRegister(instr->elements());
result = new(zone()) LStoreKeyed(external_pointer, key, val);
} }
#endif
LStoreKeyed* result = new(zone()) LStoreKeyed(elements, key, val);
ASSERT(result != NULL); ASSERT(result != NULL);
return result; return result;
} }
......
...@@ -1371,6 +1371,14 @@ class LLoadKeyed: public LTemplateInstruction<1, 2, 0> { ...@@ -1371,6 +1371,14 @@ class LLoadKeyed: public LTemplateInstruction<1, 2, 0> {
}; };
template <class T>
inline static bool ArrayOpClobbersKey(T *value) {
CHECK(value->IsLoadKeyed() || value->IsStoreKeyed());
return !value->IsConstant() && (value->key()->representation().IsTagged()
|| value->IsDehoisted());
}
class LLoadKeyedGeneric: public LTemplateInstruction<1, 2, 0> { class LLoadKeyedGeneric: public LTemplateInstruction<1, 2, 0> {
public: public:
LLoadKeyedGeneric(LOperand* obj, LOperand* key) { LLoadKeyedGeneric(LOperand* obj, LOperand* key) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment