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 5064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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, ¬_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 Loading... |
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 Loading... |
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 Loading... |
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(¬_seq_nor_cons); |
| 5450 // Compare flags are still set. |
| 5451 __ b(gt, ¬_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(¬_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 Loading... |
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 Loading... |
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 |
OLD | NEW |