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 2938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2949 ExternalReference::address_of_regexp_stack_memory_size(isolate); | 2949 ExternalReference::address_of_regexp_stack_memory_size(isolate); |
2950 __ Load(kScratchRegister, address_of_regexp_stack_memory_size); | 2950 __ Load(kScratchRegister, address_of_regexp_stack_memory_size); |
2951 __ testq(kScratchRegister, kScratchRegister); | 2951 __ testq(kScratchRegister, kScratchRegister); |
2952 __ j(zero, &runtime); | 2952 __ j(zero, &runtime); |
2953 | 2953 |
2954 // Check that the first argument is a JSRegExp object. | 2954 // Check that the first argument is a JSRegExp object. |
2955 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 2955 __ movq(rax, Operand(rsp, kJSRegExpOffset)); |
2956 __ JumpIfSmi(rax, &runtime); | 2956 __ JumpIfSmi(rax, &runtime); |
2957 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); | 2957 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); |
2958 __ j(not_equal, &runtime); | 2958 __ j(not_equal, &runtime); |
| 2959 |
2959 // Check that the RegExp has been compiled (data contains a fixed array). | 2960 // Check that the RegExp has been compiled (data contains a fixed array). |
2960 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset)); | 2961 __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset)); |
2961 if (FLAG_debug_code) { | 2962 if (FLAG_debug_code) { |
2962 Condition is_smi = masm->CheckSmi(rax); | 2963 Condition is_smi = masm->CheckSmi(rax); |
2963 __ Check(NegateCondition(is_smi), | 2964 __ Check(NegateCondition(is_smi), |
2964 "Unexpected type for RegExp data, FixedArray expected"); | 2965 "Unexpected type for RegExp data, FixedArray expected"); |
2965 __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister); | 2966 __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister); |
2966 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); | 2967 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); |
2967 } | 2968 } |
2968 | 2969 |
2969 // rax: RegExp data (FixedArray) | 2970 // rax: RegExp data (FixedArray) |
2970 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | 2971 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
2971 __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset)); | 2972 __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset)); |
2972 __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP)); | 2973 __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP)); |
2973 __ j(not_equal, &runtime); | 2974 __ j(not_equal, &runtime); |
2974 | 2975 |
2975 // rax: RegExp data (FixedArray) | 2976 // rax: RegExp data (FixedArray) |
2976 // Check that the number of captures fit in the static offsets vector buffer. | 2977 // Check that the number of captures fit in the static offsets vector buffer. |
2977 __ SmiToInteger32(rdx, | 2978 __ SmiToInteger32(rdx, |
2978 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset)); | 2979 FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset)); |
2979 // Calculate number of capture registers (number_of_captures + 1) * 2. | 2980 // Check (number_of_captures + 1) * 2 <= offsets vector size |
2980 __ leal(rdx, Operand(rdx, rdx, times_1, 2)); | 2981 // Or number_of_captures <= offsets vector size / 2 - 1 |
2981 // Check that the static offsets vector buffer is large enough. | 2982 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
2982 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize)); | 2983 __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)); |
2983 __ j(above, &runtime); | 2984 __ j(above, &runtime); |
2984 | 2985 |
2985 // rax: RegExp data (FixedArray) | |
2986 // rdx: Number of capture registers | |
2987 // Check that the second argument is a string. | |
2988 __ movq(rdi, Operand(rsp, kSubjectOffset)); | |
2989 __ JumpIfSmi(rdi, &runtime); | |
2990 Condition is_string = masm->IsObjectStringType(rdi, rbx, rbx); | |
2991 __ j(NegateCondition(is_string), &runtime); | |
2992 | |
2993 // rdi: Subject string. | |
2994 // rax: RegExp data (FixedArray). | |
2995 // rdx: Number of capture registers. | |
2996 // Check that the third argument is a positive smi less than the string | |
2997 // length. A negative value will be greater (unsigned comparison). | |
2998 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); | |
2999 __ JumpIfNotSmi(rbx, &runtime); | |
3000 __ SmiCompare(rbx, FieldOperand(rdi, String::kLengthOffset)); | |
3001 __ j(above_equal, &runtime); | |
3002 | |
3003 // rax: RegExp data (FixedArray) | |
3004 // rdx: Number of capture registers | |
3005 // Check that the fourth object is a JSArray object. | |
3006 __ movq(rdi, Operand(rsp, kLastMatchInfoOffset)); | |
3007 __ JumpIfSmi(rdi, &runtime); | |
3008 __ CmpObjectType(rdi, JS_ARRAY_TYPE, kScratchRegister); | |
3009 __ j(not_equal, &runtime); | |
3010 // Check that the JSArray is in fast case. | |
3011 __ movq(rbx, FieldOperand(rdi, JSArray::kElementsOffset)); | |
3012 __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); | |
3013 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | |
3014 Heap::kFixedArrayMapRootIndex); | |
3015 __ j(not_equal, &runtime); | |
3016 // Check that the last match info has space for the capture registers and the | |
3017 // additional information. Ensure no overflow in add. | |
3018 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); | |
3019 __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset)); | |
3020 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); | |
3021 __ cmpl(rdx, rdi); | |
3022 __ j(greater, &runtime); | |
3023 | |
3024 // Reset offset for possibly sliced string. | 2986 // Reset offset for possibly sliced string. |
3025 __ Set(r14, 0); | 2987 __ Set(r14, 0); |
3026 // rax: RegExp data (FixedArray) | |
3027 // Check the representation and encoding of the subject string. | |
3028 Label seq_ascii_string, seq_two_byte_string, check_code; | |
3029 __ movq(rdi, Operand(rsp, kSubjectOffset)); | 2988 __ movq(rdi, Operand(rsp, kSubjectOffset)); |
3030 // Make a copy of the original subject string. | 2989 __ JumpIfSmi(rdi, &runtime); |
3031 __ movq(r15, rdi); | 2990 __ movq(r15, rdi); // Make a copy of the original subject string. |
3032 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 2991 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
3033 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 2992 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
3034 // First check for flat two byte string. | 2993 // rax: RegExp data (FixedArray) |
| 2994 // rdi: subject string |
| 2995 // r15: subject string |
| 2996 // Handle subject string according to its encoding and representation: |
| 2997 // (1) Sequential two byte? If yes, go to (9). |
| 2998 // (2) Sequential one byte? If yes, go to (6). |
| 2999 // (3) Anything but sequential or cons? If yes, go to (7). |
| 3000 // (4) Cons string. If the string is flat, replace subject with first string. |
| 3001 // Otherwise bailout. |
| 3002 // (5a) Is subject sequential two byte? If yes, go to (9). |
| 3003 // (5b) Is subject external? If yes, go to (8). |
| 3004 // (6) One byte sequential. Load regexp code for one byte. |
| 3005 // (E) Carry on. |
| 3006 /// [...] |
| 3007 |
| 3008 // Deferred code at the end of the stub: |
| 3009 // (7) Not a long external string? If yes, go to (10). |
| 3010 // (8) External string. Make it, offset-wise, look like a sequential string. |
| 3011 // (8a) Is the external string one byte? If yes, go to (6). |
| 3012 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). |
| 3013 // (10) Short external string or not a string? If yes, bail out to runtime. |
| 3014 // (11) Sliced string. Replace subject with parent. Go to (5a). |
| 3015 |
| 3016 Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, |
| 3017 external_string /* 8 */, check_underlying /* 5a */, |
| 3018 not_seq_nor_cons /* 7 */, check_code /* E */, |
| 3019 not_long_external /* 10 */; |
| 3020 |
| 3021 // (1) Sequential two byte? If yes, go to (9). |
3035 __ andb(rbx, Immediate(kIsNotStringMask | | 3022 __ andb(rbx, Immediate(kIsNotStringMask | |
3036 kStringRepresentationMask | | 3023 kStringRepresentationMask | |
3037 kStringEncodingMask | | 3024 kStringEncodingMask | |
3038 kShortExternalStringMask)); | 3025 kShortExternalStringMask)); |
3039 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 3026 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
3040 __ j(zero, &seq_two_byte_string, Label::kNear); | 3027 __ j(zero, &seq_two_byte_string); // Go to (9). |
3041 // Any other flat string must be a flat ASCII string. None of the following | 3028 |
3042 // string type tests will succeed if subject is not a string or a short | 3029 // (2) Sequential one byte? If yes, go to (6). |
3043 // external string. | 3030 // Any other sequential string must be one byte. |
3044 __ andb(rbx, Immediate(kIsNotStringMask | | 3031 __ andb(rbx, Immediate(kIsNotStringMask | |
3045 kStringRepresentationMask | | 3032 kStringRepresentationMask | |
3046 kShortExternalStringMask)); | 3033 kShortExternalStringMask)); |
3047 __ j(zero, &seq_ascii_string, Label::kNear); | 3034 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6). |
3048 | 3035 |
3049 // rbx: whether subject is a string and if yes, its string representation | 3036 // (3) Anything but sequential or cons? If yes, go to (7). |
3050 // Check for flat cons string or sliced string. | 3037 // We check whether the subject string is a cons, since sequential strings |
3051 // A flat cons string is a cons string where the second part is the empty | 3038 // have already been covered. |
3052 // string. In that case the subject string is just the first part of the cons | |
3053 // string. Also in this case the first part of the cons string is known to be | |
3054 // a sequential string or an external string. | |
3055 // In the case of a sliced string its offset has to be taken into account. | |
3056 Label cons_string, external_string, check_encoding; | |
3057 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 3039 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
3058 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 3040 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
3059 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 3041 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |
3060 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 3042 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |
3061 __ cmpq(rbx, Immediate(kExternalStringTag)); | 3043 __ cmpq(rbx, Immediate(kExternalStringTag)); |
3062 __ j(less, &cons_string, Label::kNear); | 3044 __ j(greater_equal, ¬_seq_nor_cons); // Go to (7). |
3063 __ j(equal, &external_string); | |
3064 | 3045 |
3065 // Catch non-string subject or short external string. | 3046 // (4) Cons string. Check that it's flat. |
3066 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | 3047 // Replace subject with first string and reload instance type. |
3067 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); | |
3068 __ j(not_zero, &runtime); | |
3069 | |
3070 // String is sliced. | |
3071 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); | |
3072 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); | |
3073 // r14: slice offset | |
3074 // r15: original subject string | |
3075 // rdi: parent string | |
3076 __ jmp(&check_encoding, Label::kNear); | |
3077 // String is a cons string, check whether it is flat. | |
3078 __ bind(&cons_string); | |
3079 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), | 3048 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), |
3080 Heap::kEmptyStringRootIndex); | 3049 Heap::kEmptyStringRootIndex); |
3081 __ j(not_equal, &runtime); | 3050 __ j(not_equal, &runtime); |
3082 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); | 3051 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); |
3083 // rdi: first part of cons string or parent of sliced string. | 3052 __ bind(&check_underlying); |
3084 // rbx: map of first part of cons string or map of parent of sliced string. | |
3085 // Is first part of cons or parent of slice a flat two byte string? | |
3086 __ bind(&check_encoding); | |
3087 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 3053 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
3088 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), | 3054 __ movq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
3089 Immediate(kStringRepresentationMask | kStringEncodingMask)); | 3055 |
| 3056 // (5a) Is subject sequential two byte? If yes, go to (9). |
| 3057 __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); |
3090 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 3058 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
3091 __ j(zero, &seq_two_byte_string, Label::kNear); | 3059 __ j(zero, &seq_two_byte_string); // Go to (9). |
3092 // Any other flat string must be sequential ASCII or external. | 3060 // (5b) Is subject external? If yes, go to (8). |
3093 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), | 3061 __ testb(rbx, Immediate(kStringRepresentationMask)); |
3094 Immediate(kStringRepresentationMask)); | 3062 // The underlying external string is never a short external string. |
3095 __ j(not_zero, &external_string); | 3063 STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength); |
| 3064 STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength); |
| 3065 __ j(not_zero, &external_string); // Go to (8) |
3096 | 3066 |
3097 __ bind(&seq_ascii_string); | 3067 // (6) One byte sequential. Load regexp code for one byte. |
3098 // rdi: subject string (sequential ASCII) | 3068 __ bind(&seq_one_byte_string); |
3099 // rax: RegExp data (FixedArray) | 3069 // rax: RegExp data (FixedArray) |
3100 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); | 3070 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); |
3101 __ Set(rcx, 1); // Type is ASCII. | 3071 __ Set(rcx, 1); // Type is one byte. |
3102 __ jmp(&check_code, Label::kNear); | |
3103 | 3072 |
3104 __ bind(&seq_two_byte_string); | 3073 // (E) Carry on. String handling is done. |
3105 // rdi: subject string (flat two-byte) | |
3106 // rax: RegExp data (FixedArray) | |
3107 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); | |
3108 __ Set(rcx, 0); // Type is two byte. | |
3109 | |
3110 __ bind(&check_code); | 3074 __ bind(&check_code); |
| 3075 // r11: irregexp code |
3111 // Check that the irregexp code has been generated for the actual string | 3076 // Check that the irregexp code has been generated for the actual string |
3112 // encoding. If it has, the field contains a code object otherwise it contains | 3077 // encoding. If it has, the field contains a code object otherwise it contains |
3113 // smi (code flushing support) | 3078 // smi (code flushing support) |
3114 __ JumpIfSmi(r11, &runtime); | 3079 __ JumpIfSmi(r11, &runtime); |
3115 | 3080 |
3116 // rdi: subject string | 3081 // rdi: sequential subject string (or look-alike, external string) |
| 3082 // r15: original subject string |
3117 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte); | 3083 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte); |
3118 // r11: code | 3084 // r11: code |
3119 // Load used arguments before starting to push arguments for call to native | 3085 // Load used arguments before starting to push arguments for call to native |
3120 // RegExp code to avoid handling changing stack height. | 3086 // RegExp code to avoid handling changing stack height. |
3121 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); | 3087 // We have to use r15 instead of rdi to load the length because rdi might |
| 3088 // have been only made to look like a sequential string when it actually |
| 3089 // is an external string. |
| 3090 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); |
| 3091 __ JumpIfNotSmi(rbx, &runtime); |
| 3092 __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset)); |
| 3093 __ j(above_equal, &runtime); |
| 3094 __ SmiToInteger64(rbx, rbx); |
3122 | 3095 |
3123 // rdi: subject string | 3096 // rdi: subject string |
3124 // rbx: previous index | 3097 // rbx: previous index |
3125 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); | 3098 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); |
3126 // r11: code | 3099 // r11: code |
3127 // All checks done. Now push arguments for native regexp code. | 3100 // All checks done. Now push arguments for native regexp code. |
3128 Counters* counters = masm->isolate()->counters(); | 3101 Counters* counters = masm->isolate()->counters(); |
3129 __ IncrementCounter(counters->regexp_entry_native(), 1); | 3102 __ IncrementCounter(counters->regexp_entry_native(), 1); |
3130 | 3103 |
3131 // Isolates: note we add an additional parameter here (isolate pointer). | 3104 // Isolates: note we add an additional parameter here (isolate pointer). |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3250 // Load RegExp data. | 3223 // Load RegExp data. |
3251 __ bind(&success); | 3224 __ bind(&success); |
3252 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 3225 __ movq(rax, Operand(rsp, kJSRegExpOffset)); |
3253 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); | 3226 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); |
3254 __ SmiToInteger32(rax, | 3227 __ SmiToInteger32(rax, |
3255 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | 3228 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); |
3256 // Calculate number of capture registers (number_of_captures + 1) * 2. | 3229 // Calculate number of capture registers (number_of_captures + 1) * 2. |
3257 __ leal(rdx, Operand(rax, rax, times_1, 2)); | 3230 __ leal(rdx, Operand(rax, rax, times_1, 2)); |
3258 | 3231 |
3259 // rdx: Number of capture registers | 3232 // rdx: Number of capture registers |
3260 // Load last_match_info which is still known to be a fast case JSArray. | 3233 // Check that the fourth object is a JSArray object. |
3261 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 3234 __ movq(r15, Operand(rsp, kLastMatchInfoOffset)); |
3262 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); | 3235 __ JumpIfSmi(r15, &runtime); |
| 3236 __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister); |
| 3237 __ j(not_equal, &runtime); |
| 3238 // Check that the JSArray is in fast case. |
| 3239 __ movq(rbx, FieldOperand(r15, JSArray::kElementsOffset)); |
| 3240 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); |
| 3241 __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex); |
| 3242 __ j(not_equal, &runtime); |
| 3243 // Check that the last match info has space for the capture registers and the |
| 3244 // additional information. Ensure no overflow in add. |
| 3245 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); |
| 3246 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); |
| 3247 __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead)); |
| 3248 __ cmpl(rdx, rax); |
| 3249 __ j(greater, &runtime); |
3263 | 3250 |
3264 // rbx: last_match_info backing store (FixedArray) | 3251 // rbx: last_match_info backing store (FixedArray) |
3265 // rdx: number of capture registers | 3252 // rdx: number of capture registers |
3266 // Store the capture count. | 3253 // Store the capture count. |
3267 __ Integer32ToSmi(kScratchRegister, rdx); | 3254 __ Integer32ToSmi(kScratchRegister, rdx); |
3268 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), | 3255 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), |
3269 kScratchRegister); | 3256 kScratchRegister); |
3270 // Store last subject and last input. | 3257 // Store last subject and last input. |
3271 __ movq(rax, Operand(rsp, kSubjectOffset)); | 3258 __ movq(rax, Operand(rsp, kSubjectOffset)); |
3272 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); | 3259 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); |
| 3260 __ movq(rcx, rax); |
3273 __ RecordWriteField(rbx, | 3261 __ RecordWriteField(rbx, |
3274 RegExpImpl::kLastSubjectOffset, | 3262 RegExpImpl::kLastSubjectOffset, |
3275 rax, | 3263 rax, |
3276 rdi, | 3264 rdi, |
3277 kDontSaveFPRegs); | 3265 kDontSaveFPRegs); |
3278 __ movq(rax, Operand(rsp, kSubjectOffset)); | 3266 __ movq(rax, rcx); |
3279 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); | 3267 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); |
3280 __ RecordWriteField(rbx, | 3268 __ RecordWriteField(rbx, |
3281 RegExpImpl::kLastInputOffset, | 3269 RegExpImpl::kLastInputOffset, |
3282 rax, | 3270 rax, |
3283 rdi, | 3271 rdi, |
3284 kDontSaveFPRegs); | 3272 kDontSaveFPRegs); |
3285 | 3273 |
3286 // Get the static offsets vector filled by the native regexp code. | 3274 // Get the static offsets vector filled by the native regexp code. |
3287 __ LoadAddress(rcx, | 3275 __ LoadAddress(rcx, |
3288 ExternalReference::address_of_static_offsets_vector(isolate)); | 3276 ExternalReference::address_of_static_offsets_vector(isolate)); |
(...skipping 13 matching lines...) Expand all Loading... |
3302 // Store the smi value in the last match info. | 3290 // Store the smi value in the last match info. |
3303 __ movq(FieldOperand(rbx, | 3291 __ movq(FieldOperand(rbx, |
3304 rdx, | 3292 rdx, |
3305 times_pointer_size, | 3293 times_pointer_size, |
3306 RegExpImpl::kFirstCaptureOffset), | 3294 RegExpImpl::kFirstCaptureOffset), |
3307 rdi); | 3295 rdi); |
3308 __ jmp(&next_capture); | 3296 __ jmp(&next_capture); |
3309 __ bind(&done); | 3297 __ bind(&done); |
3310 | 3298 |
3311 // Return last match info. | 3299 // Return last match info. |
3312 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 3300 __ movq(rax, r15); |
3313 __ ret(4 * kPointerSize); | 3301 __ ret(4 * kPointerSize); |
3314 | 3302 |
3315 __ bind(&exception); | 3303 __ bind(&exception); |
3316 // Result must now be exception. If there is no pending exception already a | 3304 // Result must now be exception. If there is no pending exception already a |
3317 // stack overflow (on the backtrack stack) was detected in RegExp code but | 3305 // stack overflow (on the backtrack stack) was detected in RegExp code but |
3318 // haven't created the exception yet. Handle that in the runtime system. | 3306 // haven't created the exception yet. Handle that in the runtime system. |
3319 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 3307 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
3320 ExternalReference pending_exception_address( | 3308 ExternalReference pending_exception_address( |
3321 Isolate::kPendingExceptionAddress, isolate); | 3309 Isolate::kPendingExceptionAddress, isolate); |
3322 Operand pending_exception_operand = | 3310 Operand pending_exception_operand = |
3323 masm->ExternalOperand(pending_exception_address, rbx); | 3311 masm->ExternalOperand(pending_exception_address, rbx); |
3324 __ movq(rax, pending_exception_operand); | 3312 __ movq(rax, pending_exception_operand); |
3325 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); | 3313 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); |
3326 __ cmpq(rax, rdx); | 3314 __ cmpq(rax, rdx); |
3327 __ j(equal, &runtime); | 3315 __ j(equal, &runtime); |
3328 __ movq(pending_exception_operand, rdx); | 3316 __ movq(pending_exception_operand, rdx); |
3329 | 3317 |
3330 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); | 3318 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
3331 Label termination_exception; | 3319 Label termination_exception; |
3332 __ j(equal, &termination_exception, Label::kNear); | 3320 __ j(equal, &termination_exception, Label::kNear); |
3333 __ Throw(rax); | 3321 __ Throw(rax); |
3334 | 3322 |
3335 __ bind(&termination_exception); | 3323 __ bind(&termination_exception); |
3336 __ ThrowUncatchable(rax); | 3324 __ ThrowUncatchable(rax); |
3337 | 3325 |
3338 // External string. Short external strings have already been ruled out. | 3326 // Do the runtime call to execute the regexp. |
3339 // rdi: subject string (expected to be external) | 3327 __ bind(&runtime); |
3340 // rbx: scratch | 3328 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 3329 |
| 3330 // Deferred code for string handling. |
| 3331 // (7) Not a long external string? If yes, go to (10). |
| 3332 __ bind(¬_seq_nor_cons); |
| 3333 // Compare flags are still set from (3). |
| 3334 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). |
| 3335 |
| 3336 // (8) External string. Short external strings have been ruled out. |
3341 __ bind(&external_string); | 3337 __ bind(&external_string); |
3342 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 3338 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
3343 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 3339 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
3344 if (FLAG_debug_code) { | 3340 if (FLAG_debug_code) { |
3345 // Assert that we do not have a cons or slice (indirect strings) here. | 3341 // Assert that we do not have a cons or slice (indirect strings) here. |
3346 // Sequential strings have already been ruled out. | 3342 // Sequential strings have already been ruled out. |
3347 __ testb(rbx, Immediate(kIsIndirectStringMask)); | 3343 __ testb(rbx, Immediate(kIsIndirectStringMask)); |
3348 __ Assert(zero, "external string expected, but not found"); | 3344 __ Assert(zero, "external string expected, but not found"); |
3349 } | 3345 } |
3350 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); | 3346 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); |
3351 // Move the pointer so that offset-wise, it looks like a sequential string. | 3347 // Move the pointer so that offset-wise, it looks like a sequential string. |
3352 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 3348 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
3353 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 3349 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
3354 STATIC_ASSERT(kTwoByteStringTag == 0); | 3350 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 3351 // (8a) Is the external string one byte? If yes, go to (6). |
3355 __ testb(rbx, Immediate(kStringEncodingMask)); | 3352 __ testb(rbx, Immediate(kStringEncodingMask)); |
3356 __ j(not_zero, &seq_ascii_string); | 3353 __ j(not_zero, &seq_one_byte_string); // Goto (6). |
3357 __ jmp(&seq_two_byte_string); | |
3358 | 3354 |
3359 // Do the runtime call to execute the regexp. | 3355 // rdi: subject string (flat two-byte) |
3360 __ bind(&runtime); | 3356 // rax: RegExp data (FixedArray) |
3361 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 3357 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). |
| 3358 __ bind(&seq_two_byte_string); |
| 3359 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); |
| 3360 __ Set(rcx, 0); // Type is two byte. |
| 3361 __ jmp(&check_code); // Go to (E). |
| 3362 |
| 3363 // (10) Not a string or a short external string? If yes, bail out to runtime. |
| 3364 __ bind(¬_long_external); |
| 3365 // Catch non-string subject or short external string. |
| 3366 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); |
| 3367 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); |
| 3368 __ j(not_zero, &runtime); |
| 3369 |
| 3370 // (11) Sliced string. Replace subject with parent. Go to (5a). |
| 3371 // Load offset into r14 and replace subject string with parent. |
| 3372 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); |
| 3373 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); |
| 3374 __ jmp(&check_underlying); |
3362 #endif // V8_INTERPRETED_REGEXP | 3375 #endif // V8_INTERPRETED_REGEXP |
3363 } | 3376 } |
3364 | 3377 |
3365 | 3378 |
3366 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 3379 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
3367 const int kMaxInlineLength = 100; | 3380 const int kMaxInlineLength = 100; |
3368 Label slowcase; | 3381 Label slowcase; |
3369 Label done; | 3382 Label done; |
3370 __ movq(r8, Operand(rsp, kPointerSize * 3)); | 3383 __ movq(r8, Operand(rsp, kPointerSize * 3)); |
3371 __ JumpIfNotSmi(r8, &slowcase); | 3384 __ JumpIfNotSmi(r8, &slowcase); |
(...skipping 3340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6712 #endif | 6725 #endif |
6713 | 6726 |
6714 __ Ret(); | 6727 __ Ret(); |
6715 } | 6728 } |
6716 | 6729 |
6717 #undef __ | 6730 #undef __ |
6718 | 6731 |
6719 } } // namespace v8::internal | 6732 } } // namespace v8::internal |
6720 | 6733 |
6721 #endif // V8_TARGET_ARCH_X64 | 6734 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |