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 |