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

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 12210143: Refactor RegExpStub to check lazily. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 10 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 | Annotate | Revision Log
OLDNEW
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
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, &not_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
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
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
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(&not_seq_nor_cons);
4204 // Compare flags are still set from (3).
4205 __ j(greater, &not_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(&not_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
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
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
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.cc ('k') | src/objects.h » ('j') | src/x64/macro-assembler-x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698