Chromium Code Reviews| 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 |