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 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1343 StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldOffset, | 1343 StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldOffset, |
1344 Int32Constant(String::kEmptyHashField), | 1344 Int32Constant(String::kEmptyHashField), |
1345 MachineRepresentation::kWord32); | 1345 MachineRepresentation::kWord32); |
1346 StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent, | 1346 StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent, |
1347 MachineRepresentation::kTagged); | 1347 MachineRepresentation::kTagged); |
1348 StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset, | 1348 StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset, |
1349 MachineRepresentation::kTagged); | 1349 MachineRepresentation::kTagged); |
1350 return result; | 1350 return result; |
1351 } | 1351 } |
1352 | 1352 |
| 1353 Node* CodeStubAssembler::AllocateOneByteConsString(Node* length, Node* first, |
| 1354 Node* second) { |
| 1355 Node* result = Allocate(ConsString::kSize); |
| 1356 Node* map = LoadRoot(Heap::kConsOneByteStringMapRootIndex); |
| 1357 StoreMapNoWriteBarrier(result, map); |
| 1358 StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length, |
| 1359 MachineRepresentation::kTagged); |
| 1360 StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset, |
| 1361 Int32Constant(String::kEmptyHashField), |
| 1362 MachineRepresentation::kWord32); |
| 1363 StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first, |
| 1364 MachineRepresentation::kTagged); |
| 1365 StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second, |
| 1366 MachineRepresentation::kTagged); |
| 1367 return result; |
| 1368 } |
| 1369 |
| 1370 Node* CodeStubAssembler::AllocateTwoByteConsString(Node* length, Node* first, |
| 1371 Node* second) { |
| 1372 Node* result = Allocate(ConsString::kSize); |
| 1373 Node* map = LoadRoot(Heap::kConsStringMapRootIndex); |
| 1374 StoreMapNoWriteBarrier(result, map); |
| 1375 StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length, |
| 1376 MachineRepresentation::kTagged); |
| 1377 StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset, |
| 1378 Int32Constant(String::kEmptyHashField), |
| 1379 MachineRepresentation::kWord32); |
| 1380 StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first, |
| 1381 MachineRepresentation::kTagged); |
| 1382 StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second, |
| 1383 MachineRepresentation::kTagged); |
| 1384 return result; |
| 1385 } |
| 1386 |
1353 Node* CodeStubAssembler::AllocateRegExpResult(Node* context, Node* length, | 1387 Node* CodeStubAssembler::AllocateRegExpResult(Node* context, Node* length, |
1354 Node* index, Node* input) { | 1388 Node* index, Node* input) { |
1355 Node* const max_length = | 1389 Node* const max_length = |
1356 SmiConstant(Smi::FromInt(JSArray::kInitialMaxFastElementArray)); | 1390 SmiConstant(Smi::FromInt(JSArray::kInitialMaxFastElementArray)); |
1357 Assert(SmiLessThanOrEqual(length, max_length)); | 1391 Assert(SmiLessThanOrEqual(length, max_length)); |
1358 | 1392 |
1359 // Allocate the JSRegExpResult. | 1393 // Allocate the JSRegExpResult. |
1360 // TODO(jgruber): Fold JSArray and FixedArray allocations, then remove | 1394 // TODO(jgruber): Fold JSArray and FixedArray allocations, then remove |
1361 // unneeded store of elements. | 1395 // unneeded store of elements. |
1362 Node* const result = Allocate(JSRegExpResult::kSize); | 1396 Node* const result = Allocate(JSRegExpResult::kSize); |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1680 } | 1714 } |
1681 | 1715 |
1682 Bind(&done); | 1716 Bind(&done); |
1683 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); | 1717 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); |
1684 Comment("] CopyFixedArrayElements"); | 1718 Comment("] CopyFixedArrayElements"); |
1685 } | 1719 } |
1686 | 1720 |
1687 void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string, | 1721 void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string, |
1688 compiler::Node* to_string, | 1722 compiler::Node* to_string, |
1689 compiler::Node* from_index, | 1723 compiler::Node* from_index, |
| 1724 compiler::Node* to_index, |
1690 compiler::Node* character_count, | 1725 compiler::Node* character_count, |
1691 String::Encoding encoding) { | 1726 String::Encoding encoding) { |
1692 Label out(this); | 1727 Label out(this); |
1693 | 1728 |
1694 // Nothing to do for zero characters. | 1729 // Nothing to do for zero characters. |
1695 | 1730 |
1696 GotoIf(SmiLessThanOrEqual(character_count, SmiConstant(Smi::kZero)), &out); | 1731 GotoIf(SmiLessThanOrEqual(character_count, SmiConstant(Smi::kZero)), &out); |
1697 | 1732 |
1698 // Calculate offsets into the strings. | 1733 // Calculate offsets into the strings. |
1699 | 1734 |
1700 Node* from_offset; | 1735 Node* from_offset; |
1701 Node* limit_offset; | 1736 Node* limit_offset; |
1702 Node* to_offset; | 1737 Node* to_offset; |
1703 | 1738 |
1704 { | 1739 { |
1705 Node* byte_count = SmiUntag(character_count); | 1740 Node* byte_count = SmiUntag(character_count); |
1706 Node* from_byte_index = SmiUntag(from_index); | 1741 Node* from_byte_index = SmiUntag(from_index); |
| 1742 Node* to_byte_index = SmiUntag(to_index); |
1707 if (encoding == String::ONE_BYTE_ENCODING) { | 1743 if (encoding == String::ONE_BYTE_ENCODING) { |
1708 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag; | 1744 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag; |
1709 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index); | 1745 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index); |
1710 limit_offset = IntPtrAdd(from_offset, byte_count); | 1746 limit_offset = IntPtrAdd(from_offset, byte_count); |
1711 to_offset = IntPtrConstant(offset); | 1747 to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index); |
1712 } else { | 1748 } else { |
1713 STATIC_ASSERT(2 == sizeof(uc16)); | 1749 STATIC_ASSERT(2 == sizeof(uc16)); |
1714 byte_count = WordShl(byte_count, 1); | 1750 byte_count = WordShl(byte_count, 1); |
1715 from_byte_index = WordShl(from_byte_index, 1); | 1751 from_byte_index = WordShl(from_byte_index, 1); |
| 1752 to_byte_index = WordShl(to_byte_index, 1); |
1716 | 1753 |
1717 const int offset = SeqTwoByteString::kHeaderSize - kHeapObjectTag; | 1754 const int offset = SeqTwoByteString::kHeaderSize - kHeapObjectTag; |
1718 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index); | 1755 from_offset = IntPtrAdd(IntPtrConstant(offset), from_byte_index); |
1719 limit_offset = IntPtrAdd(from_offset, byte_count); | 1756 limit_offset = IntPtrAdd(from_offset, byte_count); |
1720 to_offset = IntPtrConstant(offset); | 1757 to_offset = IntPtrAdd(IntPtrConstant(offset), to_byte_index); |
1721 } | 1758 } |
1722 } | 1759 } |
1723 | 1760 |
1724 Variable var_from_offset(this, MachineType::PointerRepresentation()); | 1761 Variable var_from_offset(this, MachineType::PointerRepresentation()); |
1725 Variable var_to_offset(this, MachineType::PointerRepresentation()); | 1762 Variable var_to_offset(this, MachineType::PointerRepresentation()); |
1726 | 1763 |
1727 var_from_offset.Bind(from_offset); | 1764 var_from_offset.Bind(from_offset); |
1728 var_to_offset.Bind(to_offset); | 1765 var_to_offset.Bind(to_offset); |
1729 | 1766 |
1730 Variable* vars[] = {&var_from_offset, &var_to_offset}; | 1767 Variable* vars[] = {&var_from_offset, &var_to_offset}; |
(...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2508 // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length. | 2545 // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length. |
2509 Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, | 2546 Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, |
2510 Node* from, Node* from_instance_type, | 2547 Node* from, Node* from_instance_type, |
2511 Node* from_index, Node* character_count) { | 2548 Node* from_index, Node* character_count) { |
2512 typedef CodeStubAssembler::Label Label; | 2549 typedef CodeStubAssembler::Label Label; |
2513 typedef CodeStubAssembler::Variable Variable; | 2550 typedef CodeStubAssembler::Variable Variable; |
2514 | 2551 |
2515 Label end(a), two_byte_sequential(a); | 2552 Label end(a), two_byte_sequential(a); |
2516 Variable var_result(a, MachineRepresentation::kTagged); | 2553 Variable var_result(a, MachineRepresentation::kTagged); |
2517 | 2554 |
| 2555 Node* const smi_zero = a->SmiConstant(Smi::kZero); |
| 2556 |
2518 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 2557 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
2519 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, | 2558 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, |
2520 a->Int32Constant(kStringEncodingMask)), | 2559 a->Int32Constant(kStringEncodingMask)), |
2521 a->Int32Constant(0)), | 2560 a->Int32Constant(0)), |
2522 &two_byte_sequential); | 2561 &two_byte_sequential); |
2523 | 2562 |
2524 // The subject string is a sequential one-byte string. | 2563 // The subject string is a sequential one-byte string. |
2525 { | 2564 { |
2526 Node* result = | 2565 Node* result = |
2527 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); | 2566 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); |
2528 a->CopyStringCharacters(from, result, from_index, character_count, | 2567 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, |
2529 String::ONE_BYTE_ENCODING); | 2568 String::ONE_BYTE_ENCODING); |
2530 var_result.Bind(result); | 2569 var_result.Bind(result); |
2531 | 2570 |
2532 a->Goto(&end); | 2571 a->Goto(&end); |
2533 } | 2572 } |
2534 | 2573 |
2535 // The subject string is a sequential two-byte string. | 2574 // The subject string is a sequential two-byte string. |
2536 a->Bind(&two_byte_sequential); | 2575 a->Bind(&two_byte_sequential); |
2537 { | 2576 { |
2538 Node* result = | 2577 Node* result = |
2539 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); | 2578 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); |
2540 a->CopyStringCharacters(from, result, from_index, character_count, | 2579 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, |
2541 String::TWO_BYTE_ENCODING); | 2580 String::TWO_BYTE_ENCODING); |
2542 var_result.Bind(result); | 2581 var_result.Bind(result); |
2543 | 2582 |
2544 a->Goto(&end); | 2583 a->Goto(&end); |
2545 } | 2584 } |
2546 | 2585 |
2547 a->Bind(&end); | 2586 a->Bind(&end); |
2548 return var_result.value(); | 2587 return var_result.value(); |
2549 } | 2588 } |
2550 | 2589 |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2765 { | 2804 { |
2766 var_result.Bind( | 2805 var_result.Bind( |
2767 CallRuntime(Runtime::kSubString, context, string, from, to)); | 2806 CallRuntime(Runtime::kSubString, context, string, from, to)); |
2768 Goto(&end); | 2807 Goto(&end); |
2769 } | 2808 } |
2770 | 2809 |
2771 Bind(&end); | 2810 Bind(&end); |
2772 return var_result.value(); | 2811 return var_result.value(); |
2773 } | 2812 } |
2774 | 2813 |
| 2814 Node* CodeStubAssembler::StringConcat(Node* context, Node* first, |
| 2815 Node* second) { |
| 2816 Variable var_result(this, MachineRepresentation::kTagged); |
| 2817 |
| 2818 Label out(this), runtime(this, Label::kDeferred); |
| 2819 |
| 2820 // TODO(jgruber): Handle indirect, external, and two-byte strings. |
| 2821 |
| 2822 Node* const one_byte_seq_mask = Int32Constant( |
| 2823 kIsIndirectStringMask | kExternalStringTag | kStringEncodingMask); |
| 2824 Node* const expected_masked = Int32Constant(kOneByteStringTag); |
| 2825 |
| 2826 Node* const first_instance_type = LoadInstanceType(first); |
| 2827 GotoUnless(Word32Equal(Word32And(first_instance_type, one_byte_seq_mask), |
| 2828 expected_masked), |
| 2829 &runtime); |
| 2830 |
| 2831 Node* const second_instance_type = LoadInstanceType(second); |
| 2832 GotoUnless(Word32Equal(Word32And(second_instance_type, one_byte_seq_mask), |
| 2833 expected_masked), |
| 2834 &runtime); |
| 2835 |
| 2836 Node* const smi_zero = SmiConstant(Smi::kZero); |
| 2837 Node* const first_length = LoadStringLength(first); |
| 2838 Node* const second_length = LoadStringLength(second); |
| 2839 Node* const length = SmiAdd(first_length, second_length); |
| 2840 |
| 2841 Label if_makeseqstring(this), if_makeconsstring(this); |
| 2842 Node* const min_cons_length = |
| 2843 SmiConstant(Smi::FromInt(ConsString::kMinLength)); |
| 2844 Branch(SmiLessThan(length, min_cons_length), &if_makeseqstring, |
| 2845 &if_makeconsstring); |
| 2846 |
| 2847 Bind(&if_makeseqstring); |
| 2848 { |
| 2849 Node* result = AllocateSeqOneByteString(context, SmiToWord(length)); |
| 2850 |
| 2851 CopyStringCharacters(first, result, smi_zero, smi_zero, first_length, |
| 2852 String::ONE_BYTE_ENCODING); |
| 2853 CopyStringCharacters(second, result, smi_zero, first_length, second_length, |
| 2854 String::ONE_BYTE_ENCODING); |
| 2855 |
| 2856 var_result.Bind(result); |
| 2857 Goto(&out); |
| 2858 } |
| 2859 |
| 2860 Bind(&if_makeconsstring); |
| 2861 { |
| 2862 Node* result = AllocateOneByteConsString(length, first, second); |
| 2863 var_result.Bind(result); |
| 2864 Goto(&out); |
| 2865 } |
| 2866 |
| 2867 Bind(&runtime); |
| 2868 { |
| 2869 Node* const result = |
| 2870 CallRuntime(Runtime::kStringAdd, context, first, second); |
| 2871 var_result.Bind(result); |
| 2872 Goto(&out); |
| 2873 } |
| 2874 |
| 2875 Bind(&out); |
| 2876 return var_result.value(); |
| 2877 } |
| 2878 |
| 2879 Node* CodeStubAssembler::StringIndexOfChar(Node* context, Node* string, |
| 2880 Node* needle_char, Node* from) { |
| 2881 Variable var_result(this, MachineRepresentation::kTagged); |
| 2882 |
| 2883 Label out(this), runtime(this, Label::kDeferred); |
| 2884 |
| 2885 // Let runtime handle non-one-byte {needle_char}. |
| 2886 |
| 2887 Node* const one_byte_char_mask = IntPtrConstant(0xFF); |
| 2888 GotoUnless(WordEqual(WordAnd(needle_char, one_byte_char_mask), needle_char), |
| 2889 &runtime); |
| 2890 |
| 2891 // TODO(jgruber): Handle external and two-byte strings. |
| 2892 |
| 2893 Node* const one_byte_seq_mask = Int32Constant( |
| 2894 kIsIndirectStringMask | kExternalStringTag | kStringEncodingMask); |
| 2895 Node* const expected_masked = Int32Constant(kOneByteStringTag); |
| 2896 |
| 2897 Node* const string_instance_type = LoadInstanceType(string); |
| 2898 GotoUnless(Word32Equal(Word32And(string_instance_type, one_byte_seq_mask), |
| 2899 expected_masked), |
| 2900 &runtime); |
| 2901 |
| 2902 // If we reach this, {string} is a non-indirect, non-external one-byte string. |
| 2903 |
| 2904 Node* const length = LoadStringLength(string); |
| 2905 Node* const search_range_length = SmiUntag(SmiSub(length, from)); |
| 2906 |
| 2907 const int offset = SeqOneByteString::kHeaderSize - kHeapObjectTag; |
| 2908 Node* const begin = IntPtrConstant(offset); |
| 2909 Node* const cursor = IntPtrAdd(begin, SmiUntag(from)); |
| 2910 Node* const end = IntPtrAdd(cursor, search_range_length); |
| 2911 |
| 2912 Variable var_cursor(this, MachineType::PointerRepresentation()); |
| 2913 Variable* vars[] = {&var_cursor}; |
| 2914 Label loop(this, 1, vars), loop_tail(this); |
| 2915 |
| 2916 var_cursor.Bind(cursor); |
| 2917 var_result.Bind(SmiConstant(Smi::FromInt(-1))); |
| 2918 |
| 2919 Goto(&loop); |
| 2920 Bind(&loop); |
| 2921 { |
| 2922 Node* const cursor = var_cursor.value(); |
| 2923 |
| 2924 Node* value = Load(MachineType::Uint8(), string, cursor); |
| 2925 GotoUnless(WordEqual(value, needle_char), &loop_tail); |
| 2926 |
| 2927 // Found a match. |
| 2928 Node* index = SmiTag(IntPtrSub(cursor, begin)); |
| 2929 var_result.Bind(index); |
| 2930 Goto(&out); |
| 2931 |
| 2932 Bind(&loop_tail); |
| 2933 { |
| 2934 Node* const new_cursor = IntPtrAdd(cursor, IntPtrConstant(1)); |
| 2935 var_cursor.Bind(new_cursor); |
| 2936 Branch(IntPtrLessThan(new_cursor, end), &loop, &out); |
| 2937 } |
| 2938 } |
| 2939 |
| 2940 Bind(&runtime); |
| 2941 { |
| 2942 Node* const pattern = StringFromCharCode(needle_char); |
| 2943 Node* const result = |
| 2944 CallRuntime(Runtime::kStringIndexOf, context, string, pattern, from); |
| 2945 var_result.Bind(result); |
| 2946 var_cursor.Bind(IntPtrConstant(0)); |
| 2947 Goto(&out); |
| 2948 } |
| 2949 |
| 2950 Bind(&out); |
| 2951 return var_result.value(); |
| 2952 } |
| 2953 |
2775 Node* CodeStubAssembler::StringFromCodePoint(compiler::Node* codepoint, | 2954 Node* CodeStubAssembler::StringFromCodePoint(compiler::Node* codepoint, |
2776 UnicodeEncoding encoding) { | 2955 UnicodeEncoding encoding) { |
2777 Variable var_result(this, MachineRepresentation::kTagged); | 2956 Variable var_result(this, MachineRepresentation::kTagged); |
2778 var_result.Bind(EmptyStringConstant()); | 2957 var_result.Bind(EmptyStringConstant()); |
2779 | 2958 |
2780 Label if_isword16(this), if_isword32(this), return_result(this); | 2959 Label if_isword16(this), if_isword32(this), return_result(this); |
2781 | 2960 |
2782 Branch(Uint32LessThan(codepoint, Int32Constant(0x10000)), &if_isword16, | 2961 Branch(Uint32LessThan(codepoint, Int32Constant(0x10000)), &if_isword16, |
2783 &if_isword32); | 2962 &if_isword32); |
2784 | 2963 |
(...skipping 4452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7237 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable)); | 7416 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable)); |
7238 Goto(&end); | 7417 Goto(&end); |
7239 } | 7418 } |
7240 | 7419 |
7241 Bind(&end); | 7420 Bind(&end); |
7242 return result.value(); | 7421 return result.value(); |
7243 } | 7422 } |
7244 | 7423 |
7245 } // namespace internal | 7424 } // namespace internal |
7246 } // namespace v8 | 7425 } // namespace v8 |
OLD | NEW |