Index: src/hydrogen-instructions.h |
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
index 3aa15e375a78aee6cbb4b31395cb1a87957ebe54..eea429e6f2b11ea2d506d448e7bf39871886d472 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) \ |
@@ -4160,6 +4162,106 @@ class HLoadGlobalGeneric: public HTemplateInstruction<2> { |
}; |
+class HAllocateObject: public HTemplateInstruction<1> { |
+ public: |
+ HAllocateObject(HValue* context, Handle<JSFunction> constructor) |
+ : constructor_(constructor) { |
+ SetOperandAt(0, context); |
+ set_representation(Representation::Tagged()); |
+ SetGVNFlag(kChangesNewSpacePromotion); |
+ } |
+ |
+ // Maximum instance size for which allocations will be inlined. |
+ static const int kMaxSize = 64 * kPointerSize; |
+ |
+ HValue* context() { return OperandAt(0); } |
+ Handle<JSFunction> constructor() { return constructor_; } |
+ |
+ virtual Representation RequiredInputRepresentation(int index) { |
+ return Representation::Tagged(); |
+ } |
+ virtual Handle<Map> GetMonomorphicJSObjectMap() { |
+ ASSERT(constructor()->has_initial_map()); |
+ return Handle<Map>(constructor()->initial_map()); |
+ } |
+ virtual HType CalculateInferredType(); |
+ |
+ DECLARE_CONCRETE_INSTRUCTION(AllocateObject) |
+ |
+ private: |
+ // TODO(svenpanne) Might be safe, but leave it out until we know for sure. |
+ // virtual bool IsDeletable() const { return true; } |
+ |
+ Handle<JSFunction> constructor_; |
+}; |
+ |
+ |
+class HAllocate: public HTemplateInstruction<2> { |
+ public: |
+ enum Flags { |
+ CAN_ALLOCATE_IN_NEW_SPACE = 1 << 0, |
+ CAN_ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1, |
+ CAN_ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2, |
+ ALLOCATE_DOUBLE_ALIGNED = 1 << 3 |
+ }; |
+ |
+ HAllocate(HValue* context, HValue* size, HType type, Flags flags) |
+ : type_(type), |
+ flags_(flags) { |
+ ASSERT((flags & CAN_ALLOCATE_IN_OLD_DATA_SPACE) == 0); // unimplemented |
+ ASSERT((flags & CAN_ALLOCATE_IN_OLD_POINTER_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 CanAllocateInOldDataSpace() const { |
+ return (flags_ & CAN_ALLOCATE_IN_OLD_DATA_SPACE) != 0; |
+ } |
+ |
+ bool CanAllocateInOldPointerSpace() const { |
+ return (flags_ & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) != 0; |
+ } |
+ |
+ bool CanAllocateInOldSpace() const { |
+ return CanAllocateInOldDataSpace() || |
+ CanAllocateInOldPointerSpace(); |
+ } |
+ |
+ bool GuaranteedInNewSpace() const { |
+ return CanAllocateInNewSpace() && !CanAllocateInOldSpace(); |
+ } |
+ |
+ bool MustAllocateDoubleAligned() const { |
+ return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0; |
+ } |
+ |
+ DECLARE_CONCRETE_INSTRUCTION(Allocate) |
+ |
+ private: |
+ HType type_; |
+ Flags flags_; |
+}; |
+ |
+ |
inline bool StoringValueNeedsWriteBarrier(HValue* value) { |
return !value->type().IsBoolean() |
&& !value->type().IsSmi() |
@@ -4169,8 +4271,13 @@ inline bool StoringValueNeedsWriteBarrier(HValue* value) { |
inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, |
HValue* new_space_dominator) { |
- return (!object->IsAllocateObject() && !object->IsFastLiteral()) || |
- (object != new_space_dominator); |
+ if (object != new_space_dominator) return true; |
+ if (object->IsFastLiteral()) return false; |
+ if (object->IsAllocateObject()) return false; |
+ if (object->IsAllocate()) { |
+ return !HAllocate::cast(object)->GuaranteedInNewSpace(); |
+ } |
+ return true; |
} |
@@ -4502,15 +4609,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); |
@@ -4523,8 +4638,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()); |
} |
@@ -4573,6 +4687,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) |
@@ -4595,6 +4712,7 @@ class HLoadKeyed |
virtual void PrintDataTo(StringStream* stream); |
+ bool UsesMustHandleHole() const; |
bool RequiresHoleCheck() const; |
virtual Range* InferRange(Zone* zone); |
@@ -4619,11 +4737,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 |
}; |
@@ -4633,6 +4753,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 |
@@ -4771,11 +4894,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)) { |
@@ -4843,11 +4973,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()); |
} |
} |
@@ -4861,6 +4999,7 @@ class HStoreKeyed |
ElementsKind elements_kind_; |
uint32_t index_offset_; |
bool is_dehoisted_; |
+ HValue* new_space_dominator_; |
}; |
@@ -4899,9 +5038,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), |
@@ -4909,6 +5049,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()) { |
@@ -4927,6 +5068,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_; } |
@@ -5079,40 +5221,6 @@ class HStringLength: public HUnaryOperation { |
}; |
-class HAllocateObject: public HTemplateInstruction<1> { |
- public: |
- HAllocateObject(HValue* context, Handle<JSFunction> constructor) |
- : constructor_(constructor) { |
- SetOperandAt(0, context); |
- set_representation(Representation::Tagged()); |
- SetGVNFlag(kChangesNewSpacePromotion); |
- } |
- |
- // Maximum instance size for which allocations will be inlined. |
- static const int kMaxSize = 64 * kPointerSize; |
- |
- HValue* context() { return OperandAt(0); } |
- Handle<JSFunction> constructor() { return constructor_; } |
- |
- virtual Representation RequiredInputRepresentation(int index) { |
- return Representation::Tagged(); |
- } |
- virtual Handle<Map> GetMonomorphicJSObjectMap() { |
- ASSERT(constructor()->has_initial_map()); |
- return Handle<Map>(constructor()->initial_map()); |
- } |
- virtual HType CalculateInferredType(); |
- |
- DECLARE_CONCRETE_INSTRUCTION(AllocateObject) |
- |
- private: |
- // TODO(svenpanne) Might be safe, but leave it out until we know for sure. |
- // virtual bool IsDeletable() const { return true; } |
- |
- Handle<JSFunction> constructor_; |
-}; |
- |
- |
template <int V> |
class HMaterializedLiteral: public HTemplateInstruction<V> { |
public: |
@@ -5346,6 +5454,22 @@ class HTypeof: public HTemplateInstruction<2> { |
}; |
+class HTrapAllocationMemento : public HTemplateInstruction<1> { |
+ 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) { |