OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 // Or number_of_captures <= offsets vector size / 2 - 1 | 660 // Or number_of_captures <= offsets vector size / 2 - 1 |
661 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); | 661 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
662 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); | 662 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); |
663 __ j(above, &runtime); | 663 __ j(above, &runtime); |
664 | 664 |
665 // Reset offset for possibly sliced string. | 665 // Reset offset for possibly sliced string. |
666 __ Set(r14, 0); | 666 __ Set(r14, 0); |
667 __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); | 667 __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); |
668 __ JumpIfSmi(rdi, &runtime); | 668 __ JumpIfSmi(rdi, &runtime); |
669 __ movp(r15, rdi); // Make a copy of the original subject string. | 669 __ movp(r15, rdi); // Make a copy of the original subject string. |
670 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | |
671 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | |
672 // rax: RegExp data (FixedArray) | 670 // rax: RegExp data (FixedArray) |
673 // rdi: subject string | 671 // rdi: subject string |
674 // r15: subject string | 672 // r15: subject string |
675 // Handle subject string according to its encoding and representation: | 673 // Handle subject string according to its encoding and representation: |
676 // (1) Sequential two byte? If yes, go to (9). | 674 // (1) Sequential two byte? If yes, go to (9). |
677 // (2) Sequential one byte? If yes, go to (6). | 675 // (2) Sequential one byte? If yes, go to (5). |
678 // (3) Anything but sequential or cons? If yes, go to (7). | 676 // (3) Sequential or cons? If not, go to (6). |
679 // (4) Cons string. If the string is flat, replace subject with first string. | 677 // (4) Cons string. If the string is flat, replace subject with first string |
680 // Otherwise bailout. | 678 // and go to (1). Otherwise bail out to runtime. |
681 // (5a) Is subject sequential two byte? If yes, go to (9). | 679 // (5) One byte sequential. Load regexp code for one byte. |
682 // (5b) Is subject external? If yes, go to (8). | |
683 // (6) One byte sequential. Load regexp code for one byte. | |
684 // (E) Carry on. | 680 // (E) Carry on. |
685 /// [...] | 681 /// [...] |
686 | 682 |
687 // Deferred code at the end of the stub: | 683 // Deferred code at the end of the stub: |
688 // (7) Not a long external string? If yes, go to (10). | 684 // (6) Long external string? If not, go to (10). |
689 // (8) External string. Make it, offset-wise, look like a sequential string. | 685 // (7) External string. Make it, offset-wise, look like a sequential string. |
690 // (8a) Is the external string one byte? If yes, go to (6). | 686 // (8) Is the external string one byte? If yes, go to (5). |
691 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). | 687 // (9) Two byte sequential. Load regexp code for two byte. Go to (E). |
692 // (10) Short external string or not a string? If yes, bail out to runtime. | 688 // (10) Short external string or not a string? If yes, bail out to runtime. |
693 // (11) Sliced string. Replace subject with parent. Go to (5a). | 689 // (11) Sliced string. Replace subject with parent. Go to (1). |
694 | 690 |
695 Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, | 691 Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */, |
696 external_string /* 8 */, check_underlying /* 5a */, | 692 external_string /* 7 */, check_underlying /* 1 */, |
697 not_seq_nor_cons /* 7 */, check_code /* E */, | 693 not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */; |
698 not_long_external /* 10 */; | 694 |
| 695 __ bind(&check_underlying); |
| 696 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 697 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
699 | 698 |
700 // (1) Sequential two byte? If yes, go to (9). | 699 // (1) Sequential two byte? If yes, go to (9). |
701 __ andb(rbx, Immediate(kIsNotStringMask | | 700 __ andb(rbx, Immediate(kIsNotStringMask | |
702 kStringRepresentationMask | | 701 kStringRepresentationMask | |
703 kStringEncodingMask | | 702 kStringEncodingMask | |
704 kShortExternalStringMask)); | 703 kShortExternalStringMask)); |
705 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 704 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
706 __ j(zero, &seq_two_byte_string); // Go to (9). | 705 __ j(zero, &seq_two_byte_string); // Go to (9). |
707 | 706 |
708 // (2) Sequential one byte? If yes, go to (6). | 707 // (2) Sequential one byte? If yes, go to (5). |
709 // Any other sequential string must be one byte. | 708 // Any other sequential string must be one byte. |
710 __ andb(rbx, Immediate(kIsNotStringMask | | 709 __ andb(rbx, Immediate(kIsNotStringMask | |
711 kStringRepresentationMask | | 710 kStringRepresentationMask | |
712 kShortExternalStringMask)); | 711 kShortExternalStringMask)); |
713 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6). | 712 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5). |
714 | 713 |
715 // (3) Anything but sequential or cons? If yes, go to (7). | 714 // (3) Sequential or cons? If not, go to (6). |
716 // We check whether the subject string is a cons, since sequential strings | 715 // We check whether the subject string is a cons, since sequential strings |
717 // have already been covered. | 716 // have already been covered. |
718 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 717 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
719 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 718 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
720 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 719 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |
721 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 720 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |
722 __ cmpp(rbx, Immediate(kExternalStringTag)); | 721 __ cmpp(rbx, Immediate(kExternalStringTag)); |
723 __ j(greater_equal, ¬_seq_nor_cons); // Go to (7). | 722 __ j(greater_equal, ¬_seq_nor_cons); // Go to (6). |
724 | 723 |
725 // (4) Cons string. Check that it's flat. | 724 // (4) Cons string. Check that it's flat. |
726 // Replace subject with first string and reload instance type. | 725 // Replace subject with first string and reload instance type. |
727 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), | 726 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), |
728 Heap::kempty_stringRootIndex); | 727 Heap::kempty_stringRootIndex); |
729 __ j(not_equal, &runtime); | 728 __ j(not_equal, &runtime); |
730 __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); | 729 __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); |
731 __ bind(&check_underlying); | 730 __ jmp(&check_underlying); |
732 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | |
733 __ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | |
734 | 731 |
735 // (5a) Is subject sequential two byte? If yes, go to (9). | 732 // (5) One byte sequential. Load regexp code for one byte. |
736 __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); | |
737 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | |
738 __ j(zero, &seq_two_byte_string); // Go to (9). | |
739 // (5b) Is subject external? If yes, go to (8). | |
740 __ testb(rbx, Immediate(kStringRepresentationMask)); | |
741 // The underlying external string is never a short external string. | |
742 STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); | |
743 STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); | |
744 __ j(not_zero, &external_string); // Go to (8) | |
745 | |
746 // (6) One byte sequential. Load regexp code for one byte. | |
747 __ bind(&seq_one_byte_string); | 733 __ bind(&seq_one_byte_string); |
748 // rax: RegExp data (FixedArray) | 734 // rax: RegExp data (FixedArray) |
749 __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset)); | 735 __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset)); |
750 __ Set(rcx, 1); // Type is one byte. | 736 __ Set(rcx, 1); // Type is one byte. |
751 | 737 |
752 // (E) Carry on. String handling is done. | 738 // (E) Carry on. String handling is done. |
753 __ bind(&check_code); | 739 __ bind(&check_code); |
754 // r11: irregexp code | 740 // r11: irregexp code |
755 // Check that the irregexp code has been generated for the actual string | 741 // Check that the irregexp code has been generated for the actual string |
756 // encoding. If it has, the field contains a code object otherwise it contains | 742 // encoding. If it has, the field contains a code object otherwise it contains |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 __ j(equal, &runtime); | 969 __ j(equal, &runtime); |
984 | 970 |
985 // For exception, throw the exception again. | 971 // For exception, throw the exception again. |
986 __ TailCallRuntime(Runtime::kRegExpExecReThrow); | 972 __ TailCallRuntime(Runtime::kRegExpExecReThrow); |
987 | 973 |
988 // Do the runtime call to execute the regexp. | 974 // Do the runtime call to execute the regexp. |
989 __ bind(&runtime); | 975 __ bind(&runtime); |
990 __ TailCallRuntime(Runtime::kRegExpExec); | 976 __ TailCallRuntime(Runtime::kRegExpExec); |
991 | 977 |
992 // Deferred code for string handling. | 978 // Deferred code for string handling. |
993 // (7) Not a long external string? If yes, go to (10). | 979 // (6) Long external string? If not, go to (10). |
994 __ bind(¬_seq_nor_cons); | 980 __ bind(¬_seq_nor_cons); |
995 // Compare flags are still set from (3). | 981 // Compare flags are still set from (3). |
996 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). | 982 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). |
997 | 983 |
998 // (8) External string. Short external strings have been ruled out. | 984 // (7) External string. Short external strings have been ruled out. |
999 __ bind(&external_string); | 985 __ bind(&external_string); |
1000 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 986 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
1001 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 987 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
1002 if (FLAG_debug_code) { | 988 if (FLAG_debug_code) { |
1003 // Assert that we do not have a cons or slice (indirect strings) here. | 989 // Assert that we do not have a cons or slice (indirect strings) here. |
1004 // Sequential strings have already been ruled out. | 990 // Sequential strings have already been ruled out. |
1005 __ testb(rbx, Immediate(kIsIndirectStringMask)); | 991 __ testb(rbx, Immediate(kIsIndirectStringMask)); |
1006 __ Assert(zero, kExternalStringExpectedButNotFound); | 992 __ Assert(zero, kExternalStringExpectedButNotFound); |
1007 } | 993 } |
1008 __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); | 994 __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); |
1009 // Move the pointer so that offset-wise, it looks like a sequential string. | 995 // Move the pointer so that offset-wise, it looks like a sequential string. |
1010 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 996 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
1011 __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 997 __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
1012 STATIC_ASSERT(kTwoByteStringTag == 0); | 998 STATIC_ASSERT(kTwoByteStringTag == 0); |
1013 // (8a) Is the external string one byte? If yes, go to (6). | 999 // (8) Is the external string one byte? If yes, go to (5). |
1014 __ testb(rbx, Immediate(kStringEncodingMask)); | 1000 __ testb(rbx, Immediate(kStringEncodingMask)); |
1015 __ j(not_zero, &seq_one_byte_string); // Goto (6). | 1001 __ j(not_zero, &seq_one_byte_string); // Go to (5). |
1016 | 1002 |
1017 // rdi: subject string (flat two-byte) | 1003 // rdi: subject string (flat two-byte) |
1018 // rax: RegExp data (FixedArray) | 1004 // rax: RegExp data (FixedArray) |
1019 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). | 1005 // (9) Two byte sequential. Load regexp code for two byte. Go to (E). |
1020 __ bind(&seq_two_byte_string); | 1006 __ bind(&seq_two_byte_string); |
1021 __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); | 1007 __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); |
1022 __ Set(rcx, 0); // Type is two byte. | 1008 __ Set(rcx, 0); // Type is two byte. |
1023 __ jmp(&check_code); // Go to (E). | 1009 __ jmp(&check_code); // Go to (E). |
1024 | 1010 |
1025 // (10) Not a string or a short external string? If yes, bail out to runtime. | 1011 // (10) Not a string or a short external string? If yes, bail out to runtime. |
1026 __ bind(¬_long_external); | 1012 __ bind(¬_long_external); |
1027 // Catch non-string subject or short external string. | 1013 // Catch non-string subject or short external string. |
1028 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | 1014 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); |
1029 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); | 1015 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); |
1030 __ j(not_zero, &runtime); | 1016 __ j(not_zero, &runtime); |
1031 | 1017 |
1032 // (11) Sliced string. Replace subject with parent. Go to (5a). | 1018 // (11) Sliced string. Replace subject with parent. Go to (1). |
1033 // Load offset into r14 and replace subject string with parent. | 1019 // Load offset into r14 and replace subject string with parent. |
1034 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); | 1020 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); |
1035 __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); | 1021 __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); |
1036 __ jmp(&check_underlying); | 1022 __ jmp(&check_underlying); |
1037 #endif // V8_INTERPRETED_REGEXP | 1023 #endif // V8_INTERPRETED_REGEXP |
1038 } | 1024 } |
1039 | 1025 |
1040 | 1026 |
1041 static int NegativeComparisonResult(Condition cc) { | 1027 static int NegativeComparisonResult(Condition cc) { |
1042 DCHECK(cc != equal); | 1028 DCHECK(cc != equal); |
(...skipping 4600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5643 NULL); | 5629 NULL); |
5644 } | 5630 } |
5645 | 5631 |
5646 | 5632 |
5647 #undef __ | 5633 #undef __ |
5648 | 5634 |
5649 } // namespace internal | 5635 } // namespace internal |
5650 } // namespace v8 | 5636 } // namespace v8 |
5651 | 5637 |
5652 #endif // V8_TARGET_ARCH_X64 | 5638 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |