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 3562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3573 times_pointer_size, | 3573 times_pointer_size, |
3574 FixedArray::kHeaderSize)); | 3574 FixedArray::kHeaderSize)); |
3575 __ JumpIfSmi(string, &bailout); | 3575 __ JumpIfSmi(string, &bailout); |
3576 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); | 3576 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); |
3577 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3577 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
3578 __ and_(scratch, Immediate( | 3578 __ and_(scratch, Immediate( |
3579 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | 3579 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); |
3580 __ cmp(scratch, kStringTag | kOneByteStringTag | kSeqStringTag); | 3580 __ cmp(scratch, kStringTag | kOneByteStringTag | kSeqStringTag); |
3581 __ j(not_equal, &bailout); | 3581 __ j(not_equal, &bailout); |
3582 __ add(string_length, | 3582 __ add(string_length, |
3583 FieldOperand(string, SeqAsciiString::kLengthOffset)); | 3583 FieldOperand(string, SeqOneByteString::kLengthOffset)); |
3584 __ j(overflow, &bailout); | 3584 __ j(overflow, &bailout); |
3585 __ add(index, Immediate(1)); | 3585 __ add(index, Immediate(1)); |
3586 __ cmp(index, array_length); | 3586 __ cmp(index, array_length); |
3587 __ j(less, &loop); | 3587 __ j(less, &loop); |
3588 | 3588 |
3589 // If array_length is 1, return elements[0], a string. | 3589 // If array_length is 1, return elements[0], a string. |
3590 __ cmp(array_length, 1); | 3590 __ cmp(array_length, 1); |
3591 __ j(not_equal, ¬_size_one_array); | 3591 __ j(not_equal, ¬_size_one_array); |
3592 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize)); | 3592 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize)); |
3593 __ mov(result_operand, scratch); | 3593 __ mov(result_operand, scratch); |
(...skipping 16 matching lines...) Expand all Loading... |
3610 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3610 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
3611 __ and_(scratch, Immediate( | 3611 __ and_(scratch, Immediate( |
3612 kIsNotStringMask | kStringEncodingMask | kAsciiDataHintMask | | 3612 kIsNotStringMask | kStringEncodingMask | kAsciiDataHintMask | |
3613 kStringRepresentationMask)); | 3613 kStringRepresentationMask)); |
3614 __ cmp(scratch, ASCII_STRING_TYPE); | 3614 __ cmp(scratch, ASCII_STRING_TYPE); |
3615 __ j(not_equal, &bailout); | 3615 __ j(not_equal, &bailout); |
3616 | 3616 |
3617 // Add (separator length times array_length) - separator length | 3617 // Add (separator length times array_length) - separator length |
3618 // to string_length. | 3618 // to string_length. |
3619 __ mov(scratch, separator_operand); | 3619 __ mov(scratch, separator_operand); |
3620 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset)); | 3620 __ mov(scratch, FieldOperand(scratch, SeqOneByteString::kLengthOffset)); |
3621 __ sub(string_length, scratch); // May be negative, temporarily. | 3621 __ sub(string_length, scratch); // May be negative, temporarily. |
3622 __ imul(scratch, array_length_operand); | 3622 __ imul(scratch, array_length_operand); |
3623 __ j(overflow, &bailout); | 3623 __ j(overflow, &bailout); |
3624 __ add(string_length, scratch); | 3624 __ add(string_length, scratch); |
3625 __ j(overflow, &bailout); | 3625 __ j(overflow, &bailout); |
3626 | 3626 |
3627 __ shr(string_length, 1); | 3627 __ shr(string_length, 1); |
3628 // Live registers and stack values: | 3628 // Live registers and stack values: |
3629 // string_length | 3629 // string_length |
3630 // elements | 3630 // elements |
3631 __ AllocateAsciiString(result_pos, string_length, scratch, | 3631 __ AllocateAsciiString(result_pos, string_length, scratch, |
3632 index, string, &bailout); | 3632 index, string, &bailout); |
3633 __ mov(result_operand, result_pos); | 3633 __ mov(result_operand, result_pos); |
3634 __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize)); | 3634 __ lea(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize)); |
3635 | 3635 |
3636 | 3636 |
3637 __ mov(string, separator_operand); | 3637 __ mov(string, separator_operand); |
3638 __ cmp(FieldOperand(string, SeqAsciiString::kLengthOffset), | 3638 __ cmp(FieldOperand(string, SeqOneByteString::kLengthOffset), |
3639 Immediate(Smi::FromInt(1))); | 3639 Immediate(Smi::FromInt(1))); |
3640 __ j(equal, &one_char_separator); | 3640 __ j(equal, &one_char_separator); |
3641 __ j(greater, &long_separator); | 3641 __ j(greater, &long_separator); |
3642 | 3642 |
3643 | 3643 |
3644 // Empty separator case | 3644 // Empty separator case |
3645 __ mov(index, Immediate(0)); | 3645 __ mov(index, Immediate(0)); |
3646 __ jmp(&loop_1_condition); | 3646 __ jmp(&loop_1_condition); |
3647 // Loop condition: while (index < length). | 3647 // Loop condition: while (index < length). |
3648 __ bind(&loop_1); | 3648 __ bind(&loop_1); |
3649 // Each iteration of the loop concatenates one string to the result. | 3649 // Each iteration of the loop concatenates one string to the result. |
3650 // Live values in registers: | 3650 // Live values in registers: |
3651 // index: which element of the elements array we are adding to the result. | 3651 // index: which element of the elements array we are adding to the result. |
3652 // result_pos: the position to which we are currently copying characters. | 3652 // result_pos: the position to which we are currently copying characters. |
3653 // elements: the FixedArray of strings we are joining. | 3653 // elements: the FixedArray of strings we are joining. |
3654 | 3654 |
3655 // Get string = array[index]. | 3655 // Get string = array[index]. |
3656 __ mov(string, FieldOperand(elements, index, | 3656 __ mov(string, FieldOperand(elements, index, |
3657 times_pointer_size, | 3657 times_pointer_size, |
3658 FixedArray::kHeaderSize)); | 3658 FixedArray::kHeaderSize)); |
3659 __ mov(string_length, | 3659 __ mov(string_length, |
3660 FieldOperand(string, String::kLengthOffset)); | 3660 FieldOperand(string, String::kLengthOffset)); |
3661 __ shr(string_length, 1); | 3661 __ shr(string_length, 1); |
3662 __ lea(string, | 3662 __ lea(string, |
3663 FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3663 FieldOperand(string, SeqOneByteString::kHeaderSize)); |
3664 __ CopyBytes(string, result_pos, string_length, scratch); | 3664 __ CopyBytes(string, result_pos, string_length, scratch); |
3665 __ add(index, Immediate(1)); | 3665 __ add(index, Immediate(1)); |
3666 __ bind(&loop_1_condition); | 3666 __ bind(&loop_1_condition); |
3667 __ cmp(index, array_length_operand); | 3667 __ cmp(index, array_length_operand); |
3668 __ j(less, &loop_1); // End while (index < length). | 3668 __ j(less, &loop_1); // End while (index < length). |
3669 __ jmp(&done); | 3669 __ jmp(&done); |
3670 | 3670 |
3671 | 3671 |
3672 | 3672 |
3673 // One-character separator case | 3673 // One-character separator case |
3674 __ bind(&one_char_separator); | 3674 __ bind(&one_char_separator); |
3675 // Replace separator with its ASCII character value. | 3675 // Replace separator with its ASCII character value. |
3676 __ mov_b(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3676 __ mov_b(scratch, FieldOperand(string, SeqOneByteString::kHeaderSize)); |
3677 __ mov_b(separator_operand, scratch); | 3677 __ mov_b(separator_operand, scratch); |
3678 | 3678 |
3679 __ Set(index, Immediate(0)); | 3679 __ Set(index, Immediate(0)); |
3680 // Jump into the loop after the code that copies the separator, so the first | 3680 // Jump into the loop after the code that copies the separator, so the first |
3681 // element is not preceded by a separator | 3681 // element is not preceded by a separator |
3682 __ jmp(&loop_2_entry); | 3682 __ jmp(&loop_2_entry); |
3683 // Loop condition: while (index < length). | 3683 // Loop condition: while (index < length). |
3684 __ bind(&loop_2); | 3684 __ bind(&loop_2); |
3685 // Each iteration of the loop concatenates one string to the result. | 3685 // Each iteration of the loop concatenates one string to the result. |
3686 // Live values in registers: | 3686 // Live values in registers: |
3687 // index: which element of the elements array we are adding to the result. | 3687 // index: which element of the elements array we are adding to the result. |
3688 // result_pos: the position to which we are currently copying characters. | 3688 // result_pos: the position to which we are currently copying characters. |
3689 | 3689 |
3690 // Copy the separator character to the result. | 3690 // Copy the separator character to the result. |
3691 __ mov_b(scratch, separator_operand); | 3691 __ mov_b(scratch, separator_operand); |
3692 __ mov_b(Operand(result_pos, 0), scratch); | 3692 __ mov_b(Operand(result_pos, 0), scratch); |
3693 __ inc(result_pos); | 3693 __ inc(result_pos); |
3694 | 3694 |
3695 __ bind(&loop_2_entry); | 3695 __ bind(&loop_2_entry); |
3696 // Get string = array[index]. | 3696 // Get string = array[index]. |
3697 __ mov(string, FieldOperand(elements, index, | 3697 __ mov(string, FieldOperand(elements, index, |
3698 times_pointer_size, | 3698 times_pointer_size, |
3699 FixedArray::kHeaderSize)); | 3699 FixedArray::kHeaderSize)); |
3700 __ mov(string_length, | 3700 __ mov(string_length, |
3701 FieldOperand(string, String::kLengthOffset)); | 3701 FieldOperand(string, String::kLengthOffset)); |
3702 __ shr(string_length, 1); | 3702 __ shr(string_length, 1); |
3703 __ lea(string, | 3703 __ lea(string, |
3704 FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3704 FieldOperand(string, SeqOneByteString::kHeaderSize)); |
3705 __ CopyBytes(string, result_pos, string_length, scratch); | 3705 __ CopyBytes(string, result_pos, string_length, scratch); |
3706 __ add(index, Immediate(1)); | 3706 __ add(index, Immediate(1)); |
3707 | 3707 |
3708 __ cmp(index, array_length_operand); | 3708 __ cmp(index, array_length_operand); |
3709 __ j(less, &loop_2); // End while (index < length). | 3709 __ j(less, &loop_2); // End while (index < length). |
3710 __ jmp(&done); | 3710 __ jmp(&done); |
3711 | 3711 |
3712 | 3712 |
3713 // Long separator case (separator is more than one character). | 3713 // Long separator case (separator is more than one character). |
3714 __ bind(&long_separator); | 3714 __ bind(&long_separator); |
3715 | 3715 |
3716 __ Set(index, Immediate(0)); | 3716 __ Set(index, Immediate(0)); |
3717 // Jump into the loop after the code that copies the separator, so the first | 3717 // Jump into the loop after the code that copies the separator, so the first |
3718 // element is not preceded by a separator | 3718 // element is not preceded by a separator |
3719 __ jmp(&loop_3_entry); | 3719 __ jmp(&loop_3_entry); |
3720 // Loop condition: while (index < length). | 3720 // Loop condition: while (index < length). |
3721 __ bind(&loop_3); | 3721 __ bind(&loop_3); |
3722 // Each iteration of the loop concatenates one string to the result. | 3722 // Each iteration of the loop concatenates one string to the result. |
3723 // Live values in registers: | 3723 // Live values in registers: |
3724 // index: which element of the elements array we are adding to the result. | 3724 // index: which element of the elements array we are adding to the result. |
3725 // result_pos: the position to which we are currently copying characters. | 3725 // result_pos: the position to which we are currently copying characters. |
3726 | 3726 |
3727 // Copy the separator to the result. | 3727 // Copy the separator to the result. |
3728 __ mov(string, separator_operand); | 3728 __ mov(string, separator_operand); |
3729 __ mov(string_length, | 3729 __ mov(string_length, |
3730 FieldOperand(string, String::kLengthOffset)); | 3730 FieldOperand(string, String::kLengthOffset)); |
3731 __ shr(string_length, 1); | 3731 __ shr(string_length, 1); |
3732 __ lea(string, | 3732 __ lea(string, |
3733 FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3733 FieldOperand(string, SeqOneByteString::kHeaderSize)); |
3734 __ CopyBytes(string, result_pos, string_length, scratch); | 3734 __ CopyBytes(string, result_pos, string_length, scratch); |
3735 | 3735 |
3736 __ bind(&loop_3_entry); | 3736 __ bind(&loop_3_entry); |
3737 // Get string = array[index]. | 3737 // Get string = array[index]. |
3738 __ mov(string, FieldOperand(elements, index, | 3738 __ mov(string, FieldOperand(elements, index, |
3739 times_pointer_size, | 3739 times_pointer_size, |
3740 FixedArray::kHeaderSize)); | 3740 FixedArray::kHeaderSize)); |
3741 __ mov(string_length, | 3741 __ mov(string_length, |
3742 FieldOperand(string, String::kLengthOffset)); | 3742 FieldOperand(string, String::kLengthOffset)); |
3743 __ shr(string_length, 1); | 3743 __ shr(string_length, 1); |
3744 __ lea(string, | 3744 __ lea(string, |
3745 FieldOperand(string, SeqAsciiString::kHeaderSize)); | 3745 FieldOperand(string, SeqOneByteString::kHeaderSize)); |
3746 __ CopyBytes(string, result_pos, string_length, scratch); | 3746 __ CopyBytes(string, result_pos, string_length, scratch); |
3747 __ add(index, Immediate(1)); | 3747 __ add(index, Immediate(1)); |
3748 | 3748 |
3749 __ cmp(index, array_length_operand); | 3749 __ cmp(index, array_length_operand); |
3750 __ j(less, &loop_3); // End while (index < length). | 3750 __ j(less, &loop_3); // End while (index < length). |
3751 __ jmp(&done); | 3751 __ jmp(&done); |
3752 | 3752 |
3753 | 3753 |
3754 __ bind(&bailout); | 3754 __ bind(&bailout); |
3755 __ mov(result_operand, isolate()->factory()->undefined_value()); | 3755 __ mov(result_operand, isolate()->factory()->undefined_value()); |
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4498 *stack_depth = 0; | 4498 *stack_depth = 0; |
4499 *context_length = 0; | 4499 *context_length = 0; |
4500 return previous_; | 4500 return previous_; |
4501 } | 4501 } |
4502 | 4502 |
4503 #undef __ | 4503 #undef __ |
4504 | 4504 |
4505 } } // namespace v8::internal | 4505 } } // namespace v8::internal |
4506 | 4506 |
4507 #endif // V8_TARGET_ARCH_IA32 | 4507 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |