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

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

Issue 2738413002: [regexp] Port RegExpExecStub to CSA (mostly) (Closed)
Patch Set: Rebase Created 3 years, 9 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
« no previous file with comments | « src/interface-descriptors.cc ('k') | src/mips/interface-descriptors-mips.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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_MIPS 5 #if V8_TARGET_ARCH_MIPS
6 6
7 #include "src/code-stubs.h" 7 #include "src/code-stubs.h"
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after
1265 // Restore callee-saved fpu registers. 1265 // Restore callee-saved fpu registers.
1266 __ MultiPopFPU(kCalleeSavedFPU); 1266 __ MultiPopFPU(kCalleeSavedFPU);
1267 1267
1268 // Restore callee saved registers from the stack. 1268 // Restore callee saved registers from the stack.
1269 __ MultiPop(kCalleeSaved | ra.bit()); 1269 __ MultiPop(kCalleeSaved | ra.bit());
1270 // Return. 1270 // Return.
1271 __ Jump(ra); 1271 __ Jump(ra);
1272 } 1272 }
1273 1273
1274 void RegExpExecStub::Generate(MacroAssembler* masm) { 1274 void RegExpExecStub::Generate(MacroAssembler* masm) {
1275 // Just jump directly to runtime if native RegExp is not selected at compile
1276 // time or if regexp entry in generated code is turned off runtime switch or
1277 // at compilation.
1278 #ifdef V8_INTERPRETED_REGEXP 1275 #ifdef V8_INTERPRETED_REGEXP
1279 __ TailCallRuntime(Runtime::kRegExpExec); 1276 // This case is handled prior to the RegExpExecStub call.
1277 __ Abort(kUnexpectedRegExpExecCall);
1280 #else // V8_INTERPRETED_REGEXP 1278 #else // V8_INTERPRETED_REGEXP
1281
1282 // Stack frame on entry.
1283 // sp[0]: last_match_info (expected JSArray)
1284 // sp[4]: previous index
1285 // sp[8]: subject string
1286 // sp[12]: JSRegExp object
1287
1288 const int kLastMatchInfoOffset = 0 * kPointerSize;
1289 const int kPreviousIndexOffset = 1 * kPointerSize;
1290 const int kSubjectOffset = 2 * kPointerSize;
1291 const int kJSRegExpOffset = 3 * kPointerSize;
1292
1293 Label runtime;
1294 // Allocation of registers for this function. These are in callee save
1295 // registers and will be preserved by the call to the native RegExp code, as
1296 // this code is called using the normal C calling convention. When calling
1297 // directly from generated code the native RegExp code will not do a GC and
1298 // therefore the content of these registers are safe to use after the call.
1299 // MIPS - using s0..s2, since we are not using CEntry Stub.
1300 Register subject = s0;
1301 Register regexp_data = s1;
1302 Register last_match_info_elements = s2;
1303
1304 // Ensure that a RegExp stack is allocated.
1305 ExternalReference address_of_regexp_stack_memory_address =
1306 ExternalReference::address_of_regexp_stack_memory_address(isolate());
1307 ExternalReference address_of_regexp_stack_memory_size =
1308 ExternalReference::address_of_regexp_stack_memory_size(isolate());
1309 __ li(a0, Operand(address_of_regexp_stack_memory_size));
1310 __ lw(a0, MemOperand(a0, 0));
1311 __ Branch(&runtime, eq, a0, Operand(zero_reg));
1312
1313 // Check that the first argument is a JSRegExp object.
1314 __ lw(a0, MemOperand(sp, kJSRegExpOffset));
1315 STATIC_ASSERT(kSmiTag == 0);
1316 __ JumpIfSmi(a0, &runtime);
1317 __ GetObjectType(a0, a1, a1);
1318 __ Branch(&runtime, ne, a1, Operand(JS_REGEXP_TYPE));
1319
1320 // Check that the RegExp has been compiled (data contains a fixed array).
1321 __ lw(regexp_data, FieldMemOperand(a0, JSRegExp::kDataOffset));
1322 if (FLAG_debug_code) {
1323 __ SmiTst(regexp_data, t0);
1324 __ Check(nz,
1325 kUnexpectedTypeForRegExpDataFixedArrayExpected,
1326 t0,
1327 Operand(zero_reg));
1328 __ GetObjectType(regexp_data, a0, a0);
1329 __ Check(eq,
1330 kUnexpectedTypeForRegExpDataFixedArrayExpected,
1331 a0,
1332 Operand(FIXED_ARRAY_TYPE));
1333 }
1334
1335 // regexp_data: RegExp data (FixedArray)
1336 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
1337 __ lw(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
1338 __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
1339
1340 // regexp_data: RegExp data (FixedArray)
1341 // Check that the number of captures fit in the static offsets vector buffer.
1342 __ lw(a2,
1343 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
1344 // Check (number_of_captures + 1) * 2 <= offsets vector size
1345 // Or number_of_captures * 2 <= offsets vector size - 2
1346 // Multiplying by 2 comes for free since a2 is smi-tagged.
1347 STATIC_ASSERT(kSmiTag == 0);
1348 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
1349 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
1350 __ Branch(
1351 &runtime, hi, a2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
1352
1353 // Reset offset for possibly sliced string.
1354 __ mov(t0, zero_reg);
1355 __ lw(subject, MemOperand(sp, kSubjectOffset));
1356 __ JumpIfSmi(subject, &runtime);
1357 __ mov(a3, subject); // Make a copy of the original subject string.
1358 // subject: subject string
1359 // a3: subject string
1360 // regexp_data: RegExp data (FixedArray)
1361 // Handle subject string according to its encoding and representation:
1362 // (1) Sequential string? If yes, go to (4).
1363 // (2) Sequential or cons? If not, go to (5).
1364 // (3) Cons string. If the string is flat, replace subject with first string
1365 // and go to (1). Otherwise bail out to runtime.
1366 // (4) Sequential string. Load regexp code according to encoding.
1367 // (E) Carry on.
1368 /// [...]
1369
1370 // Deferred code at the end of the stub:
1371 // (5) Long external string? If not, go to (7).
1372 // (6) External string. Make it, offset-wise, look like a sequential string.
1373 // Go to (4).
1374 // (7) Short external string or not a string? If yes, bail out to runtime.
1375 // (8) Sliced or thin string. Replace subject with parent. Go to (1).
1376
1377 Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
1378 not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
1379
1380 __ bind(&check_underlying);
1381 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
1382 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
1383
1384 // (1) Sequential string? If yes, go to (4).
1385 __ And(a1,
1386 a0,
1387 Operand(kIsNotStringMask |
1388 kStringRepresentationMask |
1389 kShortExternalStringMask));
1390 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
1391 __ Branch(&seq_string, eq, a1, Operand(zero_reg)); // Go to (5).
1392
1393 // (2) Sequential or cons? If not, go to (5).
1394 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
1395 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
1396 STATIC_ASSERT(kThinStringTag > kExternalStringTag);
1397 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
1398 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
1399 // Go to (5).
1400 __ Branch(&not_seq_nor_cons, ge, a1, Operand(kExternalStringTag));
1401
1402 // (3) Cons string. Check that it's flat.
1403 // Replace subject with first string and reload instance type.
1404 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset));
1405 __ LoadRoot(a1, Heap::kempty_stringRootIndex);
1406 __ Branch(&runtime, ne, a0, Operand(a1));
1407 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
1408 __ jmp(&check_underlying);
1409
1410 // (4) Sequential string. Load regexp code according to encoding.
1411 __ bind(&seq_string);
1412 // subject: sequential subject string (or look-alike, external string)
1413 // a3: original subject string
1414 // Load previous index and check range before a3 is overwritten. We have to
1415 // use a3 instead of subject here because subject might have been only made
1416 // to look like a sequential string when it actually is an external string.
1417 __ lw(a1, MemOperand(sp, kPreviousIndexOffset));
1418 __ JumpIfNotSmi(a1, &runtime);
1419 __ lw(a3, FieldMemOperand(a3, String::kLengthOffset));
1420 __ Branch(&runtime, ls, a3, Operand(a1));
1421 __ sra(a1, a1, kSmiTagSize); // Untag the Smi.
1422
1423 STATIC_ASSERT(kStringEncodingMask == 8);
1424 STATIC_ASSERT(kOneByteStringTag == 8);
1425 STATIC_ASSERT(kTwoByteStringTag == 0);
1426 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for one-byte.
1427 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset));
1428 __ sra(a3, a0, 3); // a3 is 1 for ASCII, 0 for UC16 (used below).
1429 __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
1430 __ Movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset.
1431
1432 // (E) Carry on. String handling is done.
1433 // t9: irregexp code
1434 // Check that the irregexp code has been generated for the actual string
1435 // encoding. If it has, the field contains a code object otherwise it contains
1436 // a smi (code flushing support).
1437 __ JumpIfSmi(t9, &runtime);
1438
1439 // a1: previous index
1440 // a3: encoding of subject string (1 if one_byte, 0 if two_byte);
1441 // t9: code
1442 // subject: Subject string
1443 // regexp_data: RegExp data (FixedArray)
1444 // All checks done. Now push arguments for native regexp code.
1445 __ IncrementCounter(isolate()->counters()->regexp_entry_native(),
1446 1, a0, a2);
1447
1448 // Isolates: note we add an additional parameter here (isolate pointer). 1279 // Isolates: note we add an additional parameter here (isolate pointer).
1449 const int kRegExpExecuteArguments = 9; 1280 const int kRegExpExecuteArguments = 9;
1450 const int kParameterRegisters = 4; 1281 const int kParameterRegisters = 4;
1451 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 1282 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
1452 1283
1453 // Stack pointer now points to cell where return address is to be written. 1284 // Stack pointer now points to cell where return address is to be written.
1454 // Arguments are before that on the stack or in registers, meaning we 1285 // Arguments are before that on the stack or in registers, meaning we
1455 // treat the return address as argument 5. Thus every argument after that 1286 // treat the return address as argument 5. Thus every argument after that
1456 // needs to be shifted back by 1. Since DirectCEntryStub will handle 1287 // needs to be shifted back by 1. Since DirectCEntryStub will handle
1457 // allocating space for the c argument slots, we don't need to calculate 1288 // allocating space for the c argument slots, we don't need to calculate
1458 // that into the argument positions on the stack. This is how the stack will 1289 // that into the argument positions on the stack. This is how the stack will
1459 // look (sp meaning the value of sp at this moment): 1290 // look (sp meaning the value of sp at this moment):
1460 // [sp + 5] - Argument 9 1291 // [sp + 5] - Argument 9
1461 // [sp + 4] - Argument 8 1292 // [sp + 4] - Argument 8
1462 // [sp + 3] - Argument 7 1293 // [sp + 3] - Argument 7
1463 // [sp + 2] - Argument 6 1294 // [sp + 2] - Argument 6
1464 // [sp + 1] - Argument 5 1295 // [sp + 1] - Argument 5
1465 // [sp + 0] - saved ra 1296 // [sp + 0] - saved ra
1466 1297
1467 // Argument 9: Pass current isolate address. 1298 // Argument 9: Pass current isolate address.
1468 // CFunctionArgumentOperand handles MIPS stack argument slots. 1299 // CFunctionArgumentOperand handles MIPS stack argument slots.
1469 __ li(a0, Operand(ExternalReference::isolate_address(isolate()))); 1300 __ li(t1, Operand(ExternalReference::isolate_address(isolate())));
1470 __ sw(a0, MemOperand(sp, 5 * kPointerSize)); 1301 __ sw(t1, MemOperand(sp, 5 * kPointerSize));
1471 1302
1472 // Argument 8: Indicate that this is a direct call from JavaScript. 1303 // Argument 8: Indicate that this is a direct call from JavaScript.
1473 __ li(a0, Operand(1)); 1304 __ li(t1, Operand(1));
1474 __ sw(a0, MemOperand(sp, 4 * kPointerSize)); 1305 __ sw(t1, MemOperand(sp, 4 * kPointerSize));
1475 1306
1476 // Argument 7: Start (high end) of backtracking stack memory area. 1307 // Argument 7: Start (high end) of backtracking stack memory area.
1477 __ li(a0, Operand(address_of_regexp_stack_memory_address)); 1308 ExternalReference address_of_regexp_stack_memory_address =
1478 __ lw(a0, MemOperand(a0, 0)); 1309 ExternalReference::address_of_regexp_stack_memory_address(isolate());
1479 __ li(a2, Operand(address_of_regexp_stack_memory_size)); 1310 ExternalReference address_of_regexp_stack_memory_size =
1480 __ lw(a2, MemOperand(a2, 0)); 1311 ExternalReference::address_of_regexp_stack_memory_size(isolate());
1481 __ addu(a0, a0, a2); 1312 __ li(t1, Operand(address_of_regexp_stack_memory_address));
1482 __ sw(a0, MemOperand(sp, 3 * kPointerSize)); 1313 __ lw(t1, MemOperand(t1, 0));
1314 __ li(t2, Operand(address_of_regexp_stack_memory_size));
1315 __ lw(t2, MemOperand(t2, 0));
1316 __ addu(t1, t1, t2);
1317 __ sw(t1, MemOperand(sp, 3 * kPointerSize));
1483 1318
1484 // Argument 6: Set the number of capture registers to zero to force global 1319 // Argument 6: Set the number of capture registers to zero to force global
1485 // regexps to behave as non-global. This does not affect non-global regexps. 1320 // regexps to behave as non-global. This does not affect non-global regexps.
1486 __ mov(a0, zero_reg); 1321 __ mov(t1, zero_reg);
1487 __ sw(a0, MemOperand(sp, 2 * kPointerSize)); 1322 __ sw(t1, MemOperand(sp, 2 * kPointerSize));
1488 1323
1489 // Argument 5: static offsets vector buffer. 1324 // Argument 5: static offsets vector buffer.
1490 __ li(a0, Operand( 1325 __ li(
1491 ExternalReference::address_of_static_offsets_vector(isolate()))); 1326 t1,
1492 __ sw(a0, MemOperand(sp, 1 * kPointerSize)); 1327 Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
1328 __ sw(t1, MemOperand(sp, 1 * kPointerSize));
1493 1329
1494 // For arguments 4 and 3 get string length, calculate start of string data
1495 // calculate the shift of the index (0 for one-byte and 1 for two-byte).
1496 __ Addu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
1497 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte.
1498 // Load the length from the original subject string from the previous stack
1499 // frame. Therefore we have to use fp, which points exactly to two pointer
1500 // sizes below the previous sp. (Because creating a new stack frame pushes
1501 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
1502 __ lw(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
1503 // If slice offset is not 0, load the length from the original sliced string.
1504 // Argument 4, a3: End of string data 1330 // Argument 4, a3: End of string data
1505 // Argument 3, a2: Start of string data 1331 // Argument 3, a2: Start of string data
1506 // Prepare start and end index of the input. 1332 CHECK(a3.is(RegExpExecDescriptor::StringEndRegister()));
1507 __ sllv(t1, t0, a3); 1333 CHECK(a2.is(RegExpExecDescriptor::StringStartRegister()));
1508 __ addu(t0, t2, t1);
1509 __ sllv(t1, a1, a3);
1510 __ addu(a2, t0, t1);
1511 1334
1512 __ lw(t2, FieldMemOperand(subject, String::kLengthOffset));
1513 __ sra(t2, t2, kSmiTagSize);
1514 __ sllv(t1, t2, a3);
1515 __ addu(a3, t0, t1);
1516 // Argument 2 (a1): Previous index. 1335 // Argument 2 (a1): Previous index.
1517 // Already there 1336 CHECK(a1.is(RegExpExecDescriptor::LastIndexRegister()));
1518 1337
1519 // Argument 1 (a0): Subject string. 1338 // Argument 1 (a0): Subject string.
1520 __ mov(a0, subject); 1339 CHECK(a0.is(RegExpExecDescriptor::StringRegister()));
1521 1340
1522 // Locate the code entry and call it. 1341 // Locate the code entry and call it.
1523 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); 1342 Register code_reg = RegExpExecDescriptor::CodeRegister();
1343 __ Addu(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
1524 DirectCEntryStub stub(isolate()); 1344 DirectCEntryStub stub(isolate());
1525 stub.GenerateCall(masm, t9); 1345 stub.GenerateCall(masm, code_reg);
1526 1346
1527 __ LeaveExitFrame(false, no_reg, true); 1347 __ LeaveExitFrame(false, no_reg, true);
1528 1348
1529 // v0: result 1349 // Return the smi-tagged result.
1530 // subject: subject string (callee saved) 1350 __ SmiTag(v0);
1531 // regexp_data: RegExp data (callee saved) 1351 __ Ret();
1532 // last_match_info_elements: Last match info elements (callee saved)
1533 // Check the result.
1534 Label success;
1535 __ Branch(&success, eq, v0, Operand(1));
1536 // We expect exactly one result since we force the called regexp to behave
1537 // as non-global.
1538 Label failure;
1539 __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE));
1540 // If not exception it can only be retry. Handle that in the runtime system.
1541 __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
1542 // Result must now be exception. If there is no pending exception already a
1543 // stack overflow (on the backtrack stack) was detected in RegExp code but
1544 // haven't created the exception yet. Handle that in the runtime system.
1545 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
1546 __ li(a1, Operand(isolate()->factory()->the_hole_value()));
1547 __ li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1548 isolate())));
1549 __ lw(v0, MemOperand(a2, 0));
1550 __ Branch(&runtime, eq, v0, Operand(a1));
1551
1552 // For exception, throw the exception again.
1553 __ TailCallRuntime(Runtime::kRegExpExecReThrow);
1554
1555 __ bind(&failure);
1556 // For failure and exception return null.
1557 __ li(v0, Operand(isolate()->factory()->null_value()));
1558 __ DropAndRet(4);
1559
1560 // Process the result from the native regexp code.
1561 __ bind(&success);
1562 __ lw(a1,
1563 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
1564 // Calculate number of capture registers (number_of_captures + 1) * 2.
1565 // Multiplying by 2 comes for free since r1 is smi-tagged.
1566 STATIC_ASSERT(kSmiTag == 0);
1567 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
1568 __ Addu(a1, a1, Operand(2)); // a1 was a smi.
1569
1570 // Check that the last match info is a FixedArray.
1571 __ lw(last_match_info_elements, MemOperand(sp, kLastMatchInfoOffset));
1572 __ JumpIfSmi(last_match_info_elements, &runtime);
1573 // Check that the object has fast elements.
1574 __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
1575 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex);
1576 __ Branch(&runtime, ne, a0, Operand(at));
1577 // Check that the last match info has space for the capture registers and the
1578 // additional information.
1579 __ lw(a0,
1580 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
1581 __ Addu(a2, a1, Operand(RegExpMatchInfo::kLastMatchOverhead));
1582 __ sra(at, a0, kSmiTagSize);
1583 __ Branch(&runtime, gt, a2, Operand(at));
1584
1585 // a1: number of capture registers
1586 // subject: subject string
1587 // Store the capture count.
1588 __ sll(a2, a1, kSmiTagSize + kSmiShiftSize); // To smi.
1589 __ sw(a2, FieldMemOperand(last_match_info_elements,
1590 RegExpMatchInfo::kNumberOfCapturesOffset));
1591 // Store last subject and last input.
1592 __ sw(subject, FieldMemOperand(last_match_info_elements,
1593 RegExpMatchInfo::kLastSubjectOffset));
1594 __ mov(a2, subject);
1595 __ RecordWriteField(last_match_info_elements,
1596 RegExpMatchInfo::kLastSubjectOffset, subject, t3,
1597 kRAHasNotBeenSaved, kDontSaveFPRegs);
1598 __ mov(subject, a2);
1599 __ sw(subject, FieldMemOperand(last_match_info_elements,
1600 RegExpMatchInfo::kLastInputOffset));
1601 __ RecordWriteField(last_match_info_elements,
1602 RegExpMatchInfo::kLastInputOffset, subject, t3,
1603 kRAHasNotBeenSaved, kDontSaveFPRegs);
1604
1605 // Get the static offsets vector filled by the native regexp code.
1606 ExternalReference address_of_static_offsets_vector =
1607 ExternalReference::address_of_static_offsets_vector(isolate());
1608 __ li(a2, Operand(address_of_static_offsets_vector));
1609
1610 // a1: number of capture registers
1611 // a2: offsets vector
1612 Label next_capture, done;
1613 // Capture register counter starts from number of capture registers and
1614 // counts down until wrapping after zero.
1615 __ Addu(a0, last_match_info_elements,
1616 Operand(RegExpMatchInfo::kFirstCaptureOffset - kHeapObjectTag));
1617 __ bind(&next_capture);
1618 __ Subu(a1, a1, Operand(1));
1619 __ Branch(&done, lt, a1, Operand(zero_reg));
1620 // Read the value from the static offsets vector buffer.
1621 __ lw(a3, MemOperand(a2, 0));
1622 __ addiu(a2, a2, kPointerSize);
1623 // Store the smi value in the last match info.
1624 __ sll(a3, a3, kSmiTagSize); // Convert to Smi.
1625 __ sw(a3, MemOperand(a0, 0));
1626 __ Branch(&next_capture, USE_DELAY_SLOT);
1627 __ addiu(a0, a0, kPointerSize); // In branch delay slot.
1628
1629 __ bind(&done);
1630
1631 // Return last match info.
1632 __ mov(v0, last_match_info_elements);
1633 __ DropAndRet(4);
1634
1635 // Do the runtime call to execute the regexp.
1636 __ bind(&runtime);
1637 __ TailCallRuntime(Runtime::kRegExpExec);
1638
1639 // Deferred code for string handling.
1640 // (5) Long external string? If not, go to (7).
1641 __ bind(&not_seq_nor_cons);
1642 // Go to (7).
1643 __ Branch(&not_long_external, gt, a1, Operand(kExternalStringTag));
1644
1645 // (6) External string. Make it, offset-wise, look like a sequential string.
1646 __ bind(&external_string);
1647 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
1648 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
1649 if (FLAG_debug_code) {
1650 // Assert that we do not have a cons or slice (indirect strings) here.
1651 // Sequential strings have already been ruled out.
1652 __ And(at, a0, Operand(kIsIndirectStringMask));
1653 __ Assert(eq,
1654 kExternalStringExpectedButNotFound,
1655 at,
1656 Operand(zero_reg));
1657 }
1658 __ lw(subject,
1659 FieldMemOperand(subject, ExternalString::kResourceDataOffset));
1660 // Move the pointer so that offset-wise, it looks like a sequential string.
1661 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
1662 __ Subu(subject,
1663 subject,
1664 SeqTwoByteString::kHeaderSize - kHeapObjectTag);
1665 __ jmp(&seq_string); // Go to (5).
1666
1667 // (7) Short external string or not a string? If yes, bail out to runtime.
1668 __ bind(&not_long_external);
1669 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
1670 __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
1671 __ Branch(&runtime, ne, at, Operand(zero_reg));
1672
1673 // (8) Sliced or thin string. Replace subject with parent. Go to (4).
1674 Label thin_string;
1675 __ Branch(&thin_string, eq, a1, Operand(kThinStringTag));
1676 // Load offset into t0 and replace subject string with parent.
1677 __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
1678 __ sra(t0, t0, kSmiTagSize);
1679 __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
1680 __ jmp(&check_underlying); // Go to (4).
1681
1682 __ bind(&thin_string);
1683 __ lw(subject, FieldMemOperand(subject, ThinString::kActualOffset));
1684 __ jmp(&check_underlying); // Go to (4).
1685 #endif // V8_INTERPRETED_REGEXP 1352 #endif // V8_INTERPRETED_REGEXP
1686 } 1353 }
1687 1354
1688 1355
1689 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { 1356 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
1690 // a0 : number of arguments to the construct function 1357 // a0 : number of arguments to the construct function
1691 // a2 : feedback vector 1358 // a2 : feedback vector
1692 // a3 : slot in feedback vector (Smi) 1359 // a3 : slot in feedback vector (Smi)
1693 // a1 : the function to call 1360 // a1 : the function to call
1694 FrameScope scope(masm, StackFrame::INTERNAL); 1361 FrameScope scope(masm, StackFrame::INTERNAL);
(...skipping 1822 matching lines...) Expand 10 before | Expand all | Expand 10 after
3517 kStackUnwindSpace, kInvalidStackOffset, 3184 kStackUnwindSpace, kInvalidStackOffset,
3518 return_value_operand, NULL); 3185 return_value_operand, NULL);
3519 } 3186 }
3520 3187
3521 #undef __ 3188 #undef __
3522 3189
3523 } // namespace internal 3190 } // namespace internal
3524 } // namespace v8 3191 } // namespace v8
3525 3192
3526 #endif // V8_TARGET_ARCH_MIPS 3193 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/interface-descriptors.cc ('k') | src/mips/interface-descriptors-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698