Index: src/hydrogen-instructions.h |
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
index 0c3ee1dc081101e47646daa14e0c1beb464f9ceb..772185a7446054a3ea9f54382286f19e4d75eb87 100644 |
--- a/src/hydrogen-instructions.h |
+++ b/src/hydrogen-instructions.h |
@@ -5238,35 +5238,92 @@ class HStoreContextSlot: public HTemplateInstruction<2> { |
}; |
+// Represents an access (load or store) to a portion of an object for GVN. |
+// TODO(titzer): only represents non-array-element loads and stores for now |
+class ObjectAccess { |
+ public: |
+ enum Portion { |
+ kElementsKind, |
danno
2013/04/26 09:39:38
The seems redundant to me. It seems like this is w
titzer
2013/04/30 15:56:47
As discussed in person, I think we can make this w
|
+ kArrayLengths, |
+ kInobject, |
+ kBackingStore, |
+ kElementsPointer, |
+ kMaps |
+ }; |
+ |
+ ObjectAccess(Portion portion, int offset, bool may_allocate, |
+ Handle<String> name = Handle<String>::null()) |
+ : portion_(portion), offset_(offset), may_allocate_(may_allocate) { } |
+ |
+ void SetGVNFlags(HValue *instr, bool is_store) { |
danno
2013/04/26 09:39:38
Make this protected and add HLoadNamedFiled and HS
titzer
2013/04/30 15:56:47
Done.
|
+ // set the appropriate GVN flags for a given load or store instruction |
+ if (!is_store) { |
+ instr->SetFlag(HValue::kUseGVN); // try to GVN loads |
+ instr->SetGVNFlag(kDependsOnMaps); // but don't hoist above map changes |
+ } |
+ |
+ // if this instruction might trigger an allocation |
+ if (may_allocate_) instr->SetGVNFlag(kChangesNewSpacePromotion); |
danno
2013/04/26 09:39:38
When does this actually happen? We should try to g
titzer
2013/04/30 15:56:47
Done.
|
+ |
+ switch (portion_) { |
+ case kElementsKind: |
+ instr->SetGVNFlag( |
+ is_store ? kChangesElementsKind : kDependsOnElementsKind); |
danno
2013/04/26 09:39:38
Don't know if it makes the code cleaner, but maybe
titzer
2013/04/30 15:56:47
That method takes a GVNFlagSet and does a shift. I
|
+ break; |
+ case kArrayLengths: |
+ instr->SetGVNFlag( |
+ is_store ? kChangesArrayLengths : kDependsOnArrayLengths); |
+ break; |
+ case kInobject: |
+ instr->SetGVNFlag( |
+ is_store ? kChangesInobjectFields : kDependsOnInobjectFields); |
+ break; |
+ case kBackingStore: |
+ instr->SetGVNFlag( |
+ is_store ? kChangesBackingStoreFields : kDependsOnBackingStoreFields); |
+ break; |
+ case kElementsPointer: |
+ instr->SetGVNFlag( |
+ is_store ? kChangesElementsPointer : kDependsOnElementsPointer); |
+ break; |
+ case kMaps: |
+ instr->SetGVNFlag( |
+ is_store ? kChangesMaps : kDependsOnMaps); |
+ break; |
+ } |
danno
2013/04/26 09:39:38
This guy really belongs in the .cc file.
titzer
2013/04/30 15:56:47
Done.
|
+ } |
+ |
+ inline bool IsInobject() { |
+ return portion_ != kBackingStore; |
+ } |
+ |
+ inline int offset() { |
+ return offset_; |
+ } |
+ |
+ inline Handle<String> name() { |
danno
2013/04/26 09:39:38
This can be calculated by looking in the map's fie
titzer
2013/04/30 15:56:47
I agree with that approach in the long run. We can
|
+ return name_; |
+ } |
+ |
+ private: |
+ Portion portion_; |
+ int offset_; |
+ bool may_allocate_; |
+ Handle<String> name_; |
danno
2013/04/26 09:39:38
You don't need to store this it can be looked-up i
danno
2013/05/02 14:16:47
You didn't address this comment. Why not?
On 2013
|
+}; |
+ |
+ |
class HLoadNamedField: public HTemplateInstruction<2> { |
public: |
- HLoadNamedField(HValue* object, bool is_in_object, int offset, |
- HValue* typecheck = NULL) |
- : is_in_object_(is_in_object), |
- offset_(offset) { |
+ HLoadNamedField(HValue* object, ObjectAccess access, HValue* typecheck = NULL) |
danno
2013/04/26 09:39:38
Unless the objects is the size of intptr_t, then w
titzer
2013/04/30 15:56:47
Done.
|
+ : is_in_object_(access.IsInobject()), |
+ offset_(access.offset()) { |
ASSERT(object != NULL); |
SetOperandAt(0, object); |
SetOperandAt(1, typecheck != NULL ? typecheck : object); |
set_representation(Representation::Tagged()); |
- SetFlag(kUseGVN); |
- SetGVNFlag(kDependsOnMaps); |
- if (is_in_object) { |
- SetGVNFlag(kDependsOnInobjectFields); |
- } else { |
- SetGVNFlag(kDependsOnBackingStoreFields); |
- } |
- } |
- |
- static HLoadNamedField* NewArrayLength(Zone* zone, HValue* object, |
- HValue* typecheck, |
- HType type = HType::Tagged()) { |
- HLoadNamedField* result = new(zone) HLoadNamedField( |
- object, true, JSArray::kLengthOffset, typecheck); |
- result->set_type(type); |
- result->SetGVNFlag(kDependsOnArrayLengths); |
- result->ClearGVNFlag(kDependsOnInobjectFields); |
- return result; |
+ access.SetGVNFlags(this, false); |
} |
HValue* object() { return OperandAt(0); } |
@@ -5590,24 +5647,17 @@ class HLoadKeyedGeneric: public HTemplateInstruction<3> { |
class HStoreNamedField: public HTemplateInstruction<2> { |
public: |
HStoreNamedField(HValue* obj, |
- Handle<String> name, |
- HValue* val, |
- bool in_object, |
- int offset) |
- : name_(name), |
- is_in_object_(in_object), |
- offset_(offset), |
+ ObjectAccess access, |
+ HValue* val) |
+ : name_(access.name()), |
+ is_in_object_(access.IsInobject()), |
+ offset_(access.offset()), |
transition_unique_id_(), |
new_space_dominator_(NULL) { |
SetOperandAt(0, obj); |
SetOperandAt(1, val); |
SetFlag(kTrackSideEffectDominators); |
- SetGVNFlag(kDependsOnNewSpacePromotion); |
- if (is_in_object_) { |
- SetGVNFlag(kChangesInobjectFields); |
- } else { |
- SetGVNFlag(kChangesBackingStoreFields); |
- } |
+ access.SetGVNFlags(this, true); |
} |
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) |