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

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

Issue 12210143: Refactor RegExpStub to check lazily. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: addressed comments 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
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2938 matching lines...) Expand 10 before | Expand all | Expand 10 after
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, &not_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
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
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(&not_seq_nor_cons);
3333 // Compare flags are still set from (3).
3334 __ j(greater, &not_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(&not_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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698