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 |