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 #include "src/code-stub-assembler.h" | 5 #include "src/code-stub-assembler.h" |
6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
8 #include "src/frames.h" | 8 #include "src/frames.h" |
9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
(...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldOffset, | 1330 StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldOffset, |
1331 Int32Constant(String::kEmptyHashField), | 1331 Int32Constant(String::kEmptyHashField), |
1332 MachineRepresentation::kWord32); | 1332 MachineRepresentation::kWord32); |
1333 StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent, | 1333 StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent, |
1334 MachineRepresentation::kTagged); | 1334 MachineRepresentation::kTagged); |
1335 StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset, | 1335 StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset, |
1336 MachineRepresentation::kTagged); | 1336 MachineRepresentation::kTagged); |
1337 return result; | 1337 return result; |
1338 } | 1338 } |
1339 | 1339 |
| 1340 Node* CodeStubAssembler::AllocateOneByteConsString(Node* length, Node* first, |
| 1341 Node* second) { |
| 1342 Node* result = Allocate(ConsString::kSize); |
| 1343 Node* map = LoadRoot(Heap::kConsOneByteStringMapRootIndex); |
| 1344 StoreMapNoWriteBarrier(result, map); |
| 1345 StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length, |
| 1346 MachineRepresentation::kTagged); |
| 1347 StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset, |
| 1348 Int32Constant(String::kEmptyHashField), |
| 1349 MachineRepresentation::kWord32); |
| 1350 StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first, |
| 1351 MachineRepresentation::kTagged); |
| 1352 StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second, |
| 1353 MachineRepresentation::kTagged); |
| 1354 return result; |
| 1355 } |
| 1356 |
| 1357 Node* CodeStubAssembler::AllocateTwoByteConsString(Node* length, Node* first, |
| 1358 Node* second) { |
| 1359 Node* result = Allocate(ConsString::kSize); |
| 1360 Node* map = LoadRoot(Heap::kConsStringMapRootIndex); |
| 1361 StoreMapNoWriteBarrier(result, map); |
| 1362 StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length, |
| 1363 MachineRepresentation::kTagged); |
| 1364 StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset, |
| 1365 Int32Constant(String::kEmptyHashField), |
| 1366 MachineRepresentation::kWord32); |
| 1367 StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first, |
| 1368 MachineRepresentation::kTagged); |
| 1369 StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second, |
| 1370 MachineRepresentation::kTagged); |
| 1371 return result; |
| 1372 } |
| 1373 |
1340 Node* CodeStubAssembler::AllocateRegExpResult(Node* context, Node* length, | 1374 Node* CodeStubAssembler::AllocateRegExpResult(Node* context, Node* length, |
1341 Node* index, Node* input) { | 1375 Node* index, Node* input) { |
1342 Node* const max_length = | 1376 Node* const max_length = |
1343 SmiConstant(Smi::FromInt(JSArray::kInitialMaxFastElementArray)); | 1377 SmiConstant(Smi::FromInt(JSArray::kInitialMaxFastElementArray)); |
1344 Assert(SmiLessThanOrEqual(length, max_length)); | 1378 Assert(SmiLessThanOrEqual(length, max_length)); |
1345 | 1379 |
1346 // Allocate the JSRegExpResult. | 1380 // Allocate the JSRegExpResult. |
1347 // TODO(jgruber): Fold JSArray and FixedArray allocations, then remove | 1381 // TODO(jgruber): Fold JSArray and FixedArray allocations, then remove |
1348 // unneeded store of elements. | 1382 // unneeded store of elements. |
1349 Node* const result = Allocate(JSRegExpResult::kSize); | 1383 Node* const result = Allocate(JSRegExpResult::kSize); |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1664 } | 1698 } |
1665 | 1699 |
1666 Bind(&done); | 1700 Bind(&done); |
1667 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); | 1701 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); |
1668 Comment("] CopyFixedArrayElements"); | 1702 Comment("] CopyFixedArrayElements"); |
1669 } | 1703 } |
1670 | 1704 |
1671 void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string, | 1705 void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string, |
1672 compiler::Node* to_string, | 1706 compiler::Node* to_string, |
1673 compiler::Node* from_index, | 1707 compiler::Node* from_index, |
| 1708 compiler::Node* to_index, |
1674 compiler::Node* character_count, | 1709 compiler::Node* character_count, |
1675 String::Encoding encoding) { | 1710 String::Encoding encoding) { |
1676 Label out(this); | 1711 Label out(this); |
1677 | 1712 |
1678 // Nothing to do for zero characters. | 1713 // Nothing to do for zero characters. |
1679 | 1714 |
1680 GotoIf(SmiLessThanOrEqual(character_count, SmiConstant(Smi::FromInt(0))), | 1715 GotoIf(SmiLessThanOrEqual(character_count, SmiConstant(Smi::FromInt(0))), |
1681 &out); | 1716 &out); |
1682 | 1717 |
1683 // Calculate offsets into the strings. | 1718 // Calculate offsets into the strings. |
1684 | 1719 |
1685 Node* from_offset; | 1720 Node* from_offset; |
1686 Node* limit_offset; | 1721 Node* limit_offset; |
1687 Node* to_offset; | 1722 Node* to_offset; |
1688 | 1723 |
1689 { | 1724 { |
1690 Node* byte_count = SmiUntag(character_count); | 1725 Node* byte_count = SmiUntag(character_count); |
1691 Node* from_byte_index = SmiUntag(from_index); | 1726 Node* from_byte_index = SmiUntag(from_index); |
| 1727 Node* to_byte_index = SmiUntag(to_index); |
1692 if (encoding == String::ONE_BYTE_ENCODING) { | 1728 if (encoding == String::ONE_BYTE_ENCODING) { |
1693 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag; | 1729 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag; |
1694 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index); | 1730 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index); |
1695 limit_offset = IntPtrAdd(from_offset, byte_count); | 1731 limit_offset = IntPtrAdd(from_offset, byte_count); |
1696 to_offset = IntPtrConstant(offset); | 1732 to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index); |
1697 } else { | 1733 } else { |
1698 STATIC_ASSERT(2 == sizeof(uc16)); | 1734 STATIC_ASSERT(2 == sizeof(uc16)); |
1699 byte_count = WordShl(byte_count, 1); | 1735 byte_count = WordShl(byte_count, 1); |
1700 from_byte_index = WordShl(from_byte_index, 1); | 1736 from_byte_index = WordShl(from_byte_index, 1); |
| 1737 to_byte_index = WordShl(to_byte_index, 1); |
1701 | 1738 |
1702 const int offset = SeqTwoByteString::kHeaderSize - kHeapObjectTag; | 1739 const int offset = SeqTwoByteString::kHeaderSize - kHeapObjectTag; |
1703 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index); | 1740 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index); |
1704 limit_offset = IntPtrAdd(from_offset, byte_count); | 1741 limit_offset = IntPtrAdd(from_offset, byte_count); |
1705 to_offset = IntPtrConstant(offset); | 1742 to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index); |
1706 } | 1743 } |
1707 } | 1744 } |
1708 | 1745 |
1709 Variable var_from_offset(this, MachineType::PointerRepresentation()); | 1746 Variable var_from_offset(this, MachineType::PointerRepresentation()); |
1710 Variable var_to_offset(this, MachineType::PointerRepresentation()); | 1747 Variable var_to_offset(this, MachineType::PointerRepresentation()); |
1711 | 1748 |
1712 var_from_offset.Bind(from_offset); | 1749 var_from_offset.Bind(from_offset); |
1713 var_to_offset.Bind(to_offset); | 1750 var_to_offset.Bind(to_offset); |
1714 | 1751 |
1715 Variable* vars[] = {&var_from_offset, &var_to_offset}; | 1752 Variable* vars[] = {&var_from_offset, &var_to_offset}; |
(...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2493 // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length. | 2530 // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length. |
2494 Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, | 2531 Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, |
2495 Node* from, Node* from_instance_type, | 2532 Node* from, Node* from_instance_type, |
2496 Node* from_index, Node* character_count) { | 2533 Node* from_index, Node* character_count) { |
2497 typedef CodeStubAssembler::Label Label; | 2534 typedef CodeStubAssembler::Label Label; |
2498 typedef CodeStubAssembler::Variable Variable; | 2535 typedef CodeStubAssembler::Variable Variable; |
2499 | 2536 |
2500 Label end(a), two_byte_sequential(a); | 2537 Label end(a), two_byte_sequential(a); |
2501 Variable var_result(a, MachineRepresentation::kTagged); | 2538 Variable var_result(a, MachineRepresentation::kTagged); |
2502 | 2539 |
| 2540 Node* const smi_zero = a->SmiConstant(Smi::FromInt(0)); |
| 2541 |
2503 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 2542 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
2504 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, | 2543 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, |
2505 a->Int32Constant(kStringEncodingMask)), | 2544 a->Int32Constant(kStringEncodingMask)), |
2506 a->Int32Constant(0)), | 2545 a->Int32Constant(0)), |
2507 &two_byte_sequential); | 2546 &two_byte_sequential); |
2508 | 2547 |
2509 // The subject string is a sequential one-byte string. | 2548 // The subject string is a sequential one-byte string. |
2510 { | 2549 { |
2511 Node* result = | 2550 Node* result = |
2512 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); | 2551 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); |
2513 a->CopyStringCharacters(from, result, from_index, character_count, | 2552 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, |
2514 String::ONE_BYTE_ENCODING); | 2553 String::ONE_BYTE_ENCODING); |
2515 var_result.Bind(result); | 2554 var_result.Bind(result); |
2516 | 2555 |
2517 a->Goto(&end); | 2556 a->Goto(&end); |
2518 } | 2557 } |
2519 | 2558 |
2520 // The subject string is a sequential two-byte string. | 2559 // The subject string is a sequential two-byte string. |
2521 a->Bind(&two_byte_sequential); | 2560 a->Bind(&two_byte_sequential); |
2522 { | 2561 { |
2523 Node* result = | 2562 Node* result = |
2524 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); | 2563 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); |
2525 a->CopyStringCharacters(from, result, from_index, character_count, | 2564 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, |
2526 String::TWO_BYTE_ENCODING); | 2565 String::TWO_BYTE_ENCODING); |
2527 var_result.Bind(result); | 2566 var_result.Bind(result); |
2528 | 2567 |
2529 a->Goto(&end); | 2568 a->Goto(&end); |
2530 } | 2569 } |
2531 | 2570 |
2532 a->Bind(&end); | 2571 a->Bind(&end); |
2533 return var_result.value(); | 2572 return var_result.value(); |
2534 } | 2573 } |
2535 | 2574 |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2750 { | 2789 { |
2751 var_result.Bind( | 2790 var_result.Bind( |
2752 CallRuntime(Runtime::kSubString, context, string, from, to)); | 2791 CallRuntime(Runtime::kSubString, context, string, from, to)); |
2753 Goto(&end); | 2792 Goto(&end); |
2754 } | 2793 } |
2755 | 2794 |
2756 Bind(&end); | 2795 Bind(&end); |
2757 return var_result.value(); | 2796 return var_result.value(); |
2758 } | 2797 } |
2759 | 2798 |
| 2799 Node* CodeStubAssembler::StringConcat(Node* context, Node* first, |
| 2800 Node* second) { |
| 2801 Variable var_result(this, MachineRepresentation::kTagged); |
| 2802 |
| 2803 Label out(this), runtime(this, Label::kDeferred); |
| 2804 |
| 2805 // TODO(jgruber): Handle indirect, external, and two-byte strings. |
| 2806 |
| 2807 Node* const one_byte_seq_mask = Int32Constant( |
| 2808 kIsIndirectStringMask | kExternalStringTag | kStringEncodingMask); |
| 2809 Node* const expected_masked = Int32Constant(kOneByteStringTag); |
| 2810 |
| 2811 Node* const first_instance_type = LoadInstanceType(first); |
| 2812 GotoUnless(Word32Equal(Word32And(first_instance_type, one_byte_seq_mask), |
| 2813 expected_masked), |
| 2814 &runtime); |
| 2815 |
| 2816 Node* const second_instance_type = LoadInstanceType(second); |
| 2817 GotoUnless(Word32Equal(Word32And(second_instance_type, one_byte_seq_mask), |
| 2818 expected_masked), |
| 2819 &runtime); |
| 2820 |
| 2821 Node* const smi_zero = SmiConstant(Smi::FromInt(0)); |
| 2822 Node* const first_length = LoadStringLength(first); |
| 2823 Node* const second_length = LoadStringLength(second); |
| 2824 Node* const length = SmiAdd(first_length, second_length); |
| 2825 |
| 2826 Label if_makeseqstring(this), if_makeconsstring(this); |
| 2827 Node* const min_cons_length = |
| 2828 SmiConstant(Smi::FromInt(ConsString::kMinLength)); |
| 2829 Branch(SmiLessThan(length, min_cons_length), &if_makeseqstring, |
| 2830 &if_makeconsstring); |
| 2831 |
| 2832 Bind(&if_makeseqstring); |
| 2833 { |
| 2834 Node* result = AllocateSeqOneByteString(context, SmiToWord(length)); |
| 2835 |
| 2836 CopyStringCharacters(first, result, smi_zero, smi_zero, first_length, |
| 2837 String::ONE_BYTE_ENCODING); |
| 2838 CopyStringCharacters(second, result, smi_zero, first_length, second_length, |
| 2839 String::ONE_BYTE_ENCODING); |
| 2840 |
| 2841 var_result.Bind(result); |
| 2842 Goto(&out); |
| 2843 } |
| 2844 |
| 2845 Bind(&if_makeconsstring); |
| 2846 { |
| 2847 Node* result = AllocateOneByteConsString(length, first, second); |
| 2848 var_result.Bind(result); |
| 2849 Goto(&out); |
| 2850 } |
| 2851 |
| 2852 Bind(&runtime); |
| 2853 { |
| 2854 Node* const result = |
| 2855 CallRuntime(Runtime::kStringAdd, context, first, second); |
| 2856 var_result.Bind(result); |
| 2857 Goto(&out); |
| 2858 } |
| 2859 |
| 2860 Bind(&out); |
| 2861 return var_result.value(); |
| 2862 } |
| 2863 |
| 2864 Node* CodeStubAssembler::StringIndexOfChar(Node* context, Node* string, |
| 2865 Node* needle_char, Node* from) { |
| 2866 Variable var_result(this, MachineRepresentation::kTagged); |
| 2867 |
| 2868 Label out(this), runtime(this, Label::kDeferred); |
| 2869 |
| 2870 // Let runtime handle non-one-byte {needle_char}. |
| 2871 |
| 2872 Node* const one_byte_char_mask = IntPtrConstant(0xFF); |
| 2873 GotoUnless(WordEqual(WordAnd(needle_char, one_byte_char_mask), needle_char), |
| 2874 &runtime); |
| 2875 |
| 2876 // TODO(jgruber): Handle external and two-byte strings. |
| 2877 |
| 2878 Node* const one_byte_seq_mask = Int32Constant( |
| 2879 kIsIndirectStringMask | kExternalStringTag | kStringEncodingMask); |
| 2880 Node* const expected_masked = Int32Constant(kOneByteStringTag); |
| 2881 |
| 2882 Node* const string_instance_type = LoadInstanceType(string); |
| 2883 GotoUnless(Word32Equal(Word32And(string_instance_type, one_byte_seq_mask), |
| 2884 expected_masked), |
| 2885 &runtime); |
| 2886 |
| 2887 // If we reach this, {string} is a non-indirect, non-external one-byte string. |
| 2888 |
| 2889 Node* const length = LoadStringLength(string); |
| 2890 Node* const search_range_length = SmiUntag(SmiSub(length, from)); |
| 2891 |
| 2892 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag; |
| 2893 Node* const begin = IntPtrConstant(offset); |
| 2894 Node* const cursor = IntPtrAdd(begin, SmiUntag(from)); |
| 2895 Node* const end = IntPtrAdd(cursor, search_range_length); |
| 2896 |
| 2897 Variable var_cursor(this, MachineType::PointerRepresentation()); |
| 2898 Variable* vars[] = {&var_cursor}; |
| 2899 Label loop(this, 1, vars), loop_tail(this); |
| 2900 |
| 2901 var_cursor.Bind(cursor); |
| 2902 var_result.Bind(SmiConstant(Smi::FromInt(-1))); |
| 2903 |
| 2904 Goto(&loop); |
| 2905 Bind(&loop); |
| 2906 { |
| 2907 Node* const cursor = var_cursor.value(); |
| 2908 |
| 2909 Node* value = Load(MachineType::Uint8(), string, cursor); |
| 2910 GotoUnless(WordEqual(value, needle_char), &loop_tail); |
| 2911 |
| 2912 // Found a match. |
| 2913 Node* index = SmiTag(IntPtrSub(cursor, begin)); |
| 2914 var_result.Bind(index); |
| 2915 Goto(&out); |
| 2916 |
| 2917 Bind(&loop_tail); |
| 2918 { |
| 2919 Node* const new_cursor = IntPtrAdd(cursor, IntPtrConstant(1)); |
| 2920 var_cursor.Bind(new_cursor); |
| 2921 Branch(IntPtrLessThan(new_cursor, end), &loop, &out); |
| 2922 } |
| 2923 } |
| 2924 |
| 2925 Bind(&runtime); |
| 2926 { |
| 2927 Node* const pattern = StringFromCharCode(needle_char); |
| 2928 Node* const result = |
| 2929 CallRuntime(Runtime::kStringIndexOf, context, string, pattern, from); |
| 2930 var_result.Bind(result); |
| 2931 var_cursor.Bind(IntPtrConstant(0)); |
| 2932 Goto(&out); |
| 2933 } |
| 2934 |
| 2935 Bind(&out); |
| 2936 return var_result.value(); |
| 2937 } |
| 2938 |
2760 Node* CodeStubAssembler::StringFromCodePoint(compiler::Node* codepoint, | 2939 Node* CodeStubAssembler::StringFromCodePoint(compiler::Node* codepoint, |
2761 UnicodeEncoding encoding) { | 2940 UnicodeEncoding encoding) { |
2762 Variable var_result(this, MachineRepresentation::kTagged); | 2941 Variable var_result(this, MachineRepresentation::kTagged); |
2763 var_result.Bind(EmptyStringConstant()); | 2942 var_result.Bind(EmptyStringConstant()); |
2764 | 2943 |
2765 Label if_isword16(this), if_isword32(this), return_result(this); | 2944 Label if_isword16(this), if_isword32(this), return_result(this); |
2766 | 2945 |
2767 Branch(Uint32LessThan(codepoint, Int32Constant(0x10000)), &if_isword16, | 2946 Branch(Uint32LessThan(codepoint, Int32Constant(0x10000)), &if_isword16, |
2768 &if_isword32); | 2947 &if_isword32); |
2769 | 2948 |
(...skipping 3028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5798 [fixed_array, body](CodeStubAssembler* assembler, Node* offset) { | 5977 [fixed_array, body](CodeStubAssembler* assembler, Node* offset) { |
5799 body(assembler, fixed_array, offset); | 5978 body(assembler, fixed_array, offset); |
5800 }, | 5979 }, |
5801 direction == ForEachDirection::kReverse ? -increment : increment, | 5980 direction == ForEachDirection::kReverse ? -increment : increment, |
5802 direction == ForEachDirection::kReverse ? IndexAdvanceMode::kPre | 5981 direction == ForEachDirection::kReverse ? IndexAdvanceMode::kPre |
5803 : IndexAdvanceMode::kPost); | 5982 : IndexAdvanceMode::kPost); |
5804 } | 5983 } |
5805 | 5984 |
5806 } // namespace internal | 5985 } // namespace internal |
5807 } // namespace v8 | 5986 } // namespace v8 |
OLD | NEW |