| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 3540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3551 times_pointer_size, | 3551 times_pointer_size, |
| 3552 FixedArray::kHeaderSize)); | 3552 FixedArray::kHeaderSize)); |
| 3553 __ JumpIfSmi(string, &bailout); | 3553 __ JumpIfSmi(string, &bailout); |
| 3554 __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset)); | 3554 __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset)); |
| 3555 __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3555 __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
| 3556 __ andb(scratch, Immediate( | 3556 __ andb(scratch, Immediate( |
| 3557 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | 3557 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); |
| 3558 __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag)); | 3558 __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag)); |
| 3559 __ j(not_equal, &bailout); | 3559 __ j(not_equal, &bailout); |
| 3560 __ AddSmiField(string_length, | 3560 __ AddSmiField(string_length, |
| 3561 FieldOperand(string, SeqAsciiString::kLengthOffset)); | 3561 FieldOperand(string, SeqOneByteString::kLengthOffset)); |
| 3562 __ j(overflow, &bailout); | 3562 __ j(overflow, &bailout); |
| 3563 __ incl(index); | 3563 __ incl(index); |
| 3564 __ cmpl(index, array_length); | 3564 __ cmpl(index, array_length); |
| 3565 __ j(less, &loop); | 3565 __ j(less, &loop); |
| 3566 | 3566 |
| 3567 // Live registers: | 3567 // Live registers: |
| 3568 // string_length: Sum of string lengths. | 3568 // string_length: Sum of string lengths. |
| 3569 // elements: FixedArray of strings. | 3569 // elements: FixedArray of strings. |
| 3570 // index: Array length. | 3570 // index: Array length. |
| 3571 // array_length: Array length. | 3571 // array_length: Array length. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3598 __ j(not_equal, &bailout); | 3598 __ j(not_equal, &bailout); |
| 3599 | 3599 |
| 3600 // Live registers: | 3600 // Live registers: |
| 3601 // string_length: Sum of string lengths. | 3601 // string_length: Sum of string lengths. |
| 3602 // elements: FixedArray of strings. | 3602 // elements: FixedArray of strings. |
| 3603 // index: Array length. | 3603 // index: Array length. |
| 3604 // string: Separator string. | 3604 // string: Separator string. |
| 3605 | 3605 |
| 3606 // Add (separator length times (array_length - 1)) to string_length. | 3606 // Add (separator length times (array_length - 1)) to string_length. |
| 3607 __ SmiToInteger32(scratch, | 3607 __ SmiToInteger32(scratch, |
| 3608 FieldOperand(string, SeqAsciiString::kLengthOffset)); | 3608 FieldOperand(string, SeqOneByteString::kLengthOffset)); |
| 3609 __ decl(index); | 3609 __ decl(index); |
| 3610 __ imull(scratch, index); | 3610 __ imull(scratch, index); |
| 3611 __ j(overflow, &bailout); | 3611 __ j(overflow, &bailout); |
| 3612 __ addl(string_length, scratch); | 3612 __ addl(string_length, scratch); |
| 3613 __ j(overflow, &bailout); | 3613 __ j(overflow, &bailout); |
| 3614 | 3614 |
| 3615 // Live registers and stack values: | 3615 // Live registers and stack values: |
| 3616 // string_length: Total length of result string. | 3616 // string_length: Total length of result string. |
| 3617 // elements: FixedArray of strings. | 3617 // elements: FixedArray of strings. |
| 3618 __ AllocateAsciiString(result_pos, string_length, scratch, | 3618 __ AllocateAsciiString(result_pos, string_length, scratch, |
| 3619 index, string, &bailout); | 3619 index, string, &bailout); |
| 3620 __ movq(result_operand, result_pos); | 3620 __ movq(result_operand, result_pos); |
| 3621 __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize)); | 3621 __ lea(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize)); |
| 3622 | 3622 |
| 3623 __ movq(string, separator_operand); | 3623 __ movq(string, separator_operand); |
| 3624 __ SmiCompare(FieldOperand(string, SeqAsciiString::kLengthOffset), | 3624 __ SmiCompare(FieldOperand(string, SeqOneByteString::kLengthOffset), |
| 3625 Smi::FromInt(1)); | 3625 Smi::FromInt(1)); |
| 3626 __ j(equal, &one_char_separator); | 3626 __ j(equal, &one_char_separator); |
| 3627 __ j(greater, &long_separator); | 3627 __ j(greater, &long_separator); |
| 3628 | 3628 |
| 3629 | 3629 |
| 3630 // Empty separator case: | 3630 // Empty separator case: |
| 3631 __ Set(index, 0); | 3631 __ Set(index, 0); |
| 3632 __ movl(scratch, array_length_operand); | 3632 __ movl(scratch, array_length_operand); |
| 3633 __ jmp(&loop_1_condition); | 3633 __ jmp(&loop_1_condition); |
| 3634 // Loop condition: while (index < array_length). | 3634 // Loop condition: while (index < array_length). |
| 3635 __ bind(&loop_1); | 3635 __ bind(&loop_1); |
| 3636 // Each iteration of the loop concatenates one string to the result. | 3636 // Each iteration of the loop concatenates one string to the result. |
| 3637 // Live values in registers: | 3637 // Live values in registers: |
| 3638 // index: which element of the elements array we are adding to the result. | 3638 // index: which element of the elements array we are adding to the result. |
| 3639 // result_pos: the position to which we are currently copying characters. | 3639 // result_pos: the position to which we are currently copying characters. |
| 3640 // elements: the FixedArray of strings we are joining. | 3640 // elements: the FixedArray of strings we are joining. |
| 3641 // scratch: array length. | 3641 // scratch: array length. |
| 3642 | 3642 |
| 3643 // Get string = array[index]. | 3643 // Get string = array[index]. |
| 3644 __ movq(string, FieldOperand(elements, index, | 3644 __ movq(string, FieldOperand(elements, index, |
| 3645 times_pointer_size, | 3645 times_pointer_size, |
| 3646 FixedArray::kHeaderSize)); | 3646 FixedArray::kHeaderSize)); |
| 3647 __ SmiToInteger32(string_length, | 3647 __ SmiToInteger32(string_length, |
| 3648 FieldOperand(string, String::kLengthOffset)); | 3648 FieldOperand(string, String::kLengthOffset)); |
| 3649 __ lea(string, | 3649 __ lea(string, |
| 3650 FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3650 FieldOperand(string, SeqOneByteString::kHeaderSize)); |
| 3651 __ CopyBytes(result_pos, string, string_length); | 3651 __ CopyBytes(result_pos, string, string_length); |
| 3652 __ incl(index); | 3652 __ incl(index); |
| 3653 __ bind(&loop_1_condition); | 3653 __ bind(&loop_1_condition); |
| 3654 __ cmpl(index, scratch); | 3654 __ cmpl(index, scratch); |
| 3655 __ j(less, &loop_1); // Loop while (index < array_length). | 3655 __ j(less, &loop_1); // Loop while (index < array_length). |
| 3656 __ jmp(&done); | 3656 __ jmp(&done); |
| 3657 | 3657 |
| 3658 // Generic bailout code used from several places. | 3658 // Generic bailout code used from several places. |
| 3659 __ bind(&bailout); | 3659 __ bind(&bailout); |
| 3660 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 3660 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 3661 __ jmp(&return_result); | 3661 __ jmp(&return_result); |
| 3662 | 3662 |
| 3663 | 3663 |
| 3664 // One-character separator case | 3664 // One-character separator case |
| 3665 __ bind(&one_char_separator); | 3665 __ bind(&one_char_separator); |
| 3666 // Get the separator ASCII character value. | 3666 // Get the separator ASCII character value. |
| 3667 // Register "string" holds the separator. | 3667 // Register "string" holds the separator. |
| 3668 __ movzxbl(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3668 __ movzxbl(scratch, FieldOperand(string, SeqOneByteString::kHeaderSize)); |
| 3669 __ Set(index, 0); | 3669 __ Set(index, 0); |
| 3670 // Jump into the loop after the code that copies the separator, so the first | 3670 // Jump into the loop after the code that copies the separator, so the first |
| 3671 // element is not preceded by a separator | 3671 // element is not preceded by a separator |
| 3672 __ jmp(&loop_2_entry); | 3672 __ jmp(&loop_2_entry); |
| 3673 // Loop condition: while (index < length). | 3673 // Loop condition: while (index < length). |
| 3674 __ bind(&loop_2); | 3674 __ bind(&loop_2); |
| 3675 // Each iteration of the loop concatenates one string to the result. | 3675 // Each iteration of the loop concatenates one string to the result. |
| 3676 // Live values in registers: | 3676 // Live values in registers: |
| 3677 // elements: The FixedArray of strings we are joining. | 3677 // elements: The FixedArray of strings we are joining. |
| 3678 // index: which element of the elements array we are adding to the result. | 3678 // index: which element of the elements array we are adding to the result. |
| 3679 // result_pos: the position to which we are currently copying characters. | 3679 // result_pos: the position to which we are currently copying characters. |
| 3680 // scratch: Separator character. | 3680 // scratch: Separator character. |
| 3681 | 3681 |
| 3682 // Copy the separator character to the result. | 3682 // Copy the separator character to the result. |
| 3683 __ movb(Operand(result_pos, 0), scratch); | 3683 __ movb(Operand(result_pos, 0), scratch); |
| 3684 __ incq(result_pos); | 3684 __ incq(result_pos); |
| 3685 | 3685 |
| 3686 __ bind(&loop_2_entry); | 3686 __ bind(&loop_2_entry); |
| 3687 // Get string = array[index]. | 3687 // Get string = array[index]. |
| 3688 __ movq(string, FieldOperand(elements, index, | 3688 __ movq(string, FieldOperand(elements, index, |
| 3689 times_pointer_size, | 3689 times_pointer_size, |
| 3690 FixedArray::kHeaderSize)); | 3690 FixedArray::kHeaderSize)); |
| 3691 __ SmiToInteger32(string_length, | 3691 __ SmiToInteger32(string_length, |
| 3692 FieldOperand(string, String::kLengthOffset)); | 3692 FieldOperand(string, String::kLengthOffset)); |
| 3693 __ lea(string, | 3693 __ lea(string, |
| 3694 FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3694 FieldOperand(string, SeqOneByteString::kHeaderSize)); |
| 3695 __ CopyBytes(result_pos, string, string_length); | 3695 __ CopyBytes(result_pos, string, string_length); |
| 3696 __ incl(index); | 3696 __ incl(index); |
| 3697 __ cmpl(index, array_length_operand); | 3697 __ cmpl(index, array_length_operand); |
| 3698 __ j(less, &loop_2); // End while (index < length). | 3698 __ j(less, &loop_2); // End while (index < length). |
| 3699 __ jmp(&done); | 3699 __ jmp(&done); |
| 3700 | 3700 |
| 3701 | 3701 |
| 3702 // Long separator case (separator is more than one character). | 3702 // Long separator case (separator is more than one character). |
| 3703 __ bind(&long_separator); | 3703 __ bind(&long_separator); |
| 3704 | 3704 |
| 3705 // Make elements point to end of elements array, and index | 3705 // Make elements point to end of elements array, and index |
| 3706 // count from -array_length to zero, so we don't need to maintain | 3706 // count from -array_length to zero, so we don't need to maintain |
| 3707 // a loop limit. | 3707 // a loop limit. |
| 3708 __ movl(index, array_length_operand); | 3708 __ movl(index, array_length_operand); |
| 3709 __ lea(elements, FieldOperand(elements, index, times_pointer_size, | 3709 __ lea(elements, FieldOperand(elements, index, times_pointer_size, |
| 3710 FixedArray::kHeaderSize)); | 3710 FixedArray::kHeaderSize)); |
| 3711 __ neg(index); | 3711 __ neg(index); |
| 3712 | 3712 |
| 3713 // Replace separator string with pointer to its first character, and | 3713 // Replace separator string with pointer to its first character, and |
| 3714 // make scratch be its length. | 3714 // make scratch be its length. |
| 3715 __ movq(string, separator_operand); | 3715 __ movq(string, separator_operand); |
| 3716 __ SmiToInteger32(scratch, | 3716 __ SmiToInteger32(scratch, |
| 3717 FieldOperand(string, String::kLengthOffset)); | 3717 FieldOperand(string, String::kLengthOffset)); |
| 3718 __ lea(string, | 3718 __ lea(string, |
| 3719 FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3719 FieldOperand(string, SeqOneByteString::kHeaderSize)); |
| 3720 __ movq(separator_operand, string); | 3720 __ movq(separator_operand, string); |
| 3721 | 3721 |
| 3722 // Jump into the loop after the code that copies the separator, so the first | 3722 // Jump into the loop after the code that copies the separator, so the first |
| 3723 // element is not preceded by a separator | 3723 // element is not preceded by a separator |
| 3724 __ jmp(&loop_3_entry); | 3724 __ jmp(&loop_3_entry); |
| 3725 // Loop condition: while (index < length). | 3725 // Loop condition: while (index < length). |
| 3726 __ bind(&loop_3); | 3726 __ bind(&loop_3); |
| 3727 // Each iteration of the loop concatenates one string to the result. | 3727 // Each iteration of the loop concatenates one string to the result. |
| 3728 // Live values in registers: | 3728 // Live values in registers: |
| 3729 // index: which element of the elements array we are adding to the result. | 3729 // index: which element of the elements array we are adding to the result. |
| 3730 // result_pos: the position to which we are currently copying characters. | 3730 // result_pos: the position to which we are currently copying characters. |
| 3731 // scratch: Separator length. | 3731 // scratch: Separator length. |
| 3732 // separator_operand (rsp[0x10]): Address of first char of separator. | 3732 // separator_operand (rsp[0x10]): Address of first char of separator. |
| 3733 | 3733 |
| 3734 // Copy the separator to the result. | 3734 // Copy the separator to the result. |
| 3735 __ movq(string, separator_operand); | 3735 __ movq(string, separator_operand); |
| 3736 __ movl(string_length, scratch); | 3736 __ movl(string_length, scratch); |
| 3737 __ CopyBytes(result_pos, string, string_length, 2); | 3737 __ CopyBytes(result_pos, string, string_length, 2); |
| 3738 | 3738 |
| 3739 __ bind(&loop_3_entry); | 3739 __ bind(&loop_3_entry); |
| 3740 // Get string = array[index]. | 3740 // Get string = array[index]. |
| 3741 __ movq(string, Operand(elements, index, times_pointer_size, 0)); | 3741 __ movq(string, Operand(elements, index, times_pointer_size, 0)); |
| 3742 __ SmiToInteger32(string_length, | 3742 __ SmiToInteger32(string_length, |
| 3743 FieldOperand(string, String::kLengthOffset)); | 3743 FieldOperand(string, String::kLengthOffset)); |
| 3744 __ lea(string, | 3744 __ lea(string, |
| 3745 FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3745 FieldOperand(string, SeqOneByteString::kHeaderSize)); |
| 3746 __ CopyBytes(result_pos, string, string_length); | 3746 __ CopyBytes(result_pos, string, string_length); |
| 3747 __ incq(index); | 3747 __ incq(index); |
| 3748 __ j(not_equal, &loop_3); // Loop while (index < 0). | 3748 __ j(not_equal, &loop_3); // Loop while (index < 0). |
| 3749 | 3749 |
| 3750 __ bind(&done); | 3750 __ bind(&done); |
| 3751 __ movq(rax, result_operand); | 3751 __ movq(rax, result_operand); |
| 3752 | 3752 |
| 3753 __ bind(&return_result); | 3753 __ bind(&return_result); |
| 3754 // Drop temp values from the stack, and restore context register. | 3754 // Drop temp values from the stack, and restore context register. |
| 3755 __ addq(rsp, Immediate(3 * kPointerSize)); | 3755 __ addq(rsp, Immediate(3 * kPointerSize)); |
| (...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4492 *context_length = 0; | 4492 *context_length = 0; |
| 4493 return previous_; | 4493 return previous_; |
| 4494 } | 4494 } |
| 4495 | 4495 |
| 4496 | 4496 |
| 4497 #undef __ | 4497 #undef __ |
| 4498 | 4498 |
| 4499 } } // namespace v8::internal | 4499 } } // namespace v8::internal |
| 4500 | 4500 |
| 4501 #endif // V8_TARGET_ARCH_X64 | 4501 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |