| Index: src/hydrogen-instructions.h
|
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
|
| index d0dd5680c0485555b013113e97cf0ea9e8d59701..f634a4488f36ef4593f8fc99a2818be563676fb1 100644
|
| --- a/src/hydrogen-instructions.h
|
| +++ b/src/hydrogen-instructions.h
|
| @@ -188,7 +188,10 @@ class LChunkBuilder;
|
| V(DateField) \
|
| V(WrapReceiver)
|
|
|
| -#define GVN_FLAG_LIST(V) \
|
| +#define GVN_TRACKED_FLAG_LIST(V) \
|
| + V(NewSpacePromotion)
|
| +
|
| +#define GVN_UNTRACKED_FLAG_LIST(V) \
|
| V(Calls) \
|
| V(InobjectFields) \
|
| V(BackingStoreFields) \
|
| @@ -506,14 +509,18 @@ class HUseIterator BASE_EMBEDDED {
|
|
|
| // There must be one corresponding kDepends flag for every kChanges flag and
|
| // the order of the kChanges flags must be exactly the same as of the kDepends
|
| -// flags.
|
| +// flags. All tracked flags should appear before untracked ones.
|
| enum GVNFlag {
|
| // Declare global value numbering flags.
|
| #define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
|
| - GVN_FLAG_LIST(DECLARE_FLAG)
|
| + GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
|
| + GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
|
| #undef DECLARE_FLAG
|
| kAfterLastFlag,
|
| - kLastFlag = kAfterLastFlag - 1
|
| + kLastFlag = kAfterLastFlag - 1,
|
| +#define COUNT_FLAG(type) + 1
|
| + kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG)
|
| +#undef COUNT_FLAG
|
| };
|
|
|
| typedef EnumSet<GVNFlag> GVNFlagSet;
|
| @@ -530,6 +537,10 @@ class HValue: public ZoneObject {
|
| // implement DataEquals(), which will be used to determine if other
|
| // occurrences of the instruction are indeed the same.
|
| kUseGVN,
|
| + // Track instructions that are dominating side effects. If an instruction
|
| + // sets this flag, it must implement SetSideEffectDominator() and should
|
| + // indicate which side effects to track by setting GVN flags.
|
| + kTrackSideEffectDominators,
|
| kCanOverflow,
|
| kBailoutOnMinusZero,
|
| kCanBeDivByZero,
|
| @@ -544,6 +555,12 @@ class HValue: public ZoneObject {
|
|
|
| static const int kChangesToDependsFlagsLeftShift = 1;
|
|
|
| + static GVNFlag ChangesFlagFromInt(int x) {
|
| + return static_cast<GVNFlag>(x * 2);
|
| + }
|
| + static GVNFlag DependsOnFlagFromInt(int x) {
|
| + return static_cast<GVNFlag>(x * 2 + 1);
|
| + }
|
| static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
|
| return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
|
| }
|
| @@ -726,6 +743,13 @@ class HValue: public ZoneObject {
|
|
|
| virtual HType CalculateInferredType();
|
|
|
| + // This function must be overridden for instructions which have the
|
| + // kTrackSideEffectDominators flag set, to track instructions that are
|
| + // dominating side effects.
|
| + virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
|
| + UNREACHABLE();
|
| + }
|
| +
|
| #ifdef DEBUG
|
| virtual void Verify() = 0;
|
| #endif
|
| @@ -756,7 +780,8 @@ class HValue: public ZoneObject {
|
| GVNFlagSet result;
|
| // Create changes mask.
|
| #define ADD_FLAG(type) result.Add(kDependsOn##type);
|
| - GVN_FLAG_LIST(ADD_FLAG)
|
| + GVN_TRACKED_FLAG_LIST(ADD_FLAG)
|
| + GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
|
| #undef ADD_FLAG
|
| return result;
|
| }
|
| @@ -765,7 +790,8 @@ class HValue: public ZoneObject {
|
| GVNFlagSet result;
|
| // Create changes mask.
|
| #define ADD_FLAG(type) result.Add(kChanges##type);
|
| - GVN_FLAG_LIST(ADD_FLAG)
|
| + GVN_TRACKED_FLAG_LIST(ADD_FLAG)
|
| + GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
|
| #undef ADD_FLAG
|
| return result;
|
| }
|
| @@ -781,6 +807,7 @@ class HValue: public ZoneObject {
|
| // an executing program (i.e. are not safe to repeat, move or remove);
|
| static GVNFlagSet AllObservableSideEffectsFlagSet() {
|
| GVNFlagSet result = AllChangesFlagSet();
|
| + result.Remove(kChangesNewSpacePromotion);
|
| result.Remove(kChangesElementsKind);
|
| result.Remove(kChangesElementsPointer);
|
| result.Remove(kChangesMaps);
|
| @@ -3557,6 +3584,12 @@ inline bool StoringValueNeedsWriteBarrier(HValue* value) {
|
| }
|
|
|
|
|
| +inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
|
| + HValue* new_space_dominator) {
|
| + return !object->IsAllocateObject() || (object != new_space_dominator);
|
| +}
|
| +
|
| +
|
| class HStoreGlobalCell: public HUnaryOperation {
|
| public:
|
| HStoreGlobalCell(HValue* value,
|
| @@ -4023,9 +4056,12 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
| int offset)
|
| : name_(name),
|
| is_in_object_(in_object),
|
| - offset_(offset) {
|
| + offset_(offset),
|
| + new_space_dominator_(NULL) {
|
| SetOperandAt(0, obj);
|
| SetOperandAt(1, val);
|
| + SetFlag(kTrackSideEffectDominators);
|
| + SetGVNFlag(kDependsOnNewSpacePromotion);
|
| if (is_in_object_) {
|
| SetGVNFlag(kChangesInobjectFields);
|
| } else {
|
| @@ -4038,6 +4074,10 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| }
|
| + virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
|
| + ASSERT(side_effect == kChangesNewSpacePromotion);
|
| + new_space_dominator_ = dominator;
|
| + }
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| HValue* object() { return OperandAt(0); }
|
| @@ -4048,9 +4088,11 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
| int offset() const { return offset_; }
|
| Handle<Map> transition() const { return transition_; }
|
| void set_transition(Handle<Map> map) { transition_ = map; }
|
| + HValue* new_space_dominator() const { return new_space_dominator_; }
|
|
|
| bool NeedsWriteBarrier() {
|
| - return StoringValueNeedsWriteBarrier(value());
|
| + return StoringValueNeedsWriteBarrier(value()) &&
|
| + ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
|
| }
|
|
|
| private:
|
| @@ -4058,6 +4100,7 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
| bool is_in_object_;
|
| int offset_;
|
| Handle<Map> transition_;
|
| + HValue* new_space_dominator_;
|
| };
|
|
|
|
|
| @@ -4404,6 +4447,7 @@ class HAllocateObject: public HTemplateInstruction<1> {
|
| : constructor_(constructor) {
|
| SetOperandAt(0, context);
|
| set_representation(Representation::Tagged());
|
| + SetGVNFlag(kChangesNewSpacePromotion);
|
| }
|
|
|
| // Maximum instance size for which allocations will be inlined.
|
|
|