OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_CODE_STUB_ASSEMBLER_H_ | 5 #ifndef V8_CODE_STUB_ASSEMBLER_H_ |
6 #define V8_CODE_STUB_ASSEMBLER_H_ | 6 #define V8_CODE_STUB_ASSEMBLER_H_ |
7 | 7 |
8 #include <functional> | 8 #include <functional> |
9 | 9 |
10 #include "src/compiler/code-assembler.h" | 10 #include "src/compiler/code-assembler.h" |
11 #include "src/globals.h" | 11 #include "src/globals.h" |
12 #include "src/objects.h" | 12 #include "src/objects.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 class CallInterfaceDescriptor; | 17 class CallInterfaceDescriptor; |
18 class CodeStubArguments; | |
18 class StatsCounter; | 19 class StatsCounter; |
19 class StubCache; | 20 class StubCache; |
20 | 21 |
21 enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol }; | 22 enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol }; |
22 | 23 |
23 #define HEAP_CONSTANT_LIST(V) \ | 24 #define HEAP_CONSTANT_LIST(V) \ |
24 V(BooleanMap, BooleanMap) \ | 25 V(BooleanMap, BooleanMap) \ |
25 V(CodeMap, CodeMap) \ | 26 V(CodeMap, CodeMap) \ |
26 V(empty_string, EmptyString) \ | 27 V(empty_string, EmptyString) \ |
27 V(EmptyFixedArray, EmptyFixedArray) \ | 28 V(EmptyFixedArray, EmptyFixedArray) \ |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 // On 32-bit platforms, there is a slight performance advantage to doing all | 63 // On 32-bit platforms, there is a slight performance advantage to doing all |
63 // of the array offset/index arithmetic with SMIs, since it's possible | 64 // of the array offset/index arithmetic with SMIs, since it's possible |
64 // to save a few tag/untag operations without paying an extra expense when | 65 // to save a few tag/untag operations without paying an extra expense when |
65 // calculating array offset (the smi math can be folded away) and there are | 66 // calculating array offset (the smi math can be folded away) and there are |
66 // fewer live ranges. Thus only convert indices to untagged value on 64-bit | 67 // fewer live ranges. Thus only convert indices to untagged value on 64-bit |
67 // platforms. | 68 // platforms. |
68 ParameterMode OptimalParameterMode() const { | 69 ParameterMode OptimalParameterMode() const { |
69 return Is64() ? INTPTR_PARAMETERS : SMI_PARAMETERS; | 70 return Is64() ? INTPTR_PARAMETERS : SMI_PARAMETERS; |
70 } | 71 } |
71 | 72 |
73 MachineRepresentation OptimalParameterRepresentation() const { | |
74 return OptimalParameterMode() == INTPTR_PARAMETERS | |
75 ? MachineType::PointerRepresentation() | |
76 : MachineRepresentation::kTaggedSigned; | |
77 } | |
78 | |
72 compiler::Node* UntagParameter(compiler::Node* value, ParameterMode mode) { | 79 compiler::Node* UntagParameter(compiler::Node* value, ParameterMode mode) { |
73 if (mode != SMI_PARAMETERS) value = SmiUntag(value); | 80 if (mode != SMI_PARAMETERS) value = SmiUntag(value); |
74 return value; | 81 return value; |
75 } | 82 } |
76 | 83 |
77 compiler::Node* TagParameter(compiler::Node* value, ParameterMode mode) { | 84 compiler::Node* TagParameter(compiler::Node* value, ParameterMode mode) { |
78 if (mode != SMI_PARAMETERS) value = SmiTag(value); | 85 if (mode != SMI_PARAMETERS) value = SmiTag(value); |
79 return value; | 86 return value; |
80 } | 87 } |
81 | 88 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 compiler::Node* SmiMod(compiler::Node* a, compiler::Node* b); | 142 compiler::Node* SmiMod(compiler::Node* a, compiler::Node* b); |
136 // Computes a * b for Smi inputs a and b; result is not necessarily a Smi. | 143 // Computes a * b for Smi inputs a and b; result is not necessarily a Smi. |
137 compiler::Node* SmiMul(compiler::Node* a, compiler::Node* b); | 144 compiler::Node* SmiMul(compiler::Node* a, compiler::Node* b); |
138 compiler::Node* SmiOr(compiler::Node* a, compiler::Node* b) { | 145 compiler::Node* SmiOr(compiler::Node* a, compiler::Node* b) { |
139 return BitcastWordToTaggedSigned( | 146 return BitcastWordToTaggedSigned( |
140 WordOr(BitcastTaggedToWord(a), BitcastTaggedToWord(b))); | 147 WordOr(BitcastTaggedToWord(a), BitcastTaggedToWord(b))); |
141 } | 148 } |
142 | 149 |
143 // Smi | HeapNumber operations. | 150 // Smi | HeapNumber operations. |
144 compiler::Node* NumberInc(compiler::Node* value); | 151 compiler::Node* NumberInc(compiler::Node* value); |
152 void GotoIfNotNumber(compiler::Node* value, Label* is_not_number); | |
Jakob Kummerow
2016/11/23 17:17:06
nit: when you rebase, please drop all the "compile
danno
2016/11/29 14:39:59
Done.
| |
153 void GotoIfNumber(compiler::Node* value, Label* is_number); | |
145 | 154 |
146 // Allocate an object of the given size. | 155 // Allocate an object of the given size. |
147 compiler::Node* Allocate(compiler::Node* size, AllocationFlags flags = kNone); | 156 compiler::Node* Allocate(compiler::Node* size, AllocationFlags flags = kNone); |
148 compiler::Node* Allocate(int size, AllocationFlags flags = kNone); | 157 compiler::Node* Allocate(int size, AllocationFlags flags = kNone); |
149 compiler::Node* InnerAllocate(compiler::Node* previous, int offset); | 158 compiler::Node* InnerAllocate(compiler::Node* previous, int offset); |
150 compiler::Node* InnerAllocate(compiler::Node* previous, | 159 compiler::Node* InnerAllocate(compiler::Node* previous, |
151 compiler::Node* offset); | 160 compiler::Node* offset); |
152 compiler::Node* IsRegularHeapObjectSize(compiler::Node* size); | 161 compiler::Node* IsRegularHeapObjectSize(compiler::Node* size); |
153 | 162 |
154 typedef std::function<compiler::Node*()> ConditionBody; | 163 typedef std::function<compiler::Node*()> ConditionBody; |
155 void Assert(ConditionBody condition_body, const char* string = nullptr, | 164 void Assert(ConditionBody condition_body, const char* string = nullptr, |
156 const char* file = nullptr, int line = 0); | 165 const char* file = nullptr, int line = 0); |
157 | 166 |
158 // Check a value for smi-ness | 167 // Check a value for smi-ness |
159 compiler::Node* TaggedIsSmi(compiler::Node* a); | 168 compiler::Node* TaggedIsSmi(compiler::Node* a); |
169 compiler::Node* TaggedIsNotSmi(compiler::Node* a); | |
160 // Check that the value is a non-negative smi. | 170 // Check that the value is a non-negative smi. |
161 compiler::Node* WordIsPositiveSmi(compiler::Node* a); | 171 compiler::Node* WordIsPositiveSmi(compiler::Node* a); |
162 // Check that a word has a word-aligned address. | 172 // Check that a word has a word-aligned address. |
163 compiler::Node* WordIsWordAligned(compiler::Node* word); | 173 compiler::Node* WordIsWordAligned(compiler::Node* word); |
164 compiler::Node* WordIsPowerOfTwo(compiler::Node* value); | 174 compiler::Node* WordIsPowerOfTwo(compiler::Node* value); |
165 | 175 |
166 void BranchIfSmiEqual(compiler::Node* a, compiler::Node* b, Label* if_true, | 176 void BranchIfSmiEqual(compiler::Node* a, compiler::Node* b, Label* if_true, |
167 Label* if_false) { | 177 Label* if_false) { |
168 Branch(SmiEqual(a, b), if_true, if_false); | 178 Branch(SmiEqual(a, b), if_true, if_false); |
169 } | 179 } |
(...skipping 24 matching lines...) Expand all Loading... | |
194 void BranchIfSimd128Equal(compiler::Node* lhs, compiler::Node* rhs, | 204 void BranchIfSimd128Equal(compiler::Node* lhs, compiler::Node* rhs, |
195 Label* if_equal, Label* if_notequal) { | 205 Label* if_equal, Label* if_notequal) { |
196 BranchIfSimd128Equal(lhs, LoadMap(lhs), rhs, LoadMap(rhs), if_equal, | 206 BranchIfSimd128Equal(lhs, LoadMap(lhs), rhs, LoadMap(rhs), if_equal, |
197 if_notequal); | 207 if_notequal); |
198 } | 208 } |
199 | 209 |
200 void BranchIfJSReceiver(compiler::Node* object, Label* if_true, | 210 void BranchIfJSReceiver(compiler::Node* object, Label* if_true, |
201 Label* if_false); | 211 Label* if_false); |
202 void BranchIfJSObject(compiler::Node* object, Label* if_true, | 212 void BranchIfJSObject(compiler::Node* object, Label* if_true, |
203 Label* if_false); | 213 Label* if_false); |
214 | |
215 enum class FastJSArrayAccessMode { INBOUNDS_READ, ANY_ACCESS }; | |
216 | |
204 void BranchIfFastJSArray(compiler::Node* object, compiler::Node* context, | 217 void BranchIfFastJSArray(compiler::Node* object, compiler::Node* context, |
205 Label* if_true, Label* if_false); | 218 FastJSArrayAccessMode mode, Label* if_true, |
219 Label* if_false); | |
206 | 220 |
207 // Load value from current frame by given offset in bytes. | 221 // Load value from current frame by given offset in bytes. |
208 compiler::Node* LoadFromFrame(int offset, | 222 compiler::Node* LoadFromFrame(int offset, |
209 MachineType rep = MachineType::AnyTagged()); | 223 MachineType rep = MachineType::AnyTagged()); |
210 // Load value from current parent frame by given offset in bytes. | 224 // Load value from current parent frame by given offset in bytes. |
211 compiler::Node* LoadFromParentFrame( | 225 compiler::Node* LoadFromParentFrame( |
212 int offset, MachineType rep = MachineType::AnyTagged()); | 226 int offset, MachineType rep = MachineType::AnyTagged()); |
213 | 227 |
214 // Load an object pointer from a buffer that isn't in the heap. | 228 // Load an object pointer from a buffer that isn't in the heap. |
215 compiler::Node* LoadBufferObject(compiler::Node* buffer, int offset, | 229 compiler::Node* LoadBufferObject(compiler::Node* buffer, int offset, |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
365 | 379 |
366 compiler::Node* StoreFixedArrayElement( | 380 compiler::Node* StoreFixedArrayElement( |
367 compiler::Node* object, compiler::Node* index, compiler::Node* value, | 381 compiler::Node* object, compiler::Node* index, compiler::Node* value, |
368 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, | 382 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, |
369 ParameterMode parameter_mode = INTEGER_PARAMETERS); | 383 ParameterMode parameter_mode = INTEGER_PARAMETERS); |
370 | 384 |
371 compiler::Node* StoreFixedDoubleArrayElement( | 385 compiler::Node* StoreFixedDoubleArrayElement( |
372 compiler::Node* object, compiler::Node* index, compiler::Node* value, | 386 compiler::Node* object, compiler::Node* index, compiler::Node* value, |
373 ParameterMode parameter_mode = INTEGER_PARAMETERS); | 387 ParameterMode parameter_mode = INTEGER_PARAMETERS); |
374 | 388 |
389 compiler::Node* BuildAppendJSArray(ElementsKind kind, compiler::Node* context, | |
390 compiler::Node* array, | |
391 CodeStubArguments& args, | |
392 Variable& arg_index, Label* bailout); | |
393 | |
375 void StoreFieldsNoWriteBarrier(compiler::Node* start_address, | 394 void StoreFieldsNoWriteBarrier(compiler::Node* start_address, |
376 compiler::Node* end_address, | 395 compiler::Node* end_address, |
377 compiler::Node* value); | 396 compiler::Node* value); |
378 | 397 |
379 // Allocate a HeapNumber without initializing its value. | 398 // Allocate a HeapNumber without initializing its value. |
380 compiler::Node* AllocateHeapNumber(MutableMode mode = IMMUTABLE); | 399 compiler::Node* AllocateHeapNumber(MutableMode mode = IMMUTABLE); |
381 // Allocate a HeapNumber with a specific value. | 400 // Allocate a HeapNumber with a specific value. |
382 compiler::Node* AllocateHeapNumberWithValue(compiler::Node* value, | 401 compiler::Node* AllocateHeapNumberWithValue(compiler::Node* value, |
383 MutableMode mode = IMMUTABLE); | 402 MutableMode mode = IMMUTABLE); |
384 // Allocate a SeqOneByteString with the given length. | 403 // Allocate a SeqOneByteString with the given length. |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 compiler::Node* value); | 594 compiler::Node* value); |
576 compiler::Node* TruncateTaggedToWord32(compiler::Node* context, | 595 compiler::Node* TruncateTaggedToWord32(compiler::Node* context, |
577 compiler::Node* value); | 596 compiler::Node* value); |
578 // Truncate the floating point value of a HeapNumber to an Int32. | 597 // Truncate the floating point value of a HeapNumber to an Int32. |
579 compiler::Node* TruncateHeapNumberValueToWord32(compiler::Node* object); | 598 compiler::Node* TruncateHeapNumberValueToWord32(compiler::Node* object); |
580 | 599 |
581 // Conversions. | 600 // Conversions. |
582 compiler::Node* ChangeFloat64ToTagged(compiler::Node* value); | 601 compiler::Node* ChangeFloat64ToTagged(compiler::Node* value); |
583 compiler::Node* ChangeInt32ToTagged(compiler::Node* value); | 602 compiler::Node* ChangeInt32ToTagged(compiler::Node* value); |
584 compiler::Node* ChangeUint32ToTagged(compiler::Node* value); | 603 compiler::Node* ChangeUint32ToTagged(compiler::Node* value); |
604 compiler::Node* ChangeNumberToFloat64(compiler::Node* value); | |
585 | 605 |
586 // Type conversions. | 606 // Type conversions. |
587 // Throws a TypeError for {method_name} if {value} is not coercible to Object, | 607 // Throws a TypeError for {method_name} if {value} is not coercible to Object, |
588 // or returns the {value} converted to a String otherwise. | 608 // or returns the {value} converted to a String otherwise. |
589 compiler::Node* ToThisString(compiler::Node* context, compiler::Node* value, | 609 compiler::Node* ToThisString(compiler::Node* context, compiler::Node* value, |
590 char const* method_name); | 610 char const* method_name); |
591 // Throws a TypeError for {method_name} if {value} is neither of the given | 611 // Throws a TypeError for {method_name} if {value} is neither of the given |
592 // {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or | 612 // {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or |
593 // returns the {value} (or wrapped value) otherwise. | 613 // returns the {value} (or wrapped value) otherwise. |
594 compiler::Node* ToThisValue(compiler::Node* context, compiler::Node* value, | 614 compiler::Node* ToThisValue(compiler::Node* context, compiler::Node* value, |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
735 template <typename T> | 755 template <typename T> |
736 compiler::Node* IsSetWord(compiler::Node* word) { | 756 compiler::Node* IsSetWord(compiler::Node* word) { |
737 return WordNotEqual(WordAnd(word, IntPtrConstant(T::kMask)), | 757 return WordNotEqual(WordAnd(word, IntPtrConstant(T::kMask)), |
738 IntPtrConstant(0)); | 758 IntPtrConstant(0)); |
739 } | 759 } |
740 | 760 |
741 void SetCounter(StatsCounter* counter, int value); | 761 void SetCounter(StatsCounter* counter, int value); |
742 void IncrementCounter(StatsCounter* counter, int delta); | 762 void IncrementCounter(StatsCounter* counter, int delta); |
743 void DecrementCounter(StatsCounter* counter, int delta); | 763 void DecrementCounter(StatsCounter* counter, int delta); |
744 | 764 |
765 void Increment(Variable& variable, int value = 1, | |
766 ParameterMode mode = INTPTR_PARAMETERS); | |
767 | |
745 // Generates "if (false) goto label" code. Useful for marking a label as | 768 // Generates "if (false) goto label" code. Useful for marking a label as |
746 // "live" to avoid assertion failures during graph building. In the resulting | 769 // "live" to avoid assertion failures during graph building. In the resulting |
747 // code this check will be eliminated. | 770 // code this check will be eliminated. |
748 void Use(Label* label); | 771 void Use(Label* label); |
749 | 772 |
750 // Various building blocks for stubs doing property lookups. | 773 // Various building blocks for stubs doing property lookups. |
751 void TryToName(compiler::Node* key, Label* if_keyisindex, Variable* var_index, | 774 void TryToName(compiler::Node* key, Label* if_keyisindex, Variable* var_index, |
752 Label* if_keyisunique, Label* if_bailout); | 775 Label* if_keyisunique, Label* if_bailout); |
753 | 776 |
754 // Calculates array index for given dictionary entry and entry field. | 777 // Calculates array index for given dictionary entry and entry field. |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1242 }; | 1265 }; |
1243 | 1266 |
1244 class CodeStubArguments { | 1267 class CodeStubArguments { |
1245 public: | 1268 public: |
1246 // |argc| specifies the number of arguments passed to the builtin excluding | 1269 // |argc| specifies the number of arguments passed to the builtin excluding |
1247 // the receiver. | 1270 // the receiver. |
1248 CodeStubArguments(CodeStubAssembler* assembler, compiler::Node* argc, | 1271 CodeStubArguments(CodeStubAssembler* assembler, compiler::Node* argc, |
1249 CodeStubAssembler::ParameterMode mode = | 1272 CodeStubAssembler::ParameterMode mode = |
1250 CodeStubAssembler::INTPTR_PARAMETERS); | 1273 CodeStubAssembler::INTPTR_PARAMETERS); |
1251 | 1274 |
1252 compiler::Node* GetReceiver(); | 1275 compiler::Node* GetReceiver() const; |
1253 | 1276 |
1254 // |index| is zero-based and does not include the receiver | 1277 // |index| is zero-based and does not include the receiver |
1255 compiler::Node* AtIndex(compiler::Node* index, | 1278 compiler::Node* AtIndex(compiler::Node* index, |
1256 CodeStubAssembler::ParameterMode mode = | 1279 CodeStubAssembler::ParameterMode mode = |
1257 CodeStubAssembler::INTPTR_PARAMETERS); | 1280 CodeStubAssembler::INTPTR_PARAMETERS) const; |
1258 | 1281 |
1259 compiler::Node* AtIndex(int index); | 1282 compiler::Node* AtIndex(int index) const; |
1283 | |
1284 compiler::Node* GetLength() const { return argc_; } | |
1260 | 1285 |
1261 typedef std::function<void(CodeStubAssembler* assembler, compiler::Node* arg)> | 1286 typedef std::function<void(CodeStubAssembler* assembler, compiler::Node* arg)> |
1262 ForEachBodyFunction; | 1287 ForEachBodyFunction; |
1263 | 1288 |
1264 // Iteration doesn't include the receiver. |first| and |last| are zero-based. | 1289 // Iteration doesn't include the receiver. |first| and |last| are zero-based. |
1265 void ForEach(ForEachBodyFunction body, compiler::Node* first = nullptr, | 1290 void ForEach(ForEachBodyFunction body, compiler::Node* first = nullptr, |
1266 compiler::Node* last = nullptr, | 1291 compiler::Node* last = nullptr, |
1267 CodeStubAssembler::ParameterMode mode = | 1292 CodeStubAssembler::ParameterMode mode = |
1268 CodeStubAssembler::INTPTR_PARAMETERS) { | 1293 CodeStubAssembler::INTPTR_PARAMETERS) { |
1269 CodeStubAssembler::VariableList list(0, assembler_->zone()); | 1294 CodeStubAssembler::VariableList list(0, assembler_->zone()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1302 } | 1327 } |
1303 #else | 1328 #else |
1304 #define CSA_SLOW_ASSERT(csa, x) ((void)0) | 1329 #define CSA_SLOW_ASSERT(csa, x) ((void)0) |
1305 #endif | 1330 #endif |
1306 | 1331 |
1307 DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags); | 1332 DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags); |
1308 | 1333 |
1309 } // namespace internal | 1334 } // namespace internal |
1310 } // namespace v8 | 1335 } // namespace v8 |
1311 #endif // V8_CODE_STUB_ASSEMBLER_H_ | 1336 #endif // V8_CODE_STUB_ASSEMBLER_H_ |
OLD | NEW |