OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
791 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 791 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
792 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); | 792 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
793 __ cmp(edx, Isolate::kJSRegexpStaticOffsetsVectorSize - 2); | 793 __ cmp(edx, Isolate::kJSRegexpStaticOffsetsVectorSize - 2); |
794 __ j(above, &runtime); | 794 __ j(above, &runtime); |
795 | 795 |
796 // Reset offset for possibly sliced string. | 796 // Reset offset for possibly sliced string. |
797 __ Move(edi, Immediate(0)); | 797 __ Move(edi, Immediate(0)); |
798 __ mov(eax, Operand(esp, kSubjectOffset)); | 798 __ mov(eax, Operand(esp, kSubjectOffset)); |
799 __ JumpIfSmi(eax, &runtime); | 799 __ JumpIfSmi(eax, &runtime); |
800 __ mov(edx, eax); // Make a copy of the original subject string. | 800 __ mov(edx, eax); // Make a copy of the original subject string. |
801 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | |
802 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | |
803 | 801 |
804 // eax: subject string | 802 // eax: subject string |
805 // edx: subject string | 803 // edx: subject string |
806 // ebx: subject string instance type | |
807 // ecx: RegExp data (FixedArray) | 804 // ecx: RegExp data (FixedArray) |
808 // Handle subject string according to its encoding and representation: | 805 // Handle subject string according to its encoding and representation: |
809 // (1) Sequential two byte? If yes, go to (9). | 806 // (1) Sequential two byte? If yes, go to (9). |
810 // (2) Sequential one byte? If yes, go to (6). | 807 // (2) Sequential one byte? If yes, go to (5). |
811 // (3) Anything but sequential or cons? If yes, go to (7). | 808 // (3) Sequential or cons? If not, go to (6). |
812 // (4) Cons string. If the string is flat, replace subject with first string. | 809 // (4) Cons string. If the string is flat, replace subject with first string |
813 // Otherwise bailout. | 810 // and go to (1). Otherwise bail out to runtime. |
814 // (5a) Is subject sequential two byte? If yes, go to (9). | 811 // (5) One byte sequential. Load regexp code for one byte. |
815 // (5b) Is subject external? If yes, go to (8). | |
816 // (6) One byte sequential. Load regexp code for one byte. | |
817 // (E) Carry on. | 812 // (E) Carry on. |
818 /// [...] | 813 /// [...] |
819 | 814 |
820 // Deferred code at the end of the stub: | 815 // Deferred code at the end of the stub: |
821 // (7) Not a long external string? If yes, go to (10). | 816 // (6) Long external string? If not, go to (10). |
822 // (8) External string. Make it, offset-wise, look like a sequential string. | 817 // (7) External string. Make it, offset-wise, look like a sequential string. |
823 // (8a) Is the external string one byte? If yes, go to (6). | 818 // (8) Is the external string one byte? If yes, go to (5). |
824 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). | 819 // (9) Two byte sequential. Load regexp code for two byte. Go to (E). |
825 // (10) Short external string or not a string? If yes, bail out to runtime. | 820 // (10) Short external string or not a string? If yes, bail out to runtime. |
826 // (11) Sliced string. Replace subject with parent. Go to (5a). | 821 // (11) Sliced string. Replace subject with parent. Go to (1). |
827 | 822 |
828 Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, | 823 Label seq_one_byte_string /* 5 */, seq_two_byte_string /* 9 */, |
829 external_string /* 8 */, check_underlying /* 5a */, | 824 external_string /* 7 */, check_underlying /* 1 */, |
830 not_seq_nor_cons /* 7 */, check_code /* E */, | 825 not_seq_nor_cons /* 6 */, check_code /* E */, not_long_external /* 10 */; |
831 not_long_external /* 10 */; | |
832 | 826 |
| 827 __ bind(&check_underlying); |
833 // (1) Sequential two byte? If yes, go to (9). | 828 // (1) Sequential two byte? If yes, go to (9). |
| 829 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 830 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 831 |
834 __ and_(ebx, kIsNotStringMask | | 832 __ and_(ebx, kIsNotStringMask | |
835 kStringRepresentationMask | | 833 kStringRepresentationMask | |
836 kStringEncodingMask | | 834 kStringEncodingMask | |
837 kShortExternalStringMask); | 835 kShortExternalStringMask); |
838 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 836 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
839 __ j(zero, &seq_two_byte_string); // Go to (9). | 837 __ j(zero, &seq_two_byte_string); // Go to (9). |
840 | 838 |
841 // (2) Sequential one byte? If yes, go to (6). | 839 // (2) Sequential one byte? If yes, go to (5). |
842 // Any other sequential string must be one byte. | 840 // Any other sequential string must be one byte. |
843 __ and_(ebx, Immediate(kIsNotStringMask | | 841 __ and_(ebx, Immediate(kIsNotStringMask | |
844 kStringRepresentationMask | | 842 kStringRepresentationMask | |
845 kShortExternalStringMask)); | 843 kShortExternalStringMask)); |
846 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6). | 844 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (5). |
847 | 845 |
848 // (3) Anything but sequential or cons? If yes, go to (7). | 846 // (3) Sequential or cons? If not, go to (6). |
849 // We check whether the subject string is a cons, since sequential strings | 847 // We check whether the subject string is a cons, since sequential strings |
850 // have already been covered. | 848 // have already been covered. |
851 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 849 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
852 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 850 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
853 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 851 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |
854 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 852 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |
855 __ cmp(ebx, Immediate(kExternalStringTag)); | 853 __ cmp(ebx, Immediate(kExternalStringTag)); |
856 __ j(greater_equal, ¬_seq_nor_cons); // Go to (7). | 854 __ j(greater_equal, ¬_seq_nor_cons); // Go to (6). |
857 | 855 |
858 // (4) Cons string. Check that it's flat. | 856 // (4) Cons string. Check that it's flat. |
859 // Replace subject with first string and reload instance type. | 857 // Replace subject with first string and reload instance type. |
860 __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string()); | 858 __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string()); |
861 __ j(not_equal, &runtime); | 859 __ j(not_equal, &runtime); |
862 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); | 860 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); |
863 __ bind(&check_underlying); | 861 __ jmp(&check_underlying); |
864 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | |
865 __ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | |
866 | |
867 // (5a) Is subject sequential two byte? If yes, go to (9). | |
868 __ test_b(ebx, kStringRepresentationMask | kStringEncodingMask); | |
869 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | |
870 __ j(zero, &seq_two_byte_string); // Go to (9). | |
871 // (5b) Is subject external? If yes, go to (8). | |
872 __ test_b(ebx, kStringRepresentationMask); | |
873 // The underlying external string is never a short external string. | |
874 STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); | |
875 STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); | |
876 __ j(not_zero, &external_string); // Go to (8). | |
877 | 862 |
878 // eax: sequential subject string (or look-alike, external string) | 863 // eax: sequential subject string (or look-alike, external string) |
879 // edx: original subject string | 864 // edx: original subject string |
880 // ecx: RegExp data (FixedArray) | 865 // ecx: RegExp data (FixedArray) |
881 // (6) One byte sequential. Load regexp code for one byte. | 866 // (5) One byte sequential. Load regexp code for one byte. |
882 __ bind(&seq_one_byte_string); | 867 __ bind(&seq_one_byte_string); |
883 // Load previous index and check range before edx is overwritten. We have | 868 // Load previous index and check range before edx is overwritten. We have |
884 // to use edx instead of eax here because it might have been only made to | 869 // to use edx instead of eax here because it might have been only made to |
885 // look like a sequential string when it actually is an external string. | 870 // look like a sequential string when it actually is an external string. |
886 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | 871 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); |
887 __ JumpIfNotSmi(ebx, &runtime); | 872 __ JumpIfNotSmi(ebx, &runtime); |
888 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); | 873 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); |
889 __ j(above_equal, &runtime); | 874 __ j(above_equal, &runtime); |
890 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataOneByteCodeOffset)); | 875 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataOneByteCodeOffset)); |
891 __ Move(ecx, Immediate(1)); // Type is one byte. | 876 __ Move(ecx, Immediate(1)); // Type is one byte. |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1098 | 1083 |
1099 // Return last match info. | 1084 // Return last match info. |
1100 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 1085 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
1101 __ ret(4 * kPointerSize); | 1086 __ ret(4 * kPointerSize); |
1102 | 1087 |
1103 // Do the runtime call to execute the regexp. | 1088 // Do the runtime call to execute the regexp. |
1104 __ bind(&runtime); | 1089 __ bind(&runtime); |
1105 __ TailCallRuntime(Runtime::kRegExpExec); | 1090 __ TailCallRuntime(Runtime::kRegExpExec); |
1106 | 1091 |
1107 // Deferred code for string handling. | 1092 // Deferred code for string handling. |
1108 // (7) Not a long external string? If yes, go to (10). | 1093 // (6) Long external string? If not, go to (10). |
1109 __ bind(¬_seq_nor_cons); | 1094 __ bind(¬_seq_nor_cons); |
1110 // Compare flags are still set from (3). | 1095 // Compare flags are still set from (3). |
1111 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). | 1096 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). |
1112 | 1097 |
1113 // (8) External string. Short external strings have been ruled out. | 1098 // (7) External string. Short external strings have been ruled out. |
1114 __ bind(&external_string); | 1099 __ bind(&external_string); |
1115 // Reload instance type. | 1100 // Reload instance type. |
1116 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 1101 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
1117 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 1102 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
1118 if (FLAG_debug_code) { | 1103 if (FLAG_debug_code) { |
1119 // Assert that we do not have a cons or slice (indirect strings) here. | 1104 // Assert that we do not have a cons or slice (indirect strings) here. |
1120 // Sequential strings have already been ruled out. | 1105 // Sequential strings have already been ruled out. |
1121 __ test_b(ebx, kIsIndirectStringMask); | 1106 __ test_b(ebx, kIsIndirectStringMask); |
1122 __ Assert(zero, kExternalStringExpectedButNotFound); | 1107 __ Assert(zero, kExternalStringExpectedButNotFound); |
1123 } | 1108 } |
1124 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); | 1109 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); |
1125 // Move the pointer so that offset-wise, it looks like a sequential string. | 1110 // Move the pointer so that offset-wise, it looks like a sequential string. |
1126 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 1111 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
1127 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 1112 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
1128 STATIC_ASSERT(kTwoByteStringTag == 0); | 1113 STATIC_ASSERT(kTwoByteStringTag == 0); |
1129 // (8a) Is the external string one byte? If yes, go to (6). | 1114 // (8) Is the external string one byte? If yes, go to (5). |
1130 __ test_b(ebx, kStringEncodingMask); | 1115 __ test_b(ebx, kStringEncodingMask); |
1131 __ j(not_zero, &seq_one_byte_string); // Goto (6). | 1116 __ j(not_zero, &seq_one_byte_string); // Go to (5). |
1132 | 1117 |
1133 // eax: sequential subject string (or look-alike, external string) | 1118 // eax: sequential subject string (or look-alike, external string) |
1134 // edx: original subject string | 1119 // edx: original subject string |
1135 // ecx: RegExp data (FixedArray) | 1120 // ecx: RegExp data (FixedArray) |
1136 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). | 1121 // (9) Two byte sequential. Load regexp code for two byte. Go to (E). |
1137 __ bind(&seq_two_byte_string); | 1122 __ bind(&seq_two_byte_string); |
1138 // Load previous index and check range before edx is overwritten. We have | 1123 // Load previous index and check range before edx is overwritten. We have |
1139 // to use edx instead of eax here because it might have been only made to | 1124 // to use edx instead of eax here because it might have been only made to |
1140 // look like a sequential string when it actually is an external string. | 1125 // look like a sequential string when it actually is an external string. |
1141 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | 1126 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); |
1142 __ JumpIfNotSmi(ebx, &runtime); | 1127 __ JumpIfNotSmi(ebx, &runtime); |
1143 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); | 1128 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); |
1144 __ j(above_equal, &runtime); | 1129 __ j(above_equal, &runtime); |
1145 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); | 1130 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); |
1146 __ Move(ecx, Immediate(0)); // Type is two byte. | 1131 __ Move(ecx, Immediate(0)); // Type is two byte. |
1147 __ jmp(&check_code); // Go to (E). | 1132 __ jmp(&check_code); // Go to (E). |
1148 | 1133 |
1149 // (10) Not a string or a short external string? If yes, bail out to runtime. | 1134 // (10) Not a string or a short external string? If yes, bail out to runtime. |
1150 __ bind(¬_long_external); | 1135 __ bind(¬_long_external); |
1151 // Catch non-string subject or short external string. | 1136 // Catch non-string subject or short external string. |
1152 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | 1137 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); |
1153 __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag)); | 1138 __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag)); |
1154 __ j(not_zero, &runtime); | 1139 __ j(not_zero, &runtime); |
1155 | 1140 |
1156 // (11) Sliced string. Replace subject with parent. Go to (5a). | 1141 // (11) Sliced string. Replace subject with parent. Go to (1). |
1157 // Load offset into edi and replace subject string with parent. | 1142 // Load offset into edi and replace subject string with parent. |
1158 __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset)); | 1143 __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset)); |
1159 __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset)); | 1144 __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset)); |
1160 __ jmp(&check_underlying); // Go to (5a). | 1145 __ jmp(&check_underlying); // Go to (1). |
1161 #endif // V8_INTERPRETED_REGEXP | 1146 #endif // V8_INTERPRETED_REGEXP |
1162 } | 1147 } |
1163 | 1148 |
1164 | 1149 |
1165 static int NegativeComparisonResult(Condition cc) { | 1150 static int NegativeComparisonResult(Condition cc) { |
1166 DCHECK(cc != equal); | 1151 DCHECK(cc != equal); |
1167 DCHECK((cc == less) || (cc == less_equal) | 1152 DCHECK((cc == less) || (cc == less_equal) |
1168 || (cc == greater) || (cc == greater_equal)); | 1153 || (cc == greater) || (cc == greater_equal)); |
1169 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 1154 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
1170 } | 1155 } |
(...skipping 4751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5922 return_value_operand, NULL); | 5907 return_value_operand, NULL); |
5923 } | 5908 } |
5924 | 5909 |
5925 | 5910 |
5926 #undef __ | 5911 #undef __ |
5927 | 5912 |
5928 } // namespace internal | 5913 } // namespace internal |
5929 } // namespace v8 | 5914 } // namespace v8 |
5930 | 5915 |
5931 #endif // V8_TARGET_ARCH_IA32 | 5916 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |