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/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 // Or number_of_captures <= offsets vector size / 2 - 1 | 637 // Or number_of_captures <= offsets vector size / 2 - 1 |
638 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); | 638 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
639 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); | 639 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); |
640 __ j(above, &runtime); | 640 __ j(above, &runtime); |
641 | 641 |
642 // Reset offset for possibly sliced string. | 642 // Reset offset for possibly sliced string. |
643 __ Set(r14, 0); | 643 __ Set(r14, 0); |
644 __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); | 644 __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX)); |
645 __ JumpIfSmi(rdi, &runtime); | 645 __ JumpIfSmi(rdi, &runtime); |
646 __ movp(r15, rdi); // Make a copy of the original subject string. | 646 __ movp(r15, rdi); // Make a copy of the original subject string. |
647 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | |
648 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | |
649 // rax: RegExp data (FixedArray) | 647 // rax: RegExp data (FixedArray) |
650 // rdi: subject string | 648 // rdi: subject string |
651 // r15: subject string | 649 // r15: subject string |
652 // Handle subject string according to its encoding and representation: | 650 // Handle subject string according to its encoding and representation: |
653 // (1) Sequential two byte? If yes, go to (9). | 651 // (1) Sequential two byte? If yes, go to (9). |
654 // (2) Sequential one byte? If yes, go to (6). | 652 // (2) Sequential one byte? If yes, go to (5). |
655 // (3) Anything but sequential or cons? If yes, go to (7). | 653 // (3) Sequential or cons? If not, go to (6). |
656 // (4) Cons string. If the string is flat, replace subject with first string. | 654 // (4) Cons string. If the string is flat, replace subject with first string |
657 // Otherwise bailout. | 655 // and go to (1). Otherwise bail out to runtime. |
658 // (5a) Is subject sequential two byte? If yes, go to (9). | 656 // (5) One byte sequential. Load regexp code for one byte. |
659 // (5b) Is subject external? If yes, go to (8). | |
660 // (6) One byte sequential. Load regexp code for one byte. | |
661 // (E) Carry on. | 657 // (E) Carry on. |
662 /// [...] | 658 /// [...] |
663 | 659 |
664 // Deferred code at the end of the stub: | 660 // Deferred code at the end of the stub: |
665 // (7) Not a long external string? If yes, go to (10). | 661 // (6) Long external string? If not, go to (10). |
666 // (8) External string. Make it, offset-wise, look like a sequential string. | 662 // (7) External string. Make it, offset-wise, look like a sequential string. |
667 // (8a) Is the external string one byte? If yes, go to (6). | 663 // (8) Is the external string one byte? If yes, go to (5). |
668 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). | 664 // (9) Two byte sequential. Load regexp code for two byte. Go to (E). |
669 // (10) Short external string or not a string? If yes, bail out to runtime. | 665 // (10) Short external string or not a string? If yes, bail out to runtime. |
670 // (11) Sliced string. Replace subject with parent. Go to (5a). | 666 // (11) Sliced string. Replace subject with parent. Go to (1). |
671 | 667 |
672 Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, | 668 Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */, |
673 external_string /* 8 */, check_underlying /* 5a */, | 669 external_string /* 7 */, check_underlying /* 1 */, |
674 not_seq_nor_cons /* 7 */, check_code /* E */, | 670 not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */; |
675 not_long_external /* 10 */; | 671 |
| 672 __ bind(&check_underlying); |
| 673 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 674 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
676 | 675 |
677 // (1) Sequential two byte? If yes, go to (9). | 676 // (1) Sequential two byte? If yes, go to (9). |
678 __ andb(rbx, Immediate(kIsNotStringMask | | 677 __ andb(rbx, Immediate(kIsNotStringMask | |
679 kStringRepresentationMask | | 678 kStringRepresentationMask | |
680 kStringEncodingMask | | 679 kStringEncodingMask | |
681 kShortExternalStringMask)); | 680 kShortExternalStringMask)); |
682 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 681 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
683 __ j(zero, &seq_two_byte_string); // Go to (9). | 682 __ j(zero, &seq_two_byte_string); // Go to (9). |
684 | 683 |
685 // (2) Sequential one byte? If yes, go to (6). | 684 // (2) Sequential one byte? If yes, go to (5). |
686 // Any other sequential string must be one byte. | 685 // Any other sequential string must be one byte. |
687 __ andb(rbx, Immediate(kIsNotStringMask | | 686 __ andb(rbx, Immediate(kIsNotStringMask | |
688 kStringRepresentationMask | | 687 kStringRepresentationMask | |
689 kShortExternalStringMask)); | 688 kShortExternalStringMask)); |
690 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6). | 689 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5). |
691 | 690 |
692 // (3) Anything but sequential or cons? If yes, go to (7). | 691 // (3) Sequential or cons? If not, go to (6). |
693 // We check whether the subject string is a cons, since sequential strings | 692 // We check whether the subject string is a cons, since sequential strings |
694 // have already been covered. | 693 // have already been covered. |
695 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 694 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
696 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 695 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
697 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 696 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |
698 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 697 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |
699 __ cmpp(rbx, Immediate(kExternalStringTag)); | 698 __ cmpp(rbx, Immediate(kExternalStringTag)); |
700 __ j(greater_equal, ¬_seq_nor_cons); // Go to (7). | 699 __ j(greater_equal, ¬_seq_nor_cons); // Go to (6). |
701 | 700 |
702 // (4) Cons string. Check that it's flat. | 701 // (4) Cons string. Check that it's flat. |
703 // Replace subject with first string and reload instance type. | 702 // Replace subject with first string and reload instance type. |
704 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), | 703 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), |
705 Heap::kempty_stringRootIndex); | 704 Heap::kempty_stringRootIndex); |
706 __ j(not_equal, &runtime); | 705 __ j(not_equal, &runtime); |
707 __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); | 706 __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); |
708 __ bind(&check_underlying); | 707 __ jmp(&check_underlying); |
709 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | |
710 __ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | |
711 | 708 |
712 // (5a) Is subject sequential two byte? If yes, go to (9). | 709 // (5) One byte sequential. Load regexp code for one byte. |
713 __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); | |
714 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | |
715 __ j(zero, &seq_two_byte_string); // Go to (9). | |
716 // (5b) Is subject external? If yes, go to (8). | |
717 __ testb(rbx, Immediate(kStringRepresentationMask)); | |
718 // The underlying external string is never a short external string. | |
719 STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); | |
720 STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); | |
721 __ j(not_zero, &external_string); // Go to (8) | |
722 | |
723 // (6) One byte sequential. Load regexp code for one byte. | |
724 __ bind(&seq_one_byte_string); | 710 __ bind(&seq_one_byte_string); |
725 // rax: RegExp data (FixedArray) | 711 // rax: RegExp data (FixedArray) |
726 __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset)); | 712 __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset)); |
727 __ Set(rcx, 1); // Type is one byte. | 713 __ Set(rcx, 1); // Type is one byte. |
728 | 714 |
729 // (E) Carry on. String handling is done. | 715 // (E) Carry on. String handling is done. |
730 __ bind(&check_code); | 716 __ bind(&check_code); |
731 // r11: irregexp code | 717 // r11: irregexp code |
732 // Check that the irregexp code has been generated for the actual string | 718 // Check that the irregexp code has been generated for the actual string |
733 // encoding. If it has, the field contains a code object otherwise it contains | 719 // 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... |
960 __ j(equal, &runtime); | 946 __ j(equal, &runtime); |
961 | 947 |
962 // For exception, throw the exception again. | 948 // For exception, throw the exception again. |
963 __ TailCallRuntime(Runtime::kRegExpExecReThrow); | 949 __ TailCallRuntime(Runtime::kRegExpExecReThrow); |
964 | 950 |
965 // Do the runtime call to execute the regexp. | 951 // Do the runtime call to execute the regexp. |
966 __ bind(&runtime); | 952 __ bind(&runtime); |
967 __ TailCallRuntime(Runtime::kRegExpExec); | 953 __ TailCallRuntime(Runtime::kRegExpExec); |
968 | 954 |
969 // Deferred code for string handling. | 955 // Deferred code for string handling. |
970 // (7) Not a long external string? If yes, go to (10). | 956 // (6) Long external string? If not, go to (10). |
971 __ bind(¬_seq_nor_cons); | 957 __ bind(¬_seq_nor_cons); |
972 // Compare flags are still set from (3). | 958 // Compare flags are still set from (3). |
973 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). | 959 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). |
974 | 960 |
975 // (8) External string. Short external strings have been ruled out. | 961 // (7) External string. Short external strings have been ruled out. |
976 __ bind(&external_string); | 962 __ bind(&external_string); |
977 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 963 __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
978 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 964 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
979 if (FLAG_debug_code) { | 965 if (FLAG_debug_code) { |
980 // Assert that we do not have a cons or slice (indirect strings) here. | 966 // Assert that we do not have a cons or slice (indirect strings) here. |
981 // Sequential strings have already been ruled out. | 967 // Sequential strings have already been ruled out. |
982 __ testb(rbx, Immediate(kIsIndirectStringMask)); | 968 __ testb(rbx, Immediate(kIsIndirectStringMask)); |
983 __ Assert(zero, kExternalStringExpectedButNotFound); | 969 __ Assert(zero, kExternalStringExpectedButNotFound); |
984 } | 970 } |
985 __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); | 971 __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); |
986 // Move the pointer so that offset-wise, it looks like a sequential string. | 972 // Move the pointer so that offset-wise, it looks like a sequential string. |
987 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 973 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
988 __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 974 __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
989 STATIC_ASSERT(kTwoByteStringTag == 0); | 975 STATIC_ASSERT(kTwoByteStringTag == 0); |
990 // (8a) Is the external string one byte? If yes, go to (6). | 976 // (8) Is the external string one byte? If yes, go to (5). |
991 __ testb(rbx, Immediate(kStringEncodingMask)); | 977 __ testb(rbx, Immediate(kStringEncodingMask)); |
992 __ j(not_zero, &seq_one_byte_string); // Goto (6). | 978 __ j(not_zero, &seq_one_byte_string); // Go to (5). |
993 | 979 |
994 // rdi: subject string (flat two-byte) | 980 // rdi: subject string (flat two-byte) |
995 // rax: RegExp data (FixedArray) | 981 // rax: RegExp data (FixedArray) |
996 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). | 982 // (9) Two byte sequential. Load regexp code for two byte. Go to (E). |
997 __ bind(&seq_two_byte_string); | 983 __ bind(&seq_two_byte_string); |
998 __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); | 984 __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); |
999 __ Set(rcx, 0); // Type is two byte. | 985 __ Set(rcx, 0); // Type is two byte. |
1000 __ jmp(&check_code); // Go to (E). | 986 __ jmp(&check_code); // Go to (E). |
1001 | 987 |
1002 // (10) Not a string or a short external string? If yes, bail out to runtime. | 988 // (10) Not a string or a short external string? If yes, bail out to runtime. |
1003 __ bind(¬_long_external); | 989 __ bind(¬_long_external); |
1004 // Catch non-string subject or short external string. | 990 // Catch non-string subject or short external string. |
1005 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | 991 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); |
1006 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); | 992 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); |
1007 __ j(not_zero, &runtime); | 993 __ j(not_zero, &runtime); |
1008 | 994 |
1009 // (11) Sliced string. Replace subject with parent. Go to (5a). | 995 // (11) Sliced string. Replace subject with parent. Go to (1). |
1010 // Load offset into r14 and replace subject string with parent. | 996 // Load offset into r14 and replace subject string with parent. |
1011 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); | 997 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); |
1012 __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); | 998 __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); |
1013 __ jmp(&check_underlying); | 999 __ jmp(&check_underlying); |
1014 #endif // V8_INTERPRETED_REGEXP | 1000 #endif // V8_INTERPRETED_REGEXP |
1015 } | 1001 } |
1016 | 1002 |
1017 | 1003 |
1018 static int NegativeComparisonResult(Condition cc) { | 1004 static int NegativeComparisonResult(Condition cc) { |
1019 DCHECK(cc != equal); | 1005 DCHECK(cc != equal); |
(...skipping 4565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5585 kStackUnwindSpace, nullptr, return_value_operand, | 5571 kStackUnwindSpace, nullptr, return_value_operand, |
5586 NULL); | 5572 NULL); |
5587 } | 5573 } |
5588 | 5574 |
5589 #undef __ | 5575 #undef __ |
5590 | 5576 |
5591 } // namespace internal | 5577 } // namespace internal |
5592 } // namespace v8 | 5578 } // namespace v8 |
5593 | 5579 |
5594 #endif // V8_TARGET_ARCH_X64 | 5580 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |