Chromium Code Reviews| Index: src/hydrogen-instructions.h |
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
| index 9e6344cd5f5e08035f65ae5e702558629090238b..5447425c022180a60deb1a34de965b6b47d8be84 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,58 @@ 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) |
| : 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()) { |
| + // 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/29 14:56:13
nit:
bool is_external() const {
return ....;
}
mvstanton
2012/10/29 15:23:57
Done.
|
| + IsExternalArrayElementsKind(elements_kind()); } |
| + HValue* elements() { return OperandAt(0); } |
| HValue* key() { return OperandAt(1); } |
| HValue* dependency() { return OperandAt(2); } |
| uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); } |
| @@ -4283,8 +4308,13 @@ class HLoadKeyedFastElement |
| } |
| virtual Representation RequiredInputRepresentation(int index) { |
| - // The key is supposed to be Integer32. |
| - if (index == 0) return Representation::Tagged(); |
| + // kind_fast: tagged[int32] (none) |
| + // kind_double: tagged[int32] (none) |
| + // kind_external: external[int32] (none) |
| + if (index == 0) { |
| + return is_external() ? Representation::External() |
| + : Representation::Tagged(); |
| + } |
| if (index == 1) return Representation::Integer32(); |
| return Representation::None(); |
| } |
| @@ -4293,154 +4323,49 @@ 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); |
| + |
| if (IsDehoisted() && index_offset() != other_load->index_offset()) |
| return false; |
| return elements_kind() == other_load->elements_kind(); |
| } |
| private: |
| - virtual bool IsDeletable() const { return !RequiresHoleCheck(); } |
| - |
| - class ElementsKindField: public BitField<ElementsKind, 0, 4> {}; |
| - class IndexOffsetField: public BitField<uint32_t, 4, 27> {}; |
| - 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(); |
| + virtual bool IsDeletable() const { |
| + return !RequiresHoleCheck(); |
| } |
| - 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; } |
| + // Establish some checks around our packed fields |
| + enum LoadKeyedBits { |
| + kBitsForElementsKind = 5, |
| + kBitsForIndexOffset = 26, |
| + kBitsForIsDehoisted = 1, |
| - 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; } |
| + kStartElementsKind = 0, |
| + kStartIndexOffset = kStartElementsKind + kBitsForElementsKind, |
| + kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset |
| + }; |
| - ElementsKind elements_kind_; |
| - uint32_t index_offset_; |
| - bool is_dehoisted_; |
| + STATIC_ASSERT((kBitsForElementsKind + kBitsForIndexOffset + |
| + kBitsForIsDehoisted) <= sizeof(uint32_t)*8); |
| + STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind)); |
| + class ElementsKindField: |
| + public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind> |
| + {}; // NOLINT |
| + class IndexOffsetField: |
| + public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset> |
| + {}; // NOLINT |
| + class IsDehoistedField: |
| + public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted> |
| + {}; // NOLINT |
| + uint32_t bit_field_; |
| }; |
| @@ -4461,6 +4386,7 @@ class HLoadKeyedGeneric: public HTemplateInstruction<3> { |
| virtual void PrintDataTo(StringStream* stream); |
| virtual Representation RequiredInputRepresentation(int index) { |
| + // tagged[tagged] |
| return Representation::Tagged(); |
| } |
| @@ -4566,84 +4492,55 @@ 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) |
| : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) { |
| SetOperandAt(0, obj); |
| SetOperandAt(1, key); |
| SetOperandAt(2, val); |
| - SetGVNFlag(kChangesArrayElements); |
| - } |
| - |
| - virtual Representation RequiredInputRepresentation(int index) { |
| - // The key is supposed to be Integer32. |
| - return index == 1 |
| - ? Representation::Integer32() |
| - : Representation::Tagged(); |
| - } |
| - |
| - HValue* object() { return OperandAt(0); } |
| - HValue* key() { return OperandAt(1); } |
| - HValue* value() { return OperandAt(2); } |
| - bool value_is_smi() { |
| - return IsFastSmiElementsKind(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; } |
| - bool NeedsWriteBarrier() { |
| - if (value_is_smi()) { |
| - return false; |
| + if (is_external()) { |
| + SetGVNFlag(kChangesSpecializedArrayElements); |
| + } else if (IsFastDoubleElementsKind(elements_kind)) { |
| + SetGVNFlag(kChangesDoubleArrayElements); |
| + SetFlag(kDeoptimizeOnUndefined); |
| } else { |
| - return StoringValueNeedsWriteBarrier(value()); |
| + SetGVNFlag(kChangesArrayElements); |
| } |
| } |
| - 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) { |
| + // kind_fast: tagged[int32] = tagged |
| + // kind_double: tagged[int32] = double |
| + // kind_external: external[int32] = (double | int32) |
| + if (index == 0) { |
| + return is_external() ? Representation::External() |
| + : Representation::Tagged(); |
| + } else if (index == 1) { |
| return Representation::Integer32(); |
| - } else if (index == 2) { |
| + } |
| + |
| + ASSERT_EQ(index, 2); |
| + if (IsDoubleOrFloatElementsKind(elements_kind())) { |
| return Representation::Double(); |
| - } else { |
| - return Representation::Tagged(); |
| } |
| + |
| + return is_external() ? Representation::Integer32() |
| + : Representation::Tagged(); |
| } |
| + bool is_external() const { return |
| + IsExternalArrayElementsKind(elements_kind()); } |
| HValue* elements() { return OperandAt(0); } |
| HValue* key() { return OperandAt(1); } |
| HValue* value() { return OperandAt(2); } |
| + 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(); } |
| @@ -4652,64 +4549,18 @@ class HStoreKeyedFastDoubleElement |
| void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } |
| bool NeedsWriteBarrier() { |
| - return StoringValueNeedsWriteBarrier(value()); |
| + if (value_is_smi()) { |
| + return false; |
| + } else { |
| + 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 +4591,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(); |
| } |