| 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 |