| Index: src/hydrogen-instructions.h
|
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
|
| index 9e6344cd5f5e08035f65ae5e702558629090238b..39b3fdfe06b9a55d77ecbf76691ff247a1252a9e 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,59 @@ 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 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 +4309,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 +4324,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 +4387,7 @@ class HLoadKeyedGeneric: public HTemplateInstruction<3> {
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| + // tagged[tagged]
|
| return Representation::Tagged();
|
| }
|
|
|
| @@ -4566,84 +4493,56 @@ 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 +4551,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 +4593,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();
|
| }
|
|
|
|
|