OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 15 matching lines...) Expand all Loading... |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_ | 28 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_ |
29 #define V8_HYDROGEN_INSTRUCTIONS_H_ | 29 #define V8_HYDROGEN_INSTRUCTIONS_H_ |
30 | 30 |
31 #include "v8.h" | 31 #include "v8.h" |
32 | 32 |
33 #include "allocation.h" | 33 #include "allocation.h" |
34 #include "code-stubs.h" | 34 #include "code-stubs.h" |
35 #include "data-flow.h" | 35 #include "data-flow.h" |
| 36 #include "deoptimizer.h" |
36 #include "small-pointer-list.h" | 37 #include "small-pointer-list.h" |
37 #include "string-stream.h" | 38 #include "string-stream.h" |
38 #include "v8conversions.h" | 39 #include "v8conversions.h" |
39 #include "v8utils.h" | 40 #include "v8utils.h" |
40 #include "zone.h" | 41 #include "zone.h" |
41 | 42 |
42 namespace v8 { | 43 namespace v8 { |
43 namespace internal { | 44 namespace internal { |
44 | 45 |
45 // Forward declarations. | 46 // Forward declarations. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 V(CallNamed) \ | 85 V(CallNamed) \ |
85 V(CallNew) \ | 86 V(CallNew) \ |
86 V(CallNewArray) \ | 87 V(CallNewArray) \ |
87 V(CallRuntime) \ | 88 V(CallRuntime) \ |
88 V(CallStub) \ | 89 V(CallStub) \ |
89 V(Change) \ | 90 V(Change) \ |
90 V(CheckFunction) \ | 91 V(CheckFunction) \ |
91 V(CheckHeapObject) \ | 92 V(CheckHeapObject) \ |
92 V(CheckInstanceType) \ | 93 V(CheckInstanceType) \ |
93 V(CheckMaps) \ | 94 V(CheckMaps) \ |
| 95 V(CheckMapValue) \ |
| 96 V(CheckPrototypeMaps) \ |
94 V(CheckSmi) \ | 97 V(CheckSmi) \ |
95 V(CheckPrototypeMaps) \ | |
96 V(ClampToUint8) \ | 98 V(ClampToUint8) \ |
97 V(ClassOfTestAndBranch) \ | 99 V(ClassOfTestAndBranch) \ |
98 V(CompareNumericAndBranch) \ | 100 V(CompareNumericAndBranch) \ |
99 V(CompareGeneric) \ | 101 V(CompareGeneric) \ |
100 V(CompareObjectEqAndBranch) \ | 102 V(CompareObjectEqAndBranch) \ |
101 V(CompareMap) \ | 103 V(CompareMap) \ |
102 V(CompareConstantEqAndBranch) \ | |
103 V(Constant) \ | 104 V(Constant) \ |
104 V(Context) \ | 105 V(Context) \ |
| 106 V(DateField) \ |
105 V(DebugBreak) \ | 107 V(DebugBreak) \ |
106 V(DeclareGlobals) \ | 108 V(DeclareGlobals) \ |
107 V(Deoptimize) \ | 109 V(Deoptimize) \ |
108 V(Div) \ | 110 V(Div) \ |
109 V(DummyUse) \ | 111 V(DummyUse) \ |
110 V(ElementsKind) \ | 112 V(ElementsKind) \ |
111 V(EnterInlined) \ | 113 V(EnterInlined) \ |
112 V(EnvironmentMarker) \ | 114 V(EnvironmentMarker) \ |
113 V(ForceRepresentation) \ | 115 V(ForceRepresentation) \ |
| 116 V(ForInCacheArray) \ |
| 117 V(ForInPrepareMap) \ |
114 V(FunctionLiteral) \ | 118 V(FunctionLiteral) \ |
115 V(GetCachedArrayIndex) \ | 119 V(GetCachedArrayIndex) \ |
116 V(GlobalObject) \ | 120 V(GlobalObject) \ |
117 V(GlobalReceiver) \ | 121 V(GlobalReceiver) \ |
118 V(Goto) \ | 122 V(Goto) \ |
119 V(HasCachedArrayIndexAndBranch) \ | 123 V(HasCachedArrayIndexAndBranch) \ |
120 V(HasInstanceTypeAndBranch) \ | 124 V(HasInstanceTypeAndBranch) \ |
121 V(InductionVariableAnnotation) \ | 125 V(InductionVariableAnnotation) \ |
122 V(InnerAllocatedObject) \ | 126 V(InnerAllocatedObject) \ |
123 V(InstanceOf) \ | 127 V(InstanceOf) \ |
124 V(InstanceOfKnownGlobal) \ | 128 V(InstanceOfKnownGlobal) \ |
125 V(InstanceSize) \ | 129 V(InstanceSize) \ |
126 V(InvokeFunction) \ | 130 V(InvokeFunction) \ |
127 V(IsConstructCallAndBranch) \ | 131 V(IsConstructCallAndBranch) \ |
128 V(IsObjectAndBranch) \ | 132 V(IsObjectAndBranch) \ |
129 V(IsNumberAndBranch) \ | 133 V(IsNumberAndBranch) \ |
130 V(IsStringAndBranch) \ | 134 V(IsStringAndBranch) \ |
131 V(IsSmiAndBranch) \ | 135 V(IsSmiAndBranch) \ |
132 V(IsUndetectableAndBranch) \ | 136 V(IsUndetectableAndBranch) \ |
133 V(LeaveInlined) \ | 137 V(LeaveInlined) \ |
134 V(LinkObjectInList) \ | 138 V(LinkObjectInList) \ |
135 V(LoadContextSlot) \ | 139 V(LoadContextSlot) \ |
136 V(LoadExternalArrayPointer) \ | 140 V(LoadExternalArrayPointer) \ |
| 141 V(LoadFieldByIndex) \ |
137 V(LoadFunctionPrototype) \ | 142 V(LoadFunctionPrototype) \ |
138 V(LoadGlobalCell) \ | 143 V(LoadGlobalCell) \ |
139 V(LoadGlobalGeneric) \ | 144 V(LoadGlobalGeneric) \ |
140 V(LoadKeyed) \ | 145 V(LoadKeyed) \ |
141 V(LoadKeyedGeneric) \ | 146 V(LoadKeyedGeneric) \ |
142 V(LoadNamedField) \ | 147 V(LoadNamedField) \ |
143 V(LoadNamedFieldPolymorphic) \ | 148 V(LoadNamedFieldPolymorphic) \ |
144 V(LoadNamedGeneric) \ | 149 V(LoadNamedGeneric) \ |
145 V(MapEnumLength) \ | 150 V(MapEnumLength) \ |
146 V(MathFloorOfDiv) \ | 151 V(MathFloorOfDiv) \ |
147 V(MathMinMax) \ | 152 V(MathMinMax) \ |
148 V(Mod) \ | 153 V(Mod) \ |
149 V(Mul) \ | 154 V(Mul) \ |
150 V(NumericConstraint) \ | 155 V(NumericConstraint) \ |
151 V(OsrEntry) \ | 156 V(OsrEntry) \ |
152 V(OuterContext) \ | 157 V(OuterContext) \ |
153 V(Parameter) \ | 158 V(Parameter) \ |
154 V(Power) \ | 159 V(Power) \ |
155 V(PushArgument) \ | 160 V(PushArgument) \ |
156 V(Random) \ | 161 V(Random) \ |
157 V(RegExpLiteral) \ | 162 V(RegExpLiteral) \ |
158 V(Return) \ | 163 V(Return) \ |
159 V(Ror) \ | 164 V(Ror) \ |
160 V(Sar) \ | 165 V(Sar) \ |
161 V(SeqStringSetChar) \ | 166 V(SeqStringSetChar) \ |
162 V(Shl) \ | 167 V(Shl) \ |
163 V(Shr) \ | 168 V(Shr) \ |
164 V(Simulate) \ | 169 V(Simulate) \ |
165 V(SoftDeoptimize) \ | |
166 V(StackCheck) \ | 170 V(StackCheck) \ |
167 V(StoreContextSlot) \ | 171 V(StoreContextSlot) \ |
168 V(StoreGlobalCell) \ | 172 V(StoreGlobalCell) \ |
169 V(StoreGlobalGeneric) \ | 173 V(StoreGlobalGeneric) \ |
170 V(StoreKeyed) \ | 174 V(StoreKeyed) \ |
171 V(StoreKeyedGeneric) \ | 175 V(StoreKeyedGeneric) \ |
172 V(StoreNamedField) \ | 176 V(StoreNamedField) \ |
173 V(StoreNamedGeneric) \ | 177 V(StoreNamedGeneric) \ |
174 V(StringAdd) \ | 178 V(StringAdd) \ |
175 V(StringCharCodeAt) \ | 179 V(StringCharCodeAt) \ |
176 V(StringCharFromCode) \ | 180 V(StringCharFromCode) \ |
177 V(StringCompareAndBranch) \ | 181 V(StringCompareAndBranch) \ |
178 V(StringLength) \ | 182 V(StringLength) \ |
179 V(Sub) \ | 183 V(Sub) \ |
180 V(ThisFunction) \ | 184 V(ThisFunction) \ |
181 V(Throw) \ | 185 V(Throw) \ |
182 V(ToFastProperties) \ | 186 V(ToFastProperties) \ |
183 V(TransitionElementsKind) \ | 187 V(TransitionElementsKind) \ |
184 V(TrapAllocationMemento) \ | 188 V(TrapAllocationMemento) \ |
185 V(Typeof) \ | 189 V(Typeof) \ |
186 V(TypeofIsAndBranch) \ | 190 V(TypeofIsAndBranch) \ |
187 V(UnaryMathOperation) \ | 191 V(UnaryMathOperation) \ |
188 V(UnknownOSRValue) \ | 192 V(UnknownOSRValue) \ |
189 V(UseConst) \ | 193 V(UseConst) \ |
190 V(ValueOf) \ | 194 V(ValueOf) \ |
191 V(ForInPrepareMap) \ | |
192 V(ForInCacheArray) \ | |
193 V(CheckMapValue) \ | |
194 V(LoadFieldByIndex) \ | |
195 V(DateField) \ | |
196 V(WrapReceiver) | 195 V(WrapReceiver) |
197 | 196 |
198 #define GVN_TRACKED_FLAG_LIST(V) \ | 197 #define GVN_TRACKED_FLAG_LIST(V) \ |
199 V(Maps) \ | 198 V(Maps) \ |
200 V(NewSpacePromotion) | 199 V(NewSpacePromotion) |
201 | 200 |
202 #define GVN_UNTRACKED_FLAG_LIST(V) \ | 201 #define GVN_UNTRACKED_FLAG_LIST(V) \ |
| 202 V(ArrayElements) \ |
| 203 V(ArrayLengths) \ |
| 204 V(BackingStoreFields) \ |
203 V(Calls) \ | 205 V(Calls) \ |
204 V(InobjectFields) \ | 206 V(ContextSlots) \ |
205 V(BackingStoreFields) \ | 207 V(DoubleArrayElements) \ |
206 V(DoubleFields) \ | 208 V(DoubleFields) \ |
207 V(ElementsKind) \ | 209 V(ElementsKind) \ |
208 V(ElementsPointer) \ | 210 V(ElementsPointer) \ |
209 V(ArrayElements) \ | |
210 V(DoubleArrayElements) \ | |
211 V(SpecializedArrayElements) \ | |
212 V(GlobalVars) \ | 211 V(GlobalVars) \ |
213 V(ArrayLengths) \ | 212 V(InobjectFields) \ |
214 V(ContextSlots) \ | 213 V(OsrEntries) \ |
215 V(OsrEntries) | 214 V(SpecializedArrayElements) |
| 215 |
216 | 216 |
217 #define DECLARE_ABSTRACT_INSTRUCTION(type) \ | 217 #define DECLARE_ABSTRACT_INSTRUCTION(type) \ |
218 virtual bool Is##type() const { return true; } \ | 218 virtual bool Is##type() const { return true; } \ |
219 static H##type* cast(HValue* value) { \ | 219 static H##type* cast(HValue* value) { \ |
220 ASSERT(value->Is##type()); \ | 220 ASSERT(value->Is##type()); \ |
221 return reinterpret_cast<H##type*>(value); \ | 221 return reinterpret_cast<H##type*>(value); \ |
222 } | 222 } |
223 | 223 |
224 | 224 |
225 #define DECLARE_CONCRETE_INSTRUCTION(type) \ | 225 #define DECLARE_CONCRETE_INSTRUCTION(type) \ |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 } | 287 } |
288 | 288 |
289 void Intersect(Range* other); | 289 void Intersect(Range* other); |
290 void Union(Range* other); | 290 void Union(Range* other); |
291 void CombinedMax(Range* other); | 291 void CombinedMax(Range* other); |
292 void CombinedMin(Range* other); | 292 void CombinedMin(Range* other); |
293 | 293 |
294 void AddConstant(int32_t value); | 294 void AddConstant(int32_t value); |
295 void Sar(int32_t value); | 295 void Sar(int32_t value); |
296 void Shl(int32_t value); | 296 void Shl(int32_t value); |
297 bool AddAndCheckOverflow(Range* other); | 297 bool AddAndCheckOverflow(const Representation& r, Range* other); |
298 bool SubAndCheckOverflow(Range* other); | 298 bool SubAndCheckOverflow(const Representation& r, Range* other); |
299 bool MulAndCheckOverflow(Range* other); | 299 bool MulAndCheckOverflow(const Representation& r, Range* other); |
300 | 300 |
301 private: | 301 private: |
302 int32_t lower_; | 302 int32_t lower_; |
303 int32_t upper_; | 303 int32_t upper_; |
304 Range* next_; | 304 Range* next_; |
305 bool can_be_minus_zero_; | 305 bool can_be_minus_zero_; |
306 }; | 306 }; |
307 | 307 |
308 | 308 |
309 class UniqueValueId { | 309 class UniqueValueId { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 bool IsHeapNumber() const { | 400 bool IsHeapNumber() const { |
401 ASSERT(type_ != kUninitialized); | 401 ASSERT(type_ != kUninitialized); |
402 return ((type_ & kHeapNumber) == kHeapNumber); | 402 return ((type_ & kHeapNumber) == kHeapNumber); |
403 } | 403 } |
404 | 404 |
405 bool IsString() const { | 405 bool IsString() const { |
406 ASSERT(type_ != kUninitialized); | 406 ASSERT(type_ != kUninitialized); |
407 return ((type_ & kString) == kString); | 407 return ((type_ & kString) == kString); |
408 } | 408 } |
409 | 409 |
| 410 bool IsNonString() const { |
| 411 return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() || |
| 412 IsBoolean() || IsJSArray(); |
| 413 } |
| 414 |
410 bool IsBoolean() const { | 415 bool IsBoolean() const { |
411 ASSERT(type_ != kUninitialized); | 416 ASSERT(type_ != kUninitialized); |
412 return ((type_ & kBoolean) == kBoolean); | 417 return ((type_ & kBoolean) == kBoolean); |
413 } | 418 } |
414 | 419 |
415 bool IsNonPrimitive() const { | 420 bool IsNonPrimitive() const { |
416 ASSERT(type_ != kUninitialized); | 421 ASSERT(type_ != kUninitialized); |
417 return ((type_ & kNonPrimitive) == kNonPrimitive); | 422 return ((type_ & kNonPrimitive) == kNonPrimitive); |
418 } | 423 } |
419 | 424 |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 // sets this flag, it must implement HandleSideEffectDominator() and should | 798 // sets this flag, it must implement HandleSideEffectDominator() and should |
794 // indicate which side effects to track by setting GVN flags. | 799 // indicate which side effects to track by setting GVN flags. |
795 kTrackSideEffectDominators, | 800 kTrackSideEffectDominators, |
796 kCanOverflow, | 801 kCanOverflow, |
797 kBailoutOnMinusZero, | 802 kBailoutOnMinusZero, |
798 kCanBeDivByZero, | 803 kCanBeDivByZero, |
799 kAllowUndefinedAsNaN, | 804 kAllowUndefinedAsNaN, |
800 kIsArguments, | 805 kIsArguments, |
801 kTruncatingToInt32, | 806 kTruncatingToInt32, |
802 kAllUsesTruncatingToInt32, | 807 kAllUsesTruncatingToInt32, |
| 808 kTruncatingToSmi, |
| 809 kAllUsesTruncatingToSmi, |
803 // Set after an instruction is killed. | 810 // Set after an instruction is killed. |
804 kIsDead, | 811 kIsDead, |
805 // Instructions that are allowed to produce full range unsigned integer | 812 // Instructions that are allowed to produce full range unsigned integer |
806 // values are marked with kUint32 flag. If arithmetic shift or a load from | 813 // values are marked with kUint32 flag. If arithmetic shift or a load from |
807 // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag | 814 // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag |
808 // it will deoptimize if result does not fit into signed integer range. | 815 // it will deoptimize if result does not fit into signed integer range. |
809 // HGraph::ComputeSafeUint32Operations is responsible for setting this | 816 // HGraph::ComputeSafeUint32Operations is responsible for setting this |
810 // flag. | 817 // flag. |
811 kUint32, | 818 kUint32, |
812 // If a phi is involved in the evaluation of a numeric constraint the | 819 // If a phi is involved in the evaluation of a numeric constraint the |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
879 | 886 |
880 // Note: Never call this method for an unlinked value. | 887 // Note: Never call this method for an unlinked value. |
881 Isolate* isolate() const; | 888 Isolate* isolate() const; |
882 | 889 |
883 int id() const { return id_; } | 890 int id() const { return id_; } |
884 void set_id(int id) { id_ = id; } | 891 void set_id(int id) { id_ = id; } |
885 | 892 |
886 HUseIterator uses() const { return HUseIterator(use_list_); } | 893 HUseIterator uses() const { return HUseIterator(use_list_); } |
887 | 894 |
888 virtual bool EmitAtUses() { return false; } | 895 virtual bool EmitAtUses() { return false; } |
| 896 |
889 Representation representation() const { return representation_; } | 897 Representation representation() const { return representation_; } |
890 void ChangeRepresentation(Representation r) { | 898 void ChangeRepresentation(Representation r) { |
891 ASSERT(CheckFlag(kFlexibleRepresentation)); | 899 ASSERT(CheckFlag(kFlexibleRepresentation)); |
892 ASSERT(!CheckFlag(kCannotBeTagged) || !r.IsTagged()); | 900 ASSERT(!CheckFlag(kCannotBeTagged) || !r.IsTagged()); |
893 RepresentationChanged(r); | 901 RepresentationChanged(r); |
894 representation_ = r; | 902 representation_ = r; |
895 if (r.IsTagged()) { | 903 if (r.IsTagged()) { |
896 // Tagged is the bottom of the lattice, don't go any further. | 904 // Tagged is the bottom of the lattice, don't go any further. |
897 ClearFlag(kFlexibleRepresentation); | 905 ClearFlag(kFlexibleRepresentation); |
898 } | 906 } |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 virtual bool DataEquals(HValue* other) { | 1162 virtual bool DataEquals(HValue* other) { |
1155 UNREACHABLE(); | 1163 UNREACHABLE(); |
1156 return false; | 1164 return false; |
1157 } | 1165 } |
1158 | 1166 |
1159 virtual Representation RepresentationFromInputs() { | 1167 virtual Representation RepresentationFromInputs() { |
1160 return representation(); | 1168 return representation(); |
1161 } | 1169 } |
1162 Representation RepresentationFromUses(); | 1170 Representation RepresentationFromUses(); |
1163 Representation RepresentationFromUseRequirements(); | 1171 Representation RepresentationFromUseRequirements(); |
| 1172 bool HasNonSmiUse(); |
1164 virtual void UpdateRepresentation(Representation new_rep, | 1173 virtual void UpdateRepresentation(Representation new_rep, |
1165 HInferRepresentationPhase* h_infer, | 1174 HInferRepresentationPhase* h_infer, |
1166 const char* reason); | 1175 const char* reason); |
1167 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer); | 1176 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer); |
1168 | 1177 |
1169 virtual void RepresentationChanged(Representation to) { } | 1178 virtual void RepresentationChanged(Representation to) { } |
1170 | 1179 |
1171 virtual Range* InferRange(Zone* zone); | 1180 virtual Range* InferRange(Zone* zone); |
1172 virtual void DeleteFromGraph() = 0; | 1181 virtual void DeleteFromGraph() = 0; |
1173 virtual void InternalSetOperandAt(int index, HValue* value) = 0; | 1182 virtual void InternalSetOperandAt(int index, HValue* value) = 0; |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1486 HValue* related_value) | 1495 HValue* related_value) |
1487 : relation_(relation) { | 1496 : relation_(relation) { |
1488 SetOperandAt(0, constrained_value); | 1497 SetOperandAt(0, constrained_value); |
1489 SetOperandAt(1, related_value); | 1498 SetOperandAt(1, related_value); |
1490 } | 1499 } |
1491 | 1500 |
1492 NumericRelation relation_; | 1501 NumericRelation relation_; |
1493 }; | 1502 }; |
1494 | 1503 |
1495 | 1504 |
1496 // We insert soft-deoptimize when we hit code with unknown typefeedback, | 1505 class HDeoptimize: public HTemplateInstruction<0> { |
1497 // so that we get a chance of re-optimizing with useful typefeedback. | |
1498 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize. | |
1499 class HSoftDeoptimize: public HTemplateInstruction<0> { | |
1500 public: | 1506 public: |
| 1507 explicit HDeoptimize(Deoptimizer::BailoutType type) : type_(type) {} |
| 1508 |
1501 virtual Representation RequiredInputRepresentation(int index) { | 1509 virtual Representation RequiredInputRepresentation(int index) { |
1502 return Representation::None(); | 1510 return Representation::None(); |
1503 } | 1511 } |
1504 | 1512 |
1505 DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize) | 1513 Deoptimizer::BailoutType type() { return type_; } |
| 1514 |
| 1515 DECLARE_CONCRETE_INSTRUCTION(Deoptimize) |
| 1516 |
| 1517 private: |
| 1518 Deoptimizer::BailoutType type_; |
1506 }; | 1519 }; |
1507 | 1520 |
1508 | 1521 |
1509 // Inserts an int3/stop break instruction for debugging purposes. | 1522 // Inserts an int3/stop break instruction for debugging purposes. |
1510 class HDebugBreak: public HTemplateInstruction<0> { | 1523 class HDebugBreak: public HTemplateInstruction<0> { |
1511 public: | 1524 public: |
1512 virtual Representation RequiredInputRepresentation(int index) { | 1525 virtual Representation RequiredInputRepresentation(int index) { |
1513 return Representation::None(); | 1526 return Representation::None(); |
1514 } | 1527 } |
1515 | 1528 |
1516 DECLARE_CONCRETE_INSTRUCTION(DebugBreak) | 1529 DECLARE_CONCRETE_INSTRUCTION(DebugBreak) |
1517 }; | 1530 }; |
1518 | 1531 |
1519 | 1532 |
1520 class HDeoptimize: public HControlInstruction { | |
1521 public: | |
1522 HDeoptimize(int environment_length, | |
1523 int first_local_index, | |
1524 int first_expression_index, | |
1525 Zone* zone) | |
1526 : values_(environment_length, zone), | |
1527 first_local_index_(first_local_index), | |
1528 first_expression_index_(first_expression_index) { } | |
1529 | |
1530 virtual Representation RequiredInputRepresentation(int index) { | |
1531 return Representation::None(); | |
1532 } | |
1533 | |
1534 virtual int OperandCount() { return values_.length(); } | |
1535 virtual HValue* OperandAt(int index) const { return values_[index]; } | |
1536 virtual void PrintDataTo(StringStream* stream); | |
1537 | |
1538 virtual int SuccessorCount() { return 0; } | |
1539 virtual HBasicBlock* SuccessorAt(int i) { | |
1540 UNREACHABLE(); | |
1541 return NULL; | |
1542 } | |
1543 virtual void SetSuccessorAt(int i, HBasicBlock* block) { | |
1544 UNREACHABLE(); | |
1545 } | |
1546 | |
1547 void AddEnvironmentValue(HValue* value, Zone* zone) { | |
1548 values_.Add(NULL, zone); | |
1549 SetOperandAt(values_.length() - 1, value); | |
1550 } | |
1551 int first_local_index() { return first_local_index_; } | |
1552 int first_expression_index() { return first_expression_index_; } | |
1553 | |
1554 DECLARE_CONCRETE_INSTRUCTION(Deoptimize) | |
1555 | |
1556 enum UseEnvironment { | |
1557 kNoUses, | |
1558 kUseAll | |
1559 }; | |
1560 | |
1561 protected: | |
1562 virtual void InternalSetOperandAt(int index, HValue* value) { | |
1563 values_[index] = value; | |
1564 } | |
1565 | |
1566 private: | |
1567 ZoneList<HValue*> values_; | |
1568 int first_local_index_; | |
1569 int first_expression_index_; | |
1570 }; | |
1571 | |
1572 | |
1573 class HGoto: public HTemplateControlInstruction<1, 0> { | 1533 class HGoto: public HTemplateControlInstruction<1, 0> { |
1574 public: | 1534 public: |
1575 explicit HGoto(HBasicBlock* target) { | 1535 explicit HGoto(HBasicBlock* target) { |
1576 SetSuccessorAt(0, target); | 1536 SetSuccessorAt(0, target); |
1577 } | 1537 } |
1578 | 1538 |
1579 virtual Representation RequiredInputRepresentation(int index) { | 1539 virtual Representation RequiredInputRepresentation(int index) { |
1580 return Representation::None(); | 1540 return Representation::None(); |
1581 } | 1541 } |
1582 | 1542 |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1751 virtual void PrintDataTo(StringStream* stream); | 1711 virtual void PrintDataTo(StringStream* stream); |
1752 | 1712 |
1753 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation) | 1713 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation) |
1754 }; | 1714 }; |
1755 | 1715 |
1756 | 1716 |
1757 class HChange: public HUnaryOperation { | 1717 class HChange: public HUnaryOperation { |
1758 public: | 1718 public: |
1759 HChange(HValue* value, | 1719 HChange(HValue* value, |
1760 Representation to, | 1720 Representation to, |
1761 bool is_truncating, | 1721 bool is_truncating_to_smi, |
| 1722 bool is_truncating_to_int32, |
1762 bool allow_undefined_as_nan) | 1723 bool allow_undefined_as_nan) |
1763 : HUnaryOperation(value) { | 1724 : HUnaryOperation(value) { |
1764 ASSERT(!value->representation().IsNone()); | 1725 ASSERT(!value->representation().IsNone()); |
1765 ASSERT(!to.IsNone()); | 1726 ASSERT(!to.IsNone()); |
1766 ASSERT(!value->representation().Equals(to)); | 1727 ASSERT(!value->representation().Equals(to)); |
1767 set_representation(to); | 1728 set_representation(to); |
1768 SetFlag(kUseGVN); | 1729 SetFlag(kUseGVN); |
1769 if (allow_undefined_as_nan) SetFlag(kAllowUndefinedAsNaN); | 1730 if (allow_undefined_as_nan) SetFlag(kAllowUndefinedAsNaN); |
1770 if (is_truncating) SetFlag(kTruncatingToInt32); | 1731 if (is_truncating_to_smi) SetFlag(kTruncatingToSmi); |
| 1732 if (is_truncating_to_int32) SetFlag(kTruncatingToInt32); |
1771 if (value->representation().IsSmi() || value->type().IsSmi()) { | 1733 if (value->representation().IsSmi() || value->type().IsSmi()) { |
1772 set_type(HType::Smi()); | 1734 set_type(HType::Smi()); |
1773 } else { | 1735 } else { |
1774 set_type(HType::TaggedNumber()); | 1736 set_type(HType::TaggedNumber()); |
1775 if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion); | 1737 if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion); |
1776 } | 1738 } |
1777 } | 1739 } |
1778 | 1740 |
1779 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); | 1741 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); |
1780 virtual HType CalculateInferredType(); | 1742 virtual HType CalculateInferredType(); |
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2661 } | 2623 } |
2662 | 2624 |
2663 private: | 2625 private: |
2664 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op) | 2626 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op) |
2665 : op_(op) { | 2627 : op_(op) { |
2666 SetOperandAt(0, context); | 2628 SetOperandAt(0, context); |
2667 SetOperandAt(1, value); | 2629 SetOperandAt(1, value); |
2668 switch (op) { | 2630 switch (op) { |
2669 case kMathFloor: | 2631 case kMathFloor: |
2670 case kMathRound: | 2632 case kMathRound: |
| 2633 // TODO(verwaest): Set representation to flexible int starting as smi. |
2671 set_representation(Representation::Integer32()); | 2634 set_representation(Representation::Integer32()); |
2672 break; | 2635 break; |
2673 case kMathAbs: | 2636 case kMathAbs: |
2674 // Not setting representation here: it is None intentionally. | 2637 // Not setting representation here: it is None intentionally. |
2675 SetFlag(kFlexibleRepresentation); | 2638 SetFlag(kFlexibleRepresentation); |
2676 // TODO(svenpanne) This flag is actually only needed if representation() | 2639 // TODO(svenpanne) This flag is actually only needed if representation() |
2677 // is tagged, and not when it is an unboxed double or unboxed integer. | 2640 // is tagged, and not when it is an unboxed double or unboxed integer. |
2678 SetGVNFlag(kChangesNewSpacePromotion); | 2641 SetGVNFlag(kChangesNewSpacePromotion); |
2679 break; | 2642 break; |
2680 case kMathLog: | 2643 case kMathLog: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2725 virtual bool DataEquals(HValue* other) { return true; } | 2688 virtual bool DataEquals(HValue* other) { return true; } |
2726 | 2689 |
2727 private: | 2690 private: |
2728 virtual bool IsDeletable() const { return true; } | 2691 virtual bool IsDeletable() const { return true; } |
2729 }; | 2692 }; |
2730 | 2693 |
2731 | 2694 |
2732 class HCheckMaps: public HTemplateInstruction<2> { | 2695 class HCheckMaps: public HTemplateInstruction<2> { |
2733 public: | 2696 public: |
2734 static HCheckMaps* New(HValue* value, Handle<Map> map, Zone* zone, | 2697 static HCheckMaps* New(HValue* value, Handle<Map> map, Zone* zone, |
2735 HValue *typecheck = NULL) { | 2698 CompilationInfo* info, HValue *typecheck = NULL); |
2736 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); | |
2737 check_map->map_set_.Add(map, zone); | |
2738 return check_map; | |
2739 } | |
2740 | |
2741 static HCheckMaps* New(HValue* value, SmallMapList* maps, Zone* zone, | 2699 static HCheckMaps* New(HValue* value, SmallMapList* maps, Zone* zone, |
2742 HValue *typecheck = NULL) { | 2700 HValue *typecheck = NULL) { |
2743 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); | 2701 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); |
2744 for (int i = 0; i < maps->length(); i++) { | 2702 for (int i = 0; i < maps->length(); i++) { |
2745 check_map->map_set_.Add(maps->at(i), zone); | 2703 check_map->map_set_.Add(maps->at(i), zone); |
2746 } | 2704 } |
2747 check_map->map_set_.Sort(); | 2705 check_map->map_set_.Sort(); |
2748 return check_map; | 2706 return check_map; |
2749 } | 2707 } |
2750 | 2708 |
2751 static HCheckMaps* NewWithTransitions(HValue* value, Handle<Map> map, | 2709 static HCheckMaps* NewWithTransitions(HValue* value, Handle<Map> map, |
2752 Zone* zone) { | 2710 Zone* zone, CompilationInfo* info); |
2753 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, value); | |
2754 check_map->map_set_.Add(map, zone); | |
2755 | 2711 |
2756 // Since transitioned elements maps of the initial map don't fail the map | 2712 bool CanOmitMapChecks() { return omit_; } |
2757 // check, the CheckMaps instruction doesn't need to depend on ElementsKinds. | |
2758 check_map->ClearGVNFlag(kDependsOnElementsKind); | |
2759 | |
2760 ElementsKind kind = map->elements_kind(); | |
2761 bool packed = IsFastPackedElementsKind(kind); | |
2762 while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) { | |
2763 kind = GetNextMoreGeneralFastElementsKind(kind, packed); | |
2764 Map* transitioned_map = | |
2765 map->LookupElementsTransitionMap(kind); | |
2766 if (transitioned_map) { | |
2767 check_map->map_set_.Add(Handle<Map>(transitioned_map), zone); | |
2768 } | |
2769 }; | |
2770 check_map->map_set_.Sort(); | |
2771 return check_map; | |
2772 } | |
2773 | 2713 |
2774 virtual bool HasEscapingOperandAt(int index) { return false; } | 2714 virtual bool HasEscapingOperandAt(int index) { return false; } |
2775 virtual Representation RequiredInputRepresentation(int index) { | 2715 virtual Representation RequiredInputRepresentation(int index) { |
2776 return Representation::Tagged(); | 2716 return Representation::Tagged(); |
2777 } | 2717 } |
2778 virtual void HandleSideEffectDominator(GVNFlag side_effect, | 2718 virtual void HandleSideEffectDominator(GVNFlag side_effect, |
2779 HValue* dominator); | 2719 HValue* dominator); |
2780 virtual void PrintDataTo(StringStream* stream); | 2720 virtual void PrintDataTo(StringStream* stream); |
2781 virtual HType CalculateInferredType(); | 2721 virtual HType CalculateInferredType(); |
2782 | 2722 |
(...skipping 16 matching lines...) Expand all Loading... |
2799 if (map_unique_ids_.at(i) != b->map_unique_ids_.at(i)) { | 2739 if (map_unique_ids_.at(i) != b->map_unique_ids_.at(i)) { |
2800 return false; | 2740 return false; |
2801 } | 2741 } |
2802 } | 2742 } |
2803 return true; | 2743 return true; |
2804 } | 2744 } |
2805 | 2745 |
2806 private: | 2746 private: |
2807 // Clients should use one of the static New* methods above. | 2747 // Clients should use one of the static New* methods above. |
2808 HCheckMaps(HValue* value, Zone *zone, HValue* typecheck) | 2748 HCheckMaps(HValue* value, Zone *zone, HValue* typecheck) |
2809 : map_unique_ids_(0, zone) { | 2749 : omit_(false), map_unique_ids_(0, zone) { |
2810 SetOperandAt(0, value); | 2750 SetOperandAt(0, value); |
2811 // Use the object value for the dependency if NULL is passed. | 2751 // Use the object value for the dependency if NULL is passed. |
2812 // TODO(titzer): do GVN flags already express this dependency? | 2752 // TODO(titzer): do GVN flags already express this dependency? |
2813 SetOperandAt(1, typecheck != NULL ? typecheck : value); | 2753 SetOperandAt(1, typecheck != NULL ? typecheck : value); |
2814 set_representation(Representation::Tagged()); | 2754 set_representation(Representation::Tagged()); |
2815 SetFlag(kUseGVN); | 2755 SetFlag(kUseGVN); |
2816 SetFlag(kTrackSideEffectDominators); | 2756 SetFlag(kTrackSideEffectDominators); |
2817 SetGVNFlag(kDependsOnMaps); | 2757 SetGVNFlag(kDependsOnMaps); |
2818 SetGVNFlag(kDependsOnElementsKind); | 2758 SetGVNFlag(kDependsOnElementsKind); |
2819 } | 2759 } |
2820 | 2760 |
| 2761 void omit(CompilationInfo* info) { |
| 2762 omit_ = true; |
| 2763 for (int i = 0; i < map_set_.length(); i++) { |
| 2764 Handle<Map> map = map_set_.at(i); |
| 2765 map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup, |
| 2766 info); |
| 2767 } |
| 2768 } |
| 2769 |
| 2770 bool omit_; |
2821 SmallMapList map_set_; | 2771 SmallMapList map_set_; |
2822 ZoneList<UniqueValueId> map_unique_ids_; | 2772 ZoneList<UniqueValueId> map_unique_ids_; |
2823 }; | 2773 }; |
2824 | 2774 |
2825 | 2775 |
2826 class HCheckFunction: public HUnaryOperation { | 2776 class HCheckFunction: public HUnaryOperation { |
2827 public: | 2777 public: |
2828 HCheckFunction(HValue* value, Handle<JSFunction> function) | 2778 HCheckFunction(HValue* value, Handle<JSFunction> function) |
2829 : HUnaryOperation(value), target_(function), target_unique_id_() { | 2779 : HUnaryOperation(value), target_(function), target_unique_id_() { |
2830 set_representation(Representation::Tagged()); | 2780 set_representation(Representation::Tagged()); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3067 | 3017 |
3068 private: | 3018 private: |
3069 ZoneList<Handle<JSObject> > prototypes_; | 3019 ZoneList<Handle<JSObject> > prototypes_; |
3070 ZoneList<Handle<Map> > maps_; | 3020 ZoneList<Handle<Map> > maps_; |
3071 UniqueValueId first_prototype_unique_id_; | 3021 UniqueValueId first_prototype_unique_id_; |
3072 UniqueValueId last_prototype_unique_id_; | 3022 UniqueValueId last_prototype_unique_id_; |
3073 bool can_omit_prototype_maps_; | 3023 bool can_omit_prototype_maps_; |
3074 }; | 3024 }; |
3075 | 3025 |
3076 | 3026 |
| 3027 class InductionVariableData; |
| 3028 |
| 3029 |
| 3030 struct InductionVariableLimitUpdate { |
| 3031 InductionVariableData* updated_variable; |
| 3032 HValue* limit; |
| 3033 bool limit_is_upper; |
| 3034 bool limit_is_included; |
| 3035 |
| 3036 InductionVariableLimitUpdate() |
| 3037 : updated_variable(NULL), limit(NULL), |
| 3038 limit_is_upper(false), limit_is_included(false) {} |
| 3039 }; |
| 3040 |
| 3041 |
| 3042 class HBoundsCheck; |
| 3043 class HPhi; |
| 3044 class HConstant; |
| 3045 class HBitwise; |
| 3046 |
| 3047 |
| 3048 class InductionVariableData : public ZoneObject { |
| 3049 public: |
| 3050 class InductionVariableCheck : public ZoneObject { |
| 3051 public: |
| 3052 HBoundsCheck* check() { return check_; } |
| 3053 InductionVariableCheck* next() { return next_; } |
| 3054 bool HasUpperLimit() { return upper_limit_ >= 0; } |
| 3055 int32_t upper_limit() { |
| 3056 ASSERT(HasUpperLimit()); |
| 3057 return upper_limit_; |
| 3058 } |
| 3059 void set_upper_limit(int32_t upper_limit) { |
| 3060 upper_limit_ = upper_limit; |
| 3061 } |
| 3062 |
| 3063 bool processed() { return processed_; } |
| 3064 void set_processed() { processed_ = true; } |
| 3065 |
| 3066 InductionVariableCheck(HBoundsCheck* check, |
| 3067 InductionVariableCheck* next, |
| 3068 int32_t upper_limit = kNoLimit) |
| 3069 : check_(check), next_(next), upper_limit_(upper_limit), |
| 3070 processed_(false) {} |
| 3071 |
| 3072 private: |
| 3073 HBoundsCheck* check_; |
| 3074 InductionVariableCheck* next_; |
| 3075 int32_t upper_limit_; |
| 3076 bool processed_; |
| 3077 }; |
| 3078 |
| 3079 class ChecksRelatedToLength : public ZoneObject { |
| 3080 public: |
| 3081 HValue* length() { return length_; } |
| 3082 ChecksRelatedToLength* next() { return next_; } |
| 3083 InductionVariableCheck* checks() { return checks_; } |
| 3084 |
| 3085 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit); |
| 3086 void CloseCurrentBlock(); |
| 3087 |
| 3088 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next) |
| 3089 : length_(length), next_(next), checks_(NULL), |
| 3090 first_check_in_block_(NULL), |
| 3091 added_index_(NULL), |
| 3092 added_constant_(NULL), |
| 3093 current_and_mask_in_block_(0), |
| 3094 current_or_mask_in_block_(0) {} |
| 3095 |
| 3096 private: |
| 3097 void UseNewIndexInCurrentBlock(Token::Value token, |
| 3098 int32_t mask, |
| 3099 HValue* index_base, |
| 3100 HValue* context); |
| 3101 |
| 3102 HBoundsCheck* first_check_in_block() { return first_check_in_block_; } |
| 3103 HBitwise* added_index() { return added_index_; } |
| 3104 void set_added_index(HBitwise* index) { added_index_ = index; } |
| 3105 HConstant* added_constant() { return added_constant_; } |
| 3106 void set_added_constant(HConstant* constant) { added_constant_ = constant; } |
| 3107 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; } |
| 3108 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; } |
| 3109 int32_t current_upper_limit() { return current_upper_limit_; } |
| 3110 |
| 3111 HValue* length_; |
| 3112 ChecksRelatedToLength* next_; |
| 3113 InductionVariableCheck* checks_; |
| 3114 |
| 3115 HBoundsCheck* first_check_in_block_; |
| 3116 HBitwise* added_index_; |
| 3117 HConstant* added_constant_; |
| 3118 int32_t current_and_mask_in_block_; |
| 3119 int32_t current_or_mask_in_block_; |
| 3120 int32_t current_upper_limit_; |
| 3121 }; |
| 3122 |
| 3123 struct LimitFromPredecessorBlock { |
| 3124 InductionVariableData* variable; |
| 3125 Token::Value token; |
| 3126 HValue* limit; |
| 3127 HBasicBlock* other_target; |
| 3128 |
| 3129 bool LimitIsValid() { return token != Token::ILLEGAL; } |
| 3130 |
| 3131 bool LimitIsIncluded() { |
| 3132 return Token::IsEqualityOp(token) || |
| 3133 token == Token::GTE || token == Token::LTE; |
| 3134 } |
| 3135 bool LimitIsUpper() { |
| 3136 return token == Token::LTE || token == Token::LT || token == Token::NE; |
| 3137 } |
| 3138 |
| 3139 LimitFromPredecessorBlock() |
| 3140 : variable(NULL), |
| 3141 token(Token::ILLEGAL), |
| 3142 limit(NULL), |
| 3143 other_target(NULL) {} |
| 3144 }; |
| 3145 |
| 3146 static const int32_t kNoLimit = -1; |
| 3147 |
| 3148 static InductionVariableData* ExaminePhi(HPhi* phi); |
| 3149 static void ComputeLimitFromPredecessorBlock( |
| 3150 HBasicBlock* block, |
| 3151 LimitFromPredecessorBlock* result); |
| 3152 static bool ComputeInductionVariableLimit( |
| 3153 HBasicBlock* block, |
| 3154 InductionVariableLimitUpdate* additional_limit); |
| 3155 |
| 3156 struct BitwiseDecompositionResult { |
| 3157 HValue* base; |
| 3158 int32_t and_mask; |
| 3159 int32_t or_mask; |
| 3160 HValue* context; |
| 3161 |
| 3162 BitwiseDecompositionResult() |
| 3163 : base(NULL), and_mask(0), or_mask(0), context(NULL) {} |
| 3164 }; |
| 3165 static void DecomposeBitwise(HValue* value, |
| 3166 BitwiseDecompositionResult* result); |
| 3167 |
| 3168 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit); |
| 3169 |
| 3170 bool CheckIfBranchIsLoopGuard(Token::Value token, |
| 3171 HBasicBlock* current_branch, |
| 3172 HBasicBlock* other_branch); |
| 3173 |
| 3174 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update); |
| 3175 |
| 3176 HPhi* phi() { return phi_; } |
| 3177 HValue* base() { return base_; } |
| 3178 int32_t increment() { return increment_; } |
| 3179 HValue* limit() { return limit_; } |
| 3180 bool limit_included() { return limit_included_; } |
| 3181 HBasicBlock* limit_validity() { return limit_validity_; } |
| 3182 HBasicBlock* induction_exit_block() { return induction_exit_block_; } |
| 3183 HBasicBlock* induction_exit_target() { return induction_exit_target_; } |
| 3184 ChecksRelatedToLength* checks() { return checks_; } |
| 3185 HValue* additional_upper_limit() { return additional_upper_limit_; } |
| 3186 bool additional_upper_limit_is_included() { |
| 3187 return additional_upper_limit_is_included_; |
| 3188 } |
| 3189 HValue* additional_lower_limit() { return additional_lower_limit_; } |
| 3190 bool additional_lower_limit_is_included() { |
| 3191 return additional_lower_limit_is_included_; |
| 3192 } |
| 3193 |
| 3194 bool LowerLimitIsNonNegativeConstant() { |
| 3195 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) { |
| 3196 return true; |
| 3197 } |
| 3198 if (additional_lower_limit() != NULL && |
| 3199 additional_lower_limit()->IsInteger32Constant() && |
| 3200 additional_lower_limit()->GetInteger32Constant() >= 0) { |
| 3201 // Ignoring the corner case of !additional_lower_limit_is_included() |
| 3202 // is safe, handling it adds unneeded complexity. |
| 3203 return true; |
| 3204 } |
| 3205 return false; |
| 3206 } |
| 3207 |
| 3208 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask); |
| 3209 |
| 3210 private: |
| 3211 template <class T> void swap(T* a, T* b) { |
| 3212 T c(*a); |
| 3213 *a = *b; |
| 3214 *b = c; |
| 3215 } |
| 3216 |
| 3217 InductionVariableData(HPhi* phi, HValue* base, int32_t increment) |
| 3218 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment), |
| 3219 limit_(NULL), limit_included_(false), limit_validity_(NULL), |
| 3220 induction_exit_block_(NULL), induction_exit_target_(NULL), |
| 3221 checks_(NULL), |
| 3222 additional_upper_limit_(NULL), |
| 3223 additional_upper_limit_is_included_(false), |
| 3224 additional_lower_limit_(NULL), |
| 3225 additional_lower_limit_is_included_(false) {} |
| 3226 |
| 3227 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand); |
| 3228 |
| 3229 static HValue* IgnoreOsrValue(HValue* v); |
| 3230 static InductionVariableData* GetInductionVariableData(HValue* v); |
| 3231 |
| 3232 HPhi* phi_; |
| 3233 HValue* base_; |
| 3234 int32_t increment_; |
| 3235 HValue* limit_; |
| 3236 bool limit_included_; |
| 3237 HBasicBlock* limit_validity_; |
| 3238 HBasicBlock* induction_exit_block_; |
| 3239 HBasicBlock* induction_exit_target_; |
| 3240 ChecksRelatedToLength* checks_; |
| 3241 HValue* additional_upper_limit_; |
| 3242 bool additional_upper_limit_is_included_; |
| 3243 HValue* additional_lower_limit_; |
| 3244 bool additional_lower_limit_is_included_; |
| 3245 }; |
| 3246 |
| 3247 |
3077 class HPhi: public HValue { | 3248 class HPhi: public HValue { |
3078 public: | 3249 public: |
3079 HPhi(int merged_index, Zone* zone) | 3250 HPhi(int merged_index, Zone* zone) |
3080 : inputs_(2, zone), | 3251 : inputs_(2, zone), |
3081 merged_index_(merged_index), | 3252 merged_index_(merged_index), |
3082 phi_id_(-1) { | 3253 phi_id_(-1), |
| 3254 induction_variable_data_(NULL) { |
3083 for (int i = 0; i < Representation::kNumRepresentations; i++) { | 3255 for (int i = 0; i < Representation::kNumRepresentations; i++) { |
3084 non_phi_uses_[i] = 0; | 3256 non_phi_uses_[i] = 0; |
3085 indirect_uses_[i] = 0; | 3257 indirect_uses_[i] = 0; |
3086 } | 3258 } |
3087 ASSERT(merged_index >= 0); | 3259 ASSERT(merged_index >= 0); |
3088 SetFlag(kFlexibleRepresentation); | 3260 SetFlag(kFlexibleRepresentation); |
3089 SetFlag(kAllowUndefinedAsNaN); | 3261 SetFlag(kAllowUndefinedAsNaN); |
3090 } | 3262 } |
3091 | 3263 |
3092 virtual Representation RepresentationFromInputs(); | 3264 virtual Representation RepresentationFromInputs(); |
(...skipping 10 matching lines...) Expand all Loading... |
3103 virtual int OperandCount() { return inputs_.length(); } | 3275 virtual int OperandCount() { return inputs_.length(); } |
3104 virtual HValue* OperandAt(int index) const { return inputs_[index]; } | 3276 virtual HValue* OperandAt(int index) const { return inputs_[index]; } |
3105 HValue* GetRedundantReplacement(); | 3277 HValue* GetRedundantReplacement(); |
3106 void AddInput(HValue* value); | 3278 void AddInput(HValue* value); |
3107 bool HasRealUses(); | 3279 bool HasRealUses(); |
3108 | 3280 |
3109 bool IsReceiver() const { return merged_index_ == 0; } | 3281 bool IsReceiver() const { return merged_index_ == 0; } |
3110 | 3282 |
3111 int merged_index() const { return merged_index_; } | 3283 int merged_index() const { return merged_index_; } |
3112 | 3284 |
| 3285 InductionVariableData* induction_variable_data() { |
| 3286 return induction_variable_data_; |
| 3287 } |
| 3288 bool IsInductionVariable() { |
| 3289 return induction_variable_data_ != NULL; |
| 3290 } |
| 3291 bool IsLimitedInductionVariable() { |
| 3292 return IsInductionVariable() && |
| 3293 induction_variable_data_->limit() != NULL; |
| 3294 } |
| 3295 void DetectInductionVariable() { |
| 3296 ASSERT(induction_variable_data_ == NULL); |
| 3297 induction_variable_data_ = InductionVariableData::ExaminePhi(this); |
| 3298 } |
| 3299 |
3113 virtual void AddInformativeDefinitions(); | 3300 virtual void AddInformativeDefinitions(); |
3114 | 3301 |
3115 virtual void PrintTo(StringStream* stream); | 3302 virtual void PrintTo(StringStream* stream); |
3116 | 3303 |
3117 #ifdef DEBUG | 3304 #ifdef DEBUG |
3118 virtual void Verify(); | 3305 virtual void Verify(); |
3119 #endif | 3306 #endif |
3120 | 3307 |
3121 void InitRealUses(int id); | 3308 void InitRealUses(int id); |
3122 void AddNonPhiUsesFrom(HPhi* other); | 3309 void AddNonPhiUsesFrom(HPhi* other); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3170 int offset = 0, | 3357 int offset = 0, |
3171 int scale = 0); | 3358 int scale = 0); |
3172 | 3359 |
3173 private: | 3360 private: |
3174 ZoneList<HValue*> inputs_; | 3361 ZoneList<HValue*> inputs_; |
3175 int merged_index_; | 3362 int merged_index_; |
3176 | 3363 |
3177 int non_phi_uses_[Representation::kNumRepresentations]; | 3364 int non_phi_uses_[Representation::kNumRepresentations]; |
3178 int indirect_uses_[Representation::kNumRepresentations]; | 3365 int indirect_uses_[Representation::kNumRepresentations]; |
3179 int phi_id_; | 3366 int phi_id_; |
| 3367 InductionVariableData* induction_variable_data_; |
3180 }; | 3368 }; |
3181 | 3369 |
3182 | 3370 |
3183 class HInductionVariableAnnotation : public HUnaryOperation { | 3371 class HInductionVariableAnnotation : public HUnaryOperation { |
3184 public: | 3372 public: |
3185 static HInductionVariableAnnotation* AddToGraph(HPhi* phi, | 3373 static HInductionVariableAnnotation* AddToGraph(HPhi* phi, |
3186 NumericRelation relation, | 3374 NumericRelation relation, |
3187 int operand_index); | 3375 int operand_index); |
3188 | 3376 |
3189 NumericRelation relation() { return relation_; } | 3377 NumericRelation relation() { return relation_; } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3289 Factory* factory = Isolate::Current()->factory(); | 3477 Factory* factory = Isolate::Current()->factory(); |
3290 // Default arguments to is_not_in_new_space depend on this heap number | 3478 // Default arguments to is_not_in_new_space depend on this heap number |
3291 // to be tenured so that it's guaranteed not be be located in new space. | 3479 // to be tenured so that it's guaranteed not be be located in new space. |
3292 handle_ = factory->NewNumber(double_value_, TENURED); | 3480 handle_ = factory->NewNumber(double_value_, TENURED); |
3293 } | 3481 } |
3294 AllowDeferredHandleDereference smi_check; | 3482 AllowDeferredHandleDereference smi_check; |
3295 ASSERT(has_int32_value_ || !handle_->IsSmi()); | 3483 ASSERT(has_int32_value_ || !handle_->IsSmi()); |
3296 return handle_; | 3484 return handle_; |
3297 } | 3485 } |
3298 | 3486 |
| 3487 bool InstanceOf(Handle<Map> map) { |
| 3488 return handle_->IsJSObject() && |
| 3489 Handle<JSObject>::cast(handle_)->map() == *map; |
| 3490 } |
| 3491 |
3299 bool IsSpecialDouble() const { | 3492 bool IsSpecialDouble() const { |
3300 return has_double_value_ && | 3493 return has_double_value_ && |
3301 (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) || | 3494 (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) || |
3302 FixedDoubleArray::is_the_hole_nan(double_value_) || | 3495 FixedDoubleArray::is_the_hole_nan(double_value_) || |
3303 std::isnan(double_value_)); | 3496 std::isnan(double_value_)); |
3304 } | 3497 } |
3305 | 3498 |
3306 bool NotInNewSpace() const { | 3499 bool NotInNewSpace() const { |
3307 return is_not_in_new_space_; | 3500 return is_not_in_new_space_; |
3308 } | 3501 } |
(...skipping 23 matching lines...) Expand all Loading... |
3332 | 3525 |
3333 bool IsCell() const { | 3526 bool IsCell() const { |
3334 return is_cell_; | 3527 return is_cell_; |
3335 } | 3528 } |
3336 | 3529 |
3337 virtual Representation RequiredInputRepresentation(int index) { | 3530 virtual Representation RequiredInputRepresentation(int index) { |
3338 return Representation::None(); | 3531 return Representation::None(); |
3339 } | 3532 } |
3340 | 3533 |
3341 virtual Representation KnownOptimalRepresentation() { | 3534 virtual Representation KnownOptimalRepresentation() { |
3342 if (HasSmiValue()) return Representation::Smi(); | 3535 if (HasSmiValue() && kSmiValueSize == 31) return Representation::Smi(); |
3343 if (HasInteger32Value()) return Representation::Integer32(); | 3536 if (HasInteger32Value()) return Representation::Integer32(); |
3344 if (HasNumberValue()) return Representation::Double(); | 3537 if (HasNumberValue()) return Representation::Double(); |
3345 return Representation::Tagged(); | 3538 return Representation::Tagged(); |
3346 } | 3539 } |
3347 | 3540 |
3348 virtual bool EmitAtUses(); | 3541 virtual bool EmitAtUses(); |
3349 virtual void PrintDataTo(StringStream* stream); | 3542 virtual void PrintDataTo(StringStream* stream); |
3350 virtual HType CalculateInferredType(); | 3543 virtual HType CalculateInferredType(); |
3351 bool IsInteger() { return handle()->IsSmi(); } | 3544 bool IsInteger() { return handle()->IsSmi(); } |
3352 HConstant* CopyToRepresentation(Representation r, Zone* zone) const; | 3545 HConstant* CopyToRepresentation(Representation r, Zone* zone) const; |
3353 HConstant* CopyToTruncatedInt32(Zone* zone) const; | 3546 Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone); |
| 3547 Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone); |
3354 bool HasInteger32Value() const { return has_int32_value_; } | 3548 bool HasInteger32Value() const { return has_int32_value_; } |
3355 int32_t Integer32Value() const { | 3549 int32_t Integer32Value() const { |
3356 ASSERT(HasInteger32Value()); | 3550 ASSERT(HasInteger32Value()); |
3357 return int32_value_; | 3551 return int32_value_; |
3358 } | 3552 } |
3359 bool HasSmiValue() const { return has_smi_value_; } | 3553 bool HasSmiValue() const { return has_smi_value_; } |
3360 bool HasDoubleValue() const { return has_double_value_; } | 3554 bool HasDoubleValue() const { return has_double_value_; } |
3361 double DoubleValue() const { | 3555 double DoubleValue() const { |
3362 ASSERT(HasDoubleValue()); | 3556 ASSERT(HasDoubleValue()); |
3363 return double_value_; | 3557 return double_value_; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3493 if (!IsCommutative()) return false; | 3687 if (!IsCommutative()) return false; |
3494 | 3688 |
3495 // Constant operands are better off on the right, they can be inlined in | 3689 // Constant operands are better off on the right, they can be inlined in |
3496 // many situations on most platforms. | 3690 // many situations on most platforms. |
3497 if (left()->IsConstant()) return true; | 3691 if (left()->IsConstant()) return true; |
3498 if (right()->IsConstant()) return false; | 3692 if (right()->IsConstant()) return false; |
3499 | 3693 |
3500 // Otherwise, if there is only one use of the right operand, it would be | 3694 // Otherwise, if there is only one use of the right operand, it would be |
3501 // better off on the left for platforms that only have 2-arg arithmetic | 3695 // better off on the left for platforms that only have 2-arg arithmetic |
3502 // ops (e.g ia32, x64) that clobber the left operand. | 3696 // ops (e.g ia32, x64) that clobber the left operand. |
3503 return (right()->UseCount() == 1); | 3697 return right()->UseCount() == 1; |
3504 } | 3698 } |
3505 | 3699 |
3506 HValue* BetterLeftOperand() { | 3700 HValue* BetterLeftOperand() { |
3507 return AreOperandsBetterSwitched() ? right() : left(); | 3701 return AreOperandsBetterSwitched() ? right() : left(); |
3508 } | 3702 } |
3509 | 3703 |
3510 HValue* BetterRightOperand() { | 3704 HValue* BetterRightOperand() { |
3511 return AreOperandsBetterSwitched() ? left() : right(); | 3705 return AreOperandsBetterSwitched() ? left() : right(); |
3512 } | 3706 } |
3513 | 3707 |
3514 void set_observed_input_representation(int index, Representation rep) { | 3708 void set_observed_input_representation(int index, Representation rep) { |
3515 ASSERT(index >= 1 && index <= 2); | 3709 ASSERT(index >= 1 && index <= 2); |
3516 observed_input_representation_[index - 1] = rep; | 3710 observed_input_representation_[index - 1] = rep; |
3517 } | 3711 } |
3518 | 3712 |
3519 virtual void initialize_output_representation(Representation observed) { | 3713 virtual void initialize_output_representation(Representation observed) { |
3520 observed_output_representation_ = observed; | 3714 observed_output_representation_ = observed; |
3521 } | 3715 } |
3522 | 3716 |
3523 virtual Representation observed_input_representation(int index) { | 3717 virtual Representation observed_input_representation(int index) { |
3524 if (index == 0) return Representation::Tagged(); | 3718 if (index == 0) return Representation::Tagged(); |
3525 return observed_input_representation_[index - 1]; | 3719 return observed_input_representation_[index - 1]; |
3526 } | 3720 } |
3527 | 3721 |
| 3722 virtual void UpdateRepresentation(Representation new_rep, |
| 3723 HInferRepresentationPhase* h_infer, |
| 3724 const char* reason) { |
| 3725 Representation rep = !FLAG_smi_binop && new_rep.IsSmi() |
| 3726 ? Representation::Integer32() : new_rep; |
| 3727 HValue::UpdateRepresentation(rep, h_infer, reason); |
| 3728 } |
| 3729 |
3528 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 3730 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
3529 virtual Representation RepresentationFromInputs(); | 3731 virtual Representation RepresentationFromInputs(); |
| 3732 Representation RepresentationFromOutput(); |
3530 virtual void AssumeRepresentation(Representation r); | 3733 virtual void AssumeRepresentation(Representation r); |
3531 | 3734 |
3532 virtual void UpdateRepresentation(Representation new_rep, | |
3533 HInferRepresentationPhase* h_infer, | |
3534 const char* reason) { | |
3535 // By default, binary operations don't handle Smis. | |
3536 if (new_rep.IsSmi()) { | |
3537 new_rep = Representation::Integer32(); | |
3538 } | |
3539 HValue::UpdateRepresentation(new_rep, h_infer, reason); | |
3540 } | |
3541 | |
3542 virtual bool IsCommutative() const { return false; } | 3735 virtual bool IsCommutative() const { return false; } |
3543 | 3736 |
3544 virtual void PrintDataTo(StringStream* stream); | 3737 virtual void PrintDataTo(StringStream* stream); |
3545 | 3738 |
| 3739 virtual Representation RequiredInputRepresentation(int index) { |
| 3740 if (index == 0) return Representation::Tagged(); |
| 3741 return representation(); |
| 3742 } |
| 3743 |
3546 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation) | 3744 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation) |
3547 | 3745 |
3548 private: | 3746 private: |
3549 bool IgnoreObservedOutputRepresentation(Representation current_rep); | 3747 bool IgnoreObservedOutputRepresentation(Representation current_rep); |
3550 | 3748 |
3551 Representation observed_input_representation_[2]; | 3749 Representation observed_input_representation_[2]; |
3552 Representation observed_output_representation_; | 3750 Representation observed_output_representation_; |
3553 }; | 3751 }; |
3554 | 3752 |
3555 | 3753 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3688 | 3886 |
3689 class HBoundsCheck: public HTemplateInstruction<2> { | 3887 class HBoundsCheck: public HTemplateInstruction<2> { |
3690 public: | 3888 public: |
3691 // Normally HBoundsCheck should be created using the | 3889 // Normally HBoundsCheck should be created using the |
3692 // HGraphBuilder::AddBoundsCheck() helper. | 3890 // HGraphBuilder::AddBoundsCheck() helper. |
3693 // However when building stubs, where we know that the arguments are Int32, | 3891 // However when building stubs, where we know that the arguments are Int32, |
3694 // it makes sense to invoke this constructor directly. | 3892 // it makes sense to invoke this constructor directly. |
3695 HBoundsCheck(HValue* index, HValue* length) | 3893 HBoundsCheck(HValue* index, HValue* length) |
3696 : skip_check_(false), | 3894 : skip_check_(false), |
3697 base_(NULL), offset_(0), scale_(0), | 3895 base_(NULL), offset_(0), scale_(0), |
3698 responsibility_direction_(DIRECTION_NONE) { | 3896 responsibility_direction_(DIRECTION_NONE), |
| 3897 allow_equality_(false) { |
3699 SetOperandAt(0, index); | 3898 SetOperandAt(0, index); |
3700 SetOperandAt(1, length); | 3899 SetOperandAt(1, length); |
3701 SetFlag(kFlexibleRepresentation); | 3900 SetFlag(kFlexibleRepresentation); |
3702 SetFlag(kUseGVN); | 3901 SetFlag(kUseGVN); |
3703 } | 3902 } |
3704 | 3903 |
3705 bool skip_check() { return skip_check_; } | 3904 bool skip_check() const { return skip_check_; } |
3706 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } | 3905 void set_skip_check() { skip_check_ = true; } |
3707 HValue* base() { return base_; } | 3906 HValue* base() { return base_; } |
3708 int offset() { return offset_; } | 3907 int offset() { return offset_; } |
3709 int scale() { return scale_; } | 3908 int scale() { return scale_; } |
3710 bool index_can_increase() { | 3909 bool index_can_increase() { |
3711 return (responsibility_direction_ & DIRECTION_LOWER) == 0; | 3910 return (responsibility_direction_ & DIRECTION_LOWER) == 0; |
3712 } | 3911 } |
3713 bool index_can_decrease() { | 3912 bool index_can_decrease() { |
3714 return (responsibility_direction_ & DIRECTION_UPPER) == 0; | 3913 return (responsibility_direction_ & DIRECTION_UPPER) == 0; |
3715 } | 3914 } |
3716 | 3915 |
(...skipping 11 matching lines...) Expand all Loading... |
3728 base_ = index(); | 3927 base_ = index(); |
3729 offset_ = 0; | 3928 offset_ = 0; |
3730 scale_ = 0; | 3929 scale_ = 0; |
3731 return false; | 3930 return false; |
3732 } | 3931 } |
3733 } | 3932 } |
3734 | 3933 |
3735 virtual Representation RequiredInputRepresentation(int arg_index) { | 3934 virtual Representation RequiredInputRepresentation(int arg_index) { |
3736 return representation(); | 3935 return representation(); |
3737 } | 3936 } |
| 3937 virtual bool IsDeletable() const { |
| 3938 return skip_check() && !FLAG_debug_code; |
| 3939 } |
3738 | 3940 |
3739 virtual bool IsRelationTrueInternal(NumericRelation relation, | 3941 virtual bool IsRelationTrueInternal(NumericRelation relation, |
3740 HValue* related_value, | 3942 HValue* related_value, |
3741 int offset = 0, | 3943 int offset = 0, |
3742 int scale = 0); | 3944 int scale = 0); |
3743 | 3945 |
3744 virtual void PrintDataTo(StringStream* stream); | 3946 virtual void PrintDataTo(StringStream* stream); |
3745 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 3947 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
3746 | 3948 |
3747 HValue* index() { return OperandAt(0); } | 3949 HValue* index() { return OperandAt(0); } |
3748 HValue* length() { return OperandAt(1); } | 3950 HValue* length() { return OperandAt(1); } |
| 3951 bool allow_equality() { return allow_equality_; } |
| 3952 void set_allow_equality(bool v) { allow_equality_ = v; } |
3749 | 3953 |
3750 virtual int RedefinedOperandIndex() { return 0; } | 3954 virtual int RedefinedOperandIndex() { return 0; } |
3751 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } | 3955 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } |
3752 virtual void AddInformativeDefinitions(); | 3956 virtual void AddInformativeDefinitions(); |
3753 | 3957 |
3754 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3958 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
3755 | 3959 |
3756 protected: | 3960 protected: |
3757 friend class HBoundsCheckBaseIndexInformation; | 3961 friend class HBoundsCheckBaseIndexInformation; |
3758 | 3962 |
3759 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { | 3963 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { |
3760 responsibility_direction_ = static_cast<RangeGuaranteeDirection>( | 3964 responsibility_direction_ = static_cast<RangeGuaranteeDirection>( |
3761 responsibility_direction_ | direction); | 3965 responsibility_direction_ | direction); |
3762 } | 3966 } |
3763 | 3967 |
3764 virtual bool DataEquals(HValue* other) { return true; } | 3968 virtual bool DataEquals(HValue* other) { return true; } |
3765 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); | 3969 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); |
3766 bool skip_check_; | 3970 bool skip_check_; |
3767 HValue* base_; | 3971 HValue* base_; |
3768 int offset_; | 3972 int offset_; |
3769 int scale_; | 3973 int scale_; |
3770 RangeGuaranteeDirection responsibility_direction_; | 3974 RangeGuaranteeDirection responsibility_direction_; |
| 3975 bool allow_equality_; |
3771 }; | 3976 }; |
3772 | 3977 |
3773 | 3978 |
3774 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { | 3979 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { |
3775 public: | 3980 public: |
3776 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { | 3981 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { |
3777 DecompositionResult decomposition; | 3982 DecompositionResult decomposition; |
3778 if (check->index()->TryDecompose(&decomposition)) { | 3983 if (check->index()->TryDecompose(&decomposition)) { |
3779 SetOperandAt(0, decomposition.base()); | 3984 SetOperandAt(0, decomposition.base()); |
3780 SetOperandAt(1, check); | 3985 SetOperandAt(1, check); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3814 class HBitwiseBinaryOperation: public HBinaryOperation { | 4019 class HBitwiseBinaryOperation: public HBinaryOperation { |
3815 public: | 4020 public: |
3816 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) | 4021 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) |
3817 : HBinaryOperation(context, left, right) { | 4022 : HBinaryOperation(context, left, right) { |
3818 SetFlag(kFlexibleRepresentation); | 4023 SetFlag(kFlexibleRepresentation); |
3819 SetFlag(kTruncatingToInt32); | 4024 SetFlag(kTruncatingToInt32); |
3820 SetFlag(kAllowUndefinedAsNaN); | 4025 SetFlag(kAllowUndefinedAsNaN); |
3821 SetAllSideEffects(); | 4026 SetAllSideEffects(); |
3822 } | 4027 } |
3823 | 4028 |
3824 virtual Representation RequiredInputRepresentation(int index) { | |
3825 return index == 0 | |
3826 ? Representation::Tagged() | |
3827 : representation(); | |
3828 } | |
3829 | |
3830 virtual void RepresentationChanged(Representation to) { | 4029 virtual void RepresentationChanged(Representation to) { |
3831 if (!to.IsTagged()) { | 4030 if (!to.IsTagged()) { |
3832 ASSERT(to.IsInteger32()); | 4031 ASSERT(to.IsSmiOrInteger32()); |
3833 ClearAllSideEffects(); | 4032 ClearAllSideEffects(); |
3834 SetFlag(kUseGVN); | 4033 SetFlag(kUseGVN); |
3835 } else { | 4034 } else { |
3836 SetAllSideEffects(); | 4035 SetAllSideEffects(); |
3837 ClearFlag(kUseGVN); | 4036 ClearFlag(kUseGVN); |
3838 } | 4037 } |
3839 } | 4038 } |
3840 | 4039 |
3841 virtual void UpdateRepresentation(Representation new_rep, | 4040 virtual void UpdateRepresentation(Representation new_rep, |
3842 HInferRepresentationPhase* h_infer, | 4041 HInferRepresentationPhase* h_infer, |
3843 const char* reason) { | 4042 const char* reason) { |
3844 // We only generate either int32 or generic tagged bitwise operations. | 4043 // We only generate either int32 or generic tagged bitwise operations. |
3845 if (new_rep.IsSmi() || new_rep.IsDouble()) { | 4044 if (new_rep.IsDouble()) new_rep = Representation::Integer32(); |
3846 new_rep = Representation::Integer32(); | 4045 HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
3847 } | 4046 } |
3848 HValue::UpdateRepresentation(new_rep, h_infer, reason); | 4047 |
| 4048 virtual Representation observed_input_representation(int index) { |
| 4049 Representation r = HBinaryOperation::observed_input_representation(index); |
| 4050 if (r.IsDouble()) return Representation::Integer32(); |
| 4051 return r; |
3849 } | 4052 } |
3850 | 4053 |
3851 virtual void initialize_output_representation(Representation observed) { | 4054 virtual void initialize_output_representation(Representation observed) { |
3852 if (observed.IsDouble()) observed = Representation::Integer32(); | 4055 if (observed.IsDouble()) observed = Representation::Integer32(); |
3853 HBinaryOperation::initialize_output_representation(observed); | 4056 HBinaryOperation::initialize_output_representation(observed); |
3854 } | 4057 } |
3855 | 4058 |
3856 virtual HType CalculateInferredType(); | 4059 virtual HType CalculateInferredType(); |
3857 | 4060 |
3858 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation) | 4061 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3904 if (to.IsTagged()) { | 4107 if (to.IsTagged()) { |
3905 SetAllSideEffects(); | 4108 SetAllSideEffects(); |
3906 ClearFlag(kUseGVN); | 4109 ClearFlag(kUseGVN); |
3907 } else { | 4110 } else { |
3908 ClearAllSideEffects(); | 4111 ClearAllSideEffects(); |
3909 SetFlag(kUseGVN); | 4112 SetFlag(kUseGVN); |
3910 } | 4113 } |
3911 } | 4114 } |
3912 | 4115 |
3913 virtual HType CalculateInferredType(); | 4116 virtual HType CalculateInferredType(); |
3914 virtual Representation RequiredInputRepresentation(int index) { | |
3915 return index == 0 | |
3916 ? Representation::Tagged() | |
3917 : representation(); | |
3918 } | |
3919 | 4117 |
3920 DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation) | 4118 DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation) |
3921 | 4119 |
3922 private: | 4120 private: |
3923 virtual bool IsDeletable() const { return true; } | 4121 virtual bool IsDeletable() const { return true; } |
3924 }; | 4122 }; |
3925 | 4123 |
3926 | 4124 |
3927 class HCompareGeneric: public HBinaryOperation { | 4125 class HCompareGeneric: public HBinaryOperation { |
3928 public: | 4126 public: |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4011 } | 4209 } |
4012 | 4210 |
4013 virtual Representation observed_input_representation(int index) { | 4211 virtual Representation observed_input_representation(int index) { |
4014 return Representation::Tagged(); | 4212 return Representation::Tagged(); |
4015 } | 4213 } |
4016 | 4214 |
4017 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch) | 4215 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch) |
4018 }; | 4216 }; |
4019 | 4217 |
4020 | 4218 |
4021 class HCompareConstantEqAndBranch: public HUnaryControlInstruction { | |
4022 public: | |
4023 HCompareConstantEqAndBranch(HValue* left, int right, Token::Value op) | |
4024 : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) { | |
4025 ASSERT(op == Token::EQ_STRICT); | |
4026 } | |
4027 | |
4028 Token::Value op() const { return op_; } | |
4029 HValue* left() { return value(); } | |
4030 int right() const { return right_; } | |
4031 | |
4032 virtual Representation RequiredInputRepresentation(int index) { | |
4033 return Representation::Integer32(); | |
4034 } | |
4035 | |
4036 DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch); | |
4037 | |
4038 private: | |
4039 const Token::Value op_; | |
4040 const int right_; | |
4041 }; | |
4042 | |
4043 | |
4044 class HIsObjectAndBranch: public HUnaryControlInstruction { | 4219 class HIsObjectAndBranch: public HUnaryControlInstruction { |
4045 public: | 4220 public: |
4046 explicit HIsObjectAndBranch(HValue* value) | 4221 explicit HIsObjectAndBranch(HValue* value) |
4047 : HUnaryControlInstruction(value, NULL, NULL) { } | 4222 : HUnaryControlInstruction(value, NULL, NULL) { } |
4048 | 4223 |
4049 virtual Representation RequiredInputRepresentation(int index) { | 4224 virtual Representation RequiredInputRepresentation(int index) { |
4050 return Representation::Tagged(); | 4225 return Representation::Tagged(); |
4051 } | 4226 } |
4052 | 4227 |
4053 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch) | 4228 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch) |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4468 | 4643 |
4469 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); | 4644 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); |
4470 | 4645 |
4471 virtual HValue* Canonicalize(); | 4646 virtual HValue* Canonicalize(); |
4472 | 4647 |
4473 // Only commutative if it is certain that not two objects are multiplicated. | 4648 // Only commutative if it is certain that not two objects are multiplicated. |
4474 virtual bool IsCommutative() const { | 4649 virtual bool IsCommutative() const { |
4475 return !representation().IsTagged(); | 4650 return !representation().IsTagged(); |
4476 } | 4651 } |
4477 | 4652 |
| 4653 virtual void UpdateRepresentation(Representation new_rep, |
| 4654 HInferRepresentationPhase* h_infer, |
| 4655 const char* reason) { |
| 4656 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
| 4657 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
| 4658 } |
| 4659 |
4478 DECLARE_CONCRETE_INSTRUCTION(Mul) | 4660 DECLARE_CONCRETE_INSTRUCTION(Mul) |
4479 | 4661 |
4480 protected: | 4662 protected: |
4481 virtual bool DataEquals(HValue* other) { return true; } | 4663 virtual bool DataEquals(HValue* other) { return true; } |
4482 | 4664 |
4483 virtual Range* InferRange(Zone* zone); | 4665 virtual Range* InferRange(Zone* zone); |
4484 | 4666 |
4485 private: | 4667 private: |
4486 HMul(HValue* context, HValue* left, HValue* right) | 4668 HMul(HValue* context, HValue* left, HValue* right) |
4487 : HArithmeticBinaryOperation(context, left, right) { | 4669 : HArithmeticBinaryOperation(context, left, right) { |
(...skipping 19 matching lines...) Expand all Loading... |
4507 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value)); | 4689 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value)); |
4508 } | 4690 } |
4509 | 4691 |
4510 return false; | 4692 return false; |
4511 } | 4693 } |
4512 | 4694 |
4513 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); | 4695 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); |
4514 | 4696 |
4515 virtual HValue* Canonicalize(); | 4697 virtual HValue* Canonicalize(); |
4516 | 4698 |
| 4699 virtual void UpdateRepresentation(Representation new_rep, |
| 4700 HInferRepresentationPhase* h_infer, |
| 4701 const char* reason) { |
| 4702 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
| 4703 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
| 4704 } |
| 4705 |
4517 DECLARE_CONCRETE_INSTRUCTION(Mod) | 4706 DECLARE_CONCRETE_INSTRUCTION(Mod) |
4518 | 4707 |
4519 protected: | 4708 protected: |
4520 virtual bool DataEquals(HValue* other) { return true; } | 4709 virtual bool DataEquals(HValue* other) { return true; } |
4521 | 4710 |
4522 virtual Range* InferRange(Zone* zone); | 4711 virtual Range* InferRange(Zone* zone); |
4523 | 4712 |
4524 private: | 4713 private: |
4525 HMod(HValue* context, | 4714 HMod(HValue* context, |
4526 HValue* left, | 4715 HValue* left, |
(...skipping 22 matching lines...) Expand all Loading... |
4549 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value)); | 4738 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value)); |
4550 } | 4739 } |
4551 | 4740 |
4552 return false; | 4741 return false; |
4553 } | 4742 } |
4554 | 4743 |
4555 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); | 4744 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); |
4556 | 4745 |
4557 virtual HValue* Canonicalize(); | 4746 virtual HValue* Canonicalize(); |
4558 | 4747 |
| 4748 virtual void UpdateRepresentation(Representation new_rep, |
| 4749 HInferRepresentationPhase* h_infer, |
| 4750 const char* reason) { |
| 4751 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
| 4752 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
| 4753 } |
| 4754 |
4559 DECLARE_CONCRETE_INSTRUCTION(Div) | 4755 DECLARE_CONCRETE_INSTRUCTION(Div) |
4560 | 4756 |
4561 protected: | 4757 protected: |
4562 virtual bool DataEquals(HValue* other) { return true; } | 4758 virtual bool DataEquals(HValue* other) { return true; } |
4563 | 4759 |
4564 virtual Range* InferRange(Zone* zone); | 4760 virtual Range* InferRange(Zone* zone); |
4565 | 4761 |
4566 private: | 4762 private: |
4567 HDiv(HValue* context, HValue* left, HValue* right) | 4763 HDiv(HValue* context, HValue* left, HValue* right) |
4568 : HArithmeticBinaryOperation(context, left, right) { | 4764 : HArithmeticBinaryOperation(context, left, right) { |
(...skipping 20 matching lines...) Expand all Loading... |
4589 | 4785 |
4590 virtual Representation observed_input_representation(int index) { | 4786 virtual Representation observed_input_representation(int index) { |
4591 return RequiredInputRepresentation(index); | 4787 return RequiredInputRepresentation(index); |
4592 } | 4788 } |
4593 | 4789 |
4594 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 4790 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
4595 | 4791 |
4596 virtual Representation RepresentationFromInputs() { | 4792 virtual Representation RepresentationFromInputs() { |
4597 Representation left_rep = left()->representation(); | 4793 Representation left_rep = left()->representation(); |
4598 Representation right_rep = right()->representation(); | 4794 Representation right_rep = right()->representation(); |
4599 if ((left_rep.IsNone() || left_rep.IsInteger32()) && | 4795 Representation result = Representation::Smi(); |
4600 (right_rep.IsNone() || right_rep.IsInteger32())) { | 4796 result = result.generalize(left_rep); |
4601 return Representation::Integer32(); | 4797 result = result.generalize(right_rep); |
4602 } | 4798 if (result.IsTagged()) return Representation::Double(); |
4603 return Representation::Double(); | 4799 return result; |
4604 } | 4800 } |
4605 | 4801 |
4606 virtual bool IsCommutative() const { return true; } | 4802 virtual bool IsCommutative() const { return true; } |
4607 | 4803 |
4608 Operation operation() { return operation_; } | 4804 Operation operation() { return operation_; } |
4609 | 4805 |
4610 DECLARE_CONCRETE_INSTRUCTION(MathMinMax) | 4806 DECLARE_CONCRETE_INSTRUCTION(MathMinMax) |
4611 | 4807 |
4612 protected: | 4808 protected: |
4613 virtual bool DataEquals(HValue* other) { | 4809 virtual bool DataEquals(HValue* other) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4648 virtual bool DataEquals(HValue* other) { | 4844 virtual bool DataEquals(HValue* other) { |
4649 return op() == HBitwise::cast(other)->op(); | 4845 return op() == HBitwise::cast(other)->op(); |
4650 } | 4846 } |
4651 | 4847 |
4652 virtual Range* InferRange(Zone* zone); | 4848 virtual Range* InferRange(Zone* zone); |
4653 | 4849 |
4654 private: | 4850 private: |
4655 HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right) | 4851 HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right) |
4656 : HBitwiseBinaryOperation(context, left, right), op_(op) { | 4852 : HBitwiseBinaryOperation(context, left, right), op_(op) { |
4657 ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR); | 4853 ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR); |
| 4854 // BIT_AND with a smi-range positive value will always unset the |
| 4855 // entire sign-extension of the smi-sign. |
| 4856 if (op == Token::BIT_AND && |
| 4857 ((left->IsConstant() && |
| 4858 left->representation().IsSmi() && |
| 4859 HConstant::cast(left)->Integer32Value() >= 0) || |
| 4860 (right->IsConstant() && |
| 4861 right->representation().IsSmi() && |
| 4862 HConstant::cast(right)->Integer32Value() >= 0))) { |
| 4863 SetFlag(kTruncatingToSmi); |
| 4864 // BIT_OR with a smi-range negative value will always set the entire |
| 4865 // sign-extension of the smi-sign. |
| 4866 } else if (op == Token::BIT_OR && |
| 4867 ((left->IsConstant() && |
| 4868 left->representation().IsSmi() && |
| 4869 HConstant::cast(left)->Integer32Value() < 0) || |
| 4870 (right->IsConstant() && |
| 4871 right->representation().IsSmi() && |
| 4872 HConstant::cast(right)->Integer32Value() < 0))) { |
| 4873 SetFlag(kTruncatingToSmi); |
| 4874 } |
4658 } | 4875 } |
4659 | 4876 |
4660 Token::Value op_; | 4877 Token::Value op_; |
4661 }; | 4878 }; |
4662 | 4879 |
4663 | 4880 |
4664 class HShl: public HBitwiseBinaryOperation { | 4881 class HShl: public HBitwiseBinaryOperation { |
4665 public: | 4882 public: |
4666 static HInstruction* New(Zone* zone, | 4883 static HInstruction* New(Zone* zone, |
4667 HValue* context, | 4884 HValue* context, |
4668 HValue* left, | 4885 HValue* left, |
4669 HValue* right); | 4886 HValue* right); |
4670 | 4887 |
4671 virtual Range* InferRange(Zone* zone); | 4888 virtual Range* InferRange(Zone* zone); |
4672 | 4889 |
| 4890 virtual void UpdateRepresentation(Representation new_rep, |
| 4891 HInferRepresentationPhase* h_infer, |
| 4892 const char* reason) { |
| 4893 if (new_rep.IsSmi() && |
| 4894 !(right()->IsInteger32Constant() && |
| 4895 right()->GetInteger32Constant() >= 0)) { |
| 4896 new_rep = Representation::Integer32(); |
| 4897 } |
| 4898 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
| 4899 } |
| 4900 |
4673 DECLARE_CONCRETE_INSTRUCTION(Shl) | 4901 DECLARE_CONCRETE_INSTRUCTION(Shl) |
4674 | 4902 |
4675 protected: | 4903 protected: |
4676 virtual bool DataEquals(HValue* other) { return true; } | 4904 virtual bool DataEquals(HValue* other) { return true; } |
4677 | 4905 |
4678 private: | 4906 private: |
4679 HShl(HValue* context, HValue* left, HValue* right) | 4907 HShl(HValue* context, HValue* left, HValue* right) |
4680 : HBitwiseBinaryOperation(context, left, right) { } | 4908 : HBitwiseBinaryOperation(context, left, right) { } |
4681 }; | 4909 }; |
4682 | 4910 |
(...skipping 12 matching lines...) Expand all Loading... |
4695 // like ((base + offset) >> scale) with one single decomposition. | 4923 // like ((base + offset) >> scale) with one single decomposition. |
4696 left()->TryDecompose(decomposition); | 4924 left()->TryDecompose(decomposition); |
4697 return true; | 4925 return true; |
4698 } | 4926 } |
4699 } | 4927 } |
4700 return false; | 4928 return false; |
4701 } | 4929 } |
4702 | 4930 |
4703 virtual Range* InferRange(Zone* zone); | 4931 virtual Range* InferRange(Zone* zone); |
4704 | 4932 |
| 4933 virtual void UpdateRepresentation(Representation new_rep, |
| 4934 HInferRepresentationPhase* h_infer, |
| 4935 const char* reason) { |
| 4936 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
| 4937 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
| 4938 } |
| 4939 |
4705 DECLARE_CONCRETE_INSTRUCTION(Shr) | 4940 DECLARE_CONCRETE_INSTRUCTION(Shr) |
4706 | 4941 |
4707 protected: | 4942 protected: |
4708 virtual bool DataEquals(HValue* other) { return true; } | 4943 virtual bool DataEquals(HValue* other) { return true; } |
4709 | 4944 |
4710 private: | 4945 private: |
4711 HShr(HValue* context, HValue* left, HValue* right) | 4946 HShr(HValue* context, HValue* left, HValue* right) |
4712 : HBitwiseBinaryOperation(context, left, right) { } | 4947 : HBitwiseBinaryOperation(context, left, right) { } |
4713 }; | 4948 }; |
4714 | 4949 |
(...skipping 12 matching lines...) Expand all Loading... |
4727 // like ((base + offset) >> scale) with one single decomposition. | 4962 // like ((base + offset) >> scale) with one single decomposition. |
4728 left()->TryDecompose(decomposition); | 4963 left()->TryDecompose(decomposition); |
4729 return true; | 4964 return true; |
4730 } | 4965 } |
4731 } | 4966 } |
4732 return false; | 4967 return false; |
4733 } | 4968 } |
4734 | 4969 |
4735 virtual Range* InferRange(Zone* zone); | 4970 virtual Range* InferRange(Zone* zone); |
4736 | 4971 |
| 4972 virtual void UpdateRepresentation(Representation new_rep, |
| 4973 HInferRepresentationPhase* h_infer, |
| 4974 const char* reason) { |
| 4975 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
| 4976 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
| 4977 } |
| 4978 |
4737 DECLARE_CONCRETE_INSTRUCTION(Sar) | 4979 DECLARE_CONCRETE_INSTRUCTION(Sar) |
4738 | 4980 |
4739 protected: | 4981 protected: |
4740 virtual bool DataEquals(HValue* other) { return true; } | 4982 virtual bool DataEquals(HValue* other) { return true; } |
4741 | 4983 |
4742 private: | 4984 private: |
4743 HSar(HValue* context, HValue* left, HValue* right) | 4985 HSar(HValue* context, HValue* left, HValue* right) |
4744 : HBitwiseBinaryOperation(context, left, right) { } | 4986 : HBitwiseBinaryOperation(context, left, right) { } |
4745 }; | 4987 }; |
4746 | 4988 |
4747 | 4989 |
4748 class HRor: public HBitwiseBinaryOperation { | 4990 class HRor: public HBitwiseBinaryOperation { |
4749 public: | 4991 public: |
4750 HRor(HValue* context, HValue* left, HValue* right) | 4992 HRor(HValue* context, HValue* left, HValue* right) |
4751 : HBitwiseBinaryOperation(context, left, right) { | 4993 : HBitwiseBinaryOperation(context, left, right) { |
4752 ChangeRepresentation(Representation::Integer32()); | 4994 ChangeRepresentation(Representation::Integer32()); |
4753 } | 4995 } |
4754 | 4996 |
| 4997 virtual void UpdateRepresentation(Representation new_rep, |
| 4998 HInferRepresentationPhase* h_infer, |
| 4999 const char* reason) { |
| 5000 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
| 5001 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
| 5002 } |
| 5003 |
4755 DECLARE_CONCRETE_INSTRUCTION(Ror) | 5004 DECLARE_CONCRETE_INSTRUCTION(Ror) |
4756 | 5005 |
4757 protected: | 5006 protected: |
4758 virtual bool DataEquals(HValue* other) { return true; } | 5007 virtual bool DataEquals(HValue* other) { return true; } |
4759 }; | 5008 }; |
4760 | 5009 |
4761 | 5010 |
4762 class HOsrEntry: public HTemplateInstruction<0> { | 5011 class HOsrEntry: public HTemplateInstruction<0> { |
4763 public: | 5012 public: |
4764 explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) { | 5013 explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) { |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4962 public: | 5211 public: |
4963 enum Flags { | 5212 enum Flags { |
4964 CAN_ALLOCATE_IN_NEW_SPACE = 1 << 0, | 5213 CAN_ALLOCATE_IN_NEW_SPACE = 1 << 0, |
4965 CAN_ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1, | 5214 CAN_ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1, |
4966 CAN_ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2, | 5215 CAN_ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2, |
4967 ALLOCATE_DOUBLE_ALIGNED = 1 << 3, | 5216 ALLOCATE_DOUBLE_ALIGNED = 1 << 3, |
4968 PREFILL_WITH_FILLER = 1 << 4 | 5217 PREFILL_WITH_FILLER = 1 << 4 |
4969 }; | 5218 }; |
4970 | 5219 |
4971 HAllocate(HValue* context, HValue* size, HType type, Flags flags) | 5220 HAllocate(HValue* context, HValue* size, HType type, Flags flags) |
4972 : type_(type), | 5221 : flags_(flags) { |
4973 flags_(flags) { | |
4974 SetOperandAt(0, context); | 5222 SetOperandAt(0, context); |
4975 SetOperandAt(1, size); | 5223 SetOperandAt(1, size); |
| 5224 set_type(type); |
4976 set_representation(Representation::Tagged()); | 5225 set_representation(Representation::Tagged()); |
4977 SetFlag(kTrackSideEffectDominators); | 5226 SetFlag(kTrackSideEffectDominators); |
4978 SetGVNFlag(kChangesNewSpacePromotion); | 5227 SetGVNFlag(kChangesNewSpacePromotion); |
4979 SetGVNFlag(kDependsOnNewSpacePromotion); | 5228 SetGVNFlag(kDependsOnNewSpacePromotion); |
4980 } | 5229 } |
4981 | 5230 |
4982 // Maximum instance size for which allocations will be inlined. | 5231 // Maximum instance size for which allocations will be inlined. |
4983 static const int kMaxInlineSize = 64 * kPointerSize; | 5232 static const int kMaxInlineSize = 64 * kPointerSize; |
4984 | 5233 |
4985 static Flags DefaultFlags() { | 5234 static Flags DefaultFlags() { |
4986 return CAN_ALLOCATE_IN_NEW_SPACE; | 5235 return CAN_ALLOCATE_IN_NEW_SPACE; |
4987 } | 5236 } |
4988 | 5237 |
4989 static Flags DefaultFlags(ElementsKind kind) { | 5238 static Flags DefaultFlags(ElementsKind kind) { |
4990 Flags flags = CAN_ALLOCATE_IN_NEW_SPACE; | 5239 Flags flags = CAN_ALLOCATE_IN_NEW_SPACE; |
4991 if (IsFastDoubleElementsKind(kind)) { | 5240 if (IsFastDoubleElementsKind(kind)) { |
4992 flags = static_cast<HAllocate::Flags>( | 5241 flags = static_cast<HAllocate::Flags>( |
4993 flags | HAllocate::ALLOCATE_DOUBLE_ALIGNED); | 5242 flags | HAllocate::ALLOCATE_DOUBLE_ALIGNED); |
4994 } | 5243 } |
4995 return flags; | 5244 return flags; |
4996 } | 5245 } |
4997 | 5246 |
4998 HValue* context() { return OperandAt(0); } | 5247 HValue* context() { return OperandAt(0); } |
4999 HValue* size() { return OperandAt(1); } | 5248 HValue* size() { return OperandAt(1); } |
5000 HType type() { return type_; } | |
5001 | 5249 |
5002 virtual Representation RequiredInputRepresentation(int index) { | 5250 virtual Representation RequiredInputRepresentation(int index) { |
5003 if (index == 0) { | 5251 if (index == 0) { |
5004 return Representation::Tagged(); | 5252 return Representation::Tagged(); |
5005 } else { | 5253 } else { |
5006 return Representation::Integer32(); | 5254 return Representation::Integer32(); |
5007 } | 5255 } |
5008 } | 5256 } |
5009 | 5257 |
5010 virtual Handle<Map> GetMonomorphicJSObjectMap() { | 5258 virtual Handle<Map> GetMonomorphicJSObjectMap() { |
5011 return known_initial_map_; | 5259 return known_initial_map_; |
5012 } | 5260 } |
5013 | 5261 |
5014 void set_known_initial_map(Handle<Map> known_initial_map) { | 5262 void set_known_initial_map(Handle<Map> known_initial_map) { |
5015 known_initial_map_ = known_initial_map; | 5263 known_initial_map_ = known_initial_map; |
5016 } | 5264 } |
5017 | 5265 |
5018 virtual HType CalculateInferredType(); | |
5019 | |
5020 bool CanAllocateInNewSpace() const { | 5266 bool CanAllocateInNewSpace() const { |
5021 return (flags_ & CAN_ALLOCATE_IN_NEW_SPACE) != 0; | 5267 return (flags_ & CAN_ALLOCATE_IN_NEW_SPACE) != 0; |
5022 } | 5268 } |
5023 | 5269 |
5024 bool CanAllocateInOldDataSpace() const { | 5270 bool CanAllocateInOldDataSpace() const { |
5025 return (flags_ & CAN_ALLOCATE_IN_OLD_DATA_SPACE) != 0; | 5271 return (flags_ & CAN_ALLOCATE_IN_OLD_DATA_SPACE) != 0; |
5026 } | 5272 } |
5027 | 5273 |
5028 bool CanAllocateInOldPointerSpace() const { | 5274 bool CanAllocateInOldPointerSpace() const { |
5029 return (flags_ & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) != 0; | 5275 return (flags_ & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) != 0; |
(...skipping 25 matching lines...) Expand all Loading... |
5055 } | 5301 } |
5056 | 5302 |
5057 virtual void HandleSideEffectDominator(GVNFlag side_effect, | 5303 virtual void HandleSideEffectDominator(GVNFlag side_effect, |
5058 HValue* dominator); | 5304 HValue* dominator); |
5059 | 5305 |
5060 virtual void PrintDataTo(StringStream* stream); | 5306 virtual void PrintDataTo(StringStream* stream); |
5061 | 5307 |
5062 DECLARE_CONCRETE_INSTRUCTION(Allocate) | 5308 DECLARE_CONCRETE_INSTRUCTION(Allocate) |
5063 | 5309 |
5064 private: | 5310 private: |
5065 HType type_; | |
5066 Flags flags_; | 5311 Flags flags_; |
5067 Handle<Map> known_initial_map_; | 5312 Handle<Map> known_initial_map_; |
5068 }; | 5313 }; |
5069 | 5314 |
5070 | 5315 |
5071 class HInnerAllocatedObject: public HTemplateInstruction<1> { | 5316 class HInnerAllocatedObject: public HTemplateInstruction<1> { |
5072 public: | 5317 public: |
5073 HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged()) | 5318 HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged()) |
5074 : offset_(offset), | 5319 : offset_(offset) { |
5075 type_(type) { | |
5076 ASSERT(value->IsAllocate()); | 5320 ASSERT(value->IsAllocate()); |
5077 SetOperandAt(0, value); | 5321 SetOperandAt(0, value); |
| 5322 set_type(type); |
5078 set_representation(Representation::Tagged()); | 5323 set_representation(Representation::Tagged()); |
5079 } | 5324 } |
5080 | 5325 |
5081 HValue* base_object() { return OperandAt(0); } | 5326 HValue* base_object() { return OperandAt(0); } |
5082 int offset() { return offset_; } | 5327 int offset() { return offset_; } |
5083 | 5328 |
5084 virtual Representation RequiredInputRepresentation(int index) { | 5329 virtual Representation RequiredInputRepresentation(int index) { |
5085 return Representation::Tagged(); | 5330 return Representation::Tagged(); |
5086 } | 5331 } |
5087 | 5332 |
5088 virtual HType CalculateInferredType() { return type_; } | |
5089 | |
5090 virtual void PrintDataTo(StringStream* stream); | 5333 virtual void PrintDataTo(StringStream* stream); |
5091 | 5334 |
5092 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject) | 5335 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject) |
5093 | 5336 |
5094 private: | 5337 private: |
5095 int offset_; | 5338 int offset_; |
5096 HType type_; | |
5097 }; | 5339 }; |
5098 | 5340 |
5099 | 5341 |
5100 inline bool StoringValueNeedsWriteBarrier(HValue* value) { | 5342 inline bool StoringValueNeedsWriteBarrier(HValue* value) { |
5101 return !value->type().IsBoolean() | 5343 return !value->type().IsBoolean() |
5102 && !value->type().IsSmi() | 5344 && !value->type().IsSmi() |
5103 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); | 5345 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); |
5104 } | 5346 } |
5105 | 5347 |
5106 | 5348 |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5315 class HObjectAccess { | 5557 class HObjectAccess { |
5316 public: | 5558 public: |
5317 inline bool IsInobject() const { | 5559 inline bool IsInobject() const { |
5318 return portion() != kBackingStore; | 5560 return portion() != kBackingStore; |
5319 } | 5561 } |
5320 | 5562 |
5321 inline int offset() const { | 5563 inline int offset() const { |
5322 return OffsetField::decode(value_); | 5564 return OffsetField::decode(value_); |
5323 } | 5565 } |
5324 | 5566 |
| 5567 inline Representation representation() const { |
| 5568 return Representation::FromKind(RepresentationField::decode(value_)); |
| 5569 } |
| 5570 |
5325 inline Handle<String> name() const { | 5571 inline Handle<String> name() const { |
5326 return name_; | 5572 return name_; |
5327 } | 5573 } |
5328 | 5574 |
| 5575 inline HObjectAccess WithRepresentation(Representation representation) { |
| 5576 return HObjectAccess(portion(), offset(), representation, name()); |
| 5577 } |
| 5578 |
5329 static HObjectAccess ForHeapNumberValue() { | 5579 static HObjectAccess ForHeapNumberValue() { |
5330 return HObjectAccess(kDouble, HeapNumber::kValueOffset); | 5580 return HObjectAccess( |
| 5581 kDouble, HeapNumber::kValueOffset, Representation::Double()); |
5331 } | 5582 } |
5332 | 5583 |
5333 static HObjectAccess ForElementsPointer() { | 5584 static HObjectAccess ForElementsPointer() { |
5334 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset); | 5585 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset); |
5335 } | 5586 } |
5336 | 5587 |
5337 static HObjectAccess ForArrayLength() { | 5588 static HObjectAccess ForArrayLength(ElementsKind elements_kind) { |
5338 return HObjectAccess(kArrayLengths, JSArray::kLengthOffset); | 5589 return HObjectAccess( |
| 5590 kArrayLengths, JSArray::kLengthOffset, |
| 5591 IsFastElementsKind(elements_kind) && FLAG_track_fields ? |
| 5592 Representation::Smi() : Representation::Tagged()); |
5339 } | 5593 } |
5340 | 5594 |
5341 static HObjectAccess ForAllocationSiteTransitionInfo() { | 5595 static HObjectAccess ForAllocationSiteTransitionInfo() { |
5342 return HObjectAccess(kInobject, AllocationSite::kTransitionInfoOffset); | 5596 return HObjectAccess(kInobject, AllocationSite::kTransitionInfoOffset); |
5343 } | 5597 } |
5344 | 5598 |
5345 static HObjectAccess ForAllocationSiteWeakNext() { | 5599 static HObjectAccess ForAllocationSiteWeakNext() { |
5346 return HObjectAccess(kInobject, AllocationSite::kWeakNextOffset); | 5600 return HObjectAccess(kInobject, AllocationSite::kWeakNextOffset); |
5347 } | 5601 } |
5348 | 5602 |
5349 static HObjectAccess ForFixedArrayLength() { | 5603 static HObjectAccess ForFixedArrayLength() { |
5350 return HObjectAccess(kArrayLengths, FixedArray::kLengthOffset); | 5604 return HObjectAccess( |
| 5605 kArrayLengths, FixedArray::kLengthOffset, |
| 5606 FLAG_track_fields ? |
| 5607 Representation::Smi() : Representation::Tagged()); |
5351 } | 5608 } |
5352 | 5609 |
5353 static HObjectAccess ForPropertiesPointer() { | 5610 static HObjectAccess ForPropertiesPointer() { |
5354 return HObjectAccess(kInobject, JSObject::kPropertiesOffset); | 5611 return HObjectAccess(kInobject, JSObject::kPropertiesOffset); |
5355 } | 5612 } |
5356 | 5613 |
5357 static HObjectAccess ForPrototypeOrInitialMap() { | 5614 static HObjectAccess ForPrototypeOrInitialMap() { |
5358 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset); | 5615 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset); |
5359 } | 5616 } |
5360 | 5617 |
(...skipping 10 matching lines...) Expand all Loading... |
5371 } | 5628 } |
5372 | 5629 |
5373 static HObjectAccess ForAllocationMementoSite() { | 5630 static HObjectAccess ForAllocationMementoSite() { |
5374 return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset); | 5631 return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset); |
5375 } | 5632 } |
5376 | 5633 |
5377 // Create an access to an offset in a fixed array header. | 5634 // Create an access to an offset in a fixed array header. |
5378 static HObjectAccess ForFixedArrayHeader(int offset); | 5635 static HObjectAccess ForFixedArrayHeader(int offset); |
5379 | 5636 |
5380 // Create an access to an in-object property in a JSObject. | 5637 // Create an access to an in-object property in a JSObject. |
5381 static HObjectAccess ForJSObjectOffset(int offset); | 5638 static HObjectAccess ForJSObjectOffset(int offset, |
| 5639 Representation representation = Representation::Tagged()); |
5382 | 5640 |
5383 // Create an access to an in-object property in a JSArray. | 5641 // Create an access to an in-object property in a JSArray. |
5384 static HObjectAccess ForJSArrayOffset(int offset); | 5642 static HObjectAccess ForJSArrayOffset(int offset); |
5385 | 5643 |
5386 // Create an access to the backing store of an object. | 5644 // Create an access to the backing store of an object. |
5387 static HObjectAccess ForBackingStoreOffset(int offset); | 5645 static HObjectAccess ForBackingStoreOffset(int offset, |
| 5646 Representation representation = Representation::Tagged()); |
5388 | 5647 |
5389 // Create an access to a resolved field (in-object or backing store). | 5648 // Create an access to a resolved field (in-object or backing store). |
5390 static HObjectAccess ForField(Handle<Map> map, | 5649 static HObjectAccess ForField(Handle<Map> map, |
5391 LookupResult *lookup, Handle<String> name = Handle<String>::null()); | 5650 LookupResult *lookup, Handle<String> name = Handle<String>::null()); |
5392 | 5651 |
5393 // Create an access for the payload of a Cell or JSGlobalPropertyCell. | 5652 // Create an access for the payload of a Cell or JSGlobalPropertyCell. |
5394 static HObjectAccess ForCellPayload(Isolate* isolate); | 5653 static HObjectAccess ForCellPayload(Isolate* isolate); |
5395 | 5654 |
5396 void PrintTo(StringStream* stream); | 5655 void PrintTo(StringStream* stream); |
5397 | 5656 |
5398 inline bool Equals(HObjectAccess that) const { | 5657 inline bool Equals(HObjectAccess that) const { |
5399 return value_ == that.value_; // portion and offset must match | 5658 return value_ == that.value_; // portion and offset must match |
5400 } | 5659 } |
5401 | 5660 |
5402 protected: | 5661 protected: |
5403 void SetGVNFlags(HValue *instr, bool is_store); | 5662 void SetGVNFlags(HValue *instr, bool is_store); |
5404 | 5663 |
5405 private: | 5664 private: |
5406 // internal use only; different parts of an object or array | 5665 // internal use only; different parts of an object or array |
5407 enum Portion { | 5666 enum Portion { |
5408 kMaps, // map of an object | 5667 kMaps, // map of an object |
5409 kArrayLengths, // the length of an array | 5668 kArrayLengths, // the length of an array |
5410 kElementsPointer, // elements pointer | 5669 kElementsPointer, // elements pointer |
5411 kBackingStore, // some field in the backing store | 5670 kBackingStore, // some field in the backing store |
5412 kDouble, // some double field | 5671 kDouble, // some double field |
5413 kInobject // some other in-object field | 5672 kInobject // some other in-object field |
5414 }; | 5673 }; |
5415 | 5674 |
5416 HObjectAccess(Portion portion, int offset, | 5675 HObjectAccess(Portion portion, int offset, |
5417 Handle<String> name = Handle<String>::null()) | 5676 Representation representation = Representation::Tagged(), |
5418 : value_(PortionField::encode(portion) | OffsetField::encode(offset)), | 5677 Handle<String> name = Handle<String>::null()) |
| 5678 : value_(PortionField::encode(portion) | |
| 5679 RepresentationField::encode(representation.kind()) | |
| 5680 OffsetField::encode(offset)), |
5419 name_(name) { | 5681 name_(name) { |
5420 ASSERT(this->offset() == offset); // offset should decode correctly | 5682 // assert that the fields decode correctly |
5421 ASSERT(this->portion() == portion); // portion should decode correctly | 5683 ASSERT(this->offset() == offset); |
| 5684 ASSERT(this->portion() == portion); |
| 5685 ASSERT(RepresentationField::decode(value_) == representation.kind()); |
5422 } | 5686 } |
5423 | 5687 |
5424 class PortionField : public BitField<Portion, 0, 3> {}; | 5688 class PortionField : public BitField<Portion, 0, 3> {}; |
5425 class OffsetField : public BitField<int, 3, 29> {}; | 5689 class RepresentationField : public BitField<Representation::Kind, 3, 3> {}; |
| 5690 class OffsetField : public BitField<int, 6, 26> {}; |
5426 | 5691 |
5427 uint32_t value_; // encodes both portion and offset | 5692 uint32_t value_; // encodes portion, representation, and offset |
5428 Handle<String> name_; | 5693 Handle<String> name_; |
5429 | 5694 |
5430 friend class HLoadNamedField; | 5695 friend class HLoadNamedField; |
5431 friend class HStoreNamedField; | 5696 friend class HStoreNamedField; |
5432 | 5697 |
5433 inline Portion portion() const { | 5698 inline Portion portion() const { |
5434 return PortionField::decode(value_); | 5699 return PortionField::decode(value_); |
5435 } | 5700 } |
5436 }; | 5701 }; |
5437 | 5702 |
(...skipping 27 matching lines...) Expand all Loading... |
5465 private: | 5730 private: |
5466 HObjectAccess store_field_; | 5731 HObjectAccess store_field_; |
5467 KnownList known_list_; | 5732 KnownList known_list_; |
5468 }; | 5733 }; |
5469 | 5734 |
5470 | 5735 |
5471 class HLoadNamedField: public HTemplateInstruction<2> { | 5736 class HLoadNamedField: public HTemplateInstruction<2> { |
5472 public: | 5737 public: |
5473 HLoadNamedField(HValue* object, | 5738 HLoadNamedField(HValue* object, |
5474 HObjectAccess access, | 5739 HObjectAccess access, |
5475 HValue* typecheck = NULL, | 5740 HValue* typecheck = NULL) |
5476 Representation field_representation | 5741 : access_(access) { |
5477 = Representation::Tagged()) | |
5478 : access_(access), | |
5479 field_representation_(field_representation) { | |
5480 ASSERT(object != NULL); | 5742 ASSERT(object != NULL); |
5481 SetOperandAt(0, object); | 5743 SetOperandAt(0, object); |
5482 SetOperandAt(1, typecheck != NULL ? typecheck : object); | 5744 SetOperandAt(1, typecheck != NULL ? typecheck : object); |
5483 | 5745 |
5484 if (FLAG_track_fields && field_representation.IsSmi()) { | 5746 Representation representation = access.representation(); |
| 5747 if (representation.IsSmi()) { |
5485 set_type(HType::Smi()); | 5748 set_type(HType::Smi()); |
5486 set_representation(field_representation); | 5749 set_representation(representation); |
5487 } else if (FLAG_track_double_fields && field_representation.IsDouble()) { | 5750 } else if (representation.IsDouble()) { |
5488 set_representation(field_representation); | 5751 set_representation(representation); |
5489 } else if (FLAG_track_heap_object_fields && | 5752 } else if (FLAG_track_heap_object_fields && |
5490 field_representation.IsHeapObject()) { | 5753 representation.IsHeapObject()) { |
5491 set_type(HType::NonPrimitive()); | 5754 set_type(HType::NonPrimitive()); |
5492 set_representation(Representation::Tagged()); | 5755 set_representation(Representation::Tagged()); |
5493 } else { | 5756 } else { |
5494 set_representation(Representation::Tagged()); | 5757 set_representation(Representation::Tagged()); |
5495 } | 5758 } |
5496 access.SetGVNFlags(this, false); | 5759 access.SetGVNFlags(this, false); |
5497 } | 5760 } |
5498 | 5761 |
5499 HValue* object() { return OperandAt(0); } | 5762 HValue* object() { return OperandAt(0); } |
5500 HValue* typecheck() { | 5763 HValue* typecheck() { |
5501 ASSERT(HasTypeCheck()); | 5764 ASSERT(HasTypeCheck()); |
5502 return OperandAt(1); | 5765 return OperandAt(1); |
5503 } | 5766 } |
5504 | 5767 |
5505 bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); } | 5768 bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); } |
5506 HObjectAccess access() const { return access_; } | 5769 HObjectAccess access() const { return access_; } |
5507 Representation field_representation() const { return representation_; } | 5770 Representation field_representation() const { |
| 5771 return access_.representation(); |
| 5772 } |
5508 | 5773 |
5509 virtual bool HasEscapingOperandAt(int index) { return false; } | 5774 virtual bool HasEscapingOperandAt(int index) { return false; } |
5510 virtual Representation RequiredInputRepresentation(int index) { | 5775 virtual Representation RequiredInputRepresentation(int index) { |
5511 return Representation::Tagged(); | 5776 return Representation::Tagged(); |
5512 } | 5777 } |
5513 virtual void PrintDataTo(StringStream* stream); | 5778 virtual void PrintDataTo(StringStream* stream); |
5514 | 5779 |
5515 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) | 5780 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) |
5516 | 5781 |
5517 protected: | 5782 protected: |
5518 virtual bool DataEquals(HValue* other) { | 5783 virtual bool DataEquals(HValue* other) { |
5519 HLoadNamedField* b = HLoadNamedField::cast(other); | 5784 HLoadNamedField* b = HLoadNamedField::cast(other); |
5520 return access_.Equals(b->access_); | 5785 return access_.Equals(b->access_); |
5521 } | 5786 } |
5522 | 5787 |
5523 private: | 5788 private: |
5524 virtual bool IsDeletable() const { return true; } | 5789 virtual bool IsDeletable() const { return true; } |
5525 | 5790 |
5526 HObjectAccess access_; | 5791 HObjectAccess access_; |
5527 Representation field_representation_; | |
5528 }; | 5792 }; |
5529 | 5793 |
5530 | 5794 |
5531 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> { | 5795 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> { |
5532 public: | 5796 public: |
5533 HLoadNamedFieldPolymorphic(HValue* context, | 5797 HLoadNamedFieldPolymorphic(HValue* context, |
5534 HValue* object, | 5798 HValue* object, |
5535 SmallMapList* types, | 5799 SmallMapList* types, |
5536 Handle<String> name, | 5800 Handle<String> name, |
5537 Zone* zone); | 5801 Zone* zone); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5618 class ArrayInstructionInterface { | 5882 class ArrayInstructionInterface { |
5619 public: | 5883 public: |
5620 virtual HValue* GetKey() = 0; | 5884 virtual HValue* GetKey() = 0; |
5621 virtual void SetKey(HValue* key) = 0; | 5885 virtual void SetKey(HValue* key) = 0; |
5622 virtual void SetIndexOffset(uint32_t index_offset) = 0; | 5886 virtual void SetIndexOffset(uint32_t index_offset) = 0; |
5623 virtual bool IsDehoisted() = 0; | 5887 virtual bool IsDehoisted() = 0; |
5624 virtual void SetDehoisted(bool is_dehoisted) = 0; | 5888 virtual void SetDehoisted(bool is_dehoisted) = 0; |
5625 virtual ~ArrayInstructionInterface() { }; | 5889 virtual ~ArrayInstructionInterface() { }; |
5626 | 5890 |
5627 static Representation KeyedAccessIndexRequirement(Representation r) { | 5891 static Representation KeyedAccessIndexRequirement(Representation r) { |
5628 return r.IsInteger32() ? Representation::Integer32() | 5892 return r.IsInteger32() || kSmiValueSize != 31 |
5629 : Representation::Smi(); | 5893 ? Representation::Integer32() : Representation::Smi(); |
5630 } | 5894 } |
5631 }; | 5895 }; |
5632 | 5896 |
5633 | 5897 |
5634 enum LoadKeyedHoleMode { | 5898 enum LoadKeyedHoleMode { |
5635 NEVER_RETURN_HOLE, | 5899 NEVER_RETURN_HOLE, |
5636 ALLOW_RETURN_HOLE | 5900 ALLOW_RETURN_HOLE |
5637 }; | 5901 }; |
5638 | 5902 |
5639 | 5903 |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5817 virtual HValue* Canonicalize(); | 6081 virtual HValue* Canonicalize(); |
5818 | 6082 |
5819 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric) | 6083 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric) |
5820 }; | 6084 }; |
5821 | 6085 |
5822 | 6086 |
5823 class HStoreNamedField: public HTemplateInstruction<2> { | 6087 class HStoreNamedField: public HTemplateInstruction<2> { |
5824 public: | 6088 public: |
5825 HStoreNamedField(HValue* obj, | 6089 HStoreNamedField(HValue* obj, |
5826 HObjectAccess access, | 6090 HObjectAccess access, |
5827 HValue* val, | 6091 HValue* val) |
5828 Representation field_representation | |
5829 = Representation::Tagged()) | |
5830 : access_(access), | 6092 : access_(access), |
5831 field_representation_(field_representation), | |
5832 transition_(), | 6093 transition_(), |
5833 transition_unique_id_(), | 6094 transition_unique_id_(), |
5834 new_space_dominator_(NULL), | 6095 new_space_dominator_(NULL), |
5835 write_barrier_mode_(UPDATE_WRITE_BARRIER) { | 6096 write_barrier_mode_(UPDATE_WRITE_BARRIER) { |
5836 SetOperandAt(0, obj); | 6097 SetOperandAt(0, obj); |
5837 SetOperandAt(1, val); | 6098 SetOperandAt(1, val); |
5838 access.SetGVNFlags(this, true); | 6099 access.SetGVNFlags(this, true); |
5839 } | 6100 } |
5840 | 6101 |
5841 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) | 6102 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) |
5842 | 6103 |
5843 virtual bool HasEscapingOperandAt(int index) { return index == 1; } | 6104 virtual bool HasEscapingOperandAt(int index) { return index == 1; } |
5844 virtual Representation RequiredInputRepresentation(int index) { | 6105 virtual Representation RequiredInputRepresentation(int index) { |
5845 if (FLAG_track_double_fields && | 6106 if (index == 1 && field_representation().IsDouble()) { |
5846 index == 1 && field_representation_.IsDouble()) { | 6107 return field_representation(); |
5847 return field_representation_; | 6108 } else if (index == 1 && field_representation().IsSmi()) { |
5848 } else if (FLAG_track_fields && | 6109 return field_representation(); |
5849 index == 1 && field_representation_.IsSmi()) { | |
5850 return field_representation_; | |
5851 } | 6110 } |
5852 return Representation::Tagged(); | 6111 return Representation::Tagged(); |
5853 } | 6112 } |
5854 virtual void HandleSideEffectDominator(GVNFlag side_effect, | 6113 virtual void HandleSideEffectDominator(GVNFlag side_effect, |
5855 HValue* dominator) { | 6114 HValue* dominator) { |
5856 ASSERT(side_effect == kChangesNewSpacePromotion); | 6115 ASSERT(side_effect == kChangesNewSpacePromotion); |
5857 new_space_dominator_ = dominator; | 6116 new_space_dominator_ = dominator; |
5858 } | 6117 } |
5859 virtual void PrintDataTo(StringStream* stream); | 6118 virtual void PrintDataTo(StringStream* stream); |
5860 | 6119 |
(...skipping 11 matching lines...) Expand all Loading... |
5872 void SetTransition(Handle<Map> map, CompilationInfo* info) { | 6131 void SetTransition(Handle<Map> map, CompilationInfo* info) { |
5873 ASSERT(transition_.is_null()); // Only set once. | 6132 ASSERT(transition_.is_null()); // Only set once. |
5874 if (map->CanBeDeprecated()) { | 6133 if (map->CanBeDeprecated()) { |
5875 map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info); | 6134 map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info); |
5876 } | 6135 } |
5877 transition_ = map; | 6136 transition_ = map; |
5878 } | 6137 } |
5879 HValue* new_space_dominator() const { return new_space_dominator_; } | 6138 HValue* new_space_dominator() const { return new_space_dominator_; } |
5880 | 6139 |
5881 bool NeedsWriteBarrier() { | 6140 bool NeedsWriteBarrier() { |
5882 ASSERT(!(FLAG_track_double_fields && field_representation_.IsDouble()) || | 6141 ASSERT(!(FLAG_track_double_fields && field_representation().IsDouble()) || |
5883 transition_.is_null()); | 6142 transition_.is_null()); |
5884 if (IsSkipWriteBarrier()) return false; | 6143 if (IsSkipWriteBarrier()) return false; |
5885 return (!FLAG_track_fields || !field_representation_.IsSmi()) && | 6144 if (field_representation().IsDouble()) return false; |
5886 // If there is a transition, a new storage object needs to be allocated. | 6145 if (field_representation().IsSmi()) return false; |
5887 !(FLAG_track_double_fields && field_representation_.IsDouble()) && | 6146 return StoringValueNeedsWriteBarrier(value()) && |
5888 StoringValueNeedsWriteBarrier(value()) && | |
5889 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); | 6147 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); |
5890 } | 6148 } |
5891 | 6149 |
5892 bool NeedsWriteBarrierForMap() { | 6150 bool NeedsWriteBarrierForMap() { |
5893 if (IsSkipWriteBarrier()) return false; | 6151 if (IsSkipWriteBarrier()) return false; |
5894 return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); | 6152 return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); |
5895 } | 6153 } |
5896 | 6154 |
5897 virtual void FinalizeUniqueValueId() { | 6155 virtual void FinalizeUniqueValueId() { |
5898 transition_unique_id_ = UniqueValueId(transition_); | 6156 transition_unique_id_ = UniqueValueId(transition_); |
5899 } | 6157 } |
5900 | 6158 |
5901 Representation field_representation() const { | 6159 Representation field_representation() const { |
5902 return field_representation_; | 6160 return access_.representation(); |
5903 } | 6161 } |
5904 | 6162 |
5905 private: | 6163 private: |
5906 HObjectAccess access_; | 6164 HObjectAccess access_; |
5907 Representation field_representation_; | |
5908 Handle<Map> transition_; | 6165 Handle<Map> transition_; |
5909 UniqueValueId transition_unique_id_; | 6166 UniqueValueId transition_unique_id_; |
5910 HValue* new_space_dominator_; | 6167 HValue* new_space_dominator_; |
5911 WriteBarrierMode write_barrier_mode_; | 6168 WriteBarrierMode write_barrier_mode_; |
5912 }; | 6169 }; |
5913 | 6170 |
5914 | 6171 |
5915 class HStoreNamedGeneric: public HTemplateInstruction<3> { | 6172 class HStoreNamedGeneric: public HTemplateInstruction<3> { |
5916 public: | 6173 public: |
5917 HStoreNamedGeneric(HValue* context, | 6174 HStoreNamedGeneric(HValue* context, |
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6694 virtual bool IsDeletable() const { return true; } | 6951 virtual bool IsDeletable() const { return true; } |
6695 }; | 6952 }; |
6696 | 6953 |
6697 | 6954 |
6698 #undef DECLARE_INSTRUCTION | 6955 #undef DECLARE_INSTRUCTION |
6699 #undef DECLARE_CONCRETE_INSTRUCTION | 6956 #undef DECLARE_CONCRETE_INSTRUCTION |
6700 | 6957 |
6701 } } // namespace v8::internal | 6958 } } // namespace v8::internal |
6702 | 6959 |
6703 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6960 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |