| OLD | NEW |
| 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 1427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 // and go to (1). Otherwise bail out to runtime. | 1438 // and go to (1). Otherwise bail out to runtime. |
| 1439 // (4) Sequential string. Load regexp code according to encoding. | 1439 // (4) Sequential string. Load regexp code according to encoding. |
| 1440 // (E) Carry on. | 1440 // (E) Carry on. |
| 1441 /// [...] | 1441 /// [...] |
| 1442 | 1442 |
| 1443 // Deferred code at the end of the stub: | 1443 // Deferred code at the end of the stub: |
| 1444 // (5) Long external string? If not, go to (7). | 1444 // (5) Long external string? If not, go to (7). |
| 1445 // (6) External string. Make it, offset-wise, look like a sequential string. | 1445 // (6) External string. Make it, offset-wise, look like a sequential string. |
| 1446 // Go to (4). | 1446 // Go to (4). |
| 1447 // (7) Short external string or not a string? If yes, bail out to runtime. | 1447 // (7) Short external string or not a string? If yes, bail out to runtime. |
| 1448 // (8) Sliced or thin string. Replace subject with parent. Go to (1). | 1448 // (8) Sliced string. Replace subject with parent. Go to (1). |
| 1449 | 1449 |
| 1450 Label check_underlying; // (1) | 1450 Label check_underlying; // (1) |
| 1451 Label seq_string; // (4) | 1451 Label seq_string; // (4) |
| 1452 Label not_seq_nor_cons; // (5) | 1452 Label not_seq_nor_cons; // (5) |
| 1453 Label external_string; // (6) | 1453 Label external_string; // (6) |
| 1454 Label not_long_external; // (7) | 1454 Label not_long_external; // (7) |
| 1455 | 1455 |
| 1456 __ Bind(&check_underlying); | 1456 __ Bind(&check_underlying); |
| 1457 __ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset)); | 1457 __ Ldr(x10, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 1458 __ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset)); | 1458 __ Ldrb(string_type, FieldMemOperand(x10, Map::kInstanceTypeOffset)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1472 // | | is a SeqString | 1472 // | | is a SeqString |
| 1473 // | is not a short external String | 1473 // | is not a short external String |
| 1474 // is a String | 1474 // is a String |
| 1475 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); | 1475 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); |
| 1476 STATIC_ASSERT(kShortExternalStringTag != 0); | 1476 STATIC_ASSERT(kShortExternalStringTag != 0); |
| 1477 __ Cbz(string_representation, &seq_string); // Go to (4). | 1477 __ Cbz(string_representation, &seq_string); // Go to (4). |
| 1478 | 1478 |
| 1479 // (2) Sequential or cons? If not, go to (5). | 1479 // (2) Sequential or cons? If not, go to (5). |
| 1480 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 1480 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
| 1481 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); | 1481 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); |
| 1482 STATIC_ASSERT(kThinStringTag > kExternalStringTag); | |
| 1483 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); | 1482 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); |
| 1484 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); | 1483 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); |
| 1485 __ Cmp(string_representation, kExternalStringTag); | 1484 __ Cmp(string_representation, kExternalStringTag); |
| 1486 __ B(ge, ¬_seq_nor_cons); // Go to (5). | 1485 __ B(ge, ¬_seq_nor_cons); // Go to (5). |
| 1487 | 1486 |
| 1488 // (3) Cons string. Check that it's flat. | 1487 // (3) Cons string. Check that it's flat. |
| 1489 __ Ldr(x10, FieldMemOperand(subject, ConsString::kSecondOffset)); | 1488 __ Ldr(x10, FieldMemOperand(subject, ConsString::kSecondOffset)); |
| 1490 __ JumpIfNotRoot(x10, Heap::kempty_stringRootIndex, &runtime); | 1489 __ JumpIfNotRoot(x10, Heap::kempty_stringRootIndex, &runtime); |
| 1491 // Replace subject with first string. | 1490 // Replace subject with first string. |
| 1492 __ Ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | 1491 __ Ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
| 1493 __ B(&check_underlying); | 1492 __ B(&check_underlying); |
| 1494 | 1493 |
| 1495 // (4) Sequential string. Load regexp code according to encoding. | 1494 // (4) Sequential string. Load regexp code according to encoding. |
| 1496 __ Bind(&seq_string); | 1495 __ Bind(&seq_string); |
| 1497 | 1496 |
| 1498 // Check that the third argument is a positive smi less than the subject | 1497 // Check that the third argument is a positive smi less than the subject |
| 1499 // string length. A negative value will be greater (unsigned comparison). | 1498 // string length. A negative value will be greater (unsigned comparison). |
| 1500 DCHECK(jssp.Is(__ StackPointer())); | 1499 DCHECK(jssp.Is(__ StackPointer())); |
| 1501 __ Peek(x10, kPreviousIndexOffset); | 1500 __ Peek(x10, kPreviousIndexOffset); |
| 1502 __ JumpIfNotSmi(x10, &runtime); | 1501 __ JumpIfNotSmi(x10, &runtime); |
| 1503 __ Cmp(jsstring_length, x10); | 1502 __ Cmp(jsstring_length, x10); |
| 1504 __ B(ls, &runtime); | 1503 __ B(ls, &runtime); |
| 1505 | 1504 |
| 1506 // Argument 2 (x1): We need to load argument 2 (the previous index) into x1 | 1505 // Argument 2 (x1): We need to load argument 2 (the previous index) into x1 |
| 1507 // before entering the exit frame. | 1506 // before entering the exit frame. |
| 1508 __ SmiUntag(x1, x10); | 1507 __ SmiUntag(x1, x10); |
| 1509 | 1508 |
| 1510 // The fourth bit determines the string encoding in string_type. | 1509 // The third bit determines the string encoding in string_type. |
| 1511 STATIC_ASSERT(kOneByteStringTag == 0x08); | 1510 STATIC_ASSERT(kOneByteStringTag == 0x04); |
| 1512 STATIC_ASSERT(kTwoByteStringTag == 0x00); | 1511 STATIC_ASSERT(kTwoByteStringTag == 0x00); |
| 1513 STATIC_ASSERT(kStringEncodingMask == 0x08); | 1512 STATIC_ASSERT(kStringEncodingMask == 0x04); |
| 1514 | 1513 |
| 1515 // Find the code object based on the assumptions above. | 1514 // Find the code object based on the assumptions above. |
| 1516 // kDataOneByteCodeOffset and kDataUC16CodeOffset are adjacent, adds an offset | 1515 // kDataOneByteCodeOffset and kDataUC16CodeOffset are adjacent, adds an offset |
| 1517 // of kPointerSize to reach the latter. | 1516 // of kPointerSize to reach the latter. |
| 1518 STATIC_ASSERT(JSRegExp::kDataOneByteCodeOffset + kPointerSize == | 1517 STATIC_ASSERT(JSRegExp::kDataOneByteCodeOffset + kPointerSize == |
| 1519 JSRegExp::kDataUC16CodeOffset); | 1518 JSRegExp::kDataUC16CodeOffset); |
| 1520 __ Mov(x10, kPointerSize); | 1519 __ Mov(x10, kPointerSize); |
| 1521 // We will need the encoding later: Latin1 = 0x08 | 1520 // We will need the encoding later: Latin1 = 0x04 |
| 1522 // UC16 = 0x00 | 1521 // UC16 = 0x00 |
| 1523 __ Ands(string_encoding, string_type, kStringEncodingMask); | 1522 __ Ands(string_encoding, string_type, kStringEncodingMask); |
| 1524 __ CzeroX(x10, ne); | 1523 __ CzeroX(x10, ne); |
| 1525 __ Add(x10, regexp_data, x10); | 1524 __ Add(x10, regexp_data, x10); |
| 1526 __ Ldr(code_object, FieldMemOperand(x10, JSRegExp::kDataOneByteCodeOffset)); | 1525 __ Ldr(code_object, FieldMemOperand(x10, JSRegExp::kDataOneByteCodeOffset)); |
| 1527 | 1526 |
| 1528 // (E) Carry on. String handling is done. | 1527 // (E) Carry on. String handling is done. |
| 1529 | 1528 |
| 1530 // Check that the irregexp code has been generated for the actual string | 1529 // Check that the irregexp code has been generated for the actual string |
| 1531 // encoding. If it has, the field contains a code object otherwise it contains | 1530 // encoding. If it has, the field contains a code object otherwise it contains |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1559 // Load start of the subject string. | 1558 // Load start of the subject string. |
| 1560 __ Add(start, subject, SeqString::kHeaderSize - kHeapObjectTag); | 1559 __ Add(start, subject, SeqString::kHeaderSize - kHeapObjectTag); |
| 1561 // Load the length from the original subject string from the previous stack | 1560 // Load the length from the original subject string from the previous stack |
| 1562 // frame. Therefore we have to use fp, which points exactly to two pointer | 1561 // frame. Therefore we have to use fp, which points exactly to two pointer |
| 1563 // sizes below the previous sp. (Because creating a new stack frame pushes | 1562 // sizes below the previous sp. (Because creating a new stack frame pushes |
| 1564 // the previous fp onto the stack and decrements sp by 2 * kPointerSize.) | 1563 // the previous fp onto the stack and decrements sp by 2 * kPointerSize.) |
| 1565 __ Ldr(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); | 1564 __ Ldr(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); |
| 1566 __ Ldr(length, UntagSmiFieldMemOperand(subject, String::kLengthOffset)); | 1565 __ Ldr(length, UntagSmiFieldMemOperand(subject, String::kLengthOffset)); |
| 1567 | 1566 |
| 1568 // Handle UC16 encoding, two bytes make one character. | 1567 // Handle UC16 encoding, two bytes make one character. |
| 1569 // string_encoding: if Latin1: 0x08 | 1568 // string_encoding: if Latin1: 0x04 |
| 1570 // if UC16: 0x00 | 1569 // if UC16: 0x00 |
| 1571 STATIC_ASSERT(kStringEncodingMask == 0x08); | 1570 STATIC_ASSERT(kStringEncodingMask == 0x04); |
| 1572 __ Ubfx(string_encoding, string_encoding, 3, 1); | 1571 __ Ubfx(string_encoding, string_encoding, 2, 1); |
| 1573 __ Eor(string_encoding, string_encoding, 1); | 1572 __ Eor(string_encoding, string_encoding, 1); |
| 1574 // string_encoding: if Latin1: 0 | 1573 // string_encoding: if Latin1: 0 |
| 1575 // if UC16: 1 | 1574 // if UC16: 1 |
| 1576 | 1575 |
| 1577 // Convert string positions from characters to bytes. | 1576 // Convert string positions from characters to bytes. |
| 1578 // Previous index is in x1. | 1577 // Previous index is in x1. |
| 1579 __ Lsl(previous_index_in_bytes, w1, string_encoding); | 1578 __ Lsl(previous_index_in_bytes, w1, string_encoding); |
| 1580 __ Lsl(length, length, string_encoding); | 1579 __ Lsl(length, length, string_encoding); |
| 1581 __ Lsl(sliced_string_offset, sliced_string_offset, string_encoding); | 1580 __ Lsl(sliced_string_offset, sliced_string_offset, string_encoding); |
| 1582 | 1581 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 __ B(&seq_string); // Go to (4). | 1774 __ B(&seq_string); // Go to (4). |
| 1776 | 1775 |
| 1777 // (7) If this is a short external string or not a string, bail out to | 1776 // (7) If this is a short external string or not a string, bail out to |
| 1778 // runtime. | 1777 // runtime. |
| 1779 __ Bind(¬_long_external); | 1778 __ Bind(¬_long_external); |
| 1780 STATIC_ASSERT(kShortExternalStringTag != 0); | 1779 STATIC_ASSERT(kShortExternalStringTag != 0); |
| 1781 __ TestAndBranchIfAnySet(string_representation, | 1780 __ TestAndBranchIfAnySet(string_representation, |
| 1782 kShortExternalStringMask | kIsNotStringMask, | 1781 kShortExternalStringMask | kIsNotStringMask, |
| 1783 &runtime); | 1782 &runtime); |
| 1784 | 1783 |
| 1785 // (8) Sliced or thin string. Replace subject with parent. | 1784 // (8) Sliced string. Replace subject with parent. |
| 1786 Label thin_string; | |
| 1787 __ Cmp(string_representation, kThinStringTag); | |
| 1788 __ B(eq, &thin_string); | |
| 1789 __ Ldr(sliced_string_offset, | 1785 __ Ldr(sliced_string_offset, |
| 1790 UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset)); | 1786 UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 1791 __ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | 1787 __ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 1792 __ B(&check_underlying); // Go to (1). | 1788 __ B(&check_underlying); // Go to (1). |
| 1793 | |
| 1794 __ bind(&thin_string); | |
| 1795 __ Ldr(subject, FieldMemOperand(subject, ThinString::kActualOffset)); | |
| 1796 __ B(&check_underlying); // Go to (1). | |
| 1797 #endif | 1789 #endif |
| 1798 } | 1790 } |
| 1799 | 1791 |
| 1800 | 1792 |
| 1801 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub, | 1793 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub, |
| 1802 Register argc, Register function, | 1794 Register argc, Register function, |
| 1803 Register feedback_vector, Register index, | 1795 Register feedback_vector, Register index, |
| 1804 Register new_target) { | 1796 Register new_target) { |
| 1805 FrameScope scope(masm, StackFrame::INTERNAL); | 1797 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1806 | 1798 |
| (...skipping 2671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4478 kStackUnwindSpace, NULL, spill_offset, | 4470 kStackUnwindSpace, NULL, spill_offset, |
| 4479 return_value_operand, NULL); | 4471 return_value_operand, NULL); |
| 4480 } | 4472 } |
| 4481 | 4473 |
| 4482 #undef __ | 4474 #undef __ |
| 4483 | 4475 |
| 4484 } // namespace internal | 4476 } // namespace internal |
| 4485 } // namespace v8 | 4477 } // namespace v8 |
| 4486 | 4478 |
| 4487 #endif // V8_TARGET_ARCH_ARM64 | 4479 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |