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

Side by Side Diff: src/arm/code-stubs-arm.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 | « no previous file | src/ia32/code-stubs-ia32.cc » ('j') | 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 5064 matching lines...) Expand 10 before | Expand all | Expand 10 after
5075 // sp[0]: last_match_info (expected JSArray) 5075 // sp[0]: last_match_info (expected JSArray)
5076 // sp[4]: previous index 5076 // sp[4]: previous index
5077 // sp[8]: subject string 5077 // sp[8]: subject string
5078 // sp[12]: JSRegExp object 5078 // sp[12]: JSRegExp object
5079 5079
5080 const int kLastMatchInfoOffset = 0 * kPointerSize; 5080 const int kLastMatchInfoOffset = 0 * kPointerSize;
5081 const int kPreviousIndexOffset = 1 * kPointerSize; 5081 const int kPreviousIndexOffset = 1 * kPointerSize;
5082 const int kSubjectOffset = 2 * kPointerSize; 5082 const int kSubjectOffset = 2 * kPointerSize;
5083 const int kJSRegExpOffset = 3 * kPointerSize; 5083 const int kJSRegExpOffset = 3 * kPointerSize;
5084 5084
5085 Label runtime, invoke_regexp; 5085 Label runtime;
5086
5087 // Allocation of registers for this function. These are in callee save 5086 // Allocation of registers for this function. These are in callee save
5088 // registers and will be preserved by the call to the native RegExp code, as 5087 // registers and will be preserved by the call to the native RegExp code, as
5089 // this code is called using the normal C calling convention. When calling 5088 // this code is called using the normal C calling convention. When calling
5090 // directly from generated code the native RegExp code will not do a GC and 5089 // directly from generated code the native RegExp code will not do a GC and
5091 // therefore the content of these registers are safe to use after the call. 5090 // therefore the content of these registers are safe to use after the call.
5092 Register subject = r4; 5091 Register subject = r4;
5093 Register regexp_data = r5; 5092 Register regexp_data = r5;
5094 Register last_match_info_elements = r6; 5093 Register last_match_info_elements = r6;
5095 5094
5096 // Ensure that a RegExp stack is allocated. 5095 // Ensure that a RegExp stack is allocated.
(...skipping 26 matching lines...) Expand all
5123 // regexp_data: RegExp data (FixedArray) 5122 // regexp_data: RegExp data (FixedArray)
5124 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 5123 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
5125 __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); 5124 __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
5126 __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); 5125 __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
5127 __ b(ne, &runtime); 5126 __ b(ne, &runtime);
5128 5127
5129 // regexp_data: RegExp data (FixedArray) 5128 // regexp_data: RegExp data (FixedArray)
5130 // Check that the number of captures fit in the static offsets vector buffer. 5129 // Check that the number of captures fit in the static offsets vector buffer.
5131 __ ldr(r2, 5130 __ ldr(r2,
5132 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 5131 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
5133 // Calculate number of capture registers (number_of_captures + 1) * 2. This 5132 // Check (number_of_captures + 1) * 2 <= offsets vector size
5134 // uses the asumption that smis are 2 * their untagged value. 5133 // Or number_of_captures * 2 <= offsets vector size - 2
5134 // Multiplying by 2 comes for free since r2 is smi-tagged.
5135 STATIC_ASSERT(kSmiTag == 0); 5135 STATIC_ASSERT(kSmiTag == 0);
5136 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 5136 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
5137 __ add(r2, r2, Operand(2)); // r2 was a smi. 5137 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
5138 // Check that the static offsets vector buffer is large enough. 5138 __ cmp(r2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
5139 __ cmp(r2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize));
5140 __ b(hi, &runtime); 5139 __ b(hi, &runtime);
5141 5140
5142 // r2: Number of capture registers
5143 // regexp_data: RegExp data (FixedArray)
5144 // Check that the second argument is a string.
5145 __ ldr(subject, MemOperand(sp, kSubjectOffset));
5146 __ JumpIfSmi(subject, &runtime);
5147 Condition is_string = masm->IsObjectStringType(subject, r0);
5148 __ b(NegateCondition(is_string), &runtime);
5149 // Get the length of the string to r3.
5150 __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset));
5151
5152 // r2: Number of capture registers
5153 // r3: Length of subject string as a smi
5154 // subject: Subject string
5155 // regexp_data: RegExp data (FixedArray)
5156 // Check that the third argument is a positive smi less than the subject
5157 // string length. A negative value will be greater (unsigned comparison).
5158 __ ldr(r0, MemOperand(sp, kPreviousIndexOffset));
5159 __ JumpIfNotSmi(r0, &runtime);
5160 __ cmp(r3, Operand(r0));
5161 __ b(ls, &runtime);
5162
5163 // r2: Number of capture registers
5164 // subject: Subject string
5165 // regexp_data: RegExp data (FixedArray)
5166 // Check that the fourth object is a JSArray object.
5167 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
5168 __ JumpIfSmi(r0, &runtime);
5169 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
5170 __ b(ne, &runtime);
5171 // Check that the JSArray is in fast case.
5172 __ ldr(last_match_info_elements,
5173 FieldMemOperand(r0, JSArray::kElementsOffset));
5174 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
5175 __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex);
5176 __ b(ne, &runtime);
5177 // Check that the last match info has space for the capture registers and the
5178 // additional information.
5179 __ ldr(r0,
5180 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
5181 __ add(r2, r2, Operand(RegExpImpl::kLastMatchOverhead));
5182 __ cmp(r2, Operand(r0, ASR, kSmiTagSize));
5183 __ b(gt, &runtime);
5184
5185 // Reset offset for possibly sliced string. 5141 // Reset offset for possibly sliced string.
5186 __ mov(r9, Operand::Zero()); 5142 __ mov(r9, Operand::Zero());
5187 // subject: Subject string 5143 __ ldr(subject, MemOperand(sp, kSubjectOffset));
5188 // regexp_data: RegExp data (FixedArray) 5144 __ JumpIfSmi(subject, &runtime);
5189 // Check the representation and encoding of the subject string. 5145 __ mov(r3, subject); // Make a copy of the original subject string.
5190 Label seq_string;
5191 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 5146 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
5192 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 5147 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
5193 // First check for flat string. None of the following string type tests will 5148 // subject: subject string
5194 // succeed if subject is not a string or a short external string. 5149 // r3: subject string
5150 // r0: subject string instance type
5151 // regexp_data: RegExp data (FixedArray)
5152 // Handle subject string according to its encoding and representation:
5153 // (1) Sequential string? If yes, go to (5).
5154 // (2) Anything but sequential or cons? If yes, go to (6).
5155 // (3) Cons string. If the string is flat, replace subject with first string.
5156 // Otherwise bailout.
5157 // (4) Is subject external? If yes, go to (7).
5158 // (5) Sequential string. Load regexp code according to encoding.
5159 // (E) Carry on.
5160 /// [...]
5161
5162 // Deferred code at the end of the stub:
5163 // (6) Not a long external string? If yes, go to (8).
5164 // (7) External string. Make it, offset-wise, look like a sequential string.
5165 // Go to (5).
5166 // (8) Short external string or not a string? If yes, bail out to runtime.
5167 // (9) Sliced string. Replace subject with parent. Go to (4).
5168
5169 Label seq_string /* 5 */, external_string /* 7 */,
5170 check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
5171 not_long_external /* 8 */;
5172
5173 // (1) Sequential string? If yes, go to (5).
5195 __ and_(r1, 5174 __ and_(r1,
5196 r0, 5175 r0,
5197 Operand(kIsNotStringMask | 5176 Operand(kIsNotStringMask |
5198 kStringRepresentationMask | 5177 kStringRepresentationMask |
5199 kShortExternalStringMask), 5178 kShortExternalStringMask),
5200 SetCC); 5179 SetCC);
5201 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 5180 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
5202 __ b(eq, &seq_string); 5181 __ b(eq, &seq_string); // Go to (5).
5203 5182
5204 // subject: Subject string 5183 // (2) Anything but sequential or cons? If yes, go to (6).
5205 // regexp_data: RegExp data (FixedArray)
5206 // r1: whether subject is a string and if yes, its string representation
5207 // Check for flat cons string or sliced string.
5208 // A flat cons string is a cons string where the second part is the empty
5209 // string. In that case the subject string is just the first part of the cons
5210 // string. Also in this case the first part of the cons string is known to be
5211 // a sequential string or an external string.
5212 // In the case of a sliced string its offset has to be taken into account.
5213 Label cons_string, external_string, check_encoding;
5214 STATIC_ASSERT(kConsStringTag < kExternalStringTag); 5184 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
5215 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 5185 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
5216 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 5186 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
5217 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 5187 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
5218 __ cmp(r1, Operand(kExternalStringTag)); 5188 __ cmp(r1, Operand(kExternalStringTag));
5219 __ b(lt, &cons_string); 5189 __ b(ge, &not_seq_nor_cons); // Go to (6).
5220 __ b(eq, &external_string);
5221 5190
5222 // Catch non-string subject or short external string. 5191 // (3) Cons string. Check that it's flat.
5223 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 5192 // Replace subject with first string and reload instance type.
5224 __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask));
5225 __ b(ne, &runtime);
5226
5227 // String is sliced.
5228 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset));
5229 __ mov(r9, Operand(r9, ASR, kSmiTagSize));
5230 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
5231 // r9: offset of sliced string, smi-tagged.
5232 __ jmp(&check_encoding);
5233 // String is a cons string, check whether it is flat.
5234 __ bind(&cons_string);
5235 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); 5193 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset));
5236 __ CompareRoot(r0, Heap::kEmptyStringRootIndex); 5194 __ CompareRoot(r0, Heap::kEmptyStringRootIndex);
5237 __ b(ne, &runtime); 5195 __ b(ne, &runtime);
5238 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 5196 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
5239 // Is first part of cons or parent of slice a flat string? 5197
5240 __ bind(&check_encoding); 5198 // (4) Is subject external? If yes, go to (7).
5199 __ bind(&check_underlying);
5241 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 5200 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
5242 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 5201 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
5243 STATIC_ASSERT(kSeqStringTag == 0); 5202 STATIC_ASSERT(kSeqStringTag == 0);
5244 __ tst(r0, Operand(kStringRepresentationMask)); 5203 __ tst(r0, Operand(kStringRepresentationMask));
5245 __ b(ne, &external_string); 5204 // The underlying external string is never a short external string.
5205 STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
5206 STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
5207 __ b(ne, &external_string); // Go to (7).
5246 5208
5209 // (5) Sequential string. Load regexp code according to encoding.
5247 __ bind(&seq_string); 5210 __ bind(&seq_string);
5248 // subject: Subject string 5211 // subject: sequential subject string (or look-alike, external string)
5249 // regexp_data: RegExp data (FixedArray) 5212 // r3: original subject string
5250 // r0: Instance type of subject string 5213 // Load previous index and check range before r3 is overwritten. We have to
5214 // use r3 instead of subject here because subject might have been only made
5215 // to look like a sequential string when it actually is an external string.
5216 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset));
5217 __ JumpIfNotSmi(r1, &runtime);
5218 __ ldr(r3, FieldMemOperand(r3, String::kLengthOffset));
5219 __ cmp(r3, Operand(r1));
5220 __ b(ls, &runtime);
5221 __ mov(r1, Operand(r1, ASR, kSmiTagSize));
5222
5251 STATIC_ASSERT(4 == kOneByteStringTag); 5223 STATIC_ASSERT(4 == kOneByteStringTag);
5252 STATIC_ASSERT(kTwoByteStringTag == 0); 5224 STATIC_ASSERT(kTwoByteStringTag == 0);
5253 // Find the code object based on the assumptions above.
5254 __ and_(r0, r0, Operand(kStringEncodingMask)); 5225 __ and_(r0, r0, Operand(kStringEncodingMask));
5255 __ mov(r3, Operand(r0, ASR, 2), SetCC); 5226 __ mov(r3, Operand(r0, ASR, 2), SetCC);
5256 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); 5227 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne);
5257 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); 5228 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
5258 5229
5230 // (E) Carry on. String handling is done.
5231 // r7: irregexp code
5259 // Check that the irregexp code has been generated for the actual string 5232 // Check that the irregexp code has been generated for the actual string
5260 // encoding. If it has, the field contains a code object otherwise it contains 5233 // encoding. If it has, the field contains a code object otherwise it contains
5261 // a smi (code flushing support). 5234 // a smi (code flushing support).
5262 __ JumpIfSmi(r7, &runtime); 5235 __ JumpIfSmi(r7, &runtime);
5263 5236
5264 // r3: encoding of subject string (1 if ASCII, 0 if two_byte);
5265 // r7: code
5266 // subject: Subject string
5267 // regexp_data: RegExp data (FixedArray)
5268 // Load used arguments before starting to push arguments for call to native
5269 // RegExp code to avoid handling changing stack height.
5270 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset));
5271 __ mov(r1, Operand(r1, ASR, kSmiTagSize));
5272
5273 // r1: previous index 5237 // r1: previous index
5274 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); 5238 // r3: encoding of subject string (1 if ASCII, 0 if two_byte);
5275 // r7: code 5239 // r7: code
5276 // subject: Subject string 5240 // subject: Subject string
5277 // regexp_data: RegExp data (FixedArray) 5241 // regexp_data: RegExp data (FixedArray)
5278 // All checks done. Now push arguments for native regexp code. 5242 // All checks done. Now push arguments for native regexp code.
5279 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2); 5243 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2);
5280 5244
5281 // Isolates: note we add an additional parameter here (isolate pointer). 5245 // Isolates: note we add an additional parameter here (isolate pointer).
5282 const int kRegExpExecuteArguments = 9; 5246 const int kRegExpExecuteArguments = 9;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
5342 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); 5306 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
5343 DirectCEntryStub stub; 5307 DirectCEntryStub stub;
5344 stub.GenerateCall(masm, r7); 5308 stub.GenerateCall(masm, r7);
5345 5309
5346 __ LeaveExitFrame(false, no_reg); 5310 __ LeaveExitFrame(false, no_reg);
5347 5311
5348 // r0: result 5312 // r0: result
5349 // subject: subject string (callee saved) 5313 // subject: subject string (callee saved)
5350 // regexp_data: RegExp data (callee saved) 5314 // regexp_data: RegExp data (callee saved)
5351 // last_match_info_elements: Last match info elements (callee saved) 5315 // last_match_info_elements: Last match info elements (callee saved)
5352
5353 // Check the result. 5316 // Check the result.
5354 Label success; 5317 Label success;
5355
5356 __ cmp(r0, Operand(1)); 5318 __ cmp(r0, Operand(1));
5357 // We expect exactly one result since we force the called regexp to behave 5319 // We expect exactly one result since we force the called regexp to behave
5358 // as non-global. 5320 // as non-global.
5359 __ b(eq, &success); 5321 __ b(eq, &success);
5360 Label failure; 5322 Label failure;
5361 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); 5323 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE));
5362 __ b(eq, &failure); 5324 __ b(eq, &failure);
5363 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 5325 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
5364 // If not exception it can only be retry. Handle that in the runtime system. 5326 // If not exception it can only be retry. Handle that in the runtime system.
5365 __ b(ne, &runtime); 5327 __ b(ne, &runtime);
(...skipping 25 matching lines...) Expand all
5391 // For failure and exception return null. 5353 // For failure and exception return null.
5392 __ mov(r0, Operand(masm->isolate()->factory()->null_value())); 5354 __ mov(r0, Operand(masm->isolate()->factory()->null_value()));
5393 __ add(sp, sp, Operand(4 * kPointerSize)); 5355 __ add(sp, sp, Operand(4 * kPointerSize));
5394 __ Ret(); 5356 __ Ret();
5395 5357
5396 // Process the result from the native regexp code. 5358 // Process the result from the native regexp code.
5397 __ bind(&success); 5359 __ bind(&success);
5398 __ ldr(r1, 5360 __ ldr(r1,
5399 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 5361 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
5400 // Calculate number of capture registers (number_of_captures + 1) * 2. 5362 // Calculate number of capture registers (number_of_captures + 1) * 2.
5363 // Multiplying by 2 comes for free since r1 is smi-tagged.
5401 STATIC_ASSERT(kSmiTag == 0); 5364 STATIC_ASSERT(kSmiTag == 0);
5402 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 5365 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
5403 __ add(r1, r1, Operand(2)); // r1 was a smi. 5366 __ add(r1, r1, Operand(2)); // r1 was a smi.
5404 5367
5368 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
5369 __ JumpIfSmi(r0, &runtime);
5370 __ CompareObjectType(r0, r2, r2, JS_ARRAY_TYPE);
5371 __ b(ne, &runtime);
5372 // Check that the JSArray is in fast case.
5373 __ ldr(last_match_info_elements,
5374 FieldMemOperand(r0, JSArray::kElementsOffset));
5375 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
5376 __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex);
5377 __ b(ne, &runtime);
5378 // Check that the last match info has space for the capture registers and the
5379 // additional information.
5380 __ ldr(r0,
5381 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
5382 __ add(r2, r1, Operand(RegExpImpl::kLastMatchOverhead));
5383 __ cmp(r2, Operand(r0, ASR, kSmiTagSize));
5384 __ b(gt, &runtime);
5385
5405 // r1: number of capture registers 5386 // r1: number of capture registers
5406 // r4: subject string 5387 // r4: subject string
5407 // Store the capture count. 5388 // Store the capture count.
5408 __ mov(r2, Operand(r1, LSL, kSmiTagSize + kSmiShiftSize)); // To smi. 5389 __ mov(r2, Operand(r1, LSL, kSmiTagSize + kSmiShiftSize)); // To smi.
5409 __ str(r2, FieldMemOperand(last_match_info_elements, 5390 __ str(r2, FieldMemOperand(last_match_info_elements,
5410 RegExpImpl::kLastCaptureCountOffset)); 5391 RegExpImpl::kLastCaptureCountOffset));
5411 // Store last subject and last input. 5392 // Store last subject and last input.
5412 __ str(subject, 5393 __ str(subject,
5413 FieldMemOperand(last_match_info_elements, 5394 FieldMemOperand(last_match_info_elements,
5414 RegExpImpl::kLastSubjectOffset)); 5395 RegExpImpl::kLastSubjectOffset));
5415 __ mov(r2, subject); 5396 __ mov(r2, subject);
5416 __ RecordWriteField(last_match_info_elements, 5397 __ RecordWriteField(last_match_info_elements,
5417 RegExpImpl::kLastSubjectOffset, 5398 RegExpImpl::kLastSubjectOffset,
5418 r2, 5399 subject,
5419 r7, 5400 r7,
5420 kLRHasNotBeenSaved, 5401 kLRHasNotBeenSaved,
5421 kDontSaveFPRegs); 5402 kDontSaveFPRegs);
5403 __ mov(subject, r2);
5422 __ str(subject, 5404 __ str(subject,
5423 FieldMemOperand(last_match_info_elements, 5405 FieldMemOperand(last_match_info_elements,
5424 RegExpImpl::kLastInputOffset)); 5406 RegExpImpl::kLastInputOffset));
5425 __ RecordWriteField(last_match_info_elements, 5407 __ RecordWriteField(last_match_info_elements,
5426 RegExpImpl::kLastInputOffset, 5408 RegExpImpl::kLastInputOffset,
5427 subject, 5409 subject,
5428 r7, 5410 r7,
5429 kLRHasNotBeenSaved, 5411 kLRHasNotBeenSaved,
5430 kDontSaveFPRegs); 5412 kDontSaveFPRegs);
5431 5413
(...skipping 19 matching lines...) Expand all
5451 __ mov(r3, Operand(r3, LSL, kSmiTagSize)); 5433 __ mov(r3, Operand(r3, LSL, kSmiTagSize));
5452 __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); 5434 __ str(r3, MemOperand(r0, kPointerSize, PostIndex));
5453 __ jmp(&next_capture); 5435 __ jmp(&next_capture);
5454 __ bind(&done); 5436 __ bind(&done);
5455 5437
5456 // Return last match info. 5438 // Return last match info.
5457 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); 5439 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
5458 __ add(sp, sp, Operand(4 * kPointerSize)); 5440 __ add(sp, sp, Operand(4 * kPointerSize));
5459 __ Ret(); 5441 __ Ret();
5460 5442
5461 // External string. Short external strings have already been ruled out. 5443 // Do the runtime call to execute the regexp.
5462 // r0: scratch 5444 __ bind(&runtime);
5445 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
5446
5447 // Deferred code for string handling.
5448 // (6) Not a long external string? If yes, go to (8).
5449 __ bind(&not_seq_nor_cons);
5450 // Compare flags are still set.
5451 __ b(gt, &not_long_external); // Go to (8).
5452
5453 // (7) External string. Make it, offset-wise, look like a sequential string.
5463 __ bind(&external_string); 5454 __ bind(&external_string);
5464 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 5455 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
5465 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 5456 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
5466 if (FLAG_debug_code) { 5457 if (FLAG_debug_code) {
5467 // Assert that we do not have a cons or slice (indirect strings) here. 5458 // Assert that we do not have a cons or slice (indirect strings) here.
5468 // Sequential strings have already been ruled out. 5459 // Sequential strings have already been ruled out.
5469 __ tst(r0, Operand(kIsIndirectStringMask)); 5460 __ tst(r0, Operand(kIsIndirectStringMask));
5470 __ Assert(eq, "external string expected, but not found"); 5461 __ Assert(eq, "external string expected, but not found");
5471 } 5462 }
5472 __ ldr(subject, 5463 __ ldr(subject,
5473 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); 5464 FieldMemOperand(subject, ExternalString::kResourceDataOffset));
5474 // Move the pointer so that offset-wise, it looks like a sequential string. 5465 // Move the pointer so that offset-wise, it looks like a sequential string.
5475 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 5466 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
5476 __ sub(subject, 5467 __ sub(subject,
5477 subject, 5468 subject,
5478 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 5469 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5479 __ jmp(&seq_string); 5470 __ jmp(&seq_string); // Go to (5).
5480 5471
5481 // Do the runtime call to execute the regexp. 5472 // (8) Short external string or not a string? If yes, bail out to runtime.
5482 __ bind(&runtime); 5473 __ bind(&not_long_external);
5483 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 5474 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
5475 __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask));
5476 __ b(ne, &runtime);
5477
5478 // (9) Sliced string. Replace subject with parent. Go to (4).
5479 // Load offset into r9 and replace subject string with parent.
5480 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset));
5481 __ mov(r9, Operand(r9, ASR, kSmiTagSize));
5482 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
5483 __ jmp(&check_underlying); // Go to (4).
5484 #endif // V8_INTERPRETED_REGEXP 5484 #endif // V8_INTERPRETED_REGEXP
5485 } 5485 }
5486 5486
5487 5487
5488 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { 5488 void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
5489 const int kMaxInlineLength = 100; 5489 const int kMaxInlineLength = 100;
5490 Label slowcase; 5490 Label slowcase;
5491 Label done; 5491 Label done;
5492 Factory* factory = masm->isolate()->factory(); 5492 Factory* factory = masm->isolate()->factory();
5493 5493
(...skipping 2031 matching lines...) Expand 10 before | Expand all | Expand 10 after
7525 struct AheadOfTimeWriteBarrierStubList { 7525 struct AheadOfTimeWriteBarrierStubList {
7526 Register object, value, address; 7526 Register object, value, address;
7527 RememberedSetAction action; 7527 RememberedSetAction action;
7528 }; 7528 };
7529 7529
7530 #define REG(Name) { kRegister_ ## Name ## _Code } 7530 #define REG(Name) { kRegister_ ## Name ## _Code }
7531 7531
7532 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { 7532 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
7533 // Used in RegExpExecStub. 7533 // Used in RegExpExecStub.
7534 { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET }, 7534 { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET },
7535 { REG(r6), REG(r2), REG(r7), EMIT_REMEMBERED_SET },
7536 // Used in CompileArrayPushCall. 7535 // Used in CompileArrayPushCall.
7537 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. 7536 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
7538 // Also used in KeyedStoreIC::GenerateGeneric. 7537 // Also used in KeyedStoreIC::GenerateGeneric.
7539 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET }, 7538 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET },
7540 // Used in CompileStoreGlobal. 7539 // Used in CompileStoreGlobal.
7541 { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET }, 7540 { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET },
7542 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. 7541 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField.
7543 { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET }, 7542 { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET },
7544 { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET }, 7543 { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET },
7545 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. 7544 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField.
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
7946 7945
7947 __ Pop(lr, r5, r1); 7946 __ Pop(lr, r5, r1);
7948 __ Ret(); 7947 __ Ret();
7949 } 7948 }
7950 7949
7951 #undef __ 7950 #undef __
7952 7951
7953 } } // namespace v8::internal 7952 } } // namespace v8::internal
7954 7953
7955 #endif // V8_TARGET_ARCH_ARM 7954 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698