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
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12839 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d2dc5ff5
......@@ -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);
......@@ -1860,53 +1851,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());
ElementsKind elements_kind = instr->elements_kind();
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result =
new(zone()) LLoadKeyedFastDoubleElement(elements, key);
return AssignEnvironment(DefineAsRegister(result));
}
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);
}
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);
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;
}
......@@ -1920,66 +1898,48 @@ 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());
return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
key,
val);
LStoreKeyed* result = NULL;
if (!instr->is_external()) {
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 {
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) \
......@@ -157,10 +155,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) \
......@@ -1357,58 +1353,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;
ElementsKind elements_kind() const {
return hydrogen()->elements_kind();
}
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;
bool is_external() const {
return hydrogen()->is_external();
}
LOperand* external_pointer() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
"load-keyed-specialized-array-element")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
ElementsKind elements_kind() const {
return hydrogen()->elements_kind();
}
uint32_t additional_index() const { return hydrogen()->index_offset(); }
};
......@@ -1922,51 +1885,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(); }
};
......@@ -1990,28 +1930,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:
......
This diff is collapsed.
......@@ -377,6 +377,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_;
......
......@@ -35,9 +35,14 @@ namespace v8 {
namespace internal {
void PrintElementsKind(FILE* out, ElementsKind kind) {
const char* ElementsKindToString(ElementsKind kind) {
ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
PrintF(out, "%s", accessor->name());
return accessor->name();
}
void PrintElementsKind(FILE* out, ElementsKind kind) {
PrintF(out, "%s", ElementsKindToString(kind));
}
......
......@@ -77,6 +77,7 @@ const int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
const int kFastElementsKindCount = LAST_FAST_ELEMENTS_KIND -
FIRST_FAST_ELEMENTS_KIND + 1;
const char* ElementsKindToString(ElementsKind kind);
void PrintElementsKind(FILE* out, ElementsKind kind);
ElementsKind GetInitialFastElementsKind();
......@@ -109,6 +110,13 @@ inline bool IsFastDoubleElementsKind(ElementsKind kind) {
}
inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
return IsFastDoubleElementsKind(kind) ||
kind == EXTERNAL_DOUBLE_ELEMENTS ||
kind == EXTERNAL_FLOAT_ELEMENTS;
}
inline bool IsFastSmiOrObjectElementsKind(ElementsKind kind) {
return kind == FAST_SMI_ELEMENTS ||
kind == FAST_HOLEY_SMI_ELEMENTS ||
......
......@@ -1622,7 +1622,7 @@ Range* HShl::InferRange(Zone* zone) {
}
Range* HLoadKeyedSpecializedArrayElement::InferRange(Zone* zone) {
Range* HLoadKeyed::InferRange(Zone* zone) {
switch (elements_kind()) {
case EXTERNAL_PIXEL_ELEMENTS:
return new(zone) Range(0, 255);
......@@ -1849,8 +1849,17 @@ void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
}
void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
void HLoadKeyed::PrintDataTo(StringStream* stream) {
if (!is_external()) {
elements()->PrintNameTo(stream);
} else {
ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
elements()->PrintNameTo(stream);
stream->Add(".");
stream->Add(ElementsKindToString(elements_kind()));
}
stream->Add("[");
key()->PrintNameTo(stream);
stream->Add("] ");
......@@ -1861,29 +1870,26 @@ void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
}
bool HLoadKeyedFastElement::RequiresHoleCheck() const {
bool HLoadKeyed::RequiresHoleCheck() const {
if (IsFastPackedElementsKind(elements_kind())) {
return false;
}
if (IsFastDoubleElementsKind(elements_kind())) {
return true;
}
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
HValue* use = it.value();
if (!use->IsChange()) return true;
if (!use->IsChange()) {
return true;
}
}
return false;
}
void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
elements()->PrintNameTo(stream);
stream->Add("[");
key()->PrintNameTo(stream);
stream->Add("] ");
dependency()->PrintNameTo(stream);
}
void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add("[");
......@@ -1896,21 +1902,22 @@ HValue* HLoadKeyedGeneric::Canonicalize() {
// Recognize generic keyed loads that use property name generated
// by for-in statement as a key and rewrite them into fast property load
// by index.
if (key()->IsLoadKeyedFastElement()) {
HLoadKeyedFastElement* key_load = HLoadKeyedFastElement::cast(key());
if (key_load->object()->IsForInCacheArray()) {
if (key()->IsLoadKeyed()) {
HLoadKeyed* key_load = HLoadKeyed::cast(key());
if (key_load->elements()->IsForInCacheArray()) {
HForInCacheArray* names_cache =
HForInCacheArray::cast(key_load->object());
HForInCacheArray::cast(key_load->elements());
if (names_cache->enumerable() == object()) {
HForInCacheArray* index_cache =
names_cache->index_cache();
HCheckMapValue* map_check =
new(block()->zone()) HCheckMapValue(object(), names_cache->map());
HInstruction* index = new(block()->zone()) HLoadKeyedFastElement(
HInstruction* index = new(block()->zone()) HLoadKeyed(
index_cache,
key_load->key(),
key_load->key());
key_load->key(),
key_load->elements_kind());
map_check->InsertBefore(this);
index->InsertBefore(this);
HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
......@@ -1925,56 +1932,6 @@ HValue* HLoadKeyedGeneric::Canonicalize() {
}
void HLoadKeyedSpecializedArrayElement::PrintDataTo(
StringStream* stream) {
external_pointer()->PrintNameTo(stream);
stream->Add(".");
switch (elements_kind()) {
case EXTERNAL_BYTE_ELEMENTS:
stream->Add("byte");
break;
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
stream->Add("u_byte");
break;
case EXTERNAL_SHORT_ELEMENTS:
stream->Add("short");
break;
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
stream->Add("u_short");
break;
case EXTERNAL_INT_ELEMENTS:
stream->Add("int");
break;
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
stream->Add("u_int");
break;
case EXTERNAL_FLOAT_ELEMENTS:
stream->Add("float");
break;
case EXTERNAL_DOUBLE_ELEMENTS:
stream->Add("double");
break;
case EXTERNAL_PIXEL_ELEMENTS:
stream->Add("pixel");
break;
case FAST_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
case DICTIONARY_ELEMENTS:
case NON_STRICT_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
stream->Add("[");
key()->PrintNameTo(stream);
stream->Add("] ");
dependency()->PrintNameTo(stream);
}
void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add(".");
......@@ -2001,17 +1958,17 @@ void HStoreNamedField::PrintDataTo(StringStream* stream) {
}
void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add("[");
key()->PrintNameTo(stream);
stream->Add("] = ");
value()->PrintNameTo(stream);
}
void HStoreKeyed::PrintDataTo(StringStream* stream) {
if (!is_external()) {
elements()->PrintNameTo(stream);
} else {
elements()->PrintNameTo(stream);
stream->Add(".");
stream->Add(ElementsKindToString(elements_kind()));
ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
}
void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
elements()->PrintNameTo(stream);
stream->Add("[");
key()->PrintNameTo(stream);
stream->Add("] = ");
......@@ -2028,56 +1985,6 @@ void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
}
void HStoreKeyedSpecializedArrayElement::PrintDataTo(
StringStream* stream) {
external_pointer()->PrintNameTo(stream);
stream->Add(".");
switch (elements_kind()) {
case EXTERNAL_BYTE_ELEMENTS:
stream->Add("byte");
break;
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
stream->Add("u_byte");
break;
case EXTERNAL_SHORT_ELEMENTS:
stream->Add("short");
break;
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
stream->Add("u_short");
break;
case EXTERNAL_INT_ELEMENTS:
stream->Add("int");
break;
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
stream->Add("u_int");
break;
case EXTERNAL_FLOAT_ELEMENTS:
stream->Add("float");
break;
case EXTERNAL_DOUBLE_ELEMENTS:
stream->Add("double");
break;
case EXTERNAL_PIXEL_ELEMENTS:
stream->Add("pixel");
break;
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
case DICTIONARY_ELEMENTS:
case NON_STRICT_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
stream->Add("[");
key()->PrintNameTo(stream);
stream->Add("] = ");
value()->PrintNameTo(stream);
}
void HTransitionElementsKind::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
ElementsKind from_kind = original_map()->elements_kind();
......@@ -2368,10 +2275,10 @@ HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
}
bool HStoreKeyedFastDoubleElement::NeedsCanonicalization() {
// If value was loaded from unboxed double backing store or
// converted from an integer then we don't have to canonicalize it.
if (value()->IsLoadKeyedFastDoubleElement() ||
bool HStoreKeyed::NeedsCanonicalization() {
// If value is an integer or comes from the result of a keyed load
// then it will be a non-hole value: no need for canonicalization.
if (value()->IsLoadKeyed() ||
(value()->IsChange() && HChange::cast(value())->from().IsInteger32())) {
return false;
}
......
This diff is collapsed.
......@@ -2715,17 +2715,18 @@ bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) {
} else if (use->IsChange() || use->IsSimulate()) {
// Conversions and deoptimization have special support for unt32.
return true;
} else if (use->IsStoreKeyedSpecializedArrayElement()) {
// Storing a value into an external integer array is a bit level operation.
HStoreKeyedSpecializedArrayElement* store =
HStoreKeyedSpecializedArrayElement::cast(use);
if (store->value() == val) {
// Clamping or a conversion to double should have beed inserted.
ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS);
ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS);
ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS);
return true;
} else if (use->IsStoreKeyed()) {
HStoreKeyed* store = HStoreKeyed::cast(use);
if (store->is_external()) {
// Storing a value into an external integer array is a bit level
// operation.
if (store->value() == val) {
// Clamping or a conversion to double should have beed inserted.
ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS);
ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS);
ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS);
return true;
}
}
}
......@@ -3757,27 +3758,11 @@ void HGraph::DehoistSimpleArrayIndexComputations() {
instr != NULL;
instr = instr->next()) {
ArrayInstructionInterface* array_instruction = NULL;
if (instr->IsLoadKeyedFastElement()) {
HLoadKeyedFastElement* op = HLoadKeyedFastElement::cast(instr);
array_instruction = static_cast<ArrayInstructionInterface*>(op);
} else if (instr->IsLoadKeyedFastDoubleElement()) {
HLoadKeyedFastDoubleElement* op =
HLoadKeyedFastDoubleElement::cast(instr);
array_instruction = static_cast<ArrayInstructionInterface*>(op);
} else if (instr->IsLoadKeyedSpecializedArrayElement()) {
HLoadKeyedSpecializedArrayElement* op =
HLoadKeyedSpecializedArrayElement::cast(instr);
if (instr->IsLoadKeyed()) {
HLoadKeyed* op = HLoadKeyed::cast(instr);
array_instruction = static_cast<ArrayInstructionInterface*>(op);
} else if (instr->IsStoreKeyedFastElement()) {
HStoreKeyedFastElement* op = HStoreKeyedFastElement::cast(instr);
array_instruction = static_cast<ArrayInstructionInterface*>(op);
} else if (instr->IsStoreKeyedFastDoubleElement()) {
HStoreKeyedFastDoubleElement* op =
HStoreKeyedFastDoubleElement::cast(instr);
array_instruction = static_cast<ArrayInstructionInterface*>(op);
} else if (instr->IsStoreKeyedSpecializedArrayElement()) {
HStoreKeyedSpecializedArrayElement* op =
HStoreKeyedSpecializedArrayElement::cast(instr);
} else if (instr->IsStoreKeyed()) {
HStoreKeyed* op = HStoreKeyed::cast(instr);
array_instruction = static_cast<ArrayInstructionInterface*>(op);
} else {
continue;
......@@ -4617,10 +4602,11 @@ void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
set_current_block(loop_body);
HValue* key = AddInstruction(
new(zone()) HLoadKeyedFastElement(
new(zone()) HLoadKeyed(
environment()->ExpressionStackAt(2), // Enum cache.
environment()->ExpressionStackAt(0), // Iteration index.
environment()->ExpressionStackAt(0)));
environment()->ExpressionStackAt(0),
FAST_ELEMENTS));
// Check if the expected map still matches that of the enumerable.
// If not just deoptimize.
......@@ -5225,18 +5211,14 @@ void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
// Fall through.
case FAST_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
AddInstruction(new(zone()) HStoreKeyedFastElement(
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
AddInstruction(new(zone()) HStoreKeyed(
elements,
key,
value,
boilerplate_elements_kind));
break;
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements,
key,
value));
break;
default:
UNREACHABLE();
break;
......@@ -6085,13 +6067,15 @@ HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
UNREACHABLE();
break;
}
return new(zone()) HStoreKeyedSpecializedArrayElement(
external_elements, checked_key, val, elements_kind);
return new(zone()) HStoreKeyed(external_elements,
checked_key,
val,
elements_kind);
} else {
ASSERT(val == NULL);
HLoadKeyedSpecializedArrayElement* load =
new(zone()) HLoadKeyedSpecializedArrayElement(
external_elements, checked_key, dependency, elements_kind);
HLoadKeyed* load =
new(zone()) HLoadKeyed(
external_elements, checked_key, dependency, elements_kind);
if (FLAG_opt_safe_uint32_operations &&
elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
graph()->RecordUint32Instruction(load);
......@@ -6110,10 +6094,6 @@ HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
if (is_store) {
ASSERT(val != NULL);
switch (elements_kind) {
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
return new(zone()) HStoreKeyedFastDoubleElement(
elements, checked_key, val);
case FAST_SMI_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
// Smi-only arrays need a smi check.
......@@ -6121,7 +6101,9 @@ HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
// Fall through.
case FAST_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
return new(zone()) HStoreKeyedFastElement(
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
return new(zone()) HStoreKeyed(
elements, checked_key, val, elements_kind);
default:
UNREACHABLE();
......@@ -6129,16 +6111,10 @@ HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
}
}
// It's an element load (!is_store).
HoleCheckMode mode = IsFastPackedElementsKind(elements_kind) ?
OMIT_HOLE_CHECK :
PERFORM_HOLE_CHECK;
if (IsFastDoubleElementsKind(elements_kind)) {
return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key,
load_dependency, mode);
} else { // Smi or Object elements.
return new(zone()) HLoadKeyedFastElement(elements, checked_key,
load_dependency, elements_kind);
}
return new(zone()) HLoadKeyed(elements,
checked_key,
load_dependency,
elements_kind);
}
......
This diff is collapsed.
......@@ -340,6 +340,12 @@ class LCodeGen BASE_EMBEDDED {
int* offset);
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);
// Emits code for pushing either a tagged constant, a (non-double)
// register, or a stack slot operand.
......
......@@ -407,16 +407,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);
......@@ -1932,59 +1923,38 @@ 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 = UseRegisterAtStart(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());
bool clobbers_key = ExternalArrayOpRequiresTemp(
instr->key()->representation(), elements_kind);
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstant(instr->key());
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
LLoadKeyedSpecializedArrayElement* result =
new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
LInstruction* load_instr = DefineAsRegister(result);
if (!instr->is_external()) {
LOperand* 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);
bool can_deoptimize = instr->RequiresHoleCheck() ||
(elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
// 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;
return can_deoptimize ? AssignEnvironment(result) : result;
}
......@@ -1999,72 +1969,66 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
}
LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
HStoreKeyedFastElement* instr) {
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 = UseRegister(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::DoStoreKeyed(HStoreKeyed* instr) {
LStoreKeyed* result = NULL;
if (!instr->is_external()) {
ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
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());
if (instr->value()->representation().IsDouble()) {
LOperand* object = UseRegisterAtStart(instr->elements());
LOperand* val = UseTempRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LOperand* external_pointer = UseRegister(instr->external_pointer());
LOperand* val = NULL;
if (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
// We need a byte register in this case for the value.
val = UseFixed(instr->value(), eax);
result = new(zone()) LStoreKeyed(object, key, val);
} else {
ASSERT(instr->value()->representation().IsTagged());
bool needs_write_barrier = instr->NeedsWriteBarrier();
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 {
val = UseRegister(instr->value());
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->elements()->representation().IsExternal());
LOperand* external_pointer = UseRegister(instr->elements());
// Determine if we need a byte register in this case for the value.
bool val_is_fixed_register =
elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_PIXEL_ELEMENTS;
LOperand* val = val_is_fixed_register
? UseFixed(instr->value(), eax)
: 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);
}
bool clobbers_key = ExternalArrayOpRequiresTemp(
instr->key()->representation(), elements_kind);
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstant(instr->key());
return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
key,
val);
ASSERT(result != NULL);
return result;
}
......
......@@ -119,10 +119,8 @@ class LCodeGen;
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
V(LoadKeyedFastElement) \
V(LoadKeyedFastDoubleElement) \
V(LoadKeyed) \
V(LoadKeyedGeneric) \
V(LoadKeyedSpecializedArrayElement) \
V(LoadNamedField) \
V(LoadNamedFieldPolymorphic) \
V(LoadNamedGeneric) \
......@@ -152,10 +150,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) \
......@@ -1389,36 +1385,24 @@ 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;
ElementsKind elements_kind() const {
return hydrogen()->elements_kind();
}
bool is_external() const {
return hydrogen()->is_external();
}
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
"load-keyed-fast-double-element")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
uint32_t additional_index() const { return hydrogen()->index_offset(); }
};
......@@ -1437,27 +1421,6 @@ inline static bool ExternalArrayOpRequiresTemp(
}
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();
}
uint32_t additional_index() const { return hydrogen()->index_offset(); }
};
class LLoadKeyedGeneric: public LTemplateInstruction<1, 3, 0> {
public:
LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key) {
......@@ -2006,78 +1969,31 @@ class LStoreNamedGeneric: public LTemplateInstruction<0, 3, 0> {
};
class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val) {
LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
inputs_[0] = obj;
inputs_[1] = key;
inputs_[2] = val;
}
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* val) {
inputs_[0] = elements;
inputs_[1] = key;
inputs_[2] = val;
}
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(); }
};
class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
LOperand* key,
LOperand* val) {
inputs_[0] = external_pointer;
inputs_[1] = key;
inputs_[2] = val;
}
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 LStoreKeyedGeneric: public LTemplateInstruction<0, 4, 0> {
public:
LStoreKeyedGeneric(LOperand* context,
......
This diff is collapsed.
......@@ -335,6 +335,12 @@ class LCodeGen BASE_EMBEDDED {
};
void EnsureSpaceForLazyDeopt(int space_needed);
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_;
......
......@@ -394,16 +394,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);
......@@ -1843,63 +1834,37 @@ LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
}
LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
HLoadKeyedFastElement* instr) {
ASSERT(instr->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* obj = UseRegisterAtStart(instr->object());
bool clobbers_key = instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? UseTempRegister(instr->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());
LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsTagged());
LOperand* elements = UseRegisterAtStart(instr->elements());
ElementsKind elements_kind = instr->elements_kind();
bool clobbers_key = instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result =
new(zone()) LLoadKeyedFastDoubleElement(elements, key);
return AssignEnvironment(DefineAsRegister(result));
}
LLoadKeyed* result = NULL;
if (!instr->is_external()) {
LOperand* 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);
}
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());
bool clobbers_key = instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedSpecializedArrayElement* result =
new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
LInstruction* load_instr = DefineAsRegister(result);
DefineAsRegister(result);
bool can_deoptimize = instr->RequiresHoleCheck() ||
(elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
// 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;
return can_deoptimize ? AssignEnvironment(result) : result;
}
......@@ -1912,71 +1877,49 @@ 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());
bool clobbers_key = needs_write_barrier ||
instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? 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());
bool clobbers_key = instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
LOperand* key = (clobbers_key || needs_write_barrier)
? UseTempRegister(instr->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 = (needs_write_barrier || val_is_temp_register)
? UseTempRegister(instr->value())
: UseRegister(instr->value());
bool clobbers_key = instr->key()->representation().IsTagged();
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
key, val);
: UseRegisterAtStart(instr->value());
LStoreKeyed* result = NULL;
if (!instr->is_external()) {
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 {
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;
}
......
......@@ -126,10 +126,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) \
......@@ -157,10 +155,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) \
......@@ -1353,56 +1349,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;
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement)
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
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;
bool is_external() const {
return hydrogen()->is_external();
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
"load-keyed-fast-double-element")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
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;
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
"load-keyed-specialized-array-element")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
LOperand* external_pointer() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
ElementsKind elements_kind() const {
return hydrogen()->elements_kind();
}
uint32_t additional_index() const { return hydrogen()->index_offset(); }
};
......@@ -1899,76 +1864,29 @@ 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);
bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
uint32_t additional_index() const { return hydrogen()->index_offset(); }
};
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 LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedGeneric(LOperand* object, LOperand* key, LOperand* value) {
......
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