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. Replace subject with first string. |
| 3001 // (5a) Is subject two byte? If yes, go to (9). |
| 3002 // (5b) Is subject external? If yes, go to (8). |
| 3003 // (6) One byte sequential. Load regexp code for one byte. |
| 3004 // (E) Carry on. |
| 3005 /// [...] |
| 3006 |
| 3007 // Deferred code at the end of the stub: |
| 3008 // (7) Not a long external string? If yes, go to (10). |
| 3009 // (8) External string. Make it, offset-wise, look like a sequential string. |
| 3010 // (8a) Is the external string one byte? If yes, go to (6). |
| 3011 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). |
| 3012 // (10) Short external string or not a string? If yes, bail out to runtime. |
| 3013 // (11) Sliced string. Replace subject with parent. Go to (5a). |
| 3014 |
| 3015 Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */, |
| 3016 external_string /* 8 */, check_underlying /* 5a */, |
| 3017 not_seq_nor_cons /* 7 */, check_code /* E */, |
| 3018 not_long_external /* 10 */; |
| 3019 |
| 3020 // (1) Sequential two byte? If yes, go to (9). |
3035 __ andb(rbx, Immediate(kIsNotStringMask | | 3021 __ andb(rbx, Immediate(kIsNotStringMask | |
3036 kStringRepresentationMask | | 3022 kStringRepresentationMask | |
3037 kStringEncodingMask | | 3023 kStringEncodingMask | |
3038 kShortExternalStringMask)); | 3024 kShortExternalStringMask)); |
3039 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); | 3025 STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); |
3040 __ j(zero, &seq_two_byte_string, Label::kNear); | 3026 __ j(zero, &seq_two_byte_string); // Go to (9). |
3041 // Any other flat string must be a flat ASCII string. None of the following | 3027 |
3042 // string type tests will succeed if subject is not a string or a short | 3028 // (2) Sequential one byte? If yes, go to (6). |
3043 // external string. | 3029 // Any other sequential string must be one byte. |
3044 __ andb(rbx, Immediate(kIsNotStringMask | | 3030 __ andb(rbx, Immediate(kIsNotStringMask | |
3045 kStringRepresentationMask | | 3031 kStringRepresentationMask | |
3046 kShortExternalStringMask)); | 3032 kShortExternalStringMask)); |
3047 __ j(zero, &seq_ascii_string, Label::kNear); | 3033 __ j(zero, &seq_one_byte_string, Label::kNear); // Go to (6). |
3048 | 3034 |
3049 // rbx: whether subject is a string and if yes, its string representation | 3035 // (3) Anything but sequential or cons? If yes, go to (7). |
3050 // Check for flat cons string or sliced string. | 3036 // 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 | 3037 // 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); | 3038 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
3058 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 3039 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
3059 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 3040 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |
3060 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 3041 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |
3061 __ cmpq(rbx, Immediate(kExternalStringTag)); | 3042 __ cmpq(rbx, Immediate(kExternalStringTag)); |
3062 __ j(less, &cons_string, Label::kNear); | 3043 __ j(greater_equal, ¬_seq_nor_cons); // Go to (7). |
3063 __ j(equal, &external_string); | |
3064 | 3044 |
3065 // Catch non-string subject or short external string. | 3045 // (4) Cons string. Check that it's flat. |
3066 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | 3046 // 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), | 3047 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), |
3080 Heap::kEmptyStringRootIndex); | 3048 Heap::kEmptyStringRootIndex); |
3081 __ j(not_equal, &runtime); | 3049 __ j(not_equal, &runtime); |
3082 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); | 3050 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); |
3083 // rdi: first part of cons string or parent of sliced string. | 3051 __ 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)); | 3052 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
3088 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), | 3053 __ movq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
3089 Immediate(kStringRepresentationMask | kStringEncodingMask)); | 3054 |
| 3055 // (5a) Is subject two byte? If yes, go to (9). |
| 3056 __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); |
3090 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 3057 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
3091 __ j(zero, &seq_two_byte_string, Label::kNear); | 3058 __ j(zero, &seq_two_byte_string); // Go to (9). |
3092 // Any other flat string must be sequential ASCII or external. | 3059 // (5b) Is subject external? If yes, go to (8). |
3093 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), | 3060 __ testb(rbx, Immediate(kStringRepresentationMask)); |
3094 Immediate(kStringRepresentationMask)); | 3061 // The underlying external string is never a short external string. |
3095 __ j(not_zero, &external_string); | 3062 STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength); |
| 3063 STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength); |
| 3064 __ j(not_zero, &external_string); // Go to (8) |
3096 | 3065 |
3097 __ bind(&seq_ascii_string); | 3066 // (6) One byte sequential. Load regexp code for one byte. |
3098 // rdi: subject string (sequential ASCII) | 3067 __ bind(&seq_one_byte_string); |
3099 // rax: RegExp data (FixedArray) | 3068 // rax: RegExp data (FixedArray) |
3100 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); | 3069 __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset)); |
3101 __ Set(rcx, 1); // Type is ASCII. | 3070 __ Set(rcx, 1); // Type is one byte. |
3102 __ jmp(&check_code, Label::kNear); | |
3103 | 3071 |
3104 __ bind(&seq_two_byte_string); | 3072 // (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); | 3073 __ bind(&check_code); |
| 3074 // r11: irregexp code |
3111 // Check that the irregexp code has been generated for the actual string | 3075 // 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 | 3076 // encoding. If it has, the field contains a code object otherwise it contains |
3113 // smi (code flushing support) | 3077 // smi (code flushing support) |
3114 __ JumpIfSmi(r11, &runtime); | 3078 __ JumpIfSmi(r11, &runtime); |
3115 | 3079 |
3116 // rdi: subject string | 3080 // rdi: sequential subject string (or look-alike, external string) |
| 3081 // r15: original subject string |
3117 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte); | 3082 // rcx: encoding of subject string (1 if ASCII, 0 if two_byte); |
3118 // r11: code | 3083 // r11: code |
3119 // Load used arguments before starting to push arguments for call to native | 3084 // Load used arguments before starting to push arguments for call to native |
3120 // RegExp code to avoid handling changing stack height. | 3085 // RegExp code to avoid handling changing stack height. |
3121 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); | 3086 // We have to use r15 instead of rdi to load the length because rdi might |
| 3087 // have been only made to look like a sequential string when it actually |
| 3088 // is an external string. |
| 3089 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); |
| 3090 __ JumpIfNotSmi(rbx, &runtime); |
| 3091 __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset)); |
| 3092 __ j(above_equal, &runtime); |
| 3093 __ SmiToInteger64(rbx, rbx); |
3122 | 3094 |
3123 // rdi: subject string | 3095 // rdi: subject string |
3124 // rbx: previous index | 3096 // rbx: previous index |
3125 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); | 3097 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); |
3126 // r11: code | 3098 // r11: code |
3127 // All checks done. Now push arguments for native regexp code. | 3099 // All checks done. Now push arguments for native regexp code. |
3128 Counters* counters = masm->isolate()->counters(); | 3100 Counters* counters = masm->isolate()->counters(); |
3129 __ IncrementCounter(counters->regexp_entry_native(), 1); | 3101 __ IncrementCounter(counters->regexp_entry_native(), 1); |
3130 | 3102 |
3131 // Isolates: note we add an additional parameter here (isolate pointer). | 3103 // 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. | 3222 // Load RegExp data. |
3251 __ bind(&success); | 3223 __ bind(&success); |
3252 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 3224 __ movq(rax, Operand(rsp, kJSRegExpOffset)); |
3253 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); | 3225 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); |
3254 __ SmiToInteger32(rax, | 3226 __ SmiToInteger32(rax, |
3255 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | 3227 FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); |
3256 // Calculate number of capture registers (number_of_captures + 1) * 2. | 3228 // Calculate number of capture registers (number_of_captures + 1) * 2. |
3257 __ leal(rdx, Operand(rax, rax, times_1, 2)); | 3229 __ leal(rdx, Operand(rax, rax, times_1, 2)); |
3258 | 3230 |
3259 // rdx: Number of capture registers | 3231 // rdx: Number of capture registers |
3260 // Load last_match_info which is still known to be a fast case JSArray. | 3232 // Check that the fourth object is a JSArray object. |
3261 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 3233 __ movq(r15, Operand(rsp, kLastMatchInfoOffset)); |
3262 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); | 3234 __ JumpIfSmi(r15, &runtime); |
| 3235 __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister); |
| 3236 __ j(not_equal, &runtime); |
| 3237 // Check that the JSArray is in fast case. |
| 3238 __ movq(rbx, FieldOperand(r15, JSArray::kElementsOffset)); |
| 3239 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); |
| 3240 __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex); |
| 3241 __ j(not_equal, &runtime); |
| 3242 // Check that the last match info has space for the capture registers and the |
| 3243 // additional information. Ensure no overflow in add. |
| 3244 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); |
| 3245 __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); |
| 3246 __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead)); |
| 3247 __ cmpl(rdx, rax); |
| 3248 __ j(greater, &runtime); |
3263 | 3249 |
3264 // rbx: last_match_info backing store (FixedArray) | 3250 // rbx: last_match_info backing store (FixedArray) |
3265 // rdx: number of capture registers | 3251 // rdx: number of capture registers |
3266 // Store the capture count. | 3252 // Store the capture count. |
3267 __ Integer32ToSmi(kScratchRegister, rdx); | 3253 __ Integer32ToSmi(kScratchRegister, rdx); |
3268 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), | 3254 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), |
3269 kScratchRegister); | 3255 kScratchRegister); |
3270 // Store last subject and last input. | 3256 // Store last subject and last input. |
3271 __ movq(rax, Operand(rsp, kSubjectOffset)); | 3257 __ movq(rax, Operand(rsp, kSubjectOffset)); |
3272 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); | 3258 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); |
| 3259 __ movq(rcx, rax); |
3273 __ RecordWriteField(rbx, | 3260 __ RecordWriteField(rbx, |
3274 RegExpImpl::kLastSubjectOffset, | 3261 RegExpImpl::kLastSubjectOffset, |
3275 rax, | 3262 rax, |
3276 rdi, | 3263 rdi, |
3277 kDontSaveFPRegs); | 3264 kDontSaveFPRegs); |
3278 __ movq(rax, Operand(rsp, kSubjectOffset)); | 3265 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rcx); |
3279 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); | |
3280 __ RecordWriteField(rbx, | 3266 __ RecordWriteField(rbx, |
3281 RegExpImpl::kLastInputOffset, | 3267 RegExpImpl::kLastInputOffset, |
3282 rax, | 3268 rcx, |
3283 rdi, | 3269 rdi, |
3284 kDontSaveFPRegs); | 3270 kDontSaveFPRegs); |
3285 | 3271 |
3286 // Get the static offsets vector filled by the native regexp code. | 3272 // Get the static offsets vector filled by the native regexp code. |
3287 __ LoadAddress(rcx, | 3273 __ LoadAddress(rcx, |
3288 ExternalReference::address_of_static_offsets_vector(isolate)); | 3274 ExternalReference::address_of_static_offsets_vector(isolate)); |
3289 | 3275 |
3290 // rbx: last_match_info backing store (FixedArray) | 3276 // rbx: last_match_info backing store (FixedArray) |
3291 // rcx: offsets vector | 3277 // rcx: offsets vector |
3292 // rdx: number of capture registers | 3278 // rdx: number of capture registers |
3293 Label next_capture, done; | 3279 Label next_capture, done; |
3294 // Capture register counter starts from number of capture registers and | 3280 // Capture register counter starts from number of capture registers and |
3295 // counts down until wraping after zero. | 3281 // counts down until wraping after zero. |
3296 __ bind(&next_capture); | 3282 __ bind(&next_capture); |
3297 __ subq(rdx, Immediate(1)); | 3283 __ subq(rdx, Immediate(1)); |
3298 __ j(negative, &done, Label::kNear); | 3284 __ j(negative, &done, Label::kNear); |
3299 // Read the value from the static offsets vector buffer and make it a smi. | 3285 // Read the value from the static offsets vector buffer and make it a smi. |
3300 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0)); | 3286 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0)); |
3301 __ Integer32ToSmi(rdi, rdi); | 3287 __ Integer32ToSmi(rdi, rdi); |
3302 // Store the smi value in the last match info. | 3288 // Store the smi value in the last match info. |
3303 __ movq(FieldOperand(rbx, | 3289 __ movq(FieldOperand(rbx, |
3304 rdx, | 3290 rdx, |
3305 times_pointer_size, | 3291 times_pointer_size, |
3306 RegExpImpl::kFirstCaptureOffset), | 3292 RegExpImpl::kFirstCaptureOffset), |
3307 rdi); | 3293 rdi); |
3308 __ jmp(&next_capture); | 3294 __ jmp(&next_capture); |
3309 __ bind(&done); | 3295 __ bind(&done); |
3310 | 3296 |
3311 // Return last match info. | 3297 // Return last match info. |
3312 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 3298 __ movq(rax, r15); |
3313 __ ret(4 * kPointerSize); | 3299 __ ret(4 * kPointerSize); |
3314 | 3300 |
3315 __ bind(&exception); | 3301 __ bind(&exception); |
3316 // Result must now be exception. If there is no pending exception already a | 3302 // 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 | 3303 // 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. | 3304 // haven't created the exception yet. Handle that in the runtime system. |
3319 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 3305 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
3320 ExternalReference pending_exception_address( | 3306 ExternalReference pending_exception_address( |
3321 Isolate::kPendingExceptionAddress, isolate); | 3307 Isolate::kPendingExceptionAddress, isolate); |
3322 Operand pending_exception_operand = | 3308 Operand pending_exception_operand = |
3323 masm->ExternalOperand(pending_exception_address, rbx); | 3309 masm->ExternalOperand(pending_exception_address, rbx); |
3324 __ movq(rax, pending_exception_operand); | 3310 __ movq(rax, pending_exception_operand); |
3325 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); | 3311 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); |
3326 __ cmpq(rax, rdx); | 3312 __ cmpq(rax, rdx); |
3327 __ j(equal, &runtime); | 3313 __ j(equal, &runtime); |
3328 __ movq(pending_exception_operand, rdx); | 3314 __ movq(pending_exception_operand, rdx); |
3329 | 3315 |
3330 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); | 3316 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
3331 Label termination_exception; | 3317 Label termination_exception; |
3332 __ j(equal, &termination_exception, Label::kNear); | 3318 __ j(equal, &termination_exception, Label::kNear); |
3333 __ Throw(rax); | 3319 __ Throw(rax); |
3334 | 3320 |
3335 __ bind(&termination_exception); | 3321 __ bind(&termination_exception); |
3336 __ ThrowUncatchable(rax); | 3322 __ ThrowUncatchable(rax); |
3337 | 3323 |
3338 // External string. Short external strings have already been ruled out. | 3324 // Do the runtime call to execute the regexp. |
3339 // rdi: subject string (expected to be external) | 3325 __ bind(&runtime); |
3340 // rbx: scratch | 3326 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 3327 |
| 3328 // Deferred code for string handling. |
| 3329 // (7) Not a long external string? If yes, go to (10). |
| 3330 __ bind(¬_seq_nor_cons); |
| 3331 // Compare flags are still set from (3). |
| 3332 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). |
| 3333 |
| 3334 // (8) External string. Short external strings have been ruled out. |
3341 __ bind(&external_string); | 3335 __ bind(&external_string); |
3342 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 3336 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
3343 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 3337 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
3344 if (FLAG_debug_code) { | 3338 if (FLAG_debug_code) { |
3345 // Assert that we do not have a cons or slice (indirect strings) here. | 3339 // Assert that we do not have a cons or slice (indirect strings) here. |
3346 // Sequential strings have already been ruled out. | 3340 // Sequential strings have already been ruled out. |
3347 __ testb(rbx, Immediate(kIsIndirectStringMask)); | 3341 __ testb(rbx, Immediate(kIsIndirectStringMask)); |
3348 __ Assert(zero, "external string expected, but not found"); | 3342 __ Assert(zero, "external string expected, but not found"); |
3349 } | 3343 } |
3350 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); | 3344 __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset)); |
3351 // Move the pointer so that offset-wise, it looks like a sequential string. | 3345 // Move the pointer so that offset-wise, it looks like a sequential string. |
3352 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 3346 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
3353 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 3347 __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
3354 STATIC_ASSERT(kTwoByteStringTag == 0); | 3348 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 3349 // (8a) Is the external string one byte? If yes, go to (6). |
3355 __ testb(rbx, Immediate(kStringEncodingMask)); | 3350 __ testb(rbx, Immediate(kStringEncodingMask)); |
3356 __ j(not_zero, &seq_ascii_string); | 3351 __ j(not_zero, &seq_one_byte_string); // Goto (6). |
3357 __ jmp(&seq_two_byte_string); | |
3358 | 3352 |
3359 // Do the runtime call to execute the regexp. | 3353 // rdi: subject string (flat two-byte) |
3360 __ bind(&runtime); | 3354 // rax: RegExp data (FixedArray) |
3361 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 3355 // (9) Two byte sequential. Load regexp code for one byte. Go to (E). |
| 3356 __ bind(&seq_two_byte_string); |
| 3357 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); |
| 3358 __ Set(rcx, 0); // Type is two byte. |
| 3359 __ jmp(&check_code); // Go to (E). |
| 3360 |
| 3361 // (10) Not a string or a short external string? If yes, bail out to runtime. |
| 3362 __ bind(¬_long_external); |
| 3363 // Catch non-string subject or short external string. |
| 3364 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); |
| 3365 __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask)); |
| 3366 __ j(not_zero, &runtime); |
| 3367 |
| 3368 // (11) Sliced string. Replace subject with parent. Go to (5a). |
| 3369 // Load offset into r14 and replace subject string with parent. |
| 3370 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); |
| 3371 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); |
| 3372 __ jmp(&check_underlying); |
3362 #endif // V8_INTERPRETED_REGEXP | 3373 #endif // V8_INTERPRETED_REGEXP |
3363 } | 3374 } |
3364 | 3375 |
3365 | 3376 |
3366 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 3377 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
3367 const int kMaxInlineLength = 100; | 3378 const int kMaxInlineLength = 100; |
3368 Label slowcase; | 3379 Label slowcase; |
3369 Label done; | 3380 Label done; |
3370 __ movq(r8, Operand(rsp, kPointerSize * 3)); | 3381 __ movq(r8, Operand(rsp, kPointerSize * 3)); |
3371 __ JumpIfNotSmi(r8, &slowcase); | 3382 __ JumpIfNotSmi(r8, &slowcase); |
(...skipping 2887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6259 Register object, value, address; | 6270 Register object, value, address; |
6260 RememberedSetAction action; | 6271 RememberedSetAction action; |
6261 }; | 6272 }; |
6262 | 6273 |
6263 | 6274 |
6264 #define REG(Name) { kRegister_ ## Name ## _Code } | 6275 #define REG(Name) { kRegister_ ## Name ## _Code } |
6265 | 6276 |
6266 struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { | 6277 struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { |
6267 // Used in RegExpExecStub. | 6278 // Used in RegExpExecStub. |
6268 { REG(rbx), REG(rax), REG(rdi), EMIT_REMEMBERED_SET }, | 6279 { REG(rbx), REG(rax), REG(rdi), EMIT_REMEMBERED_SET }, |
| 6280 { REG(rbx), REG(rcx), REG(rdi), EMIT_REMEMBERED_SET }, |
6269 // Used in CompileArrayPushCall. | 6281 // Used in CompileArrayPushCall. |
6270 { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET }, | 6282 { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET }, |
6271 // Used in CompileStoreGlobal. | 6283 // Used in CompileStoreGlobal. |
6272 { REG(rbx), REG(rcx), REG(rdx), OMIT_REMEMBERED_SET }, | 6284 { REG(rbx), REG(rcx), REG(rdx), OMIT_REMEMBERED_SET }, |
6273 // Used in StoreStubCompiler::CompileStoreField and | 6285 // Used in StoreStubCompiler::CompileStoreField and |
6274 // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. | 6286 // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. |
6275 { REG(rdx), REG(rcx), REG(rbx), EMIT_REMEMBERED_SET }, | 6287 { REG(rdx), REG(rcx), REG(rbx), EMIT_REMEMBERED_SET }, |
6276 // GenerateStoreField calls the stub with two different permutations of | 6288 // GenerateStoreField calls the stub with two different permutations of |
6277 // registers. This is the second. | 6289 // registers. This is the second. |
6278 { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET }, | 6290 { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET }, |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6712 #endif | 6724 #endif |
6713 | 6725 |
6714 __ Ret(); | 6726 __ Ret(); |
6715 } | 6727 } |
6716 | 6728 |
6717 #undef __ | 6729 #undef __ |
6718 | 6730 |
6719 } } // namespace v8::internal | 6731 } } // namespace v8::internal |
6720 | 6732 |
6721 #endif // V8_TARGET_ARCH_X64 | 6733 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |