Chromium Code Reviews| Index: src/hydrogen-instructions.h |
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
| index 2d57537596b612ffff8aa628dac5b0bac9cb8027..ace5f8783e435d61a4bb707b810957be615ecdbb 100644 |
| --- a/src/hydrogen-instructions.h |
| +++ b/src/hydrogen-instructions.h |
| @@ -64,6 +64,7 @@ class LChunkBuilder; |
| V(AbnormalExit) \ |
| V(AccessArgumentsAt) \ |
| V(Add) \ |
| + V(Allocate) \ |
| V(AllocateObject) \ |
| V(ApplyArguments) \ |
| V(ArgumentsElements) \ |
| @@ -179,6 +180,7 @@ class LChunkBuilder; |
| V(Throw) \ |
| V(ToFastProperties) \ |
| V(TransitionElementsKind) \ |
| + V(TrapAllocationMemento) \ |
| V(Typeof) \ |
| V(TypeofIsAndBranch) \ |
| V(UnaryMathOperation) \ |
| @@ -4127,7 +4129,8 @@ inline bool StoringValueNeedsWriteBarrier(HValue* value) { |
| inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, |
| HValue* new_space_dominator) { |
| - return (!object->IsAllocateObject() && !object->IsFastLiteral()) || |
| + return (!object->IsAllocateObject() && !object->IsAllocate() && |
|
Michael Starzinger
2013/01/31 13:15:10
This only holds if HAllocate guarantees that it al
danno
2013/01/31 15:53:25
Done.
|
| + !object->IsFastLiteral()) || |
| (object != new_space_dominator); |
| } |
| @@ -4460,15 +4463,23 @@ class ArrayInstructionInterface { |
| }; |
| +enum LoadKeyedHoleMode { |
| + NEVER_RETURN_HOLE, |
| + ALLOW_RETURN_HOLE |
| +}; |
| + |
| + |
| class HLoadKeyed |
| : public HTemplateInstruction<3>, public ArrayInstructionInterface { |
| public: |
| HLoadKeyed(HValue* obj, |
| HValue* key, |
| HValue* dependency, |
| - ElementsKind elements_kind) |
| + ElementsKind elements_kind, |
| + LoadKeyedHoleMode mode = NEVER_RETURN_HOLE) |
| : bit_field_(0) { |
| - bit_field_ = ElementsKindField::encode(elements_kind); |
| + bit_field_ = ElementsKindField::encode(elements_kind) | |
| + HoleModeField::encode(mode); |
| SetOperandAt(0, obj); |
| SetOperandAt(1, key); |
| @@ -4481,8 +4492,7 @@ class HLoadKeyed |
| IsFastDoubleElementsKind(elements_kind)); |
| if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
| - if (IsFastSmiElementsKind(elements_kind) && |
| - IsFastPackedElementsKind(elements_kind)) { |
| + if (IsFastSmiElementsKind(elements_kind)) { |
| set_type(HType::Smi()); |
| } |
| @@ -4531,6 +4541,9 @@ class HLoadKeyed |
| ElementsKind elements_kind() const { |
| return ElementsKindField::decode(bit_field_); |
| } |
| + LoadKeyedHoleMode hole_mode() const { |
| + return HoleModeField::decode(bit_field_); |
| + } |
| virtual Representation RequiredInputRepresentation(int index) { |
| // kind_fast: tagged[int32] (none) |
| @@ -4553,6 +4566,7 @@ class HLoadKeyed |
| virtual void PrintDataTo(StringStream* stream); |
| + bool CanReturnHole() const; |
| bool RequiresHoleCheck() const; |
| virtual Range* InferRange(Zone* zone); |
| @@ -4577,11 +4591,13 @@ class HLoadKeyed |
| // Establish some checks around our packed fields |
| enum LoadKeyedBits { |
| kBitsForElementsKind = 5, |
| - kBitsForIndexOffset = 26, |
| + kBitsForHoleMode = 1, |
| + kBitsForIndexOffset = 25, |
| kBitsForIsDehoisted = 1, |
| kStartElementsKind = 0, |
| - kStartIndexOffset = kStartElementsKind + kBitsForElementsKind, |
| + kStartHoleMode = kStartElementsKind + kBitsForElementsKind, |
| + kStartIndexOffset = kStartHoleMode + kBitsForHoleMode, |
| kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset |
| }; |
| @@ -4591,6 +4607,9 @@ class HLoadKeyed |
| class ElementsKindField: |
| public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind> |
| {}; // NOLINT |
| + class HoleModeField: |
| + public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode> |
| + {}; // NOLINT |
| class IndexOffsetField: |
| public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset> |
| {}; // NOLINT |
| @@ -4729,11 +4748,18 @@ class HStoreKeyed |
| public: |
| HStoreKeyed(HValue* obj, HValue* key, HValue* val, |
| ElementsKind elements_kind) |
| - : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) { |
| + : elements_kind_(elements_kind), |
| + index_offset_(0), |
| + is_dehoisted_(false), |
| + new_space_dominator_(NULL) { |
| SetOperandAt(0, obj); |
| SetOperandAt(1, key); |
| SetOperandAt(2, val); |
| + if (IsFastObjectElementsKind(elements_kind)) { |
| + SetFlag(kTrackSideEffectDominators); |
| + SetGVNFlag(kDependsOnNewSpacePromotion); |
| + } |
| if (is_external()) { |
| SetGVNFlag(kChangesSpecializedArrayElements); |
| } else if (IsFastDoubleElementsKind(elements_kind)) { |
| @@ -4801,11 +4827,19 @@ class HStoreKeyed |
| bool IsDehoisted() { return is_dehoisted_; } |
| void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } |
| + virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { |
| + ASSERT(side_effect == kChangesNewSpacePromotion); |
| + new_space_dominator_ = dominator; |
| + } |
| + |
| + HValue* new_space_dominator() const { return new_space_dominator_; } |
| + |
| bool NeedsWriteBarrier() { |
| if (value_is_smi()) { |
| return false; |
| } else { |
| - return StoringValueNeedsWriteBarrier(value()); |
| + return StoringValueNeedsWriteBarrier(value()) && |
| + ReceiverObjectNeedsWriteBarrier(elements(), new_space_dominator()); |
| } |
| } |
| @@ -4819,6 +4853,7 @@ class HStoreKeyed |
| ElementsKind elements_kind_; |
| uint32_t index_offset_; |
| bool is_dehoisted_; |
| + HValue* new_space_dominator_; |
| }; |
| @@ -4857,9 +4892,10 @@ class HStoreKeyedGeneric: public HTemplateInstruction<4> { |
| }; |
| -class HTransitionElementsKind: public HTemplateInstruction<1> { |
| +class HTransitionElementsKind: public HTemplateInstruction<2> { |
| public: |
| - HTransitionElementsKind(HValue* object, |
| + HTransitionElementsKind(HValue* context, |
| + HValue* object, |
| Handle<Map> original_map, |
| Handle<Map> transitioned_map) |
| : original_map_(original_map), |
| @@ -4867,6 +4903,7 @@ class HTransitionElementsKind: public HTemplateInstruction<1> { |
| from_kind_(original_map->elements_kind()), |
| to_kind_(transitioned_map->elements_kind()) { |
| SetOperandAt(0, object); |
| + SetOperandAt(1, context); |
| SetFlag(kUseGVN); |
| SetGVNFlag(kChangesElementsKind); |
| if (original_map->has_fast_double_elements()) { |
| @@ -4885,6 +4922,7 @@ class HTransitionElementsKind: public HTemplateInstruction<1> { |
| } |
| HValue* object() { return OperandAt(0); } |
| + HValue* context() { return OperandAt(1); } |
| Handle<Map> original_map() { return original_map_; } |
| Handle<Map> transitioned_map() { return transitioned_map_; } |
| ElementsKind from_kind() { return from_kind_; } |
| @@ -5071,6 +5109,59 @@ class HAllocateObject: public HTemplateInstruction<1> { |
| }; |
| +class HAllocate: public HTemplateInstruction<2> { |
| + public: |
| + enum Flags { |
| + CAN_ALLOCATE_IN_NEW_SPACE = 1 << 0, |
| + CAN_ALLOCATE_IN_OLD_SPACE = 1 << 1, |
|
Michael Starzinger
2013/01/31 13:15:10
The old-space flag will need to indicate which old
danno
2013/01/31 15:53:25
Done.
|
| + ALLOCATE_DOUBLE_ALIGNED = 1 << 2, |
| + ALLOCATE_IN_ANY_SPACE = CAN_ALLOCATE_IN_NEW_SPACE | |
| + CAN_ALLOCATE_IN_OLD_SPACE |
| + }; |
| + |
| + HAllocate(HValue* context, HValue* size, HType type, Flags flags) |
| + : type_(type), |
| + flags_(flags) { |
| + ASSERT((flags & CAN_ALLOCATE_IN_OLD_SPACE) == 0); // unimplemented |
| + SetOperandAt(0, context); |
| + SetOperandAt(1, size); |
| + set_representation(Representation::Tagged()); |
| + SetGVNFlag(kChangesNewSpacePromotion); |
| + } |
| + |
| + HValue* context() { return OperandAt(0); } |
| + HValue* size() { return OperandAt(1); } |
| + |
| + virtual Representation RequiredInputRepresentation(int index) { |
| + if (index == 0) { |
| + return Representation::Tagged(); |
| + } else { |
| + return Representation::Integer32(); |
| + } |
| + } |
| + |
| + virtual HType CalculateInferredType(); |
| + |
| + bool CanAllocateInNewSpace() const { |
| + return (flags_ & CAN_ALLOCATE_IN_NEW_SPACE) != 0; |
| + } |
| + |
| + bool CanAllocateInOldSpace() const { |
| + return (flags_ & CAN_ALLOCATE_IN_OLD_SPACE) != 0; |
| + } |
| + |
| + bool MustAllocateDoubleAligned() const { |
| + return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0; |
| + } |
| + |
| + DECLARE_CONCRETE_INSTRUCTION(Allocate) |
| + |
| + private: |
| + HType type_; |
| + Flags flags_; |
| +}; |
| + |
| + |
| template <int V> |
| class HMaterializedLiteral: public HTemplateInstruction<V> { |
| public: |
| @@ -5304,6 +5395,22 @@ class HTypeof: public HTemplateInstruction<2> { |
| }; |
| +class HTrapAllocationMemento : public HTemplateInstruction<2> { |
| + public: |
| + explicit HTrapAllocationMemento(HValue* obj) { |
| + SetOperandAt(0, obj); |
| + } |
| + |
| + virtual Representation RequiredInputRepresentation(int index) { |
| + return Representation::Tagged(); |
| + } |
| + |
| + HValue* object() { return OperandAt(0); } |
| + |
| + DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento) |
| +}; |
| + |
| + |
| class HToFastProperties: public HUnaryOperation { |
| public: |
| explicit HToFastProperties(HValue* value) : HUnaryOperation(value) { |