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 5126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5137 // sp[8]: subject string | 5137 // sp[8]: subject string |
5138 // sp[12]: JSRegExp object | 5138 // sp[12]: JSRegExp object |
5139 | 5139 |
5140 const int kLastMatchInfoOffset = 0 * kPointerSize; | 5140 const int kLastMatchInfoOffset = 0 * kPointerSize; |
5141 const int kPreviousIndexOffset = 1 * kPointerSize; | 5141 const int kPreviousIndexOffset = 1 * kPointerSize; |
5142 const int kSubjectOffset = 2 * kPointerSize; | 5142 const int kSubjectOffset = 2 * kPointerSize; |
5143 const int kJSRegExpOffset = 3 * kPointerSize; | 5143 const int kJSRegExpOffset = 3 * kPointerSize; |
5144 | 5144 |
5145 Isolate* isolate = masm->isolate(); | 5145 Isolate* isolate = masm->isolate(); |
5146 | 5146 |
5147 Label runtime, invoke_regexp; | 5147 Label runtime; |
5148 | |
5149 // Allocation of registers for this function. These are in callee save | 5148 // Allocation of registers for this function. These are in callee save |
5150 // registers and will be preserved by the call to the native RegExp code, as | 5149 // registers and will be preserved by the call to the native RegExp code, as |
5151 // this code is called using the normal C calling convention. When calling | 5150 // this code is called using the normal C calling convention. When calling |
5152 // directly from generated code the native RegExp code will not do a GC and | 5151 // directly from generated code the native RegExp code will not do a GC and |
5153 // therefore the content of these registers are safe to use after the call. | 5152 // therefore the content of these registers are safe to use after the call. |
5154 // MIPS - using s0..s2, since we are not using CEntry Stub. | 5153 // MIPS - using s0..s2, since we are not using CEntry Stub. |
5155 Register subject = s0; | 5154 Register subject = s0; |
5156 Register regexp_data = s1; | 5155 Register regexp_data = s1; |
5157 Register last_match_info_elements = s2; | 5156 Register last_match_info_elements = s2; |
5158 | 5157 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5190 | 5189 |
5191 // regexp_data: RegExp data (FixedArray) | 5190 // regexp_data: RegExp data (FixedArray) |
5192 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | 5191 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
5193 __ lw(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); | 5192 __ lw(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); |
5194 __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); | 5193 __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); |
5195 | 5194 |
5196 // regexp_data: RegExp data (FixedArray) | 5195 // regexp_data: RegExp data (FixedArray) |
5197 // Check that the number of captures fit in the static offsets vector buffer. | 5196 // Check that the number of captures fit in the static offsets vector buffer. |
5198 __ lw(a2, | 5197 __ lw(a2, |
5199 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); | 5198 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); |
5200 // Calculate number of capture registers (number_of_captures + 1) * 2. This | 5199 // Check (number_of_captures + 1) * 2 <= offsets vector size |
5201 // uses the asumption that smis are 2 * their untagged value. | 5200 // Or number_of_captures * 2 <= offsets vector size - 2 |
| 5201 // Multiplying by 2 comes for free since a2 is smi-tagged. |
5202 STATIC_ASSERT(kSmiTag == 0); | 5202 STATIC_ASSERT(kSmiTag == 0); |
5203 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5203 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
5204 __ Addu(a2, a2, Operand(2)); // a2 was a smi. | 5204 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
5205 // Check that the static offsets vector buffer is large enough. | |
5206 __ Branch( | 5205 __ Branch( |
5207 &runtime, hi, a2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize)); | 5206 &runtime, hi, a2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2)); |
5208 | |
5209 // a2: Number of capture registers | |
5210 // regexp_data: RegExp data (FixedArray) | |
5211 // Check that the second argument is a string. | |
5212 __ lw(subject, MemOperand(sp, kSubjectOffset)); | |
5213 __ JumpIfSmi(subject, &runtime); | |
5214 __ GetObjectType(subject, a0, a0); | |
5215 __ And(a0, a0, Operand(kIsNotStringMask)); | |
5216 STATIC_ASSERT(kStringTag == 0); | |
5217 __ Branch(&runtime, ne, a0, Operand(zero_reg)); | |
5218 | |
5219 // Get the length of the string to r3. | |
5220 __ lw(a3, FieldMemOperand(subject, String::kLengthOffset)); | |
5221 | |
5222 // a2: Number of capture registers | |
5223 // a3: Length of subject string as a smi | |
5224 // subject: Subject string | |
5225 // regexp_data: RegExp data (FixedArray) | |
5226 // Check that the third argument is a positive smi less than the subject | |
5227 // string length. A negative value will be greater (unsigned comparison). | |
5228 __ lw(a0, MemOperand(sp, kPreviousIndexOffset)); | |
5229 __ JumpIfNotSmi(a0, &runtime); | |
5230 __ Branch(&runtime, ls, a3, Operand(a0)); | |
5231 | |
5232 // a2: Number of capture registers | |
5233 // subject: Subject string | |
5234 // regexp_data: RegExp data (FixedArray) | |
5235 // Check that the fourth object is a JSArray object. | |
5236 __ lw(a0, MemOperand(sp, kLastMatchInfoOffset)); | |
5237 __ JumpIfSmi(a0, &runtime); | |
5238 __ GetObjectType(a0, a1, a1); | |
5239 __ Branch(&runtime, ne, a1, Operand(JS_ARRAY_TYPE)); | |
5240 // Check that the JSArray is in fast case. | |
5241 __ lw(last_match_info_elements, | |
5242 FieldMemOperand(a0, JSArray::kElementsOffset)); | |
5243 __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); | |
5244 __ Branch(&runtime, ne, a0, Operand( | |
5245 isolate->factory()->fixed_array_map())); | |
5246 // Check that the last match info has space for the capture registers and the | |
5247 // additional information. | |
5248 __ lw(a0, | |
5249 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); | |
5250 __ Addu(a2, a2, Operand(RegExpImpl::kLastMatchOverhead)); | |
5251 __ sra(at, a0, kSmiTagSize); // Untag length for comparison. | |
5252 __ Branch(&runtime, gt, a2, Operand(at)); | |
5253 | 5207 |
5254 // Reset offset for possibly sliced string. | 5208 // Reset offset for possibly sliced string. |
5255 __ mov(t0, zero_reg); | 5209 __ mov(t0, zero_reg); |
5256 // subject: Subject string | 5210 __ lw(subject, MemOperand(sp, kSubjectOffset)); |
5257 // regexp_data: RegExp data (FixedArray) | 5211 __ JumpIfSmi(subject, &runtime); |
5258 // Check the representation and encoding of the subject string. | 5212 __ mov(a3, subject); // Make a copy of the original subject string. |
5259 Label seq_string; | |
5260 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 5213 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
5261 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); | 5214 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); |
5262 // First check for flat string. None of the following string type tests will | 5215 // subject: subject string |
5263 // succeed if subject is not a string or a short external string. | 5216 // a3: subject string |
| 5217 // a0: subject string instance type |
| 5218 // regexp_data: RegExp data (FixedArray) |
| 5219 // Handle subject string according to its encoding and representation: |
| 5220 // (1) Sequential string? If yes, go to (5). |
| 5221 // (2) Anything but sequential or cons? If yes, go to (6). |
| 5222 // (3) Cons string. If the string is flat, replace subject with first string. |
| 5223 // Otherwise bailout. |
| 5224 // (4) Is subject external? If yes, go to (7). |
| 5225 // (5) Sequential string. Load regexp code according to encoding. |
| 5226 // (E) Carry on. |
| 5227 /// [...] |
| 5228 |
| 5229 // Deferred code at the end of the stub: |
| 5230 // (6) Not a long external string? If yes, go to (8). |
| 5231 // (7) External string. Make it, offset-wise, look like a sequential string. |
| 5232 // Go to (5). |
| 5233 // (8) Short external string or not a string? If yes, bail out to runtime. |
| 5234 // (9) Sliced string. Replace subject with parent. Go to (4). |
| 5235 |
| 5236 Label seq_string /* 5 */, external_string /* 7 */, |
| 5237 check_underlying /* 4 */, not_seq_nor_cons /* 6 */, |
| 5238 not_long_external /* 8 */; |
| 5239 |
| 5240 // (1) Sequential string? If yes, go to (5). |
5264 __ And(a1, | 5241 __ And(a1, |
5265 a0, | 5242 a0, |
5266 Operand(kIsNotStringMask | | 5243 Operand(kIsNotStringMask | |
5267 kStringRepresentationMask | | 5244 kStringRepresentationMask | |
5268 kShortExternalStringMask)); | 5245 kShortExternalStringMask)); |
5269 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); | 5246 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); |
5270 __ Branch(&seq_string, eq, a1, Operand(zero_reg)); | 5247 __ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5). |
5271 | 5248 |
5272 // subject: Subject string | 5249 // (2) Anything but sequential or cons? If yes, go to (6). |
5273 // a0: instance type if Subject string | |
5274 // regexp_data: RegExp data (FixedArray) | |
5275 // a1: whether subject is a string and if yes, its string representation | |
5276 // Check for flat cons string or sliced string. | |
5277 // A flat cons string is a cons string where the second part is the empty | |
5278 // string. In that case the subject string is just the first part of the cons | |
5279 // string. Also in this case the first part of the cons string is known to be | |
5280 // a sequential string or an external string. | |
5281 // In the case of a sliced string its offset has to be taken into account. | |
5282 Label cons_string, external_string, check_encoding; | |
5283 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 5250 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
5284 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 5251 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
5285 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 5252 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |
5286 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 5253 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |
5287 __ Branch(&cons_string, lt, a1, Operand(kExternalStringTag)); | 5254 // Go to (6). |
5288 __ Branch(&external_string, eq, a1, Operand(kExternalStringTag)); | 5255 __ Branch(¬_seq_nor_cons, ge, a1, Operand(kExternalStringTag)); |
5289 | 5256 |
5290 // Catch non-string subject or short external string. | 5257 // (3) Cons string. Check that it's flat. |
5291 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); | 5258 // Replace subject with first string and reload instance type. |
5292 __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask)); | |
5293 __ Branch(&runtime, ne, at, Operand(zero_reg)); | |
5294 | |
5295 // String is sliced. | |
5296 __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | |
5297 __ sra(t0, t0, kSmiTagSize); | |
5298 __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | |
5299 // t5: offset of sliced string, smi-tagged. | |
5300 __ jmp(&check_encoding); | |
5301 // String is a cons string, check whether it is flat. | |
5302 __ bind(&cons_string); | |
5303 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); | 5259 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); |
5304 __ LoadRoot(a1, Heap::kEmptyStringRootIndex); | 5260 __ LoadRoot(a1, Heap::kEmptyStringRootIndex); |
5305 __ Branch(&runtime, ne, a0, Operand(a1)); | 5261 __ Branch(&runtime, ne, a0, Operand(a1)); |
5306 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | 5262 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
5307 // Is first part of cons or parent of slice a flat string? | 5263 |
5308 __ bind(&check_encoding); | 5264 // (4) Is subject external? If yes, go to (7). |
| 5265 __ bind(&check_underlying); |
5309 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 5266 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
5310 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); | 5267 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); |
5311 STATIC_ASSERT(kSeqStringTag == 0); | 5268 STATIC_ASSERT(kSeqStringTag == 0); |
5312 __ And(at, a0, Operand(kStringRepresentationMask)); | 5269 __ And(at, a0, Operand(kStringRepresentationMask)); |
5313 __ Branch(&external_string, ne, at, Operand(zero_reg)); | 5270 // The underlying external string is never a short external string. |
| 5271 STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength); |
| 5272 STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength); |
| 5273 __ Branch(&external_string, ne, at, Operand(zero_reg)); // Go to (7). |
5314 | 5274 |
| 5275 // (5) Sequential string. Load regexp code according to encoding. |
5315 __ bind(&seq_string); | 5276 __ bind(&seq_string); |
5316 // subject: Subject string | 5277 // subject: sequential subject string (or look-alike, external string) |
5317 // regexp_data: RegExp data (FixedArray) | 5278 // a3: original subject string |
5318 // a0: Instance type of subject string | 5279 // Load previous index and check range before a3 is overwritten. We have to |
| 5280 // use a3 instead of subject here because subject might have been only made |
| 5281 // to look like a sequential string when it actually is an external string. |
| 5282 __ lw(a1, MemOperand(sp, kPreviousIndexOffset)); |
| 5283 __ JumpIfNotSmi(a1, &runtime); |
| 5284 __ lw(a3, FieldMemOperand(a3, String::kLengthOffset)); |
| 5285 __ Branch(&runtime, ls, a3, Operand(a1)); |
| 5286 __ sra(a1, a1, kSmiTagSize); // Untag the Smi. |
| 5287 |
5319 STATIC_ASSERT(kStringEncodingMask == 4); | 5288 STATIC_ASSERT(kStringEncodingMask == 4); |
5320 STATIC_ASSERT(kOneByteStringTag == 4); | 5289 STATIC_ASSERT(kOneByteStringTag == 4); |
5321 STATIC_ASSERT(kTwoByteStringTag == 0); | 5290 STATIC_ASSERT(kTwoByteStringTag == 0); |
5322 // Find the code object based on the assumptions above. | |
5323 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ASCII. | 5291 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ASCII. |
5324 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); | 5292 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); |
5325 __ sra(a3, a0, 2); // a3 is 1 for ASCII, 0 for UC16 (used below). | 5293 __ sra(a3, a0, 2); // a3 is 1 for ASCII, 0 for UC16 (used below). |
5326 __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); | 5294 __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); |
5327 __ Movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. | 5295 __ Movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. |
5328 | 5296 |
| 5297 // (E) Carry on. String handling is done. |
| 5298 // t9: irregexp code |
5329 // Check that the irregexp code has been generated for the actual string | 5299 // Check that the irregexp code has been generated for the actual string |
5330 // encoding. If it has, the field contains a code object otherwise it contains | 5300 // encoding. If it has, the field contains a code object otherwise it contains |
5331 // a smi (code flushing support). | 5301 // a smi (code flushing support). |
5332 __ JumpIfSmi(t9, &runtime); | 5302 __ JumpIfSmi(t9, &runtime); |
5333 | 5303 |
5334 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); | |
5335 // t9: code | |
5336 // subject: Subject string | |
5337 // regexp_data: RegExp data (FixedArray) | |
5338 // Load used arguments before starting to push arguments for call to native | |
5339 // RegExp code to avoid handling changing stack height. | |
5340 __ lw(a1, MemOperand(sp, kPreviousIndexOffset)); | |
5341 __ sra(a1, a1, kSmiTagSize); // Untag the Smi. | |
5342 | |
5343 // a1: previous index | 5304 // a1: previous index |
5344 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); | 5305 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); |
5345 // t9: code | 5306 // t9: code |
5346 // subject: Subject string | 5307 // subject: Subject string |
5347 // regexp_data: RegExp data (FixedArray) | 5308 // regexp_data: RegExp data (FixedArray) |
5348 // All checks done. Now push arguments for native regexp code. | 5309 // All checks done. Now push arguments for native regexp code. |
5349 __ IncrementCounter(isolate->counters()->regexp_entry_native(), | 5310 __ IncrementCounter(isolate->counters()->regexp_entry_native(), |
5350 1, a0, a2); | 5311 1, a0, a2); |
5351 | 5312 |
5352 // Isolates: note we add an additional parameter here (isolate pointer). | 5313 // Isolates: note we add an additional parameter here (isolate pointer). |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5427 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); | 5388 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); |
5428 DirectCEntryStub stub; | 5389 DirectCEntryStub stub; |
5429 stub.GenerateCall(masm, t9); | 5390 stub.GenerateCall(masm, t9); |
5430 | 5391 |
5431 __ LeaveExitFrame(false, no_reg); | 5392 __ LeaveExitFrame(false, no_reg); |
5432 | 5393 |
5433 // v0: result | 5394 // v0: result |
5434 // subject: subject string (callee saved) | 5395 // subject: subject string (callee saved) |
5435 // regexp_data: RegExp data (callee saved) | 5396 // regexp_data: RegExp data (callee saved) |
5436 // last_match_info_elements: Last match info elements (callee saved) | 5397 // last_match_info_elements: Last match info elements (callee saved) |
5437 | |
5438 // Check the result. | 5398 // Check the result. |
5439 | |
5440 Label success; | 5399 Label success; |
5441 __ Branch(&success, eq, v0, Operand(1)); | 5400 __ Branch(&success, eq, v0, Operand(1)); |
5442 // We expect exactly one result since we force the called regexp to behave | 5401 // We expect exactly one result since we force the called regexp to behave |
5443 // as non-global. | 5402 // as non-global. |
5444 Label failure; | 5403 Label failure; |
5445 __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE)); | 5404 __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE)); |
5446 // If not exception it can only be retry. Handle that in the runtime system. | 5405 // If not exception it can only be retry. Handle that in the runtime system. |
5447 __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); | 5406 __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); |
5448 // Result must now be exception. If there is no pending exception already a | 5407 // Result must now be exception. If there is no pending exception already a |
5449 // stack overflow (on the backtrack stack) was detected in RegExp code but | 5408 // stack overflow (on the backtrack stack) was detected in RegExp code but |
(...skipping 20 matching lines...) Expand all Loading... |
5470 __ bind(&failure); | 5429 __ bind(&failure); |
5471 // For failure and exception return null. | 5430 // For failure and exception return null. |
5472 __ li(v0, Operand(isolate->factory()->null_value())); | 5431 __ li(v0, Operand(isolate->factory()->null_value())); |
5473 __ DropAndRet(4); | 5432 __ DropAndRet(4); |
5474 | 5433 |
5475 // Process the result from the native regexp code. | 5434 // Process the result from the native regexp code. |
5476 __ bind(&success); | 5435 __ bind(&success); |
5477 __ lw(a1, | 5436 __ lw(a1, |
5478 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); | 5437 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); |
5479 // Calculate number of capture registers (number_of_captures + 1) * 2. | 5438 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 5439 // Multiplying by 2 comes for free since r1 is smi-tagged. |
5480 STATIC_ASSERT(kSmiTag == 0); | 5440 STATIC_ASSERT(kSmiTag == 0); |
5481 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5441 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
5482 __ Addu(a1, a1, Operand(2)); // a1 was a smi. | 5442 __ Addu(a1, a1, Operand(2)); // a1 was a smi. |
5483 | 5443 |
| 5444 __ lw(a0, MemOperand(sp, kLastMatchInfoOffset)); |
| 5445 __ JumpIfSmi(a0, &runtime); |
| 5446 __ GetObjectType(a0, a2, a2); |
| 5447 __ Branch(&runtime, ne, a2, Operand(JS_ARRAY_TYPE)); |
| 5448 // Check that the JSArray is in fast case. |
| 5449 __ lw(last_match_info_elements, |
| 5450 FieldMemOperand(a0, JSArray::kElementsOffset)); |
| 5451 __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); |
| 5452 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); |
| 5453 __ Branch(&runtime, ne, a0, Operand(at)); |
| 5454 // Check that the last match info has space for the capture registers and the |
| 5455 // additional information. |
| 5456 __ lw(a0, |
| 5457 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); |
| 5458 __ Addu(a2, a1, Operand(RegExpImpl::kLastMatchOverhead)); |
| 5459 __ sra(at, a0, kSmiTagSize); |
| 5460 __ Branch(&runtime, gt, a2, Operand(at)); |
| 5461 |
5484 // a1: number of capture registers | 5462 // a1: number of capture registers |
5485 // subject: subject string | 5463 // subject: subject string |
5486 // Store the capture count. | 5464 // Store the capture count. |
5487 __ sll(a2, a1, kSmiTagSize + kSmiShiftSize); // To smi. | 5465 __ sll(a2, a1, kSmiTagSize + kSmiShiftSize); // To smi. |
5488 __ sw(a2, FieldMemOperand(last_match_info_elements, | 5466 __ sw(a2, FieldMemOperand(last_match_info_elements, |
5489 RegExpImpl::kLastCaptureCountOffset)); | 5467 RegExpImpl::kLastCaptureCountOffset)); |
5490 // Store last subject and last input. | 5468 // Store last subject and last input. |
5491 __ sw(subject, | 5469 __ sw(subject, |
5492 FieldMemOperand(last_match_info_elements, | 5470 FieldMemOperand(last_match_info_elements, |
5493 RegExpImpl::kLastSubjectOffset)); | 5471 RegExpImpl::kLastSubjectOffset)); |
5494 __ mov(a2, subject); | 5472 __ mov(a2, subject); |
5495 __ RecordWriteField(last_match_info_elements, | 5473 __ RecordWriteField(last_match_info_elements, |
5496 RegExpImpl::kLastSubjectOffset, | 5474 RegExpImpl::kLastSubjectOffset, |
5497 a2, | 5475 subject, |
5498 t3, | 5476 t3, |
5499 kRAHasNotBeenSaved, | 5477 kRAHasNotBeenSaved, |
5500 kDontSaveFPRegs); | 5478 kDontSaveFPRegs); |
| 5479 __ mov(subject, a2); |
5501 __ sw(subject, | 5480 __ sw(subject, |
5502 FieldMemOperand(last_match_info_elements, | 5481 FieldMemOperand(last_match_info_elements, |
5503 RegExpImpl::kLastInputOffset)); | 5482 RegExpImpl::kLastInputOffset)); |
5504 __ RecordWriteField(last_match_info_elements, | 5483 __ RecordWriteField(last_match_info_elements, |
5505 RegExpImpl::kLastInputOffset, | 5484 RegExpImpl::kLastInputOffset, |
5506 subject, | 5485 subject, |
5507 t3, | 5486 t3, |
5508 kRAHasNotBeenSaved, | 5487 kRAHasNotBeenSaved, |
5509 kDontSaveFPRegs); | 5488 kDontSaveFPRegs); |
5510 | 5489 |
(...skipping 21 matching lines...) Expand all Loading... |
5532 __ sw(a3, MemOperand(a0, 0)); | 5511 __ sw(a3, MemOperand(a0, 0)); |
5533 __ Branch(&next_capture, USE_DELAY_SLOT); | 5512 __ Branch(&next_capture, USE_DELAY_SLOT); |
5534 __ addiu(a0, a0, kPointerSize); // In branch delay slot. | 5513 __ addiu(a0, a0, kPointerSize); // In branch delay slot. |
5535 | 5514 |
5536 __ bind(&done); | 5515 __ bind(&done); |
5537 | 5516 |
5538 // Return last match info. | 5517 // Return last match info. |
5539 __ lw(v0, MemOperand(sp, kLastMatchInfoOffset)); | 5518 __ lw(v0, MemOperand(sp, kLastMatchInfoOffset)); |
5540 __ DropAndRet(4); | 5519 __ DropAndRet(4); |
5541 | 5520 |
5542 // External string. Short external strings have already been ruled out. | 5521 // Do the runtime call to execute the regexp. |
5543 // a0: scratch | 5522 __ bind(&runtime); |
| 5523 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 5524 |
| 5525 // Deferred code for string handling. |
| 5526 // (6) Not a long external string? If yes, go to (8). |
| 5527 __ bind(¬_seq_nor_cons); |
| 5528 // Go to (8). |
| 5529 __ Branch(¬_long_external, gt, a1, Operand(kExternalStringTag)); |
| 5530 |
| 5531 // (7) External string. Make it, offset-wise, look like a sequential string. |
5544 __ bind(&external_string); | 5532 __ bind(&external_string); |
5545 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 5533 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
5546 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); | 5534 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); |
5547 if (FLAG_debug_code) { | 5535 if (FLAG_debug_code) { |
5548 // Assert that we do not have a cons or slice (indirect strings) here. | 5536 // Assert that we do not have a cons or slice (indirect strings) here. |
5549 // Sequential strings have already been ruled out. | 5537 // Sequential strings have already been ruled out. |
5550 __ And(at, a0, Operand(kIsIndirectStringMask)); | 5538 __ And(at, a0, Operand(kIsIndirectStringMask)); |
5551 __ Assert(eq, | 5539 __ Assert(eq, |
5552 "external string expected, but not found", | 5540 "external string expected, but not found", |
5553 at, | 5541 at, |
5554 Operand(zero_reg)); | 5542 Operand(zero_reg)); |
5555 } | 5543 } |
5556 __ lw(subject, | 5544 __ lw(subject, |
5557 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); | 5545 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); |
5558 // Move the pointer so that offset-wise, it looks like a sequential string. | 5546 // Move the pointer so that offset-wise, it looks like a sequential string. |
5559 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 5547 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
5560 __ Subu(subject, | 5548 __ Subu(subject, |
5561 subject, | 5549 subject, |
5562 SeqTwoByteString::kHeaderSize - kHeapObjectTag); | 5550 SeqTwoByteString::kHeaderSize - kHeapObjectTag); |
5563 __ jmp(&seq_string); | 5551 __ jmp(&seq_string); // Go to (5). |
5564 | 5552 |
5565 // Do the runtime call to execute the regexp. | 5553 // (8) Short external string or not a string? If yes, bail out to runtime. |
5566 __ bind(&runtime); | 5554 __ bind(¬_long_external); |
5567 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 5555 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); |
| 5556 __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask)); |
| 5557 __ Branch(&runtime, ne, at, Operand(zero_reg)); |
| 5558 |
| 5559 // (9) Sliced string. Replace subject with parent. Go to (4). |
| 5560 // Load offset into t0 and replace subject string with parent. |
| 5561 __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 5562 __ sra(t0, t0, kSmiTagSize); |
| 5563 __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 5564 __ jmp(&check_underlying); // Go to (4). |
5568 #endif // V8_INTERPRETED_REGEXP | 5565 #endif // V8_INTERPRETED_REGEXP |
5569 } | 5566 } |
5570 | 5567 |
5571 | 5568 |
5572 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 5569 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
5573 const int kMaxInlineLength = 100; | 5570 const int kMaxInlineLength = 100; |
5574 Label slowcase; | 5571 Label slowcase; |
5575 Label done; | 5572 Label done; |
5576 __ lw(a1, MemOperand(sp, kPointerSize * 2)); | 5573 __ lw(a1, MemOperand(sp, kPointerSize * 2)); |
5577 STATIC_ASSERT(kSmiTag == 0); | 5574 STATIC_ASSERT(kSmiTag == 0); |
(...skipping 2058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7636 struct AheadOfTimeWriteBarrierStubList { | 7633 struct AheadOfTimeWriteBarrierStubList { |
7637 Register object, value, address; | 7634 Register object, value, address; |
7638 RememberedSetAction action; | 7635 RememberedSetAction action; |
7639 }; | 7636 }; |
7640 | 7637 |
7641 #define REG(Name) { kRegister_ ## Name ## _Code } | 7638 #define REG(Name) { kRegister_ ## Name ## _Code } |
7642 | 7639 |
7643 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { | 7640 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { |
7644 // Used in RegExpExecStub. | 7641 // Used in RegExpExecStub. |
7645 { REG(s2), REG(s0), REG(t3), EMIT_REMEMBERED_SET }, | 7642 { REG(s2), REG(s0), REG(t3), EMIT_REMEMBERED_SET }, |
7646 { REG(s2), REG(a2), REG(t3), EMIT_REMEMBERED_SET }, | |
7647 // Used in CompileArrayPushCall. | 7643 // Used in CompileArrayPushCall. |
7648 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. | 7644 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. |
7649 // Also used in KeyedStoreIC::GenerateGeneric. | 7645 // Also used in KeyedStoreIC::GenerateGeneric. |
7650 { REG(a3), REG(t0), REG(t1), EMIT_REMEMBERED_SET }, | 7646 { REG(a3), REG(t0), REG(t1), EMIT_REMEMBERED_SET }, |
7651 // Used in CompileStoreGlobal. | 7647 // Used in CompileStoreGlobal. |
7652 { REG(t0), REG(a1), REG(a2), OMIT_REMEMBERED_SET }, | 7648 { REG(t0), REG(a1), REG(a2), OMIT_REMEMBERED_SET }, |
7653 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. | 7649 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. |
7654 { REG(a1), REG(a2), REG(a3), EMIT_REMEMBERED_SET }, | 7650 { REG(a1), REG(a2), REG(a3), EMIT_REMEMBERED_SET }, |
7655 { REG(a3), REG(a2), REG(a1), EMIT_REMEMBERED_SET }, | 7651 { REG(a3), REG(a2), REG(a1), EMIT_REMEMBERED_SET }, |
7656 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. | 7652 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8061 __ Pop(ra, t1, a1); | 8057 __ Pop(ra, t1, a1); |
8062 __ Ret(); | 8058 __ Ret(); |
8063 } | 8059 } |
8064 | 8060 |
8065 | 8061 |
8066 #undef __ | 8062 #undef __ |
8067 | 8063 |
8068 } } // namespace v8::internal | 8064 } } // namespace v8::internal |
8069 | 8065 |
8070 #endif // V8_TARGET_ARCH_MIPS | 8066 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |