Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 3811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3822 // esp[4]: last_match_info (expected JSArray) | 3822 // esp[4]: last_match_info (expected JSArray) |
| 3823 // esp[8]: previous index | 3823 // esp[8]: previous index |
| 3824 // esp[12]: subject string | 3824 // esp[12]: subject string |
| 3825 // esp[16]: JSRegExp object | 3825 // esp[16]: JSRegExp object |
| 3826 | 3826 |
| 3827 static const int kLastMatchInfoOffset = 1 * kPointerSize; | 3827 static const int kLastMatchInfoOffset = 1 * kPointerSize; |
| 3828 static const int kPreviousIndexOffset = 2 * kPointerSize; | 3828 static const int kPreviousIndexOffset = 2 * kPointerSize; |
| 3829 static const int kSubjectOffset = 3 * kPointerSize; | 3829 static const int kSubjectOffset = 3 * kPointerSize; |
| 3830 static const int kJSRegExpOffset = 4 * kPointerSize; | 3830 static const int kJSRegExpOffset = 4 * kPointerSize; |
| 3831 | 3831 |
| 3832 Label runtime, invoke_regexp; | 3832 Label runtime; |
| 3833 Factory* factory = masm->isolate()->factory(); | |
| 3833 | 3834 |
| 3834 // Ensure that a RegExp stack is allocated. | 3835 // Ensure that a RegExp stack is allocated. |
| 3835 ExternalReference address_of_regexp_stack_memory_address = | 3836 ExternalReference address_of_regexp_stack_memory_address = |
| 3836 ExternalReference::address_of_regexp_stack_memory_address( | 3837 ExternalReference::address_of_regexp_stack_memory_address( |
| 3837 masm->isolate()); | 3838 masm->isolate()); |
| 3838 ExternalReference address_of_regexp_stack_memory_size = | 3839 ExternalReference address_of_regexp_stack_memory_size = |
| 3839 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate()); | 3840 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate()); |
| 3840 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 3841 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
| 3841 __ test(ebx, ebx); | 3842 __ test(ebx, ebx); |
| 3842 __ j(zero, &runtime); | 3843 __ j(zero, &runtime); |
| 3843 | 3844 |
| 3844 // Check that the first argument is a JSRegExp object. | 3845 // Check that the first argument is a JSRegExp object. |
| 3845 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 3846 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
| 3846 STATIC_ASSERT(kSmiTag == 0); | 3847 STATIC_ASSERT(kSmiTag == 0); |
| 3847 __ JumpIfSmi(eax, &runtime); | 3848 __ JumpIfSmi(eax, &runtime); |
| 3848 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); | 3849 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); |
| 3849 __ j(not_equal, &runtime); | 3850 __ j(not_equal, &runtime); |
| 3851 | |
| 3850 // Check that the RegExp has been compiled (data contains a fixed array). | 3852 // Check that the RegExp has been compiled (data contains a fixed array). |
| 3851 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 3853 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
| 3852 if (FLAG_debug_code) { | 3854 if (FLAG_debug_code) { |
| 3853 __ test(ecx, Immediate(kSmiTagMask)); | 3855 __ test(ecx, Immediate(kSmiTagMask)); |
| 3854 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected"); | 3856 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected"); |
| 3855 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); | 3857 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); |
| 3856 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); | 3858 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); |
| 3857 } | 3859 } |
| 3858 | 3860 |
| 3859 // ecx: RegExp data (FixedArray) | 3861 // ecx: RegExp data (FixedArray) |
| 3860 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | 3862 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
| 3861 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset)); | 3863 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset)); |
| 3862 __ cmp(ebx, Immediate(Smi::FromInt(JSRegExp::IRREGEXP))); | 3864 __ cmp(ebx, Immediate(Smi::FromInt(JSRegExp::IRREGEXP))); |
| 3863 __ j(not_equal, &runtime); | 3865 __ j(not_equal, &runtime); |
| 3864 | 3866 |
| 3865 // ecx: RegExp data (FixedArray) | 3867 // ecx: RegExp data (FixedArray) |
| 3866 // Check that the number of captures fit in the static offsets vector buffer. | 3868 // Check that the number of captures fit in the static offsets vector buffer. |
| 3867 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); | 3869 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); |
| 3868 // Calculate number of capture registers (number_of_captures + 1) * 2. This | 3870 // Check (number_of_captures + 1) * 2 <= offsets vector size |
| 3869 // uses the asumption that smis are 2 * their untagged value. | 3871 // Or number_of_captures * 2 <= offsets vector size - 2 |
| 3872 // Multiplying by 2 comes for free since edx is smi-tagged. | |
| 3870 STATIC_ASSERT(kSmiTag == 0); | 3873 STATIC_ASSERT(kSmiTag == 0); |
| 3871 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 3874 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
| 3872 __ add(edx, Immediate(2)); // edx was a smi. | 3875 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
| 3873 // Check that the static offsets vector buffer is large enough. | 3876 __ cmp(edx, Isolate::kJSRegexpStaticOffsetsVectorSize - 2); |
| 3874 __ cmp(edx, Isolate::kJSRegexpStaticOffsetsVectorSize); | |
| 3875 __ j(above, &runtime); | 3877 __ j(above, &runtime); |
| 3876 | 3878 |
| 3877 // ecx: RegExp data (FixedArray) | |
| 3878 // edx: Number of capture registers | |
| 3879 // Check that the second argument is a string. | |
| 3880 __ mov(eax, Operand(esp, kSubjectOffset)); | |
| 3881 __ JumpIfSmi(eax, &runtime); | |
| 3882 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); | |
| 3883 __ j(NegateCondition(is_string), &runtime); | |
| 3884 // Get the length of the string to ebx. | |
| 3885 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); | |
| 3886 | |
| 3887 // ebx: Length of subject string as a smi | |
| 3888 // ecx: RegExp data (FixedArray) | |
| 3889 // edx: Number of capture registers | |
| 3890 // Check that the third argument is a positive smi less than the subject | |
| 3891 // string length. A negative value will be greater (unsigned comparison). | |
| 3892 __ mov(eax, Operand(esp, kPreviousIndexOffset)); | |
| 3893 __ JumpIfNotSmi(eax, &runtime); | |
| 3894 __ cmp(eax, ebx); | |
| 3895 __ j(above_equal, &runtime); | |
| 3896 | |
| 3897 // ecx: RegExp data (FixedArray) | |
| 3898 // edx: Number of capture registers | |
| 3899 // Check that the fourth object is a JSArray object. | |
| 3900 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | |
| 3901 __ JumpIfSmi(eax, &runtime); | |
| 3902 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); | |
| 3903 __ j(not_equal, &runtime); | |
| 3904 // Check that the JSArray is in fast case. | |
| 3905 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); | |
| 3906 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset)); | |
| 3907 Factory* factory = masm->isolate()->factory(); | |
| 3908 __ cmp(eax, factory->fixed_array_map()); | |
| 3909 __ j(not_equal, &runtime); | |
| 3910 // Check that the last match info has space for the capture registers and the | |
| 3911 // additional information. | |
| 3912 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); | |
| 3913 __ SmiUntag(eax); | |
| 3914 __ add(edx, Immediate(RegExpImpl::kLastMatchOverhead)); | |
| 3915 __ cmp(edx, eax); | |
| 3916 __ j(greater, &runtime); | |
| 3917 | |
| 3918 // Reset offset for possibly sliced string. | 3879 // Reset offset for possibly sliced string. |
| 3919 __ Set(edi, Immediate(0)); | 3880 __ Set(edi, Immediate(0)); |
| 3920 // ecx: RegExp data (FixedArray) | |
| 3921 // Check the representation and encoding of the subject string. | |
| 3922 Label seq_ascii_string, seq_two_byte_string, check_code; | |
| 3923 __ mov(eax, Operand(esp, kSubjectOffset)); | 3881 __ mov(eax, Operand(esp, kSubjectOffset)); |
| 3882 __ JumpIfSmi(eax, &runtime); | |
| 3883 __ mov(edx, eax); // Make a copy of the original subject string. | |
| 3924 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3884 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3925 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 3885 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 3926 // First check for flat two byte string. | 3886 |
| 3887 // eax: subject string | |
| 3888 // edx: subject string | |
| 3889 // ebx: subject string instance type | |
| 3890 // ecx: RegExp data (FixedArray) | |
| 3891 // Handle subject string according to its encoding and representation: | |
| 3892 // (1) Sequential two byte? If yes, go to (9). | |
| 3893 // (2) Sequential one byte? If yes, go to (6). | |
| 3894 // (3) Anything but sequential or cons? If yes, go to (7). | |
| 3895 // (4) Cons string. Replace subject with first string. | |
|
ulan
2013/02/13 14:35:44
"(4) Cons string. If the string is flat ..., other
| |
| 3896 // (5a) Is subject two byte? If yes, go to (9). | |
|
ulan
2013/02/13 14:35:44
"Is subject sequential two byte"
| |
| 3897 // (5b) Is subject external? If yes, go to (8). | |
| 3898 // (6) One byte sequential. Load regexp code for one byte. | |
| 3899 // (E) Carry on. | |
| 3900 /// [...] | |
| 3901 | |
| 3902 // Deferred code at the end of the stub: | |
| 3903 // (7) Not a long external string? If yes, go to (10). | |
| 3904 // (8) External string. Make it, offset-wise, look like a sequential string. | |
| 3905 // (8a) Is the external string one byte? If yes, go to (6). | |
| 3906 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). | |
| 3907 // (10) Short external string or not a string? If yes, bail out to runtime. | |
| 3908 // (11) Sliced string. Replace subject with parent. Go to (5a). | |
| 3909 | |
| 3910 Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, | |
| 3911 external_string /* 8 */, check_underlying /* 5a */, | |
| 3912 not_seq_nor_cons /* 7 */, check_code /* E */, | |
| 3913 not_long_external /* 10 */; | |
| 3914 | |
| 3915 // (1) Sequential two byte? If yes, go to (9). | |
| 3927 __ and_(ebx, kIsNotStringMask | | 3916 __ and_(ebx, kIsNotStringMask | |
| 3928 kStringRepresentationMask | | 3917 kStringRepresentationMask | |
| 3929 kStringEncodingMask | | 3918 kStringEncodingMask | |
| 3930 kShortExternalStringMask); | 3919 kShortExternalStringMask); |
| 3931 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 3920 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
| 3932 __ j(zero, &seq_two_byte_string, Label::kNear); | 3921 __ j(zero, &seq_two_byte_string); // Go to (9). |
| 3933 // Any other flat string must be a flat ASCII string. None of the following | 3922 |
| 3934 // string type tests will succeed if subject is not a string or a short | 3923 // (2) Sequential one byte? If yes, go to (6). |
| 3935 // external string. | 3924 // Any other sequential string must be one byte. |
| 3936 __ and_(ebx, Immediate(kIsNotStringMask | | 3925 __ and_(ebx, Immediate(kIsNotStringMask | |
| 3937 kStringRepresentationMask | | 3926 kStringRepresentationMask | |
| 3938 kShortExternalStringMask)); | 3927 kShortExternalStringMask)); |
| 3939 __ j(zero, &seq_ascii_string, Label::kNear); | 3928 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6). |
| 3940 | 3929 |
| 3941 // ebx: whether subject is a string and if yes, its string representation | 3930 // (3) Anything but sequential or cons? If yes, go to (7). |
| 3942 // Check for flat cons string or sliced string. | 3931 // We check whether the subject string is a cons, since sequential strings |
| 3943 // A flat cons string is a cons string where the second part is the empty | 3932 // have already been covered. |
| 3944 // string. In that case the subject string is just the first part of the cons | |
| 3945 // string. Also in this case the first part of the cons string is known to be | |
| 3946 // a sequential string or an external string. | |
| 3947 // In the case of a sliced string its offset has to be taken into account. | |
| 3948 Label cons_string, external_string, check_encoding; | |
| 3949 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 3933 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
| 3950 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 3934 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
| 3951 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 3935 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |
| 3952 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 3936 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |
| 3953 __ cmp(ebx, Immediate(kExternalStringTag)); | 3937 __ cmp(ebx, Immediate(kExternalStringTag)); |
| 3954 __ j(less, &cons_string); | 3938 __ j(greater_equal, ¬_seq_nor_cons); // Go to (7). |
| 3955 __ j(equal, &external_string); | |
| 3956 | 3939 |
| 3957 // Catch non-string subject or short external string. | 3940 // (4) Cons string. Check that it's flat. |
| 3958 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | 3941 // Replace subject with first string and reload instance type. |
| 3959 __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag)); | |
| 3960 __ j(not_zero, &runtime); | |
| 3961 | |
| 3962 // String is sliced. | |
| 3963 __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset)); | |
| 3964 __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset)); | |
| 3965 // edi: offset of sliced string, smi-tagged. | |
| 3966 // eax: parent string. | |
| 3967 __ jmp(&check_encoding, Label::kNear); | |
| 3968 // String is a cons string, check whether it is flat. | |
| 3969 __ bind(&cons_string); | |
| 3970 __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string()); | 3942 __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string()); |
| 3971 __ j(not_equal, &runtime); | 3943 __ j(not_equal, &runtime); |
| 3972 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); | 3944 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); |
| 3973 __ bind(&check_encoding); | 3945 __ bind(&check_underlying); |
| 3974 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3946 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3975 // eax: first part of cons string or parent of sliced string. | 3947 __ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 3976 // ebx: map of first part of cons string or map of parent of sliced string. | 3948 |
| 3977 // Is first part of cons or parent of slice a flat two byte string? | 3949 // (5a) Is subject two byte? If yes, go to (9). |
|
ulan
2013/02/13 14:35:44
Is subject sequential two byte
| |
| 3978 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), | 3950 __ test_b(ebx, kStringRepresentationMask | kStringEncodingMask); |
| 3979 kStringRepresentationMask | kStringEncodingMask); | |
| 3980 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 3951 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
| 3981 __ j(zero, &seq_two_byte_string, Label::kNear); | 3952 __ j(zero, &seq_two_byte_string); // Go to (9). |
| 3982 // Any other flat string must be sequential ASCII or external. | 3953 // (5b) Is subject external? If yes, go to (8). |
| 3983 __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), | 3954 __ test_b(ebx, kStringRepresentationMask); |
| 3984 kStringRepresentationMask); | 3955 // The underlying external string is never a short external string. |
| 3985 __ j(not_zero, &external_string); | 3956 STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength); |
| 3957 STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength); | |
| 3958 __ j(not_zero, &external_string); // Go to (8). | |
| 3986 | 3959 |
| 3987 __ bind(&seq_ascii_string); | 3960 // eax: sequential subject string (or look-alike, external string) |
| 3988 // eax: subject string (flat ASCII) | 3961 // edx: original subject string |
| 3989 // ecx: RegExp data (FixedArray) | 3962 // ecx: RegExp data (FixedArray) |
| 3963 // (6) One byte sequential. Load regexp code for one byte. | |
| 3964 __ bind(&seq_one_byte_string); | |
| 3965 // Load previous index and check range before edx is overwritten. We have | |
| 3966 // to use edx instead of eax here because it might have been only made to | |
| 3967 // look like a sequential string when it actually is an external string. | |
| 3968 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | |
| 3969 __ JumpIfNotSmi(ebx, &runtime); | |
| 3970 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); | |
| 3971 __ j(above_equal, &runtime); | |
| 3990 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); | 3972 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); |
| 3991 __ Set(ecx, Immediate(1)); // Type is ASCII. | 3973 __ Set(ecx, Immediate(1)); // Type is one byte. |
| 3992 __ jmp(&check_code, Label::kNear); | |
| 3993 | 3974 |
| 3994 __ bind(&seq_two_byte_string); | 3975 // (E) Carry on. String handling is done. |
| 3995 // eax: subject string (flat two byte) | |
| 3996 // ecx: RegExp data (FixedArray) | |
| 3997 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); | |
| 3998 __ Set(ecx, Immediate(0)); // Type is two byte. | |
| 3999 | |
| 4000 __ bind(&check_code); | 3976 __ bind(&check_code); |
| 3977 // edx: irregexp code | |
| 4001 // Check that the irregexp code has been generated for the actual string | 3978 // Check that the irregexp code has been generated for the actual string |
| 4002 // encoding. If it has, the field contains a code object otherwise it contains | 3979 // encoding. If it has, the field contains a code object otherwise it contains |
| 4003 // a smi (code flushing support). | 3980 // a smi (code flushing support). |
| 4004 __ JumpIfSmi(edx, &runtime); | 3981 __ JumpIfSmi(edx, &runtime); |
| 4005 | 3982 |
| 4006 // eax: subject string | 3983 // eax: subject string |
| 3984 // ebx: previous index (smi) | |
| 4007 // edx: code | 3985 // edx: code |
| 4008 // ecx: encoding of subject string (1 if ASCII, 0 if two_byte); | 3986 // ecx: encoding of subject string (1 if ASCII, 0 if two_byte); |
| 4009 // Load used arguments before starting to push arguments for call to native | |
| 4010 // RegExp code to avoid handling changing stack height. | |
| 4011 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | |
| 4012 __ SmiUntag(ebx); // Previous index from smi. | |
| 4013 | |
| 4014 // eax: subject string | |
| 4015 // ebx: previous index | |
| 4016 // edx: code | |
| 4017 // ecx: encoding of subject string (1 if ASCII 0 if two_byte); | |
| 4018 // All checks done. Now push arguments for native regexp code. | 3987 // All checks done. Now push arguments for native regexp code. |
| 4019 Counters* counters = masm->isolate()->counters(); | 3988 Counters* counters = masm->isolate()->counters(); |
| 4020 __ IncrementCounter(counters->regexp_entry_native(), 1); | 3989 __ IncrementCounter(counters->regexp_entry_native(), 1); |
| 4021 | 3990 |
| 4022 // Isolates: note we add an additional parameter here (isolate pointer). | 3991 // Isolates: note we add an additional parameter here (isolate pointer). |
| 4023 static const int kRegExpExecuteArguments = 9; | 3992 static const int kRegExpExecuteArguments = 9; |
| 4024 __ EnterApiExitFrame(kRegExpExecuteArguments); | 3993 __ EnterApiExitFrame(kRegExpExecuteArguments); |
| 4025 | 3994 |
| 4026 // Argument 9: Pass current isolate address. | 3995 // Argument 9: Pass current isolate address. |
| 4027 __ mov(Operand(esp, 8 * kPointerSize), | 3996 __ mov(Operand(esp, 8 * kPointerSize), |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 4038 // Argument 6: Set the number of capture registers to zero to force global | 4007 // Argument 6: Set the number of capture registers to zero to force global |
| 4039 // regexps to behave as non-global. This does not affect non-global regexps. | 4008 // regexps to behave as non-global. This does not affect non-global regexps. |
| 4040 __ mov(Operand(esp, 5 * kPointerSize), Immediate(0)); | 4009 __ mov(Operand(esp, 5 * kPointerSize), Immediate(0)); |
| 4041 | 4010 |
| 4042 // Argument 5: static offsets vector buffer. | 4011 // Argument 5: static offsets vector buffer. |
| 4043 __ mov(Operand(esp, 4 * kPointerSize), | 4012 __ mov(Operand(esp, 4 * kPointerSize), |
| 4044 Immediate(ExternalReference::address_of_static_offsets_vector( | 4013 Immediate(ExternalReference::address_of_static_offsets_vector( |
| 4045 masm->isolate()))); | 4014 masm->isolate()))); |
| 4046 | 4015 |
| 4047 // Argument 2: Previous index. | 4016 // Argument 2: Previous index. |
| 4017 __ SmiUntag(ebx); | |
| 4048 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 4018 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 4049 | 4019 |
| 4050 // Argument 1: Original subject string. | 4020 // Argument 1: Original subject string. |
| 4051 // The original subject is in the previous stack frame. Therefore we have to | 4021 // The original subject is in the previous stack frame. Therefore we have to |
| 4052 // use ebp, which points exactly to one pointer size below the previous esp. | 4022 // use ebp, which points exactly to one pointer size below the previous esp. |
| 4053 // (Because creating a new stack frame pushes the previous ebp onto the stack | 4023 // (Because creating a new stack frame pushes the previous ebp onto the stack |
| 4054 // and thereby moves up esp by one kPointerSize.) | 4024 // and thereby moves up esp by one kPointerSize.) |
| 4055 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); | 4025 __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize)); |
| 4056 __ mov(Operand(esp, 0 * kPointerSize), esi); | 4026 __ mov(Operand(esp, 0 * kPointerSize), esi); |
| 4057 | 4027 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4147 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 4117 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
| 4148 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 4118 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
| 4149 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); | 4119 __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset)); |
| 4150 // Calculate number of capture registers (number_of_captures + 1) * 2. | 4120 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 4151 STATIC_ASSERT(kSmiTag == 0); | 4121 STATIC_ASSERT(kSmiTag == 0); |
| 4152 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 4122 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
| 4153 __ add(edx, Immediate(2)); // edx was a smi. | 4123 __ add(edx, Immediate(2)); // edx was a smi. |
| 4154 | 4124 |
| 4155 // edx: Number of capture registers | 4125 // edx: Number of capture registers |
| 4156 // Load last_match_info which is still known to be a fast case JSArray. | 4126 // Load last_match_info which is still known to be a fast case JSArray. |
| 4127 // Check that the fourth object is a JSArray object. | |
| 4157 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 4128 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
| 4129 __ JumpIfSmi(eax, &runtime); | |
| 4130 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); | |
| 4131 __ j(not_equal, &runtime); | |
| 4132 // Check that the JSArray is in fast case. | |
| 4158 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); | 4133 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); |
| 4134 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset)); | |
| 4135 __ cmp(eax, factory->fixed_array_map()); | |
| 4136 __ j(not_equal, &runtime); | |
| 4137 // Check that the last match info has space for the capture registers and the | |
| 4138 // additional information. | |
| 4139 __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset)); | |
| 4140 __ SmiUntag(eax); | |
| 4141 __ sub(eax, Immediate(RegExpImpl::kLastMatchOverhead)); | |
| 4142 __ cmp(edx, eax); | |
| 4143 __ j(greater, &runtime); | |
| 4159 | 4144 |
| 4160 // ebx: last_match_info backing store (FixedArray) | 4145 // ebx: last_match_info backing store (FixedArray) |
| 4161 // edx: number of capture registers | 4146 // edx: number of capture registers |
| 4162 // Store the capture count. | 4147 // Store the capture count. |
| 4163 __ SmiTag(edx); // Number of capture registers to smi. | 4148 __ SmiTag(edx); // Number of capture registers to smi. |
| 4164 __ mov(FieldOperand(ebx, RegExpImpl::kLastCaptureCountOffset), edx); | 4149 __ mov(FieldOperand(ebx, RegExpImpl::kLastCaptureCountOffset), edx); |
| 4165 __ SmiUntag(edx); // Number of capture registers back from smi. | 4150 __ SmiUntag(edx); // Number of capture registers back from smi. |
| 4166 // Store last subject and last input. | 4151 // Store last subject and last input. |
| 4167 __ mov(eax, Operand(esp, kSubjectOffset)); | 4152 __ mov(eax, Operand(esp, kSubjectOffset)); |
| 4153 __ mov(ecx, eax); | |
| 4168 __ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax); | 4154 __ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax); |
| 4169 __ RecordWriteField(ebx, | 4155 __ RecordWriteField(ebx, |
| 4170 RegExpImpl::kLastSubjectOffset, | 4156 RegExpImpl::kLastSubjectOffset, |
| 4171 eax, | 4157 eax, |
| 4172 edi, | 4158 edi, |
| 4173 kDontSaveFPRegs); | 4159 kDontSaveFPRegs); |
| 4174 __ mov(eax, Operand(esp, kSubjectOffset)); | 4160 __ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), ecx); |
| 4175 __ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), eax); | |
| 4176 __ RecordWriteField(ebx, | 4161 __ RecordWriteField(ebx, |
| 4177 RegExpImpl::kLastInputOffset, | 4162 RegExpImpl::kLastInputOffset, |
| 4178 eax, | 4163 ecx, |
|
ulan
2013/02/13 14:35:44
__ mov(eax, ecx) would allow to use the existing w
| |
| 4179 edi, | 4164 edi, |
| 4180 kDontSaveFPRegs); | 4165 kDontSaveFPRegs); |
| 4181 | 4166 |
| 4182 // Get the static offsets vector filled by the native regexp code. | 4167 // Get the static offsets vector filled by the native regexp code. |
| 4183 ExternalReference address_of_static_offsets_vector = | 4168 ExternalReference address_of_static_offsets_vector = |
| 4184 ExternalReference::address_of_static_offsets_vector(masm->isolate()); | 4169 ExternalReference::address_of_static_offsets_vector(masm->isolate()); |
| 4185 __ mov(ecx, Immediate(address_of_static_offsets_vector)); | 4170 __ mov(ecx, Immediate(address_of_static_offsets_vector)); |
| 4186 | 4171 |
| 4187 // ebx: last_match_info backing store (FixedArray) | 4172 // ebx: last_match_info backing store (FixedArray) |
| 4188 // ecx: offsets vector | 4173 // ecx: offsets vector |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 4202 times_pointer_size, | 4187 times_pointer_size, |
| 4203 RegExpImpl::kFirstCaptureOffset), | 4188 RegExpImpl::kFirstCaptureOffset), |
| 4204 edi); | 4189 edi); |
| 4205 __ jmp(&next_capture); | 4190 __ jmp(&next_capture); |
| 4206 __ bind(&done); | 4191 __ bind(&done); |
| 4207 | 4192 |
| 4208 // Return last match info. | 4193 // Return last match info. |
| 4209 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 4194 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
| 4210 __ ret(4 * kPointerSize); | 4195 __ ret(4 * kPointerSize); |
| 4211 | 4196 |
| 4212 // External string. Short external strings have already been ruled out. | 4197 // Do the runtime call to execute the regexp. |
| 4213 // eax: subject string (expected to be external) | 4198 __ bind(&runtime); |
| 4214 // ebx: scratch | 4199 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 4200 | |
| 4201 // Deferred code for string handling. | |
| 4202 // (7) Not a long external string? If yes, go to (10). | |
| 4203 __ bind(¬_seq_nor_cons); | |
| 4204 // Compare flags are still set from (3). | |
| 4205 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). | |
| 4206 | |
| 4207 // (8) External string. Short external strings have been ruled out. | |
| 4215 __ bind(&external_string); | 4208 __ bind(&external_string); |
| 4209 // Reload instance type. | |
| 4216 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 4210 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 4217 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 4211 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 4218 if (FLAG_debug_code) { | 4212 if (FLAG_debug_code) { |
| 4219 // Assert that we do not have a cons or slice (indirect strings) here. | 4213 // Assert that we do not have a cons or slice (indirect strings) here. |
| 4220 // Sequential strings have already been ruled out. | 4214 // Sequential strings have already been ruled out. |
| 4221 __ test_b(ebx, kIsIndirectStringMask); | 4215 __ test_b(ebx, kIsIndirectStringMask); |
| 4222 __ Assert(zero, "external string expected, but not found"); | 4216 __ Assert(zero, "external string expected, but not found"); |
| 4223 } | 4217 } |
| 4224 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); | 4218 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); |
| 4225 // Move the pointer so that offset-wise, it looks like a sequential string. | 4219 // Move the pointer so that offset-wise, it looks like a sequential string. |
| 4226 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 4220 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
| 4227 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 4221 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
| 4228 STATIC_ASSERT(kTwoByteStringTag == 0); | 4222 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 4223 // (8a) Is the external string one byte? If yes, go to (6). | |
| 4229 __ test_b(ebx, kStringEncodingMask); | 4224 __ test_b(ebx, kStringEncodingMask); |
| 4230 __ j(not_zero, &seq_ascii_string); | 4225 __ j(not_zero, &seq_one_byte_string); // Goto (6). |
| 4231 __ jmp(&seq_two_byte_string); | |
| 4232 | 4226 |
| 4233 // Do the runtime call to execute the regexp. | 4227 // eax: sequential subject string (or look-alike, external string) |
| 4234 __ bind(&runtime); | 4228 // edx: original subject string |
| 4235 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 4229 // ecx: RegExp data (FixedArray) |
| 4230 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). | |
| 4231 __ bind(&seq_two_byte_string); | |
| 4232 // Load previous index and check range before edx is overwritten. We have | |
| 4233 // to use edx instead of eax here because it might have been only made to | |
| 4234 // look like a sequential string when it actually is an external string. | |
| 4235 __ mov(ebx, Operand(esp, kPreviousIndexOffset)); | |
| 4236 __ JumpIfNotSmi(ebx, &runtime); | |
| 4237 __ cmp(ebx, FieldOperand(edx, String::kLengthOffset)); | |
| 4238 __ j(above_equal, &runtime); | |
| 4239 __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset)); | |
| 4240 __ Set(ecx, Immediate(0)); // Type is two byte. | |
| 4241 __ jmp(&check_code); // Go to (E). | |
| 4242 | |
| 4243 // (10) Not a string or a short external string? If yes, bail out to runtime. | |
| 4244 __ bind(¬_long_external); | |
| 4245 // Catch non-string subject or short external string. | |
| 4246 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | |
| 4247 __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag)); | |
| 4248 __ j(not_zero, &runtime); | |
| 4249 | |
| 4250 // (11) Sliced string. Replace subject with parent. Go to (5a). | |
| 4251 // Load offset into edi and replace subject string with parent. | |
| 4252 __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset)); | |
| 4253 __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset)); | |
| 4254 __ jmp(&check_underlying); // Go to (5a). | |
| 4236 #endif // V8_INTERPRETED_REGEXP | 4255 #endif // V8_INTERPRETED_REGEXP |
| 4237 } | 4256 } |
| 4238 | 4257 |
| 4239 | 4258 |
| 4240 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 4259 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
| 4241 const int kMaxInlineLength = 100; | 4260 const int kMaxInlineLength = 100; |
| 4242 Label slowcase; | 4261 Label slowcase; |
| 4243 Label done; | 4262 Label done; |
| 4244 __ mov(ebx, Operand(esp, kPointerSize * 3)); | 4263 __ mov(ebx, Operand(esp, kPointerSize * 3)); |
| 4245 __ JumpIfNotSmi(ebx, &slowcase); | 4264 __ JumpIfNotSmi(ebx, &slowcase); |
| (...skipping 3035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7281 Register object, value, address; | 7300 Register object, value, address; |
| 7282 RememberedSetAction action; | 7301 RememberedSetAction action; |
| 7283 }; | 7302 }; |
| 7284 | 7303 |
| 7285 | 7304 |
| 7286 #define REG(Name) { kRegister_ ## Name ## _Code } | 7305 #define REG(Name) { kRegister_ ## Name ## _Code } |
| 7287 | 7306 |
| 7288 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { | 7307 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { |
| 7289 // Used in RegExpExecStub. | 7308 // Used in RegExpExecStub. |
| 7290 { REG(ebx), REG(eax), REG(edi), EMIT_REMEMBERED_SET }, | 7309 { REG(ebx), REG(eax), REG(edi), EMIT_REMEMBERED_SET }, |
| 7310 { REG(ebx), REG(ecx), REG(edi), EMIT_REMEMBERED_SET }, | |
| 7291 // Used in CompileArrayPushCall. | 7311 // Used in CompileArrayPushCall. |
| 7292 { REG(ebx), REG(ecx), REG(edx), EMIT_REMEMBERED_SET }, | 7312 { REG(ebx), REG(ecx), REG(edx), EMIT_REMEMBERED_SET }, |
| 7293 { REG(ebx), REG(edi), REG(edx), OMIT_REMEMBERED_SET }, | 7313 { REG(ebx), REG(edi), REG(edx), OMIT_REMEMBERED_SET }, |
| 7294 // Used in CompileStoreGlobal and CallFunctionStub. | 7314 // Used in CompileStoreGlobal and CallFunctionStub. |
| 7295 { REG(ebx), REG(ecx), REG(edx), OMIT_REMEMBERED_SET }, | 7315 { REG(ebx), REG(ecx), REG(edx), OMIT_REMEMBERED_SET }, |
| 7296 // Used in StoreStubCompiler::CompileStoreField and | 7316 // Used in StoreStubCompiler::CompileStoreField and |
| 7297 // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. | 7317 // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. |
| 7298 { REG(edx), REG(ecx), REG(ebx), EMIT_REMEMBERED_SET }, | 7318 { REG(edx), REG(ecx), REG(ebx), EMIT_REMEMBERED_SET }, |
| 7299 // GenerateStoreField calls the stub with two different permutations of | 7319 // GenerateStoreField calls the stub with two different permutations of |
| 7300 // registers. This is the second. | 7320 // registers. This is the second. |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7698 // Restore ecx. | 7718 // Restore ecx. |
| 7699 __ pop(ecx); | 7719 __ pop(ecx); |
| 7700 __ ret(0); | 7720 __ ret(0); |
| 7701 } | 7721 } |
| 7702 | 7722 |
| 7703 #undef __ | 7723 #undef __ |
| 7704 | 7724 |
| 7705 } } // namespace v8::internal | 7725 } } // namespace v8::internal |
| 7706 | 7726 |
| 7707 #endif // V8_TARGET_ARCH_IA32 | 7727 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |