Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(674)

Side by Side Diff: src/code-stub-assembler.cc

Issue 2398423002: [regexp] Port RegExp.prototype[@@replace] (Closed)
Patch Set: Tweaks in string code-stub-assembler methods Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698