Index: src/hydrogen-instructions.h |
=================================================================== |
--- src/hydrogen-instructions.h (revision 7683) |
+++ src/hydrogen-instructions.h (working copy) |
@@ -104,6 +104,7 @@ |
V(Goto) \ |
V(HasInstanceType) \ |
V(HasCachedArrayIndex) \ |
+ V(In) \ |
V(InstanceOf) \ |
V(InstanceOfKnownGlobal) \ |
V(InvokeFunction) \ |
@@ -403,6 +404,62 @@ |
}; |
+class HUseListNode: public ZoneObject { |
+ public: |
+ HUseListNode(HValue* value, int index, HUseListNode* tail) |
+ : tail_(tail), value_(value), index_(index) { |
+ } |
+ |
+ HUseListNode* tail() const { return tail_; } |
+ HValue* value() const { return value_; } |
+ int index() const { return index_; } |
+ |
+ void set_tail(HUseListNode* list) { tail_ = list; } |
+ |
+#ifdef DEBUG |
+ void Zap() { |
+ tail_ = reinterpret_cast<HUseListNode*>(1); |
+ value_ = NULL; |
+ index_ = -1; |
+ } |
+#endif |
+ |
+ private: |
+ HUseListNode* tail_; |
+ HValue* value_; |
+ int index_; |
+}; |
+ |
+ |
+// We reuse use list nodes behind the scenes as uses are added and deleted. |
+// This class is the safe way to iterate uses while deleting them. |
+class HUseIterator BASE_EMBEDDED { |
+ public: |
+ bool Done() { return current_ == NULL; } |
+ void Advance(); |
+ |
+ HValue* value() { |
+ ASSERT(!Done()); |
+ return value_; |
+ } |
+ |
+ int index() { |
+ ASSERT(!Done()); |
+ return index_; |
+ } |
+ |
+ private: |
+ explicit HUseIterator(HUseListNode* head); |
+ |
+ HUseListNode* current_; |
+ HUseListNode* next_; |
+ HValue* value_; |
+ int index_; |
+ |
+ friend class HValue; |
+}; |
+ |
+ |
class HValue: public ZoneObject { |
public: |
static const int kNoNumber = -1; |
@@ -473,6 +530,7 @@ |
HValue() : block_(NULL), |
id_(kNoNumber), |
type_(HType::Tagged()), |
+ use_list_(NULL), |
range_(NULL), |
flags_(0) {} |
virtual ~HValue() {} |
@@ -483,7 +541,7 @@ |
int id() const { return id_; } |
void set_id(int id) { id_ = id; } |
- SmallPointerList<HValue>* uses() { return &uses_; } |
+ HUseIterator uses() const { return HUseIterator(use_list_); } |
virtual bool EmitAtUses() { return false; } |
Representation representation() const { return representation_; } |
@@ -498,7 +556,7 @@ |
HType type() const { return type_; } |
void set_type(HType type) { |
- ASSERT(uses_.length() == 0); |
+ ASSERT(HasNoUses()); |
type_ = type; |
} |
@@ -524,16 +582,13 @@ |
virtual HValue* OperandAt(int index) = 0; |
void SetOperandAt(int index, HValue* value); |
- int LookupOperandIndex(int occurrence_index, HValue* op); |
- bool UsesMultipleTimes(HValue* op); |
- |
- void ReplaceAndDelete(HValue* other); |
- void ReplaceValue(HValue* other); |
- void ReplaceAtUse(HValue* use, HValue* other); |
- void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r); |
- bool HasNoUses() const { return uses_.is_empty(); } |
+ void DeleteAndReplaceWith(HValue* other); |
+ bool HasNoUses() const { return use_list_ == NULL; } |
+ bool HasMultipleUses() const { |
+ return use_list_ != NULL && use_list_->tail() != NULL; |
+ } |
+ int UseCount() const; |
void ClearOperands(); |
- void Delete(); |
int flags() const { return flags_; } |
void SetFlag(Flag f) { flags_ |= (1 << f); } |
@@ -611,7 +666,12 @@ |
return ChangesFlagsMask() & ~(1 << kChangesOsrEntries); |
} |
- void InternalReplaceAtUse(HValue* use, HValue* other); |
+ // Remove the matching use from the use list if present. Returns the |
+ // removed list node or NULL. |
+ HUseListNode* RemoveUse(HValue* value, int index); |
+ |
+ void ReplaceAllUsesWith(HValue* other); |
+ |
void RegisterUse(int index, HValue* new_value); |
HBasicBlock* block_; |
@@ -622,7 +682,7 @@ |
Representation representation_; |
HType type_; |
- SmallPointerList<HValue> uses_; |
+ HUseListNode* use_list_; |
Range* range_; |
int flags_; |
@@ -2257,7 +2317,7 @@ |
void SetInputRepresentation(Representation r); |
virtual bool EmitAtUses() { |
- return !HasSideEffects() && (uses()->length() <= 1); |
+ return !HasSideEffects() && !HasMultipleUses(); |
} |
virtual Representation RequiredInputRepresentation(int index) const { |
@@ -2299,7 +2359,7 @@ |
} |
virtual bool EmitAtUses() { |
- return !HasSideEffects() && (uses()->length() <= 1); |
+ return !HasSideEffects() && !HasMultipleUses(); |
} |
virtual Representation RequiredInputRepresentation(int index) const { |
@@ -2322,7 +2382,7 @@ |
} |
virtual bool EmitAtUses() { |
- return !HasSideEffects() && (uses()->length() <= 1); |
+ return !HasSideEffects() && !HasMultipleUses(); |
} |
virtual Representation RequiredInputRepresentation(int index) const { |
@@ -2382,7 +2442,7 @@ |
} |
virtual bool EmitAtUses() { |
- return !HasSideEffects() && (uses()->length() <= 1); |
+ return !HasSideEffects() && !HasMultipleUses(); |
} |
virtual Representation RequiredInputRepresentation(int index) const { |
@@ -2504,7 +2564,7 @@ |
HValue* right() { return OperandAt(2); } |
virtual bool EmitAtUses() { |
- return !HasSideEffects() && (uses()->length() <= 1); |
+ return !HasSideEffects() && !HasMultipleUses(); |
} |
virtual Representation RequiredInputRepresentation(int index) const { |
@@ -3187,7 +3247,8 @@ |
ExternalArrayType array_type) |
: HBinaryOperation(external_elements, key), |
array_type_(array_type) { |
- if (array_type == kExternalFloatArray) { |
+ if (array_type == kExternalFloatArray || |
+ array_type == kExternalDoubleArray) { |
set_representation(Representation::Double()); |
} else { |
set_representation(Representation::Integer32()); |
@@ -3379,7 +3440,8 @@ |
if (index == 0) { |
return Representation::External(); |
} else { |
- if (index == 2 && array_type() == kExternalFloatArray) { |
+ if (index == 2 && (array_type() == kExternalFloatArray || |
+ array_type() == kExternalDoubleArray)) { |
return Representation::Double(); |
} else { |
return Representation::Integer32(); |
@@ -3719,6 +3781,32 @@ |
HValue* key() { return right(); } |
}; |
+ |
+class HIn: public HTemplateInstruction<2> { |
+ public: |
+ HIn(HValue* key, HValue* object) { |
+ SetOperandAt(0, key); |
+ SetOperandAt(1, object); |
+ set_representation(Representation::Tagged()); |
+ SetAllSideEffects(); |
+ } |
+ |
+ HValue* key() { return OperandAt(0); } |
+ HValue* object() { return OperandAt(1); } |
+ |
+ virtual Representation RequiredInputRepresentation(int index) const { |
+ return Representation::Tagged(); |
+ } |
+ |
+ virtual HType CalculateInferredType() { |
+ return HType::Boolean(); |
+ } |
+ |
+ virtual void PrintDataTo(StringStream* stream); |
+ |
+ DECLARE_CONCRETE_INSTRUCTION(In) |
+}; |
+ |
#undef DECLARE_INSTRUCTION |
#undef DECLARE_CONCRETE_INSTRUCTION |