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

Side by Side Diff: src/arm64/code-stubs-arm64.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/arm/interface-descriptors-arm.cc ('k') | src/arm64/interface-descriptors-arm64.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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_ARM64 5 #if V8_TARGET_ARCH_ARM64
6 6
7 #include "src/api-arguments.h" 7 #include "src/api-arguments.h"
8 #include "src/arm64/assembler-arm64-inl.h" 8 #include "src/arm64/assembler-arm64-inl.h"
9 #include "src/arm64/frames-arm64.h" 9 #include "src/arm64/frames-arm64.h"
10 #include "src/arm64/macro-assembler-arm64-inl.h" 10 #include "src/arm64/macro-assembler-arm64-inl.h"
(...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 __ Mov(csp, jssp); 1262 __ Mov(csp, jssp);
1263 __ SetStackPointer(csp); 1263 __ SetStackPointer(csp);
1264 __ PopCalleeSavedRegisters(); 1264 __ PopCalleeSavedRegisters();
1265 // After this point, we must not modify jssp because it is a callee-saved 1265 // After this point, we must not modify jssp because it is a callee-saved
1266 // register which we have just restored. 1266 // register which we have just restored.
1267 __ Ret(); 1267 __ Ret();
1268 } 1268 }
1269 1269
1270 void RegExpExecStub::Generate(MacroAssembler* masm) { 1270 void RegExpExecStub::Generate(MacroAssembler* masm) {
1271 #ifdef V8_INTERPRETED_REGEXP 1271 #ifdef V8_INTERPRETED_REGEXP
1272 __ TailCallRuntime(Runtime::kRegExpExec); 1272 // This case is handled prior to the RegExpExecStub call.
1273 __ Abort(kUnexpectedRegExpExecCall);
1273 #else // V8_INTERPRETED_REGEXP 1274 #else // V8_INTERPRETED_REGEXP
1274
1275 // Stack frame on entry.
1276 // jssp[0]: last_match_info (expected JSArray)
1277 // jssp[8]: previous index
1278 // jssp[16]: subject string
1279 // jssp[24]: JSRegExp object
1280 Label runtime;
1281
1282 // Use of registers for this function.
1283
1284 // Variable registers:
1285 // x10-x13 used as scratch registers
1286 // w0 string_type type of subject string
1287 // x2 jsstring_length subject string length
1288 // x3 jsregexp_object JSRegExp object
1289 // w4 string_encoding Latin1 or UC16
1290 // w5 sliced_string_offset if the string is a SlicedString
1291 // offset to the underlying string
1292 // w6 string_representation groups attributes of the string:
1293 // - is a string
1294 // - type of the string
1295 // - is a short external string
1296 Register string_type = w0;
1297 Register jsstring_length = x2;
1298 Register jsregexp_object = x3;
1299 Register string_encoding = w4;
1300 Register sliced_string_offset = w5;
1301 Register string_representation = w6;
1302
1303 // These are in callee save registers and will be preserved by the call
1304 // to the native RegExp code, as this code is called using the normal
1305 // C calling convention. When calling directly from generated code the
1306 // native RegExp code will not do a GC and therefore the content of
1307 // these registers are safe to use after the call.
1308
1309 // x19 subject subject string
1310 // x20 regexp_data RegExp data (FixedArray)
1311 // x21 last_match_info_elements info relative to the last match
1312 // (FixedArray)
1313 // x22 code_object generated regexp code
1314 Register subject = x19;
1315 Register regexp_data = x20;
1316 Register last_match_info_elements = x21;
1317 Register code_object = x22;
1318
1319 // Stack frame.
1320 // jssp[00]: last_match_info (JSArray)
1321 // jssp[08]: previous index
1322 // jssp[16]: subject string
1323 // jssp[24]: JSRegExp object
1324
1325 const int kLastMatchInfoOffset = 0 * kPointerSize;
1326 const int kPreviousIndexOffset = 1 * kPointerSize;
1327 const int kSubjectOffset = 2 * kPointerSize;
1328 const int kJSRegExpOffset = 3 * kPointerSize;
1329
1330 // Ensure that a RegExp stack is allocated.
1331 ExternalReference address_of_regexp_stack_memory_address =
1332 ExternalReference::address_of_regexp_stack_memory_address(isolate());
1333 ExternalReference address_of_regexp_stack_memory_size =
1334 ExternalReference::address_of_regexp_stack_memory_size(isolate());
1335 __ Mov(x10, address_of_regexp_stack_memory_size);
1336 __ Ldr(x10, MemOperand(x10));
1337 __ Cbz(x10, &runtime);
1338
1339 // Check that the first argument is a JSRegExp object.
1340 DCHECK(jssp.Is(__ StackPointer()));
1341 __ Peek(jsregexp_object, kJSRegExpOffset);
1342 __ JumpIfSmi(jsregexp_object, &runtime);
1343 __ JumpIfNotObjectType(jsregexp_object, x10, x10, JS_REGEXP_TYPE, &runtime);
1344
1345 // Check that the RegExp has been compiled (data contains a fixed array).
1346 __ Ldr(regexp_data, FieldMemOperand(jsregexp_object, JSRegExp::kDataOffset));
1347 if (FLAG_debug_code) {
1348 STATIC_ASSERT(kSmiTag == 0);
1349 __ Tst(regexp_data, kSmiTagMask);
1350 __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected);
1351 __ CompareObjectType(regexp_data, x10, x10, FIXED_ARRAY_TYPE);
1352 __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected);
1353 }
1354
1355 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
1356 __ Ldr(x10, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
1357 __ Cmp(x10, Smi::FromInt(JSRegExp::IRREGEXP));
1358 __ B(ne, &runtime);
1359
1360 // Check that the number of captures fit in the static offsets vector buffer.
1361 // We have always at least one capture for the whole match, plus additional
1362 // ones due to capturing parentheses. A capture takes 2 registers.
1363 // The number of capture registers then is (number_of_captures + 1) * 2.
1364 __ Ldrsw(x10,
1365 UntagSmiFieldMemOperand(regexp_data,
1366 JSRegExp::kIrregexpCaptureCountOffset));
1367 // Check (number_of_captures + 1) * 2 <= offsets vector size
1368 // number_of_captures * 2 <= offsets vector size - 2
1369 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
1370 __ Add(x10, x10, x10);
1371 __ Cmp(x10, Isolate::kJSRegexpStaticOffsetsVectorSize - 2);
1372 __ B(hi, &runtime);
1373
1374 // Initialize offset for possibly sliced string.
1375 __ Mov(sliced_string_offset, 0);
1376
1377 DCHECK(jssp.Is(__ StackPointer()));
1378 __ Peek(subject, kSubjectOffset);
1379 __ JumpIfSmi(subject, &runtime);
1380
1381 __ Ldr(jsstring_length, FieldMemOperand(subject, String::kLengthOffset));
1382
1383 // Handle subject string according to its encoding and representation:
1384 // (1) Sequential string? If yes, go to (4).
1385 // (2) Sequential or cons? If not, go to (5).
1386 // (3) Cons string. If the string is flat, replace subject with first string
1387 // and go to (1). Otherwise bail out to runtime.
1388 // (4) Sequential string. Load regexp code according to encoding.
1389 // (E) Carry on.
1390 /// [...]
1391
1392 // Deferred code at the end of the stub:
1393 // (5) Long external string? If not, go to (7).
1394 // (6) External string. Make it, offset-wise, look like a sequential string.
1395 // Go to (4).
1396 // (7) Short external string or not a string? If yes, bail out to runtime.
1397 // (8) Sliced or thin string. Replace subject with parent. Go to (1).
1398
1399 Label check_underlying; // (1)
1400 Label seq_string; // (4)
1401 Label not_seq_nor_cons; // (5)
1402 Label external_string; // (6)
1403 Label not_long_external; // (7)
1404
1405 __ Bind(&check_underlying);
1406 __ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
1407 __ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset));
1408
1409 // (1) Sequential string? If yes, go to (4).
1410 __ And(string_representation,
1411 string_type,
1412 kIsNotStringMask |
1413 kStringRepresentationMask |
1414 kShortExternalStringMask);
1415 // We depend on the fact that Strings of type
1416 // SeqString and not ShortExternalString are defined
1417 // by the following pattern:
1418 // string_type: 0XX0 XX00
1419 // ^ ^ ^^
1420 // | | ||
1421 // | | is a SeqString
1422 // | is not a short external String
1423 // is a String
1424 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
1425 STATIC_ASSERT(kShortExternalStringTag != 0);
1426 __ Cbz(string_representation, &seq_string); // Go to (4).
1427
1428 // (2) Sequential or cons? If not, go to (5).
1429 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
1430 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
1431 STATIC_ASSERT(kThinStringTag > kExternalStringTag);
1432 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
1433 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
1434 __ Cmp(string_representation, kExternalStringTag);
1435 __ B(ge, &not_seq_nor_cons); // Go to (5).
1436
1437 // (3) Cons string. Check that it's flat.
1438 __ Ldr(x10, FieldMemOperand(subject, ConsString::kSecondOffset));
1439 __ JumpIfNotRoot(x10, Heap::kempty_stringRootIndex, &runtime);
1440 // Replace subject with first string.
1441 __ Ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
1442 __ B(&check_underlying);
1443
1444 // (4) Sequential string. Load regexp code according to encoding.
1445 __ Bind(&seq_string);
1446
1447 // Check that the third argument is a positive smi less than the subject
1448 // string length. A negative value will be greater (unsigned comparison).
1449 DCHECK(jssp.Is(__ StackPointer()));
1450 __ Peek(x10, kPreviousIndexOffset);
1451 __ JumpIfNotSmi(x10, &runtime);
1452 __ Cmp(jsstring_length, x10);
1453 __ B(ls, &runtime);
1454
1455 // Argument 2 (x1): We need to load argument 2 (the previous index) into x1
1456 // before entering the exit frame.
1457 __ SmiUntag(x1, x10);
1458
1459 // The fourth bit determines the string encoding in string_type.
1460 STATIC_ASSERT(kOneByteStringTag == 0x08);
1461 STATIC_ASSERT(kTwoByteStringTag == 0x00);
1462 STATIC_ASSERT(kStringEncodingMask == 0x08);
1463
1464 // Find the code object based on the assumptions above.
1465 // kDataOneByteCodeOffset and kDataUC16CodeOffset are adjacent, adds an offset
1466 // of kPointerSize to reach the latter.
1467 STATIC_ASSERT(JSRegExp::kDataOneByteCodeOffset + kPointerSize ==
1468 JSRegExp::kDataUC16CodeOffset);
1469 __ Mov(x10, kPointerSize);
1470 // We will need the encoding later: Latin1 = 0x08
1471 // UC16 = 0x00
1472 __ Ands(string_encoding, string_type, kStringEncodingMask);
1473 __ CzeroX(x10, ne);
1474 __ Add(x10, regexp_data, x10);
1475 __ Ldr(code_object, FieldMemOperand(x10, JSRegExp::kDataOneByteCodeOffset));
1476
1477 // (E) Carry on. String handling is done.
1478
1479 // Check that the irregexp code has been generated for the actual string
1480 // encoding. If it has, the field contains a code object otherwise it contains
1481 // a smi (code flushing support).
1482 __ JumpIfSmi(code_object, &runtime);
1483
1484 // All checks done. Now push arguments for native regexp code.
1485 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1,
1486 x10,
1487 x11);
1488
1489 // Isolates: note we add an additional parameter here (isolate pointer). 1275 // Isolates: note we add an additional parameter here (isolate pointer).
1490 __ EnterExitFrame(false, x10, 1); 1276 __ EnterExitFrame(false, x10, 1);
1491 DCHECK(csp.Is(__ StackPointer())); 1277 DCHECK(csp.Is(__ StackPointer()));
1492 1278
1493 // We have 9 arguments to pass to the regexp code, therefore we have to pass 1279 // We have 9 arguments to pass to the regexp code, therefore we have to pass
1494 // one on the stack and the rest as registers. 1280 // one on the stack and the rest as registers.
1495 1281
1496 // Note that the placement of the argument on the stack isn't standard 1282 // Note that the placement of the argument on the stack isn't standard
1497 // AAPCS64: 1283 // AAPCS64:
1498 // csp[0]: Space for the return address placed by DirectCEntryStub. 1284 // csp[0]: Space for the return address placed by DirectCEntryStub.
1499 // csp[8]: Argument 9, the current isolate address. 1285 // csp[8]: Argument 9, the current isolate address.
1500 1286
1501 __ Mov(x10, ExternalReference::isolate_address(isolate())); 1287 __ Mov(x10, ExternalReference::isolate_address(isolate()));
1502 __ Poke(x10, kPointerSize); 1288 __ Poke(x10, kPointerSize);
1503 1289
1504 Register length = w11;
1505 Register previous_index_in_bytes = w12;
1506 Register start = x13;
1507
1508 // Load start of the subject string.
1509 __ Add(start, subject, SeqString::kHeaderSize - kHeapObjectTag);
1510 // Load the length from the original subject string from the previous stack
1511 // frame. Therefore we have to use fp, which points exactly to two pointer
1512 // sizes below the previous sp. (Because creating a new stack frame pushes
1513 // the previous fp onto the stack and decrements sp by 2 * kPointerSize.)
1514 __ Ldr(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
1515 __ Ldr(length, UntagSmiFieldMemOperand(subject, String::kLengthOffset));
1516
1517 // Handle UC16 encoding, two bytes make one character.
1518 // string_encoding: if Latin1: 0x08
1519 // if UC16: 0x00
1520 STATIC_ASSERT(kStringEncodingMask == 0x08);
1521 __ Ubfx(string_encoding, string_encoding, 3, 1);
1522 __ Eor(string_encoding, string_encoding, 1);
1523 // string_encoding: if Latin1: 0
1524 // if UC16: 1
1525
1526 // Convert string positions from characters to bytes.
1527 // Previous index is in x1.
1528 __ Lsl(previous_index_in_bytes, w1, string_encoding);
1529 __ Lsl(length, length, string_encoding);
1530 __ Lsl(sliced_string_offset, sliced_string_offset, string_encoding);
1531
1532 // Argument 1 (x0): Subject string. 1290 // Argument 1 (x0): Subject string.
1533 __ Mov(x0, subject); 1291 CHECK(x0.is(RegExpExecDescriptor::StringRegister()));
1534 1292
1535 // Argument 2 (x1): Previous index, already there. 1293 // Argument 2 (x1): Previous index, already there.
1294 CHECK(x1.is(RegExpExecDescriptor::LastIndexRegister()));
1536 1295
1537 // Argument 3 (x2): Get the start of input. 1296 // Argument 3 (x2): Input start.
1538 // Start of input = start of string + previous index + substring offset 1297 // Argument 4 (x3): Input end.
1539 // (0 if the string 1298 CHECK(x2.is(RegExpExecDescriptor::StringStartRegister()));
1540 // is not sliced). 1299 CHECK(x3.is(RegExpExecDescriptor::StringEndRegister()));
1541 __ Add(w10, previous_index_in_bytes, sliced_string_offset);
1542 __ Add(x2, start, Operand(w10, UXTW));
1543
1544 // Argument 4 (x3):
1545 // End of input = start of input + (length of input - previous index)
1546 __ Sub(w10, length, previous_index_in_bytes);
1547 __ Add(x3, x2, Operand(w10, UXTW));
1548 1300
1549 // Argument 5 (x4): static offsets vector buffer. 1301 // Argument 5 (x4): static offsets vector buffer.
1550 __ Mov(x4, ExternalReference::address_of_static_offsets_vector(isolate())); 1302 __ Mov(x4, ExternalReference::address_of_static_offsets_vector(isolate()));
1551 1303
1552 // Argument 6 (x5): Set the number of capture registers to zero to force 1304 // Argument 6 (x5): Set the number of capture registers to zero to force
1553 // global regexps to behave as non-global. This stub is not used for global 1305 // global regexps to behave as non-global. This stub is not used for global
1554 // regexps. 1306 // regexps.
1555 __ Mov(x5, 0); 1307 __ Mov(x5, 0);
1556 1308
1557 // Argument 7 (x6): Start (high end) of backtracking stack memory area. 1309 // Argument 7 (x6): Start (high end) of backtracking stack memory area.
1310 ExternalReference address_of_regexp_stack_memory_address =
1311 ExternalReference::address_of_regexp_stack_memory_address(isolate());
1312 ExternalReference address_of_regexp_stack_memory_size =
1313 ExternalReference::address_of_regexp_stack_memory_size(isolate());
1558 __ Mov(x10, address_of_regexp_stack_memory_address); 1314 __ Mov(x10, address_of_regexp_stack_memory_address);
1559 __ Ldr(x10, MemOperand(x10)); 1315 __ Ldr(x10, MemOperand(x10));
1560 __ Mov(x11, address_of_regexp_stack_memory_size); 1316 __ Mov(x11, address_of_regexp_stack_memory_size);
1561 __ Ldr(x11, MemOperand(x11)); 1317 __ Ldr(x11, MemOperand(x11));
1562 __ Add(x6, x10, x11); 1318 __ Add(x6, x10, x11);
1563 1319
1564 // Argument 8 (x7): Indicate that this is a direct call from JavaScript. 1320 // Argument 8 (x7): Indicate that this is a direct call from JavaScript.
1565 __ Mov(x7, 1); 1321 __ Mov(x7, 1);
1566 1322
1567 // Locate the code entry and call it. 1323 // Locate the code entry and call it.
1324 Register code_object = RegExpExecDescriptor::CodeRegister();
1568 __ Add(code_object, code_object, Code::kHeaderSize - kHeapObjectTag); 1325 __ Add(code_object, code_object, Code::kHeaderSize - kHeapObjectTag);
1569 DirectCEntryStub stub(isolate()); 1326 DirectCEntryStub stub(isolate());
1570 stub.GenerateCall(masm, code_object); 1327 stub.GenerateCall(masm, code_object);
1571 1328
1572 __ LeaveExitFrame(false, x10, true); 1329 __ LeaveExitFrame(false, x10, true);
1573 1330
1574 // The generated regexp code returns an int32 in w0. 1331 // Return the smi-tagged result.
1575 Label failure, exception; 1332 __ SmiTag(x0);
1576 __ CompareAndBranch(w0, NativeRegExpMacroAssembler::FAILURE, eq, &failure);
1577 __ CompareAndBranch(w0,
1578 NativeRegExpMacroAssembler::EXCEPTION,
1579 eq,
1580 &exception);
1581 __ CompareAndBranch(w0, NativeRegExpMacroAssembler::RETRY, eq, &runtime);
1582
1583 // Success: process the result from the native regexp code.
1584 Register number_of_capture_registers = x12;
1585
1586 // Calculate number of capture registers (number_of_captures + 1) * 2
1587 // and store it in the last match info.
1588 __ Ldrsw(x10,
1589 UntagSmiFieldMemOperand(regexp_data,
1590 JSRegExp::kIrregexpCaptureCountOffset));
1591 __ Add(x10, x10, x10);
1592 __ Add(number_of_capture_registers, x10, 2);
1593
1594 // Check that the last match info is a FixedArray.
1595 DCHECK(jssp.Is(__ StackPointer()));
1596 __ Peek(last_match_info_elements, kLastMatchInfoOffset);
1597 __ JumpIfSmi(last_match_info_elements, &runtime);
1598
1599 // Check that the object has fast elements.
1600 __ Ldr(x10,
1601 FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
1602 __ JumpIfNotRoot(x10, Heap::kFixedArrayMapRootIndex, &runtime);
1603
1604 // Check that the last match info has space for the capture registers and the
1605 // additional information (overhead).
1606 // (number_of_captures + 1) * 2 + overhead <= last match info size
1607 // (number_of_captures * 2) + 2 + overhead <= last match info size
1608 // number_of_capture_registers + overhead <= last match info size
1609 __ Ldrsw(x10,
1610 UntagSmiFieldMemOperand(last_match_info_elements,
1611 FixedArray::kLengthOffset));
1612 __ Add(x11, number_of_capture_registers, RegExpMatchInfo::kLastMatchOverhead);
1613 __ Cmp(x11, x10);
1614 __ B(gt, &runtime);
1615
1616 // Store the capture count.
1617 __ SmiTag(x10, number_of_capture_registers);
1618 __ Str(x10, FieldMemOperand(last_match_info_elements,
1619 RegExpMatchInfo::kNumberOfCapturesOffset));
1620 // Store last subject and last input.
1621 __ Str(subject, FieldMemOperand(last_match_info_elements,
1622 RegExpMatchInfo::kLastSubjectOffset));
1623 // Use x10 as the subject string in order to only need
1624 // one RecordWriteStub.
1625 __ Mov(x10, subject);
1626 __ RecordWriteField(last_match_info_elements,
1627 RegExpMatchInfo::kLastSubjectOffset, x10, x11,
1628 kLRHasNotBeenSaved, kDontSaveFPRegs);
1629 __ Str(subject, FieldMemOperand(last_match_info_elements,
1630 RegExpMatchInfo::kLastInputOffset));
1631 __ Mov(x10, subject);
1632 __ RecordWriteField(last_match_info_elements,
1633 RegExpMatchInfo::kLastInputOffset, x10, x11,
1634 kLRHasNotBeenSaved, kDontSaveFPRegs);
1635
1636 Register last_match_offsets = x13;
1637 Register offsets_vector_index = x14;
1638 Register current_offset = x15;
1639
1640 // Get the static offsets vector filled by the native regexp code
1641 // and fill the last match info.
1642 ExternalReference address_of_static_offsets_vector =
1643 ExternalReference::address_of_static_offsets_vector(isolate());
1644 __ Mov(offsets_vector_index, address_of_static_offsets_vector);
1645
1646 Label next_capture, done;
1647 // Capture register counter starts from number of capture registers and
1648 // iterates down to zero (inclusive).
1649 __ Add(last_match_offsets, last_match_info_elements,
1650 RegExpMatchInfo::kFirstCaptureOffset - kHeapObjectTag);
1651 __ Bind(&next_capture);
1652 __ Subs(number_of_capture_registers, number_of_capture_registers, 2);
1653 __ B(mi, &done);
1654 // Read two 32 bit values from the static offsets vector buffer into
1655 // an X register
1656 __ Ldr(current_offset,
1657 MemOperand(offsets_vector_index, kWRegSize * 2, PostIndex));
1658 // Store the smi values in the last match info.
1659 __ SmiTag(x10, current_offset);
1660 // Clearing the 32 bottom bits gives us a Smi.
1661 STATIC_ASSERT(kSmiTag == 0);
1662 __ Bic(x11, current_offset, kSmiShiftMask);
1663 __ Stp(x10,
1664 x11,
1665 MemOperand(last_match_offsets, kXRegSize * 2, PostIndex));
1666 __ B(&next_capture);
1667 __ Bind(&done);
1668
1669 // Return last match info.
1670 __ Mov(x0, last_match_info_elements);
1671 // Drop the 4 arguments of the stub from the stack.
1672 __ Drop(4);
1673 __ Ret(); 1333 __ Ret();
1674
1675 __ Bind(&exception);
1676 Register exception_value = x0;
1677 // A stack overflow (on the backtrack stack) may have occured
1678 // in the RegExp code but no exception has been created yet.
1679 // If there is no pending exception, handle that in the runtime system.
1680 __ Mov(x10, Operand(isolate()->factory()->the_hole_value()));
1681 __ Mov(x11,
1682 Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1683 isolate())));
1684 __ Ldr(exception_value, MemOperand(x11));
1685 __ Cmp(x10, exception_value);
1686 __ B(eq, &runtime);
1687
1688 // For exception, throw the exception again.
1689 __ TailCallRuntime(Runtime::kRegExpExecReThrow);
1690
1691 __ Bind(&failure);
1692 __ Mov(x0, Operand(isolate()->factory()->null_value()));
1693 // Drop the 4 arguments of the stub from the stack.
1694 __ Drop(4);
1695 __ Ret();
1696
1697 __ Bind(&runtime);
1698 __ TailCallRuntime(Runtime::kRegExpExec);
1699
1700 // Deferred code for string handling.
1701 // (5) Long external string? If not, go to (7).
1702 __ Bind(&not_seq_nor_cons);
1703 // Compare flags are still set.
1704 __ B(ne, &not_long_external); // Go to (7).
1705
1706 // (6) External string. Make it, offset-wise, look like a sequential string.
1707 __ Bind(&external_string);
1708 if (masm->emit_debug_code()) {
1709 // Assert that we do not have a cons or slice (indirect strings) here.
1710 // Sequential strings have already been ruled out.
1711 __ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset));
1712 __ Ldrb(x10, FieldMemOperand(x10, Map::kInstanceTypeOffset));
1713 __ Tst(x10, kIsIndirectStringMask);
1714 __ Check(eq, kExternalStringExpectedButNotFound);
1715 __ And(x10, x10, kStringRepresentationMask);
1716 __ Cmp(x10, 0);
1717 __ Check(ne, kExternalStringExpectedButNotFound);
1718 }
1719 __ Ldr(subject,
1720 FieldMemOperand(subject, ExternalString::kResourceDataOffset));
1721 // Move the pointer so that offset-wise, it looks like a sequential string.
1722 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
1723 __ Sub(subject, subject, SeqTwoByteString::kHeaderSize - kHeapObjectTag);
1724 __ B(&seq_string); // Go to (4).
1725
1726 // (7) If this is a short external string or not a string, bail out to
1727 // runtime.
1728 __ Bind(&not_long_external);
1729 STATIC_ASSERT(kShortExternalStringTag != 0);
1730 __ TestAndBranchIfAnySet(string_representation,
1731 kShortExternalStringMask | kIsNotStringMask,
1732 &runtime);
1733
1734 // (8) Sliced or thin string. Replace subject with parent.
1735 Label thin_string;
1736 __ Cmp(string_representation, kThinStringTag);
1737 __ B(eq, &thin_string);
1738 __ Ldr(sliced_string_offset,
1739 UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset));
1740 __ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
1741 __ B(&check_underlying); // Go to (1).
1742
1743 __ bind(&thin_string);
1744 __ Ldr(subject, FieldMemOperand(subject, ThinString::kActualOffset));
1745 __ B(&check_underlying); // Go to (1).
1746 #endif 1334 #endif
1747 } 1335 }
1748 1336
1749 1337
1750 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub, 1338 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub,
1751 Register argc, Register function, 1339 Register argc, Register function,
1752 Register feedback_vector, Register index, 1340 Register feedback_vector, Register index,
1753 Register new_target) { 1341 Register new_target) {
1754 FrameScope scope(masm, StackFrame::INTERNAL); 1342 FrameScope scope(masm, StackFrame::INTERNAL);
1755 1343
(...skipping 1886 matching lines...) Expand 10 before | Expand all | Expand 10 after
3642 kStackUnwindSpace, NULL, spill_offset, 3230 kStackUnwindSpace, NULL, spill_offset,
3643 return_value_operand, NULL); 3231 return_value_operand, NULL);
3644 } 3232 }
3645 3233
3646 #undef __ 3234 #undef __
3647 3235
3648 } // namespace internal 3236 } // namespace internal
3649 } // namespace v8 3237 } // namespace v8
3650 3238
3651 #endif // V8_TARGET_ARCH_ARM64 3239 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « src/arm/interface-descriptors-arm.cc ('k') | src/arm64/interface-descriptors-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698