Index: src/hydrogen-instructions.h |
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
index 9e6344cd5f5e08035f65ae5e702558629090238b..5b4f4fa9962bbd07f9366c37fc7118f2e27e1b65 100644 |
--- a/src/hydrogen-instructions.h |
+++ b/src/hydrogen-instructions.h |
@@ -133,10 +133,8 @@ class LChunkBuilder; |
V(LoadFunctionPrototype) \ |
V(LoadGlobalCell) \ |
V(LoadGlobalGeneric) \ |
- V(LoadKeyedFastDoubleElement) \ |
- V(LoadKeyedFastElement) \ |
+ V(LoadKeyed) \ |
V(LoadKeyedGeneric) \ |
- V(LoadKeyedSpecializedArrayElement) \ |
V(LoadNamedField) \ |
V(LoadNamedFieldPolymorphic) \ |
V(LoadNamedGeneric) \ |
@@ -163,10 +161,8 @@ class LChunkBuilder; |
V(StoreContextSlot) \ |
V(StoreGlobalCell) \ |
V(StoreGlobalGeneric) \ |
- V(StoreKeyedFastDoubleElement) \ |
- V(StoreKeyedFastElement) \ |
+ V(StoreKeyed) \ |
V(StoreKeyedGeneric) \ |
- V(StoreKeyedSpecializedArrayElement) \ |
V(StoreNamedField) \ |
V(StoreNamedGeneric) \ |
V(StringAdd) \ |
@@ -4243,29 +4239,66 @@ class ArrayInstructionInterface { |
virtual ~ArrayInstructionInterface() { }; |
}; |
-class HLoadKeyedFastElement |
+ |
+class HLoadKeyed |
: public HTemplateInstruction<3>, public ArrayInstructionInterface { |
public: |
- HLoadKeyedFastElement(HValue* obj, |
- HValue* key, |
- HValue* dependency, |
- ElementsKind elements_kind = FAST_ELEMENTS) |
+ HLoadKeyed(HValue* obj, |
+ HValue* key, |
+ HValue* dependency, |
+ ElementsKind elements_kind, |
+ bool is_external) |
: bit_field_(0) { |
- ASSERT(IsFastSmiOrObjectElementsKind(elements_kind)); |
bit_field_ = ElementsKindField::encode(elements_kind); |
- if (IsFastSmiElementsKind(elements_kind) && |
- IsFastPackedElementsKind(elements_kind)) { |
- set_type(HType::Smi()); |
- } |
+ |
SetOperandAt(0, obj); |
SetOperandAt(1, key); |
SetOperandAt(2, dependency); |
- set_representation(Representation::Tagged()); |
- SetGVNFlag(kDependsOnArrayElements); |
+ |
+ if (!is_external) { |
danno
2012/10/21 20:44:41
use IsExternalArrayElementsKind here
|
+ // I can detect the case between storing double (holey and fast) and |
+ // smi/object by looking at elements_kind_. |
+ ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || |
+ IsFastDoubleElementsKind(elements_kind)); |
+ |
+ if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
+ if (IsFastSmiElementsKind(elements_kind) && |
+ IsFastPackedElementsKind(elements_kind)) { |
+ set_type(HType::Smi()); |
+ } |
+ |
+ set_representation(Representation::Tagged()); |
+ SetGVNFlag(kDependsOnArrayElements); |
+ } else { |
+ set_representation(Representation::Double()); |
+ SetGVNFlag(kDependsOnDoubleArrayElements); |
+ } |
+ } else { |
+ if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
+ elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
+ set_representation(Representation::Double()); |
+ } else { |
+ set_representation(Representation::Integer32()); |
+ } |
+ |
+ SetGVNFlag(kDependsOnSpecializedArrayElements); |
+ // Native code could change the specialized array. |
+ SetGVNFlag(kDependsOnCalls); |
+ } |
+ |
SetFlag(kUseGVN); |
} |
- HValue* object() { return OperandAt(0); } |
+ bool is_external() const { return |
danno
2012/10/21 20:44:41
use IsExternalArrayElementsKind(elements_kind()) t
|
+ CheckGVNFlag(kDependsOnSpecializedArrayElements); } |
+ HValue* object() { |
+ ASSERT(!is_external()); |
+ return OperandAt(0); |
+ } |
+ HValue* external_pointer() { |
+ ASSERT(is_external()); |
+ return OperandAt(0); |
+ } |
HValue* key() { return OperandAt(1); } |
HValue* dependency() { return OperandAt(2); } |
uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); } |
@@ -4274,6 +4307,7 @@ class HLoadKeyedFastElement |
} |
HValue* GetKey() { return key(); } |
void SetKey(HValue* key) { SetOperandAt(1, key); } |
+ |
bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); } |
void SetDehoisted(bool is_dehoisted) { |
bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted); |
@@ -4283,8 +4317,12 @@ class HLoadKeyedFastElement |
} |
virtual Representation RequiredInputRepresentation(int index) { |
+ // <tagged | external>[int] (dependency = none) |
// The key is supposed to be Integer32. |
- if (index == 0) return Representation::Tagged(); |
+ if (index == 0) { |
+ return is_external() ? Representation::External() |
+ : Representation::Tagged(); |
+ } |
if (index == 1) return Representation::Integer32(); |
return Representation::None(); |
} |
@@ -4293,157 +4331,43 @@ class HLoadKeyedFastElement |
bool RequiresHoleCheck() const; |
- DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement) |
+ virtual Range* InferRange(Zone* zone); |
+ |
+ DECLARE_CONCRETE_INSTRUCTION(LoadKeyed) |
protected: |
virtual bool DataEquals(HValue* other) { |
- if (!other->IsLoadKeyedFastElement()) return false; |
- HLoadKeyedFastElement* other_load = HLoadKeyedFastElement::cast(other); |
+ if (!other->IsLoadKeyed()) return false; |
+ HLoadKeyed* other_load = HLoadKeyed::cast(other); |
+ |
+ // TODO(mvstanton): doing a special check for external here, because |
+ // external didn't care about hoisting state and index offset. |
+ // Is this nessecary at all? |
danno
2012/10/21 20:44:41
We should be able to treat all array accesses unif
mvstanton
2012/10/23 23:44:20
Done.
|
+ if (is_external() && other_load->is_external()) { |
+ return elements_kind() == other_load->elements_kind(); |
+ } |
+ |
if (IsDehoisted() && index_offset() != other_load->index_offset()) |
return false; |
return elements_kind() == other_load->elements_kind(); |
} |
private: |
- virtual bool IsDeletable() const { return !RequiresHoleCheck(); } |
+ virtual bool IsDeletable() const { |
+ return is_external() ? true : !RequiresHoleCheck(); |
danno
2012/10/21 20:44:41
RequiresHoleCheck should return false for external
mvstanton
2012/10/23 23:44:20
Done.
|
+ } |
- class ElementsKindField: public BitField<ElementsKind, 0, 4> {}; |
- class IndexOffsetField: public BitField<uint32_t, 4, 27> {}; |
+ // TODO(mvstanton) - to deal with some of the external element |
+ // kinds (PIXEL_ARRAY) I gave the ElementsKindField another bit, |
+ // taking it from the index offset. |
+ // Is this okay? |
+ class ElementsKindField: public BitField<ElementsKind, 0, 5> {}; |
+ class IndexOffsetField: public BitField<uint32_t, 5, 26> {}; |
class IsDehoistedField: public BitField<bool, 31, 1> {}; |
uint32_t bit_field_; |
}; |
-enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK }; |
- |
- |
-class HLoadKeyedFastDoubleElement |
- : public HTemplateInstruction<3>, public ArrayInstructionInterface { |
- public: |
- HLoadKeyedFastDoubleElement( |
- HValue* elements, |
- HValue* key, |
- HValue* dependency, |
- HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK) |
- : index_offset_(0), |
- is_dehoisted_(false), |
- hole_check_mode_(hole_check_mode) { |
- SetOperandAt(0, elements); |
- SetOperandAt(1, key); |
- SetOperandAt(2, dependency); |
- set_representation(Representation::Double()); |
- SetGVNFlag(kDependsOnDoubleArrayElements); |
- SetFlag(kUseGVN); |
- } |
- |
- HValue* elements() { return OperandAt(0); } |
- HValue* key() { return OperandAt(1); } |
- HValue* dependency() { return OperandAt(2); } |
- uint32_t index_offset() { return index_offset_; } |
- void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; } |
- HValue* GetKey() { return key(); } |
- void SetKey(HValue* key) { SetOperandAt(1, key); } |
- bool IsDehoisted() { return is_dehoisted_; } |
- void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } |
- |
- virtual Representation RequiredInputRepresentation(int index) { |
- // The key is supposed to be Integer32. |
- if (index == 0) return Representation::Tagged(); |
- if (index == 1) return Representation::Integer32(); |
- return Representation::None(); |
- } |
- |
- bool RequiresHoleCheck() const { |
- return hole_check_mode_ == PERFORM_HOLE_CHECK; |
- } |
- |
- virtual void PrintDataTo(StringStream* stream); |
- |
- DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement) |
- |
- protected: |
- virtual bool DataEquals(HValue* other) { |
- if (!other->IsLoadKeyedFastDoubleElement()) return false; |
- HLoadKeyedFastDoubleElement* other_load = |
- HLoadKeyedFastDoubleElement::cast(other); |
- return hole_check_mode_ == other_load->hole_check_mode_; |
- } |
- |
- private: |
- virtual bool IsDeletable() const { return !RequiresHoleCheck(); } |
- |
- uint32_t index_offset_; |
- bool is_dehoisted_; |
- HoleCheckMode hole_check_mode_; |
-}; |
- |
- |
-class HLoadKeyedSpecializedArrayElement |
- : public HTemplateInstruction<3>, public ArrayInstructionInterface { |
- public: |
- HLoadKeyedSpecializedArrayElement(HValue* external_elements, |
- HValue* key, |
- HValue* dependency, |
- ElementsKind elements_kind) |
- : elements_kind_(elements_kind), |
- index_offset_(0), |
- is_dehoisted_(false) { |
- SetOperandAt(0, external_elements); |
- SetOperandAt(1, key); |
- SetOperandAt(2, dependency); |
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
- elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
- set_representation(Representation::Double()); |
- } else { |
- set_representation(Representation::Integer32()); |
- } |
- SetGVNFlag(kDependsOnSpecializedArrayElements); |
- // Native code could change the specialized array. |
- SetGVNFlag(kDependsOnCalls); |
- SetFlag(kUseGVN); |
- } |
- |
- virtual void PrintDataTo(StringStream* stream); |
- |
- virtual Representation RequiredInputRepresentation(int index) { |
- // The key is supposed to be Integer32. |
- if (index == 0) return Representation::External(); |
- if (index == 1) return Representation::Integer32(); |
- return Representation::None(); |
- } |
- |
- HValue* external_pointer() { return OperandAt(0); } |
- HValue* key() { return OperandAt(1); } |
- HValue* dependency() { return OperandAt(2); } |
- ElementsKind elements_kind() const { return elements_kind_; } |
- uint32_t index_offset() { return index_offset_; } |
- void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; } |
- HValue* GetKey() { return key(); } |
- void SetKey(HValue* key) { SetOperandAt(1, key); } |
- bool IsDehoisted() { return is_dehoisted_; } |
- void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } |
- |
- virtual Range* InferRange(Zone* zone); |
- |
- DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement) |
- |
- protected: |
- virtual bool DataEquals(HValue* other) { |
- if (!other->IsLoadKeyedSpecializedArrayElement()) return false; |
- HLoadKeyedSpecializedArrayElement* cast_other = |
- HLoadKeyedSpecializedArrayElement::cast(other); |
- return elements_kind_ == cast_other->elements_kind(); |
- } |
- |
- private: |
- virtual bool IsDeletable() const { return true; } |
- |
- ElementsKind elements_kind_; |
- uint32_t index_offset_; |
- bool is_dehoisted_; |
-}; |
- |
- |
class HLoadKeyedGeneric: public HTemplateInstruction<3> { |
public: |
HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) { |
@@ -4566,31 +4490,65 @@ class HStoreNamedGeneric: public HTemplateInstruction<3> { |
}; |
-class HStoreKeyedFastElement |
+class HStoreKeyed |
: public HTemplateInstruction<3>, public ArrayInstructionInterface { |
public: |
- HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val, |
- ElementsKind elements_kind = FAST_ELEMENTS) |
+ HStoreKeyed(HValue* obj, HValue* key, HValue* val, |
+ ElementsKind elements_kind, bool is_external) |
danno
2012/10/21 20:44:41
Same feedback here about is_external as in the loa
mvstanton
2012/10/23 23:44:20
Done.
|
: elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) { |
SetOperandAt(0, obj); |
SetOperandAt(1, key); |
SetOperandAt(2, val); |
- SetGVNFlag(kChangesArrayElements); |
+ |
+ if (is_external) { |
+ SetGVNFlag(kChangesSpecializedArrayElements); |
+ } else if (!IsFastDoubleElementsKind(elements_kind)) { |
+ SetGVNFlag(kChangesArrayElements); |
+ } else { |
+ SetFlag(kDeoptimizeOnUndefined); |
+ SetGVNFlag(kChangesDoubleArrayElements); |
+ } |
} |
virtual Representation RequiredInputRepresentation(int index) { |
// The key is supposed to be Integer32. |
- return index == 1 |
- ? Representation::Integer32() |
- : Representation::Tagged(); |
+ // (<tagged> | <external>>[int32] = <tagged> | double | int |
danno
2012/10/21 20:44:41
nit: (<tagged> | <external>)[int32] = (<tagged> |
mvstanton
2012/10/23 23:44:20
Done.
|
+ if (index == 0) { |
+ return is_external() ? Representation::External() |
+ : Representation::Tagged(); |
+ } else if (index == 1) { |
+ return Representation::Integer32(); |
+ } |
+ |
+ ASSERT_EQ(index, 2); |
danno
2012/10/21 20:44:41
Perhaps add a new predicate in elements-kind.h tha
mvstanton
2012/10/23 23:44:20
Wow, that was quite a knot, thanks!
Actually, hav
|
+ if (is_external()) { |
+ bool float_or_double_elements = |
+ elements_kind() == EXTERNAL_FLOAT_ELEMENTS || |
+ elements_kind() == EXTERNAL_DOUBLE_ELEMENTS; |
+ return float_or_double_elements ? Representation::Double() |
+ : Representation::Integer32(); |
+ } |
+ |
+ return IsFastDoubleElementsKind(elements_kind()) ? Representation::Double() |
+ : Representation::Tagged(); |
} |
- HValue* object() { return OperandAt(0); } |
+ bool is_external() const { return |
+ CheckGVNFlag(kChangesSpecializedArrayElements); } |
+ HValue* external_pointer() { |
+ ASSERT(is_external()); |
+ return OperandAt(0); |
+ } |
+ HValue* object() { |
+ ASSERT(!is_external()); |
+ return OperandAt(0); |
+ } |
HValue* key() { return OperandAt(1); } |
HValue* value() { return OperandAt(2); } |
- bool value_is_smi() { |
+ bool value_is_smi() const { |
return IsFastSmiElementsKind(elements_kind_); |
} |
+ ElementsKind elements_kind() const { return elements_kind_; } |
uint32_t index_offset() { return index_offset_; } |
void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; } |
HValue* GetKey() { return key(); } |
@@ -4606,110 +4564,11 @@ class HStoreKeyedFastElement |
} |
} |
- virtual void PrintDataTo(StringStream* stream); |
- |
- DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement) |
- |
- private: |
- ElementsKind elements_kind_; |
- uint32_t index_offset_; |
- bool is_dehoisted_; |
-}; |
- |
- |
-class HStoreKeyedFastDoubleElement |
- : public HTemplateInstruction<3>, public ArrayInstructionInterface { |
- public: |
- HStoreKeyedFastDoubleElement(HValue* elements, |
- HValue* key, |
- HValue* val) |
- : index_offset_(0), is_dehoisted_(false) { |
- SetOperandAt(0, elements); |
- SetOperandAt(1, key); |
- SetOperandAt(2, val); |
- SetFlag(kDeoptimizeOnUndefined); |
- SetGVNFlag(kChangesDoubleArrayElements); |
- } |
- |
- virtual Representation RequiredInputRepresentation(int index) { |
- if (index == 1) { |
- return Representation::Integer32(); |
- } else if (index == 2) { |
- return Representation::Double(); |
- } else { |
- return Representation::Tagged(); |
- } |
- } |
- |
- HValue* elements() { return OperandAt(0); } |
- HValue* key() { return OperandAt(1); } |
- HValue* value() { return OperandAt(2); } |
- uint32_t index_offset() { return index_offset_; } |
- void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; } |
- HValue* GetKey() { return key(); } |
- void SetKey(HValue* key) { SetOperandAt(1, key); } |
- bool IsDehoisted() { return is_dehoisted_; } |
- void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } |
- |
- bool NeedsWriteBarrier() { |
- return StoringValueNeedsWriteBarrier(value()); |
- } |
- |
bool NeedsCanonicalization(); |
virtual void PrintDataTo(StringStream* stream); |
- DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement) |
- |
- private: |
- uint32_t index_offset_; |
- bool is_dehoisted_; |
-}; |
- |
- |
-class HStoreKeyedSpecializedArrayElement |
- : public HTemplateInstruction<3>, public ArrayInstructionInterface { |
- public: |
- HStoreKeyedSpecializedArrayElement(HValue* external_elements, |
- HValue* key, |
- HValue* val, |
- ElementsKind elements_kind) |
- : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) { |
- SetGVNFlag(kChangesSpecializedArrayElements); |
- SetOperandAt(0, external_elements); |
- SetOperandAt(1, key); |
- SetOperandAt(2, val); |
- } |
- |
- virtual void PrintDataTo(StringStream* stream); |
- |
- virtual Representation RequiredInputRepresentation(int index) { |
- if (index == 0) { |
- return Representation::External(); |
- } else { |
- bool float_or_double_elements = |
- elements_kind() == EXTERNAL_FLOAT_ELEMENTS || |
- elements_kind() == EXTERNAL_DOUBLE_ELEMENTS; |
- if (index == 2 && float_or_double_elements) { |
- return Representation::Double(); |
- } else { |
- return Representation::Integer32(); |
- } |
- } |
- } |
- |
- HValue* external_pointer() { return OperandAt(0); } |
- HValue* key() { return OperandAt(1); } |
- HValue* value() { return OperandAt(2); } |
- ElementsKind elements_kind() const { return elements_kind_; } |
- uint32_t index_offset() { return index_offset_; } |
- void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; } |
- HValue* GetKey() { return key(); } |
- void SetKey(HValue* key) { SetOperandAt(1, key); } |
- bool IsDehoisted() { return is_dehoisted_; } |
- void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } |
- |
- DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement) |
+ DECLARE_CONCRETE_INSTRUCTION(StoreKeyed) |
private: |
ElementsKind elements_kind_; |
@@ -4740,6 +4599,7 @@ class HStoreKeyedGeneric: public HTemplateInstruction<4> { |
StrictModeFlag strict_mode_flag() { return strict_mode_flag_; } |
virtual Representation RequiredInputRepresentation(int index) { |
+ // <tagged>[<tagged>] = <tagged> |
return Representation::Tagged(); |
} |