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(AccessorInfoMap, AccessorInfoMap) \ | 25 V(AccessorInfoMap, AccessorInfoMap) \ |
25 V(BooleanMap, BooleanMap) \ | 26 V(BooleanMap, BooleanMap) \ |
26 V(CodeMap, CodeMap) \ | 27 V(CodeMap, CodeMap) \ |
27 V(empty_string, EmptyString) \ | 28 V(empty_string, EmptyString) \ |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 // On 32-bit platforms, there is a slight performance advantage to doing all | 68 // On 32-bit platforms, there is a slight performance advantage to doing all |
68 // of the array offset/index arithmetic with SMIs, since it's possible | 69 // of the array offset/index arithmetic with SMIs, since it's possible |
69 // to save a few tag/untag operations without paying an extra expense when | 70 // to save a few tag/untag operations without paying an extra expense when |
70 // calculating array offset (the smi math can be folded away) and there are | 71 // calculating array offset (the smi math can be folded away) and there are |
71 // fewer live ranges. Thus only convert indices to untagged value on 64-bit | 72 // fewer live ranges. Thus only convert indices to untagged value on 64-bit |
72 // platforms. | 73 // platforms. |
73 ParameterMode OptimalParameterMode() const { | 74 ParameterMode OptimalParameterMode() const { |
74 return Is64() ? INTPTR_PARAMETERS : SMI_PARAMETERS; | 75 return Is64() ? INTPTR_PARAMETERS : SMI_PARAMETERS; |
75 } | 76 } |
76 | 77 |
| 78 MachineRepresentation OptimalParameterRepresentation() const { |
| 79 return OptimalParameterMode() == INTPTR_PARAMETERS |
| 80 ? MachineType::PointerRepresentation() |
| 81 : MachineRepresentation::kTaggedSigned; |
| 82 } |
| 83 |
77 Node* UntagParameter(Node* value, ParameterMode mode) { | 84 Node* UntagParameter(Node* value, ParameterMode mode) { |
78 if (mode != SMI_PARAMETERS) value = SmiUntag(value); | 85 if (mode != SMI_PARAMETERS) value = SmiUntag(value); |
79 return value; | 86 return value; |
80 } | 87 } |
81 | 88 |
82 Node* TagParameter(Node* value, ParameterMode mode) { | 89 Node* TagParameter(Node* value, ParameterMode mode) { |
83 if (mode != SMI_PARAMETERS) value = SmiTag(value); | 90 if (mode != SMI_PARAMETERS) value = SmiTag(value); |
84 return value; | 91 return value; |
85 } | 92 } |
86 | 93 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 Node* SmiMod(Node* a, Node* b); | 144 Node* SmiMod(Node* a, Node* b); |
138 // Computes a * b for Smi inputs a and b; result is not necessarily a Smi. | 145 // Computes a * b for Smi inputs a and b; result is not necessarily a Smi. |
139 Node* SmiMul(Node* a, Node* b); | 146 Node* SmiMul(Node* a, Node* b); |
140 Node* SmiOr(Node* a, Node* b) { | 147 Node* SmiOr(Node* a, Node* b) { |
141 return BitcastWordToTaggedSigned( | 148 return BitcastWordToTaggedSigned( |
142 WordOr(BitcastTaggedToWord(a), BitcastTaggedToWord(b))); | 149 WordOr(BitcastTaggedToWord(a), BitcastTaggedToWord(b))); |
143 } | 150 } |
144 | 151 |
145 // Smi | HeapNumber operations. | 152 // Smi | HeapNumber operations. |
146 Node* NumberInc(Node* value); | 153 Node* NumberInc(Node* value); |
| 154 void GotoIfNotNumber(Node* value, Label* is_not_number); |
| 155 void GotoIfNumber(Node* value, Label* is_number); |
147 | 156 |
148 // Allocate an object of the given size. | 157 // Allocate an object of the given size. |
149 Node* Allocate(Node* size, AllocationFlags flags = kNone); | 158 Node* Allocate(Node* size, AllocationFlags flags = kNone); |
150 Node* Allocate(int size, AllocationFlags flags = kNone); | 159 Node* Allocate(int size, AllocationFlags flags = kNone); |
151 Node* InnerAllocate(Node* previous, int offset); | 160 Node* InnerAllocate(Node* previous, int offset); |
152 Node* InnerAllocate(Node* previous, Node* offset); | 161 Node* InnerAllocate(Node* previous, Node* offset); |
153 Node* IsRegularHeapObjectSize(Node* size); | 162 Node* IsRegularHeapObjectSize(Node* size); |
154 | 163 |
155 typedef std::function<Node*()> ConditionBody; | 164 typedef std::function<Node*()> ConditionBody; |
156 void Assert(ConditionBody condition_body, const char* string = nullptr, | 165 void Assert(ConditionBody condition_body, const char* string = nullptr, |
157 const char* file = nullptr, int line = 0); | 166 const char* file = nullptr, int line = 0); |
158 | 167 |
159 // Check a value for smi-ness | 168 // Check a value for smi-ness |
160 Node* TaggedIsSmi(Node* a); | 169 Node* TaggedIsSmi(Node* a); |
| 170 Node* TaggedIsNotSmi(Node* a); |
161 // Check that the value is a non-negative smi. | 171 // Check that the value is a non-negative smi. |
162 Node* WordIsPositiveSmi(Node* a); | 172 Node* WordIsPositiveSmi(Node* a); |
163 // Check that a word has a word-aligned address. | 173 // Check that a word has a word-aligned address. |
164 Node* WordIsWordAligned(Node* word); | 174 Node* WordIsWordAligned(Node* word); |
165 Node* WordIsPowerOfTwo(Node* value); | 175 Node* WordIsPowerOfTwo(Node* value); |
166 | 176 |
167 void BranchIfSmiEqual(Node* a, Node* b, Label* if_true, Label* if_false) { | 177 void BranchIfSmiEqual(Node* a, Node* b, Label* if_true, Label* if_false) { |
168 Branch(SmiEqual(a, b), if_true, if_false); | 178 Branch(SmiEqual(a, b), if_true, if_false); |
169 } | 179 } |
170 | 180 |
(...skipping 17 matching lines...) Expand all Loading... |
188 void BranchIfSimd128Equal(Node* lhs, Node* lhs_map, Node* rhs, Node* rhs_map, | 198 void BranchIfSimd128Equal(Node* lhs, Node* lhs_map, Node* rhs, Node* rhs_map, |
189 Label* if_equal, Label* if_notequal); | 199 Label* if_equal, Label* if_notequal); |
190 void BranchIfSimd128Equal(Node* lhs, Node* rhs, Label* if_equal, | 200 void BranchIfSimd128Equal(Node* lhs, Node* rhs, Label* if_equal, |
191 Label* if_notequal) { | 201 Label* if_notequal) { |
192 BranchIfSimd128Equal(lhs, LoadMap(lhs), rhs, LoadMap(rhs), if_equal, | 202 BranchIfSimd128Equal(lhs, LoadMap(lhs), rhs, LoadMap(rhs), if_equal, |
193 if_notequal); | 203 if_notequal); |
194 } | 204 } |
195 | 205 |
196 void BranchIfJSReceiver(Node* object, Label* if_true, Label* if_false); | 206 void BranchIfJSReceiver(Node* object, Label* if_true, Label* if_false); |
197 void BranchIfJSObject(Node* object, Label* if_true, Label* if_false); | 207 void BranchIfJSObject(Node* object, Label* if_true, Label* if_false); |
198 void BranchIfFastJSArray(Node* object, Node* context, Label* if_true, | 208 |
| 209 enum class FastJSArrayAccessMode { INBOUNDS_READ, ANY_ACCESS }; |
| 210 void BranchIfFastJSArray(Node* object, Node* context, |
| 211 FastJSArrayAccessMode mode, Label* if_true, |
199 Label* if_false); | 212 Label* if_false); |
200 | 213 |
201 // Load value from current frame by given offset in bytes. | 214 // Load value from current frame by given offset in bytes. |
202 Node* LoadFromFrame(int offset, MachineType rep = MachineType::AnyTagged()); | 215 Node* LoadFromFrame(int offset, MachineType rep = MachineType::AnyTagged()); |
203 // Load value from current parent frame by given offset in bytes. | 216 // Load value from current parent frame by given offset in bytes. |
204 Node* LoadFromParentFrame(int offset, | 217 Node* LoadFromParentFrame(int offset, |
205 MachineType rep = MachineType::AnyTagged()); | 218 MachineType rep = MachineType::AnyTagged()); |
206 | 219 |
207 // Load an object pointer from a buffer that isn't in the heap. | 220 // Load an object pointer from a buffer that isn't in the heap. |
208 Node* LoadBufferObject(Node* buffer, int offset, | 221 Node* LoadBufferObject(Node* buffer, int offset, |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 Node* StoreFixedArrayElement( | 355 Node* StoreFixedArrayElement( |
343 Node* object, Node* index, Node* value, | 356 Node* object, Node* index, Node* value, |
344 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, | 357 WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER, |
345 int additional_offset = 0, | 358 int additional_offset = 0, |
346 ParameterMode parameter_mode = INTEGER_PARAMETERS); | 359 ParameterMode parameter_mode = INTEGER_PARAMETERS); |
347 | 360 |
348 Node* StoreFixedDoubleArrayElement( | 361 Node* StoreFixedDoubleArrayElement( |
349 Node* object, Node* index, Node* value, | 362 Node* object, Node* index, Node* value, |
350 ParameterMode parameter_mode = INTEGER_PARAMETERS); | 363 ParameterMode parameter_mode = INTEGER_PARAMETERS); |
351 | 364 |
| 365 Node* BuildAppendJSArray(ElementsKind kind, Node* context, Node* array, |
| 366 CodeStubArguments& args, Variable& arg_index, |
| 367 Label* bailout); |
| 368 |
352 void StoreFieldsNoWriteBarrier(Node* start_address, Node* end_address, | 369 void StoreFieldsNoWriteBarrier(Node* start_address, Node* end_address, |
353 Node* value); | 370 Node* value); |
354 | 371 |
355 // Allocate a HeapNumber without initializing its value. | 372 // Allocate a HeapNumber without initializing its value. |
356 Node* AllocateHeapNumber(MutableMode mode = IMMUTABLE); | 373 Node* AllocateHeapNumber(MutableMode mode = IMMUTABLE); |
357 // Allocate a HeapNumber with a specific value. | 374 // Allocate a HeapNumber with a specific value. |
358 Node* AllocateHeapNumberWithValue(Node* value, MutableMode mode = IMMUTABLE); | 375 Node* AllocateHeapNumberWithValue(Node* value, MutableMode mode = IMMUTABLE); |
359 // Allocate a SeqOneByteString with the given length. | 376 // Allocate a SeqOneByteString with the given length. |
360 Node* AllocateSeqOneByteString(int length, AllocationFlags flags = kNone); | 377 Node* AllocateSeqOneByteString(int length, AllocationFlags flags = kNone); |
361 Node* AllocateSeqOneByteString(Node* context, Node* length, | 378 Node* AllocateSeqOneByteString(Node* context, Node* length, |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 Node* TryTaggedToFloat64(Node* value, Label* if_valueisnotnumber); | 528 Node* TryTaggedToFloat64(Node* value, Label* if_valueisnotnumber); |
512 Node* TruncateTaggedToFloat64(Node* context, Node* value); | 529 Node* TruncateTaggedToFloat64(Node* context, Node* value); |
513 Node* TruncateTaggedToWord32(Node* context, Node* value); | 530 Node* TruncateTaggedToWord32(Node* context, Node* value); |
514 // Truncate the floating point value of a HeapNumber to an Int32. | 531 // Truncate the floating point value of a HeapNumber to an Int32. |
515 Node* TruncateHeapNumberValueToWord32(Node* object); | 532 Node* TruncateHeapNumberValueToWord32(Node* object); |
516 | 533 |
517 // Conversions. | 534 // Conversions. |
518 Node* ChangeFloat64ToTagged(Node* value); | 535 Node* ChangeFloat64ToTagged(Node* value); |
519 Node* ChangeInt32ToTagged(Node* value); | 536 Node* ChangeInt32ToTagged(Node* value); |
520 Node* ChangeUint32ToTagged(Node* value); | 537 Node* ChangeUint32ToTagged(Node* value); |
| 538 Node* ChangeNumberToFloat64(Node* value); |
521 | 539 |
522 // Type conversions. | 540 // Type conversions. |
523 // Throws a TypeError for {method_name} if {value} is not coercible to Object, | 541 // Throws a TypeError for {method_name} if {value} is not coercible to Object, |
524 // or returns the {value} converted to a String otherwise. | 542 // or returns the {value} converted to a String otherwise. |
525 Node* ToThisString(Node* context, Node* value, char const* method_name); | 543 Node* ToThisString(Node* context, Node* value, char const* method_name); |
526 // Throws a TypeError for {method_name} if {value} is neither of the given | 544 // Throws a TypeError for {method_name} if {value} is neither of the given |
527 // {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or | 545 // {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or |
528 // returns the {value} (or wrapped value) otherwise. | 546 // returns the {value} (or wrapped value) otherwise. |
529 Node* ToThisValue(Node* context, Node* value, PrimitiveType primitive_type, | 547 Node* ToThisValue(Node* context, Node* value, PrimitiveType primitive_type, |
530 char const* method_name); | 548 char const* method_name); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 template <typename T> | 674 template <typename T> |
657 Node* IsSetWord(Node* word) { | 675 Node* IsSetWord(Node* word) { |
658 return WordNotEqual(WordAnd(word, IntPtrConstant(T::kMask)), | 676 return WordNotEqual(WordAnd(word, IntPtrConstant(T::kMask)), |
659 IntPtrConstant(0)); | 677 IntPtrConstant(0)); |
660 } | 678 } |
661 | 679 |
662 void SetCounter(StatsCounter* counter, int value); | 680 void SetCounter(StatsCounter* counter, int value); |
663 void IncrementCounter(StatsCounter* counter, int delta); | 681 void IncrementCounter(StatsCounter* counter, int delta); |
664 void DecrementCounter(StatsCounter* counter, int delta); | 682 void DecrementCounter(StatsCounter* counter, int delta); |
665 | 683 |
| 684 void Increment(Variable& variable, int value = 1, |
| 685 ParameterMode mode = INTPTR_PARAMETERS); |
| 686 |
666 // Generates "if (false) goto label" code. Useful for marking a label as | 687 // Generates "if (false) goto label" code. Useful for marking a label as |
667 // "live" to avoid assertion failures during graph building. In the resulting | 688 // "live" to avoid assertion failures during graph building. In the resulting |
668 // code this check will be eliminated. | 689 // code this check will be eliminated. |
669 void Use(Label* label); | 690 void Use(Label* label); |
670 | 691 |
671 // Various building blocks for stubs doing property lookups. | 692 // Various building blocks for stubs doing property lookups. |
672 void TryToName(Node* key, Label* if_keyisindex, Variable* var_index, | 693 void TryToName(Node* key, Label* if_keyisindex, Variable* var_index, |
673 Label* if_keyisunique, Label* if_bailout); | 694 Label* if_keyisunique, Label* if_bailout); |
674 | 695 |
675 // Calculates array index for given dictionary entry and entry field. | 696 // Calculates array index for given dictionary entry and entry field. |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 class CodeStubArguments { | 1032 class CodeStubArguments { |
1012 public: | 1033 public: |
1013 typedef compiler::Node Node; | 1034 typedef compiler::Node Node; |
1014 | 1035 |
1015 // |argc| specifies the number of arguments passed to the builtin excluding | 1036 // |argc| specifies the number of arguments passed to the builtin excluding |
1016 // the receiver. | 1037 // the receiver. |
1017 CodeStubArguments(CodeStubAssembler* assembler, Node* argc, | 1038 CodeStubArguments(CodeStubAssembler* assembler, Node* argc, |
1018 CodeStubAssembler::ParameterMode mode = | 1039 CodeStubAssembler::ParameterMode mode = |
1019 CodeStubAssembler::INTPTR_PARAMETERS); | 1040 CodeStubAssembler::INTPTR_PARAMETERS); |
1020 | 1041 |
1021 Node* GetReceiver(); | 1042 Node* GetReceiver() const; |
1022 | 1043 |
1023 // |index| is zero-based and does not include the receiver | 1044 // |index| is zero-based and does not include the receiver |
1024 Node* AtIndex(Node* index, CodeStubAssembler::ParameterMode mode = | 1045 Node* AtIndex(Node* index, CodeStubAssembler::ParameterMode mode = |
1025 CodeStubAssembler::INTPTR_PARAMETERS); | 1046 CodeStubAssembler::INTPTR_PARAMETERS) const; |
1026 | 1047 |
1027 Node* AtIndex(int index); | 1048 Node* AtIndex(int index) const; |
| 1049 |
| 1050 Node* GetLength() const { return argc_; } |
1028 | 1051 |
1029 typedef std::function<void(CodeStubAssembler* assembler, Node* arg)> | 1052 typedef std::function<void(CodeStubAssembler* assembler, Node* arg)> |
1030 ForEachBodyFunction; | 1053 ForEachBodyFunction; |
1031 | 1054 |
1032 // Iteration doesn't include the receiver. |first| and |last| are zero-based. | 1055 // Iteration doesn't include the receiver. |first| and |last| are zero-based. |
1033 void ForEach(ForEachBodyFunction body, Node* first = nullptr, | 1056 void ForEach(ForEachBodyFunction body, Node* first = nullptr, |
1034 Node* last = nullptr, CodeStubAssembler::ParameterMode mode = | 1057 Node* last = nullptr, CodeStubAssembler::ParameterMode mode = |
1035 CodeStubAssembler::INTPTR_PARAMETERS) { | 1058 CodeStubAssembler::INTPTR_PARAMETERS) { |
1036 CodeStubAssembler::VariableList list(0, assembler_->zone()); | 1059 CodeStubAssembler::VariableList list(0, assembler_->zone()); |
1037 ForEach(list, body, first, last); | 1060 ForEach(list, body, first, last); |
(...skipping 30 matching lines...) Expand all Loading... |
1068 } | 1091 } |
1069 #else | 1092 #else |
1070 #define CSA_SLOW_ASSERT(csa, x) ((void)0) | 1093 #define CSA_SLOW_ASSERT(csa, x) ((void)0) |
1071 #endif | 1094 #endif |
1072 | 1095 |
1073 DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags); | 1096 DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags); |
1074 | 1097 |
1075 } // namespace internal | 1098 } // namespace internal |
1076 } // namespace v8 | 1099 } // namespace v8 |
1077 #endif // V8_CODE_STUB_ASSEMBLER_H_ | 1100 #endif // V8_CODE_STUB_ASSEMBLER_H_ |
OLD | NEW |