| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
| 8 | 8 |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 3488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3499 | 3499 |
| 3500 __ AssertString(x0); | 3500 __ AssertString(x0); |
| 3501 | 3501 |
| 3502 __ Ldr(x10, FieldMemOperand(x0, String::kHashFieldOffset)); | 3502 __ Ldr(x10, FieldMemOperand(x0, String::kHashFieldOffset)); |
| 3503 __ IndexFromHash(x10, x0); | 3503 __ IndexFromHash(x10, x0); |
| 3504 | 3504 |
| 3505 context()->Plug(x0); | 3505 context()->Plug(x0); |
| 3506 } | 3506 } |
| 3507 | 3507 |
| 3508 | 3508 |
| 3509 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { | 3509 void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) { |
| 3510 ASM_LOCATION("FullCodeGenerator::EmitFastAsciiArrayJoin"); | 3510 ASM_LOCATION("FullCodeGenerator::EmitFastOneByteArrayJoin"); |
| 3511 | 3511 |
| 3512 ZoneList<Expression*>* args = expr->arguments(); | 3512 ZoneList<Expression*>* args = expr->arguments(); |
| 3513 DCHECK(args->length() == 2); | 3513 DCHECK(args->length() == 2); |
| 3514 VisitForStackValue(args->at(1)); | 3514 VisitForStackValue(args->at(1)); |
| 3515 VisitForAccumulatorValue(args->at(0)); | 3515 VisitForAccumulatorValue(args->at(0)); |
| 3516 | 3516 |
| 3517 Register array = x0; | 3517 Register array = x0; |
| 3518 Register result = x0; | 3518 Register result = x0; |
| 3519 Register elements = x1; | 3519 Register elements = x1; |
| 3520 Register element = x2; | 3520 Register element = x2; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3552 __ Ldrsw(array_length, | 3552 __ Ldrsw(array_length, |
| 3553 UntagSmiFieldMemOperand(array, JSArray::kLengthOffset)); | 3553 UntagSmiFieldMemOperand(array, JSArray::kLengthOffset)); |
| 3554 __ Cbnz(array_length, &non_trivial_array); | 3554 __ Cbnz(array_length, &non_trivial_array); |
| 3555 __ LoadRoot(result, Heap::kempty_stringRootIndex); | 3555 __ LoadRoot(result, Heap::kempty_stringRootIndex); |
| 3556 __ B(&done); | 3556 __ B(&done); |
| 3557 | 3557 |
| 3558 __ Bind(&non_trivial_array); | 3558 __ Bind(&non_trivial_array); |
| 3559 // Get the FixedArray containing array's elements. | 3559 // Get the FixedArray containing array's elements. |
| 3560 __ Ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset)); | 3560 __ Ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset)); |
| 3561 | 3561 |
| 3562 // Check that all array elements are sequential ASCII strings, and | 3562 // Check that all array elements are sequential one-byte strings, and |
| 3563 // accumulate the sum of their lengths. | 3563 // accumulate the sum of their lengths. |
| 3564 __ Mov(string_length, 0); | 3564 __ Mov(string_length, 0); |
| 3565 __ Add(element, elements, FixedArray::kHeaderSize - kHeapObjectTag); | 3565 __ Add(element, elements, FixedArray::kHeaderSize - kHeapObjectTag); |
| 3566 __ Add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); | 3566 __ Add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); |
| 3567 // Loop condition: while (element < elements_end). | 3567 // Loop condition: while (element < elements_end). |
| 3568 // Live values in registers: | 3568 // Live values in registers: |
| 3569 // elements: Fixed array of strings. | 3569 // elements: Fixed array of strings. |
| 3570 // array_length: Length of the fixed array of strings (not smi) | 3570 // array_length: Length of the fixed array of strings (not smi) |
| 3571 // separator: Separator string | 3571 // separator: Separator string |
| 3572 // string_length: Accumulated sum of string lengths (not smi). | 3572 // string_length: Accumulated sum of string lengths (not smi). |
| 3573 // element: Current array element. | 3573 // element: Current array element. |
| 3574 // elements_end: Array end. | 3574 // elements_end: Array end. |
| 3575 if (FLAG_debug_code) { | 3575 if (FLAG_debug_code) { |
| 3576 __ Cmp(array_length, 0); | 3576 __ Cmp(array_length, 0); |
| 3577 __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin); | 3577 __ Assert(gt, kNoEmptyArraysHereInEmitFastOneByteArrayJoin); |
| 3578 } | 3578 } |
| 3579 __ Bind(&loop); | 3579 __ Bind(&loop); |
| 3580 __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 3580 __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
| 3581 __ JumpIfSmi(string, &bailout); | 3581 __ JumpIfSmi(string, &bailout); |
| 3582 __ Ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); | 3582 __ Ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 3583 __ Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 3583 __ Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 3584 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); | 3584 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout); |
| 3585 __ Ldrsw(scratch1, | 3585 __ Ldrsw(scratch1, |
| 3586 UntagSmiFieldMemOperand(string, SeqOneByteString::kLengthOffset)); | 3586 UntagSmiFieldMemOperand(string, SeqOneByteString::kLengthOffset)); |
| 3587 __ Adds(string_length, string_length, scratch1); | 3587 __ Adds(string_length, string_length, scratch1); |
| 3588 __ B(vs, &bailout); | 3588 __ B(vs, &bailout); |
| 3589 __ Cmp(element, elements_end); | 3589 __ Cmp(element, elements_end); |
| 3590 __ B(lt, &loop); | 3590 __ B(lt, &loop); |
| 3591 | 3591 |
| 3592 // If array_length is 1, return elements[0], a string. | 3592 // If array_length is 1, return elements[0], a string. |
| 3593 __ Cmp(array_length, 1); | 3593 __ Cmp(array_length, 1); |
| 3594 __ B(ne, ¬_size_one_array); | 3594 __ B(ne, ¬_size_one_array); |
| 3595 __ Ldr(result, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 3595 __ Ldr(result, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 3596 __ B(&done); | 3596 __ B(&done); |
| 3597 | 3597 |
| 3598 __ Bind(¬_size_one_array); | 3598 __ Bind(¬_size_one_array); |
| 3599 | 3599 |
| 3600 // Live values in registers: | 3600 // Live values in registers: |
| 3601 // separator: Separator string | 3601 // separator: Separator string |
| 3602 // array_length: Length of the array (not smi). | 3602 // array_length: Length of the array (not smi). |
| 3603 // string_length: Sum of string lengths (not smi). | 3603 // string_length: Sum of string lengths (not smi). |
| 3604 // elements: FixedArray of strings. | 3604 // elements: FixedArray of strings. |
| 3605 | 3605 |
| 3606 // Check that the separator is a flat ASCII string. | 3606 // Check that the separator is a flat one-byte string. |
| 3607 __ JumpIfSmi(separator, &bailout); | 3607 __ JumpIfSmi(separator, &bailout); |
| 3608 __ Ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); | 3608 __ Ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); |
| 3609 __ Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 3609 __ Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 3610 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); | 3610 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout); |
| 3611 | 3611 |
| 3612 // Add (separator length times array_length) - separator length to the | 3612 // Add (separator length times array_length) - separator length to the |
| 3613 // string_length to get the length of the result string. | 3613 // string_length to get the length of the result string. |
| 3614 // Load the separator length as untagged. | 3614 // Load the separator length as untagged. |
| 3615 // We assume little endianness, and that the length is positive. | 3615 // We assume little endianness, and that the length is positive. |
| 3616 __ Ldrsw(separator_length, | 3616 __ Ldrsw(separator_length, |
| 3617 UntagSmiFieldMemOperand(separator, | 3617 UntagSmiFieldMemOperand(separator, |
| 3618 SeqOneByteString::kLengthOffset)); | 3618 SeqOneByteString::kLengthOffset)); |
| 3619 __ Sub(string_length, string_length, separator_length); | 3619 __ Sub(string_length, string_length, separator_length); |
| 3620 __ Umaddl(string_length, array_length.W(), separator_length.W(), | 3620 __ Umaddl(string_length, array_length.W(), separator_length.W(), |
| 3621 string_length); | 3621 string_length); |
| 3622 | 3622 |
| 3623 // Get first element in the array. | 3623 // Get first element in the array. |
| 3624 __ Add(element, elements, FixedArray::kHeaderSize - kHeapObjectTag); | 3624 __ Add(element, elements, FixedArray::kHeaderSize - kHeapObjectTag); |
| 3625 // Live values in registers: | 3625 // Live values in registers: |
| 3626 // element: First array element | 3626 // element: First array element |
| 3627 // separator: Separator string | 3627 // separator: Separator string |
| 3628 // string_length: Length of result string (not smi) | 3628 // string_length: Length of result string (not smi) |
| 3629 // array_length: Length of the array (not smi). | 3629 // array_length: Length of the array (not smi). |
| 3630 __ AllocateAsciiString(result, string_length, scratch1, scratch2, scratch3, | 3630 __ AllocateOneByteString(result, string_length, scratch1, scratch2, scratch3, |
| 3631 &bailout); | 3631 &bailout); |
| 3632 | 3632 |
| 3633 // Prepare for looping. Set up elements_end to end of the array. Set | 3633 // Prepare for looping. Set up elements_end to end of the array. Set |
| 3634 // result_pos to the position of the result where to write the first | 3634 // result_pos to the position of the result where to write the first |
| 3635 // character. | 3635 // character. |
| 3636 // TODO(all): useless unless AllocateAsciiString trashes the register. | 3636 // TODO(all): useless unless AllocateOneByteString trashes the register. |
| 3637 __ Add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); | 3637 __ Add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); |
| 3638 __ Add(result_pos, result, SeqOneByteString::kHeaderSize - kHeapObjectTag); | 3638 __ Add(result_pos, result, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
| 3639 | 3639 |
| 3640 // Check the length of the separator. | 3640 // Check the length of the separator. |
| 3641 __ Cmp(separator_length, 1); | 3641 __ Cmp(separator_length, 1); |
| 3642 __ B(eq, &one_char_separator); | 3642 __ B(eq, &one_char_separator); |
| 3643 __ B(gt, &long_separator); | 3643 __ B(gt, &long_separator); |
| 3644 | 3644 |
| 3645 // Empty separator case | 3645 // Empty separator case |
| 3646 __ Bind(&empty_separator_loop); | 3646 __ Bind(&empty_separator_loop); |
| 3647 // Live values in registers: | 3647 // Live values in registers: |
| 3648 // result_pos: the position to which we are currently copying characters. | 3648 // result_pos: the position to which we are currently copying characters. |
| 3649 // element: Current array element. | 3649 // element: Current array element. |
| 3650 // elements_end: Array end. | 3650 // elements_end: Array end. |
| 3651 | 3651 |
| 3652 // Copy next array element to the result. | 3652 // Copy next array element to the result. |
| 3653 __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 3653 __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
| 3654 __ Ldrsw(string_length, | 3654 __ Ldrsw(string_length, |
| 3655 UntagSmiFieldMemOperand(string, String::kLengthOffset)); | 3655 UntagSmiFieldMemOperand(string, String::kLengthOffset)); |
| 3656 __ Add(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); | 3656 __ Add(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
| 3657 __ CopyBytes(result_pos, string, string_length, scratch1); | 3657 __ CopyBytes(result_pos, string, string_length, scratch1); |
| 3658 __ Cmp(element, elements_end); | 3658 __ Cmp(element, elements_end); |
| 3659 __ B(lt, &empty_separator_loop); // End while (element < elements_end). | 3659 __ B(lt, &empty_separator_loop); // End while (element < elements_end). |
| 3660 __ B(&done); | 3660 __ B(&done); |
| 3661 | 3661 |
| 3662 // One-character separator case | 3662 // One-character separator case |
| 3663 __ Bind(&one_char_separator); | 3663 __ Bind(&one_char_separator); |
| 3664 // Replace separator with its ASCII character value. | 3664 // Replace separator with its one-byte character value. |
| 3665 __ Ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); | 3665 __ Ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); |
| 3666 // Jump into the loop after the code that copies the separator, so the first | 3666 // Jump into the loop after the code that copies the separator, so the first |
| 3667 // element is not preceded by a separator | 3667 // element is not preceded by a separator |
| 3668 __ B(&one_char_separator_loop_entry); | 3668 __ B(&one_char_separator_loop_entry); |
| 3669 | 3669 |
| 3670 __ Bind(&one_char_separator_loop); | 3670 __ Bind(&one_char_separator_loop); |
| 3671 // Live values in registers: | 3671 // Live values in registers: |
| 3672 // result_pos: the position to which we are currently copying characters. | 3672 // result_pos: the position to which we are currently copying characters. |
| 3673 // element: Current array element. | 3673 // element: Current array element. |
| 3674 // elements_end: Array end. | 3674 // elements_end: Array end. |
| 3675 // separator: Single separator ASCII char (in lower byte). | 3675 // separator: Single separator one-byte char (in lower byte). |
| 3676 | 3676 |
| 3677 // Copy the separator character to the result. | 3677 // Copy the separator character to the result. |
| 3678 __ Strb(separator, MemOperand(result_pos, 1, PostIndex)); | 3678 __ Strb(separator, MemOperand(result_pos, 1, PostIndex)); |
| 3679 | 3679 |
| 3680 // Copy next array element to the result. | 3680 // Copy next array element to the result. |
| 3681 __ Bind(&one_char_separator_loop_entry); | 3681 __ Bind(&one_char_separator_loop_entry); |
| 3682 __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 3682 __ Ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
| 3683 __ Ldrsw(string_length, | 3683 __ Ldrsw(string_length, |
| 3684 UntagSmiFieldMemOperand(string, String::kLengthOffset)); | 3684 UntagSmiFieldMemOperand(string, String::kLengthOffset)); |
| 3685 __ Add(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); | 3685 __ Add(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
| (...skipping 1225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4911 return previous_; | 4911 return previous_; |
| 4912 } | 4912 } |
| 4913 | 4913 |
| 4914 | 4914 |
| 4915 #undef __ | 4915 #undef __ |
| 4916 | 4916 |
| 4917 | 4917 |
| 4918 } } // namespace v8::internal | 4918 } } // namespace v8::internal |
| 4919 | 4919 |
| 4920 #endif // V8_TARGET_ARCH_ARM64 | 4920 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |