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

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

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

Powered by Google App Engine
This is Rietveld 408576698