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

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: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 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. 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, &not_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
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(&not_seq_nor_cons);
3331 // Compare flags are still set from (3).
3332 __ j(greater, &not_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(&not_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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698