Index: src/hydrogen-instructions.h |
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
index c765d62cd75b06220e9c84b9ad583bc613bd3019..22de75b19390c7300f4324722dd9adcc127834ee 100644 |
--- a/src/hydrogen-instructions.h |
+++ b/src/hydrogen-instructions.h |
@@ -45,7 +45,7 @@ namespace internal { |
// Forward declarations. |
class HBasicBlock; |
class HEnvironment; |
-class HInferRepresentation; |
+class HInferRepresentationPhase; |
class HInstruction; |
class HLoopInformation; |
class HValue; |
@@ -92,10 +92,11 @@ class LChunkBuilder; |
V(CheckHeapObject) \ |
V(CheckInstanceType) \ |
V(CheckMaps) \ |
+ V(CheckSmi) \ |
V(CheckPrototypeMaps) \ |
V(ClampToUint8) \ |
V(ClassOfTestAndBranch) \ |
- V(CompareIDAndBranch) \ |
+ V(CompareNumericAndBranch) \ |
V(CompareGeneric) \ |
V(CompareObjectEqAndBranch) \ |
V(CompareMap) \ |
@@ -111,7 +112,6 @@ class LChunkBuilder; |
V(ElementsKind) \ |
V(EnterInlined) \ |
V(EnvironmentMarker) \ |
- V(FixedArrayBaseLength) \ |
V(ForceRepresentation) \ |
V(FunctionLiteral) \ |
V(GetCachedArrayIndex) \ |
@@ -129,6 +129,7 @@ class LChunkBuilder; |
V(InvokeFunction) \ |
V(IsConstructCallAndBranch) \ |
V(IsObjectAndBranch) \ |
+ V(IsNumberAndBranch) \ |
V(IsStringAndBranch) \ |
V(IsSmiAndBranch) \ |
V(IsUndetectableAndBranch) \ |
@@ -1062,12 +1063,15 @@ class HValue: public ZoneObject { |
void RemoveLastAddedRange(); |
void ComputeInitialRange(Zone* zone); |
+ // Escape analysis helpers. |
+ virtual bool HasEscapingOperandAt(int index) { return true; } |
+ |
// Representation helpers. |
virtual Representation observed_input_representation(int index) { |
return Representation::None(); |
} |
virtual Representation RequiredInputRepresentation(int index) = 0; |
- virtual void InferRepresentation(HInferRepresentation* h_infer); |
+ virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
// This gives the instruction an opportunity to replace itself with an |
// instruction that does the same in some better way. To replace an |
@@ -1159,9 +1163,9 @@ class HValue: public ZoneObject { |
Representation RepresentationFromUses(); |
Representation RepresentationFromUseRequirements(); |
virtual void UpdateRepresentation(Representation new_rep, |
- HInferRepresentation* h_infer, |
+ HInferRepresentationPhase* h_infer, |
const char* reason); |
- void AddDependantsToWorklist(HInferRepresentation* h_infer); |
+ void AddDependantsToWorklist(HInferRepresentationPhase* h_infer); |
virtual void RepresentationChanged(Representation to) { } |
@@ -1433,6 +1437,7 @@ class HDummyUse: public HTemplateInstruction<1> { |
HValue* value() { return OperandAt(0); } |
+ virtual bool HasEscapingOperandAt(int index) { return false; } |
virtual Representation RequiredInputRepresentation(int index) { |
return Representation::None(); |
} |
@@ -1601,21 +1606,11 @@ class HUnaryControlInstruction: public HTemplateControlInstruction<2, 1> { |
class HBranch: public HUnaryControlInstruction { |
public: |
HBranch(HValue* value, |
- HBasicBlock* true_target, |
- HBasicBlock* false_target, |
- ToBooleanStub::Types expected_input_types = ToBooleanStub::Types()) |
+ ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(), |
+ HBasicBlock* true_target = NULL, |
+ HBasicBlock* false_target = NULL) |
: HUnaryControlInstruction(value, true_target, false_target), |
expected_input_types_(expected_input_types) { |
- ASSERT(true_target != NULL && false_target != NULL); |
- SetFlag(kAllowUndefinedAsNaN); |
- } |
- explicit HBranch(HValue* value) |
- : HUnaryControlInstruction(value, NULL, NULL) { |
- SetFlag(kAllowUndefinedAsNaN); |
- } |
- HBranch(HValue* value, ToBooleanStub::Types expected_input_types) |
- : HUnaryControlInstruction(value, NULL, NULL), |
- expected_input_types_(expected_input_types) { |
SetFlag(kAllowUndefinedAsNaN); |
} |
@@ -1639,12 +1634,10 @@ class HCompareMap: public HUnaryControlInstruction { |
public: |
HCompareMap(HValue* value, |
Handle<Map> map, |
- HBasicBlock* true_target, |
- HBasicBlock* false_target) |
+ HBasicBlock* true_target = NULL, |
+ HBasicBlock* false_target = NULL) |
: HUnaryControlInstruction(value, true_target, false_target), |
- map_(map) { |
- ASSERT(true_target != NULL); |
- ASSERT(false_target != NULL); |
+ map_(map) { |
ASSERT(!map.is_null()); |
} |
@@ -1892,6 +1885,7 @@ class HSimulate: public HInstruction { |
virtual int OperandCount() { return values_.length(); } |
virtual HValue* OperandAt(int index) const { return values_[index]; } |
+ virtual bool HasEscapingOperandAt(int index) { return false; } |
virtual Representation RequiredInputRepresentation(int index) { |
return Representation::None(); |
} |
@@ -2488,12 +2482,12 @@ class HCallNew: public HBinaryCall { |
class HCallNewArray: public HCallNew { |
public: |
HCallNewArray(HValue* context, HValue* constructor, int argument_count, |
- Handle<Cell> type_cell) |
+ Handle<Cell> type_cell, ElementsKind elements_kind) |
: HCallNew(context, constructor, argument_count), |
- type_cell_(type_cell) { |
- elements_kind_ = static_cast<ElementsKind>( |
- Smi::cast(type_cell->value())->value()); |
- } |
+ elements_kind_(elements_kind), |
+ type_cell_(type_cell) {} |
+ |
+ virtual void PrintDataTo(StringStream* stream); |
Handle<Cell> property_cell() const { |
return type_cell_; |
@@ -2537,29 +2531,6 @@ class HCallRuntime: public HCall<1> { |
}; |
-class HFixedArrayBaseLength: public HUnaryOperation { |
- public: |
- explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) { |
- set_type(HType::Smi()); |
- set_representation(Representation::Smi()); |
- SetFlag(kUseGVN); |
- SetGVNFlag(kDependsOnArrayLengths); |
- } |
- |
- virtual Representation RequiredInputRepresentation(int index) { |
- return Representation::Tagged(); |
- } |
- |
- DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength) |
- |
- protected: |
- virtual bool DataEquals(HValue* other) { return true; } |
- |
- private: |
- virtual bool IsDeletable() const { return true; } |
-}; |
- |
- |
class HMapEnumLength: public HUnaryOperation { |
public: |
explicit HMapEnumLength(HValue* value) : HUnaryOperation(value) { |
@@ -2801,6 +2772,7 @@ class HCheckMaps: public HTemplateInstruction<2> { |
return check_map; |
} |
+ virtual bool HasEscapingOperandAt(int index) { return false; } |
virtual Representation RequiredInputRepresentation(int index) { |
return Representation::Tagged(); |
} |
@@ -2866,6 +2838,8 @@ class HCheckFunction: public HUnaryOperation { |
virtual void PrintDataTo(StringStream* stream); |
virtual HType CalculateInferredType(); |
+ virtual HValue* Canonicalize(); |
+ |
#ifdef DEBUG |
virtual void Verify(); |
#endif |
@@ -2952,6 +2926,49 @@ class HCheckInstanceType: public HUnaryOperation { |
}; |
+class HCheckSmi: public HUnaryOperation { |
+ public: |
+ explicit HCheckSmi(HValue* value) : HUnaryOperation(value) { |
+ set_representation(Representation::Smi()); |
+ SetFlag(kUseGVN); |
+ } |
+ |
+ virtual Representation RequiredInputRepresentation(int index) { |
+ return Representation::Tagged(); |
+ } |
+ |
+ virtual HType CalculateInferredType(); |
+ |
+ virtual HValue* Canonicalize() { |
+ HType value_type = value()->type(); |
+ if (value_type.IsSmi()) { |
+ return NULL; |
+ } |
+ return this; |
+ } |
+ |
+ DECLARE_CONCRETE_INSTRUCTION(CheckSmi) |
+ |
+ protected: |
+ virtual bool DataEquals(HValue* other) { return true; } |
+}; |
+ |
+ |
+class HIsNumberAndBranch: public HUnaryControlInstruction { |
+ public: |
+ explicit HIsNumberAndBranch(HValue* value) |
+ : HUnaryControlInstruction(value, NULL, NULL) { |
+ SetFlag(kFlexibleRepresentation); |
+ } |
+ |
+ virtual Representation RequiredInputRepresentation(int index) { |
+ return Representation::None(); |
+ } |
+ |
+ DECLARE_CONCRETE_INSTRUCTION(IsNumberAndBranch) |
+}; |
+ |
+ |
class HCheckHeapObject: public HUnaryOperation { |
public: |
explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) { |
@@ -3075,7 +3092,7 @@ class HPhi: public HValue { |
virtual Representation RepresentationFromInputs(); |
virtual Range* InferRange(Zone* zone); |
- virtual void InferRepresentation(HInferRepresentation* h_infer); |
+ virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
virtual Representation RequiredInputRepresentation(int index) { |
return representation(); |
} |
@@ -3228,6 +3245,7 @@ class HArgumentsObject: public HTemplateInstruction<0> { |
virtual int OperandCount() { return values_.length(); } |
virtual HValue* OperandAt(int index) const { return values_[index]; } |
+ virtual bool HasEscapingOperandAt(int index) { return false; } |
virtual Representation RequiredInputRepresentation(int index) { |
return Representation::None(); |
} |
@@ -3263,6 +3281,7 @@ class HConstant: public HTemplateInstruction<0> { |
HType type, |
bool is_internalized_string, |
bool is_not_in_new_space, |
+ bool is_cell, |
bool boolean_value); |
Handle<Object> handle() { |
@@ -3311,6 +3330,10 @@ class HConstant: public HTemplateInstruction<0> { |
unique_id_ == UniqueValueId(heap->empty_string()); |
} |
+ bool IsCell() const { |
+ return is_cell_; |
+ } |
+ |
virtual Representation RequiredInputRepresentation(int index) { |
return Representation::None(); |
} |
@@ -3322,7 +3345,7 @@ class HConstant: public HTemplateInstruction<0> { |
return Representation::Tagged(); |
} |
- virtual bool EmitAtUses() { return !representation().IsDouble(); } |
+ virtual bool EmitAtUses(); |
virtual void PrintDataTo(StringStream* stream); |
virtual HType CalculateInferredType(); |
bool IsInteger() { return handle()->IsSmi(); } |
@@ -3390,6 +3413,11 @@ class HConstant: public HTemplateInstruction<0> { |
} |
} |
+ bool UniqueValueIdsMatch(UniqueValueId other) { |
+ if (!has_double_value_) return unique_id_ == other; |
+ return false; |
+ } |
+ |
#ifdef DEBUG |
virtual void Verify() { } |
#endif |
@@ -3437,6 +3465,7 @@ class HConstant: public HTemplateInstruction<0> { |
bool has_double_value_ : 1; |
bool is_internalized_string_ : 1; // TODO(yangguo): make this part of HType. |
bool is_not_in_new_space_ : 1; |
+ bool is_cell_ : 1; |
bool boolean_value_ : 1; |
int32_t int32_value_; |
double double_value_; |
@@ -3497,12 +3526,12 @@ class HBinaryOperation: public HTemplateInstruction<3> { |
return observed_input_representation_[index - 1]; |
} |
- virtual void InferRepresentation(HInferRepresentation* h_infer); |
+ virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
virtual Representation RepresentationFromInputs(); |
virtual void AssumeRepresentation(Representation r); |
virtual void UpdateRepresentation(Representation new_rep, |
- HInferRepresentation* h_infer, |
+ HInferRepresentationPhase* h_infer, |
const char* reason) { |
// By default, binary operations don't handle Smis. |
if (new_rep.IsSmi()) { |
@@ -3714,7 +3743,7 @@ class HBoundsCheck: public HTemplateInstruction<2> { |
int scale = 0); |
virtual void PrintDataTo(StringStream* stream); |
- virtual void InferRepresentation(HInferRepresentation* h_infer); |
+ virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
HValue* index() { return OperandAt(0); } |
HValue* length() { return OperandAt(1); } |
@@ -3811,7 +3840,7 @@ class HBitwiseBinaryOperation: public HBinaryOperation { |
} |
virtual void UpdateRepresentation(Representation new_rep, |
- HInferRepresentation* h_infer, |
+ HInferRepresentationPhase* h_infer, |
const char* reason) { |
// We only generate either int32 or generic tagged bitwise operations. |
if (new_rep.IsSmi() || new_rep.IsDouble()) { |
@@ -3926,9 +3955,9 @@ class HCompareGeneric: public HBinaryOperation { |
}; |
-class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> { |
+class HCompareNumericAndBranch: public HTemplateControlInstruction<2, 2> { |
public: |
- HCompareIDAndBranch(HValue* left, HValue* right, Token::Value token) |
+ HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token) |
: token_(token) { |
SetFlag(kFlexibleRepresentation); |
ASSERT(Token::IsCompareOp(token)); |
@@ -3946,7 +3975,7 @@ class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> { |
observed_input_representation_[1] = right; |
} |
- virtual void InferRepresentation(HInferRepresentation* h_infer); |
+ virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
virtual Representation RequiredInputRepresentation(int index) { |
return representation(); |
@@ -3958,7 +3987,7 @@ class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> { |
virtual void AddInformativeDefinitions(); |
- DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch) |
+ DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch) |
private: |
Representation observed_input_representation_[2]; |
@@ -4563,7 +4592,7 @@ class HMathMinMax: public HArithmeticBinaryOperation { |
return RequiredInputRepresentation(index); |
} |
- virtual void InferRepresentation(HInferRepresentation* h_infer); |
+ virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
virtual Representation RepresentationFromInputs() { |
Representation left_rep = left()->representation(); |
@@ -4735,6 +4764,7 @@ class HOsrEntry: public HTemplateInstruction<0> { |
public: |
explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) { |
SetGVNFlag(kChangesOsrEntries); |
+ SetGVNFlag(kChangesNewSpacePromotion); |
} |
BailoutId ast_id() const { return ast_id_; } |
@@ -5089,6 +5119,9 @@ inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, |
HInnerAllocatedObject::cast(object)->base_object(), |
new_space_dominator); |
} |
+ if (object->IsConstant() && HConstant::cast(object)->IsCell()) { |
+ return false; |
+ } |
if (object != new_space_dominator) return true; |
if (object->IsAllocateObject()) return false; |
if (object->IsAllocate()) { |
@@ -5314,6 +5347,10 @@ class HObjectAccess { |
return HObjectAccess(kArrayLengths, JSArray::kLengthOffset); |
} |
+ static HObjectAccess ForAllocationSitePayload() { |
+ return HObjectAccess(kInobject, AllocationSite::kPayloadOffset); |
+ } |
+ |
static HObjectAccess ForFixedArrayLength() { |
return HObjectAccess(kArrayLengths, FixedArray::kLengthOffset); |
} |
@@ -5330,8 +5367,16 @@ class HObjectAccess { |
return HObjectAccess(kMaps, JSObject::kMapOffset); |
} |
- static HObjectAccess ForAllocationSitePayload() { |
- return HObjectAccess(kInobject, AllocationSiteInfo::kPayloadOffset); |
+ static HObjectAccess ForPropertyCellValue() { |
+ return HObjectAccess(kInobject, PropertyCell::kValueOffset); |
+ } |
+ |
+ static HObjectAccess ForCellValue() { |
+ return HObjectAccess(kInobject, Cell::kValueOffset); |
+ } |
+ |
+ static HObjectAccess ForAllocationSiteInfoSite() { |
+ return HObjectAccess(kInobject, AllocationSiteInfo::kAllocationSiteOffset); |
} |
// Create an access to an offset in a fixed array header. |
@@ -5350,6 +5395,9 @@ class HObjectAccess { |
static HObjectAccess ForField(Handle<Map> map, |
LookupResult *lookup, Handle<String> name = Handle<String>::null()); |
+ // Create an access for the payload of a Cell or JSGlobalPropertyCell. |
+ static HObjectAccess ForCellPayload(Isolate* isolate); |
+ |
void PrintTo(StringStream* stream); |
inline bool Equals(HObjectAccess that) const { |
@@ -5431,6 +5479,7 @@ class HLoadNamedField: public HTemplateInstruction<2> { |
HObjectAccess access() const { return access_; } |
Representation field_representation() const { return representation_; } |
+ virtual bool HasEscapingOperandAt(int index) { return false; } |
virtual Representation RequiredInputRepresentation(int index) { |
return Representation::Tagged(); |
} |
@@ -5755,7 +5804,8 @@ class HStoreNamedField: public HTemplateInstruction<2> { |
field_representation_(field_representation), |
transition_(), |
transition_unique_id_(), |
- new_space_dominator_(NULL) { |
+ new_space_dominator_(NULL), |
+ write_barrier_mode_(UPDATE_WRITE_BARRIER) { |
SetOperandAt(0, obj); |
SetOperandAt(1, val); |
access.SetGVNFlags(this, true); |
@@ -5763,6 +5813,7 @@ class HStoreNamedField: public HTemplateInstruction<2> { |
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) |
+ virtual bool HasEscapingOperandAt(int index) { return index == 1; } |
virtual Representation RequiredInputRepresentation(int index) { |
if (FLAG_track_double_fields && |
index == 1 && field_representation_.IsDouble()) { |
@@ -5779,6 +5830,11 @@ class HStoreNamedField: public HTemplateInstruction<2> { |
} |
virtual void PrintDataTo(StringStream* stream); |
+ void SkipWriteBarrier() { write_barrier_mode_ = SKIP_WRITE_BARRIER; } |
+ bool IsSkipWriteBarrier() const { |
+ return write_barrier_mode_ == SKIP_WRITE_BARRIER; |
+ } |
+ |
HValue* object() { return OperandAt(0); } |
HValue* value() { return OperandAt(1); } |
@@ -5797,6 +5853,7 @@ class HStoreNamedField: public HTemplateInstruction<2> { |
bool NeedsWriteBarrier() { |
ASSERT(!(FLAG_track_double_fields && field_representation_.IsDouble()) || |
transition_.is_null()); |
+ if (IsSkipWriteBarrier()) return false; |
return (!FLAG_track_fields || !field_representation_.IsSmi()) && |
// If there is a transition, a new storage object needs to be allocated. |
!(FLAG_track_double_fields && field_representation_.IsDouble()) && |
@@ -5805,6 +5862,7 @@ class HStoreNamedField: public HTemplateInstruction<2> { |
} |
bool NeedsWriteBarrierForMap() { |
+ if (IsSkipWriteBarrier()) return false; |
return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); |
} |
@@ -5822,6 +5880,7 @@ class HStoreNamedField: public HTemplateInstruction<2> { |
Handle<Map> transition_; |
UniqueValueId transition_unique_id_; |
HValue* new_space_dominator_; |
+ WriteBarrierMode write_barrier_mode_; |
}; |
@@ -5868,6 +5927,7 @@ class HStoreKeyed |
: elements_kind_(elements_kind), |
index_offset_(0), |
is_dehoisted_(false), |
+ is_uninitialized_(false), |
new_space_dominator_(NULL) { |
SetOperandAt(0, obj); |
SetOperandAt(1, key); |
@@ -5895,6 +5955,7 @@ class HStoreKeyed |
} |
} |
+ virtual bool HasEscapingOperandAt(int index) { return index != 0; } |
virtual Representation RequiredInputRepresentation(int index) { |
// kind_fast: tagged[int32] = tagged |
// kind_double: tagged[int32] = double |
@@ -5927,6 +5988,9 @@ class HStoreKeyed |
virtual Representation observed_input_representation(int index) { |
if (index < 2) return RequiredInputRepresentation(index); |
+ if (IsUninitialized()) { |
+ return Representation::None(); |
+ } |
if (IsFastSmiElementsKind(elements_kind())) { |
return Representation::Smi(); |
} |
@@ -5953,6 +6017,10 @@ class HStoreKeyed |
void SetKey(HValue* key) { SetOperandAt(1, key); } |
bool IsDehoisted() { return is_dehoisted_; } |
void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; } |
+ bool IsUninitialized() { return is_uninitialized_; } |
+ void SetUninitialized(bool is_uninitialized) { |
+ is_uninitialized_ = is_uninitialized; |
+ } |
bool IsConstantHoleStore() { |
return value()->IsConstant() && HConstant::cast(value())->IsTheHole(); |
@@ -5983,7 +6051,8 @@ class HStoreKeyed |
private: |
ElementsKind elements_kind_; |
uint32_t index_offset_; |
- bool is_dehoisted_; |
+ bool is_dehoisted_ : 1; |
+ bool is_uninitialized_ : 1; |
HValue* new_space_dominator_; |
}; |