OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 3845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3856 __ AbortIfNotSmi(result.reg(), "Computed arguments.length is not a smi."); | 3856 __ AbortIfNotSmi(result.reg(), "Computed arguments.length is not a smi."); |
3857 } | 3857 } |
3858 frame_->Push(&result); | 3858 frame_->Push(&result); |
3859 } | 3859 } |
3860 | 3860 |
3861 | 3861 |
3862 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { | 3862 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { |
3863 Comment(masm_, "[ GenerateFastCharCodeAt"); | 3863 Comment(masm_, "[ GenerateFastCharCodeAt"); |
3864 ASSERT(args->length() == 2); | 3864 ASSERT(args->length() == 2); |
3865 | 3865 |
3866 Label slow_case; | |
3867 Label end; | |
3868 Label not_a_flat_string; | |
3869 Label try_again_with_new_string; | |
3870 Label ascii_string; | |
3871 Label got_char_code; | |
3872 | |
3873 Load(args->at(0)); | 3866 Load(args->at(0)); |
3874 Load(args->at(1)); | 3867 Load(args->at(1)); |
3875 Result index = frame_->Pop(); | 3868 Result index = frame_->Pop(); |
3876 Result object = frame_->Pop(); | 3869 Result object = frame_->Pop(); |
3877 | 3870 |
3878 // Get register rcx to use as shift amount later. | |
3879 Result shift_amount; | |
3880 if (object.is_register() && object.reg().is(rcx)) { | |
3881 Result fresh = allocator_->Allocate(); | |
3882 shift_amount = object; | |
3883 object = fresh; | |
3884 __ movq(object.reg(), rcx); | |
3885 } | |
3886 if (index.is_register() && index.reg().is(rcx)) { | |
3887 Result fresh = allocator_->Allocate(); | |
3888 shift_amount = index; | |
3889 index = fresh; | |
3890 __ movq(index.reg(), rcx); | |
3891 } | |
3892 // There could be references to ecx in the frame. Allocating will | |
3893 // spill them, otherwise spill explicitly. | |
3894 if (shift_amount.is_valid()) { | |
3895 frame_->Spill(rcx); | |
3896 } else { | |
3897 shift_amount = allocator()->Allocate(rcx); | |
3898 } | |
3899 ASSERT(shift_amount.is_register()); | |
3900 ASSERT(shift_amount.reg().is(rcx)); | |
3901 ASSERT(allocator_->count(rcx) == 1); | |
3902 | |
3903 // We will mutate the index register and possibly the object register. | 3871 // We will mutate the index register and possibly the object register. |
3904 // The case where they are somehow the same register is handled | 3872 // The case where they are somehow the same register is handled |
3905 // because we only mutate them in the case where the receiver is a | 3873 // because we only mutate them in the case where the receiver is a |
3906 // heap object and the index is not. | 3874 // heap object and the index is not. |
3907 object.ToRegister(); | 3875 object.ToRegister(); |
3908 index.ToRegister(); | 3876 index.ToRegister(); |
3909 frame_->Spill(object.reg()); | 3877 frame_->Spill(object.reg()); |
3910 frame_->Spill(index.reg()); | 3878 frame_->Spill(index.reg()); |
3911 | 3879 |
3912 // We need a single extra temporary register. | 3880 // We need two extra registers. |
3913 Result temp = allocator()->Allocate(); | 3881 Result result = allocator()->Allocate(); |
3914 ASSERT(temp.is_valid()); | 3882 ASSERT(result.is_valid()); |
| 3883 Result scratch = allocator()->Allocate(); |
| 3884 ASSERT(scratch.is_valid()); |
3915 | 3885 |
3916 // There is no virtual frame effect from here up to the final result | 3886 // There is no virtual frame effect from here up to the final result |
3917 // push. | 3887 // push. |
3918 | 3888 Label slow_case; |
3919 // If the receiver is a smi trigger the slow case. | 3889 Label exit; |
3920 __ JumpIfSmi(object.reg(), &slow_case); | 3890 StringHelper::GenerateFastCharCodeAt(masm_, |
3921 | 3891 object.reg(), |
3922 // If the index is negative or non-smi trigger the slow case. | 3892 index.reg(), |
3923 __ JumpIfNotPositiveSmi(index.reg(), &slow_case); | 3893 scratch.reg(), |
3924 | 3894 result.reg(), |
3925 // Untag the index. | 3895 &slow_case, |
3926 __ SmiToInteger32(index.reg(), index.reg()); | 3896 &slow_case, |
3927 | 3897 &slow_case, |
3928 __ bind(&try_again_with_new_string); | 3898 &slow_case); |
3929 // Fetch the instance type of the receiver into rcx. | 3899 __ jmp(&exit); |
3930 __ movq(rcx, FieldOperand(object.reg(), HeapObject::kMapOffset)); | |
3931 __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); | |
3932 // If the receiver is not a string trigger the slow case. | |
3933 __ testb(rcx, Immediate(kIsNotStringMask)); | |
3934 __ j(not_zero, &slow_case); | |
3935 | |
3936 // Check for index out of range. | |
3937 __ cmpl(index.reg(), FieldOperand(object.reg(), String::kLengthOffset)); | |
3938 __ j(greater_equal, &slow_case); | |
3939 // Reload the instance type (into the temp register this time).. | |
3940 __ movq(temp.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset)); | |
3941 __ movzxbl(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset)); | |
3942 | |
3943 // We need special handling for non-flat strings. | |
3944 ASSERT_EQ(0, kSeqStringTag); | |
3945 __ testb(temp.reg(), Immediate(kStringRepresentationMask)); | |
3946 __ j(not_zero, ¬_a_flat_string); | |
3947 // Check for 1-byte or 2-byte string. | |
3948 ASSERT_EQ(0, kTwoByteStringTag); | |
3949 __ testb(temp.reg(), Immediate(kStringEncodingMask)); | |
3950 __ j(not_zero, &ascii_string); | |
3951 | |
3952 // 2-byte string. | |
3953 // Load the 2-byte character code into the temp register. | |
3954 __ movzxwl(temp.reg(), FieldOperand(object.reg(), | |
3955 index.reg(), | |
3956 times_2, | |
3957 SeqTwoByteString::kHeaderSize)); | |
3958 __ jmp(&got_char_code); | |
3959 | |
3960 // ASCII string. | |
3961 __ bind(&ascii_string); | |
3962 // Load the byte into the temp register. | |
3963 __ movzxbl(temp.reg(), FieldOperand(object.reg(), | |
3964 index.reg(), | |
3965 times_1, | |
3966 SeqAsciiString::kHeaderSize)); | |
3967 __ bind(&got_char_code); | |
3968 __ Integer32ToSmi(temp.reg(), temp.reg()); | |
3969 __ jmp(&end); | |
3970 | |
3971 // Handle non-flat strings. | |
3972 __ bind(¬_a_flat_string); | |
3973 __ and_(temp.reg(), Immediate(kStringRepresentationMask)); | |
3974 __ cmpb(temp.reg(), Immediate(kConsStringTag)); | |
3975 __ j(not_equal, &slow_case); | |
3976 | |
3977 // ConsString. | |
3978 // Check that the right hand side is the empty string (ie if this is really a | |
3979 // flat string in a cons string). If that is not the case we would rather go | |
3980 // to the runtime system now, to flatten the string. | |
3981 __ movq(temp.reg(), FieldOperand(object.reg(), ConsString::kSecondOffset)); | |
3982 __ CompareRoot(temp.reg(), Heap::kEmptyStringRootIndex); | |
3983 __ j(not_equal, &slow_case); | |
3984 // Get the first of the two strings. | |
3985 __ movq(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset)); | |
3986 __ jmp(&try_again_with_new_string); | |
3987 | 3900 |
3988 __ bind(&slow_case); | 3901 __ bind(&slow_case); |
3989 // Move the undefined value into the result register, which will | 3902 // Move the undefined value into the result register, which will |
3990 // trigger the slow case. | 3903 // trigger the slow case. |
3991 __ LoadRoot(temp.reg(), Heap::kUndefinedValueRootIndex); | 3904 __ LoadRoot(result.reg(), Heap::kUndefinedValueRootIndex); |
3992 | 3905 |
3993 __ bind(&end); | 3906 __ bind(&exit); |
3994 frame_->Push(&temp); | 3907 frame_->Push(&result); |
3995 } | 3908 } |
3996 | 3909 |
3997 | 3910 |
3998 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { | 3911 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { |
3999 Comment(masm_, "[ GenerateCharFromCode"); | 3912 Comment(masm_, "[ GenerateCharFromCode"); |
4000 ASSERT(args->length() == 1); | 3913 ASSERT(args->length() == 1); |
4001 | 3914 |
4002 Load(args->at(0)); | 3915 Load(args->at(0)); |
| 3916 |
4003 Result code = frame_->Pop(); | 3917 Result code = frame_->Pop(); |
4004 code.ToRegister(); | 3918 code.ToRegister(); |
4005 ASSERT(code.is_valid()); | 3919 ASSERT(code.is_valid()); |
4006 | 3920 |
4007 Result temp = allocator()->Allocate(); | 3921 // StringHelper::GenerateCharFromCode may do a runtime call. |
4008 ASSERT(temp.is_valid()); | 3922 frame_->SpillAll(); |
4009 | 3923 |
4010 JumpTarget slow_case; | 3924 Result result = allocator()->Allocate(); |
4011 JumpTarget exit; | 3925 ASSERT(result.is_valid()); |
| 3926 Result scratch = allocator()->Allocate(); |
| 3927 ASSERT(scratch.is_valid()); |
4012 | 3928 |
4013 // Fast case of Heap::LookupSingleCharacterStringFromCode. | 3929 StringHelper::GenerateCharFromCode(masm_, |
4014 Condition is_smi = __ CheckSmi(code.reg()); | 3930 code.reg(), |
4015 slow_case.Branch(NegateCondition(is_smi), &code, not_taken); | 3931 result.reg(), |
4016 | 3932 scratch.reg(), |
4017 __ SmiToInteger32(kScratchRegister, code.reg()); | 3933 CALL_FUNCTION); |
4018 __ cmpl(kScratchRegister, Immediate(String::kMaxAsciiCharCode)); | |
4019 slow_case.Branch(above, &code, not_taken); | |
4020 | |
4021 __ Move(temp.reg(), Factory::single_character_string_cache()); | |
4022 __ movq(temp.reg(), FieldOperand(temp.reg(), | |
4023 kScratchRegister, times_pointer_size, | |
4024 FixedArray::kHeaderSize)); | |
4025 __ CompareRoot(temp.reg(), Heap::kUndefinedValueRootIndex); | |
4026 slow_case.Branch(equal, &code, not_taken); | |
4027 code.Unuse(); | |
4028 | |
4029 frame_->Push(&temp); | |
4030 exit.Jump(); | |
4031 | |
4032 slow_case.Bind(&code); | |
4033 frame_->Push(&code); | |
4034 Result result = frame_->CallRuntime(Runtime::kCharFromCode, 1); | |
4035 frame_->Push(&result); | 3934 frame_->Push(&result); |
4036 | |
4037 exit.Bind(); | |
4038 } | 3935 } |
4039 | 3936 |
4040 | 3937 |
4041 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 3938 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
4042 ASSERT(args->length() == 1); | 3939 ASSERT(args->length() == 1); |
4043 Load(args->at(0)); | 3940 Load(args->at(0)); |
4044 Result value = frame_->Pop(); | 3941 Result value = frame_->Pop(); |
4045 value.ToRegister(); | 3942 value.ToRegister(); |
4046 ASSERT(value.is_valid()); | 3943 ASSERT(value.is_valid()); |
4047 Condition positive_smi = masm_->CheckPositiveSmi(value.reg()); | 3944 Condition positive_smi = masm_->CheckPositiveSmi(value.reg()); |
(...skipping 5742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9790 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 9687 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
9791 "CompareStub_%s%s%s%s", | 9688 "CompareStub_%s%s%s%s", |
9792 cc_name, | 9689 cc_name, |
9793 strict_name, | 9690 strict_name, |
9794 never_nan_nan_name, | 9691 never_nan_nan_name, |
9795 include_number_compare_name); | 9692 include_number_compare_name); |
9796 return name_; | 9693 return name_; |
9797 } | 9694 } |
9798 | 9695 |
9799 | 9696 |
| 9697 void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm, |
| 9698 Register object, |
| 9699 Register index, |
| 9700 Register scratch, |
| 9701 Register result, |
| 9702 Label* receiver_not_string, |
| 9703 Label* index_not_smi, |
| 9704 Label* index_out_of_range, |
| 9705 Label* slow_case) { |
| 9706 Label not_a_flat_string; |
| 9707 Label try_again_with_new_string; |
| 9708 Label ascii_string; |
| 9709 Label got_char_code; |
| 9710 |
| 9711 // If the receiver is a smi trigger the non-string case. |
| 9712 __ JumpIfSmi(object, receiver_not_string); |
| 9713 |
| 9714 // Fetch the instance type of the receiver into result register. |
| 9715 __ movq(result, FieldOperand(object, HeapObject::kMapOffset)); |
| 9716 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| 9717 // If the receiver is not a string trigger the non-string case. |
| 9718 __ testb(result, Immediate(kIsNotStringMask)); |
| 9719 __ j(not_zero, receiver_not_string); |
| 9720 |
| 9721 // If the index is non-smi trigger the non-smi case. |
| 9722 __ JumpIfNotSmi(index, index_not_smi); |
| 9723 |
| 9724 // Put untagged index into scratch register. |
| 9725 __ SmiToInteger32(scratch, index); |
| 9726 |
| 9727 // Check for index out of range. |
| 9728 __ cmpl(scratch, FieldOperand(object, String::kLengthOffset)); |
| 9729 __ j(above_equal, index_out_of_range); |
| 9730 |
| 9731 __ bind(&try_again_with_new_string); |
| 9732 // ----------- S t a t e ------------- |
| 9733 // -- object : string to access |
| 9734 // -- result : instance type of the string |
| 9735 // -- scratch : non-negative index < length |
| 9736 // ----------------------------------- |
| 9737 |
| 9738 // We need special handling for non-flat strings. |
| 9739 ASSERT_EQ(0, kSeqStringTag); |
| 9740 __ testb(result, Immediate(kStringRepresentationMask)); |
| 9741 __ j(not_zero, ¬_a_flat_string); |
| 9742 |
| 9743 // Check for 1-byte or 2-byte string. |
| 9744 ASSERT_EQ(0, kTwoByteStringTag); |
| 9745 __ testb(result, Immediate(kStringEncodingMask)); |
| 9746 __ j(not_zero, &ascii_string); |
| 9747 |
| 9748 // 2-byte string. |
| 9749 // Load the 2-byte character code into the result register. |
| 9750 __ movzxwl(result, FieldOperand(object, |
| 9751 scratch, |
| 9752 times_2, |
| 9753 SeqTwoByteString::kHeaderSize)); |
| 9754 __ jmp(&got_char_code); |
| 9755 |
| 9756 // Handle non-flat strings. |
| 9757 __ bind(¬_a_flat_string); |
| 9758 __ and_(result, Immediate(kStringRepresentationMask)); |
| 9759 __ cmpb(result, Immediate(kConsStringTag)); |
| 9760 __ j(not_equal, slow_case); |
| 9761 |
| 9762 // ConsString. |
| 9763 // Check that the right hand side is the empty string (ie if this is really a |
| 9764 // flat string in a cons string). If that is not the case we would rather go |
| 9765 // to the runtime system now, to flatten the string. |
| 9766 __ movq(result, FieldOperand(object, ConsString::kSecondOffset)); |
| 9767 __ CompareRoot(result, Heap::kEmptyStringRootIndex); |
| 9768 __ j(not_equal, slow_case); |
| 9769 // Get the first of the two strings and load its instance type. |
| 9770 __ movq(object, FieldOperand(object, ConsString::kFirstOffset)); |
| 9771 __ movq(result, FieldOperand(object, HeapObject::kMapOffset)); |
| 9772 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| 9773 __ jmp(&try_again_with_new_string); |
| 9774 |
| 9775 // ASCII string. |
| 9776 __ bind(&ascii_string); |
| 9777 // Load the byte into the result register. |
| 9778 __ movzxbl(result, FieldOperand(object, |
| 9779 scratch, |
| 9780 times_1, |
| 9781 SeqAsciiString::kHeaderSize)); |
| 9782 __ bind(&got_char_code); |
| 9783 __ Integer32ToSmi(result, result); |
| 9784 } |
| 9785 |
| 9786 |
| 9787 void StringHelper::GenerateCharFromCode(MacroAssembler* masm, |
| 9788 Register code, |
| 9789 Register result, |
| 9790 Register scratch, |
| 9791 InvokeFlag flag) { |
| 9792 ASSERT(!code.is(result)); |
| 9793 |
| 9794 Label slow_case; |
| 9795 Label exit; |
| 9796 |
| 9797 // Fast case of Heap::LookupSingleCharacterStringFromCode. |
| 9798 __ JumpIfNotSmi(code, &slow_case); |
| 9799 __ SmiToInteger32(scratch, code); |
| 9800 __ cmpl(scratch, Immediate(String::kMaxAsciiCharCode)); |
| 9801 __ j(above, &slow_case); |
| 9802 |
| 9803 __ Move(result, Factory::single_character_string_cache()); |
| 9804 __ movq(result, FieldOperand(result, |
| 9805 scratch, |
| 9806 times_pointer_size, |
| 9807 FixedArray::kHeaderSize)); |
| 9808 |
| 9809 __ CompareRoot(result, Heap::kUndefinedValueRootIndex); |
| 9810 __ j(equal, &slow_case); |
| 9811 __ jmp(&exit); |
| 9812 |
| 9813 __ bind(&slow_case); |
| 9814 if (flag == CALL_FUNCTION) { |
| 9815 __ push(code); |
| 9816 __ CallRuntime(Runtime::kCharFromCode, 1); |
| 9817 if (!result.is(rax)) { |
| 9818 __ movq(result, rax); |
| 9819 } |
| 9820 } else { |
| 9821 ASSERT(flag == JUMP_FUNCTION); |
| 9822 ASSERT(result.is(rax)); |
| 9823 __ pop(rax); // Save return address. |
| 9824 __ push(code); |
| 9825 __ push(rax); // Restore return address. |
| 9826 __ TailCallRuntime(Runtime::kCharFromCode, 1, 1); |
| 9827 } |
| 9828 |
| 9829 __ bind(&exit); |
| 9830 if (flag == JUMP_FUNCTION) { |
| 9831 ASSERT(result.is(rax)); |
| 9832 __ ret(0); |
| 9833 } |
| 9834 } |
| 9835 |
| 9836 |
9800 void StringAddStub::Generate(MacroAssembler* masm) { | 9837 void StringAddStub::Generate(MacroAssembler* masm) { |
9801 Label string_add_runtime; | 9838 Label string_add_runtime; |
9802 | 9839 |
9803 // Load the two arguments. | 9840 // Load the two arguments. |
9804 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument. | 9841 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument. |
9805 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument. | 9842 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument. |
9806 | 9843 |
9807 // Make sure that both arguments are strings if not known in advance. | 9844 // Make sure that both arguments are strings if not known in advance. |
9808 if (string_check_) { | 9845 if (string_check_) { |
9809 Condition is_smi; | 9846 Condition is_smi; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9870 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, | 9907 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, |
9871 &string_add_runtime); | 9908 &string_add_runtime); |
9872 | 9909 |
9873 // Get the two characters forming the sub string. | 9910 // Get the two characters forming the sub string. |
9874 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); | 9911 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); |
9875 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); | 9912 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); |
9876 | 9913 |
9877 // Try to lookup two character string in symbol table. If it is not found | 9914 // Try to lookup two character string in symbol table. If it is not found |
9878 // just allocate a new one. | 9915 // just allocate a new one. |
9879 Label make_two_character_string, make_flat_ascii_string; | 9916 Label make_two_character_string, make_flat_ascii_string; |
9880 GenerateTwoCharacterSymbolTableProbe(masm, rbx, rcx, r14, r12, rdi, r15, | 9917 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
9881 &make_two_character_string); | 9918 masm, rbx, rcx, r14, r12, rdi, r15, &make_two_character_string); |
9882 __ IncrementCounter(&Counters::string_add_native, 1); | 9919 __ IncrementCounter(&Counters::string_add_native, 1); |
9883 __ ret(2 * kPointerSize); | 9920 __ ret(2 * kPointerSize); |
9884 | 9921 |
9885 __ bind(&make_two_character_string); | 9922 __ bind(&make_two_character_string); |
9886 __ Set(rbx, 2); | 9923 __ Set(rbx, 2); |
9887 __ jmp(&make_flat_ascii_string); | 9924 __ jmp(&make_flat_ascii_string); |
9888 | 9925 |
9889 __ bind(&longer_than_two); | 9926 __ bind(&longer_than_two); |
9890 // Check if resulting string will be flat. | 9927 // Check if resulting string will be flat. |
9891 __ cmpl(rbx, Immediate(String::kMinNonFlatLength)); | 9928 __ cmpl(rbx, Immediate(String::kMinNonFlatLength)); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9962 // Locate first character of result. | 9999 // Locate first character of result. |
9963 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 10000 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
9964 // Locate first character of first argument | 10001 // Locate first character of first argument |
9965 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); | 10002 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); |
9966 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 10003 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
9967 // rax: first char of first argument | 10004 // rax: first char of first argument |
9968 // rbx: result string | 10005 // rbx: result string |
9969 // rcx: first character of result | 10006 // rcx: first character of result |
9970 // rdx: second string | 10007 // rdx: second string |
9971 // rdi: length of first argument | 10008 // rdi: length of first argument |
9972 GenerateCopyCharacters(masm, rcx, rax, rdi, true); | 10009 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true); |
9973 // Locate first character of second argument. | 10010 // Locate first character of second argument. |
9974 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset)); | 10011 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset)); |
9975 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 10012 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
9976 // rbx: result string | 10013 // rbx: result string |
9977 // rcx: next character of result | 10014 // rcx: next character of result |
9978 // rdx: first char of second argument | 10015 // rdx: first char of second argument |
9979 // rdi: length of second argument | 10016 // rdi: length of second argument |
9980 GenerateCopyCharacters(masm, rcx, rdx, rdi, true); | 10017 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true); |
9981 __ movq(rax, rbx); | 10018 __ movq(rax, rbx); |
9982 __ IncrementCounter(&Counters::string_add_native, 1); | 10019 __ IncrementCounter(&Counters::string_add_native, 1); |
9983 __ ret(2 * kPointerSize); | 10020 __ ret(2 * kPointerSize); |
9984 | 10021 |
9985 // Handle creating a flat two byte result. | 10022 // Handle creating a flat two byte result. |
9986 // rax: first string - known to be two byte | 10023 // rax: first string - known to be two byte |
9987 // rbx: length of resulting flat string | 10024 // rbx: length of resulting flat string |
9988 // rdx: second string | 10025 // rdx: second string |
9989 // r8: instance type of first string | 10026 // r8: instance type of first string |
9990 // r9: instance type of first string | 10027 // r9: instance type of first string |
9991 __ bind(&non_ascii_string_add_flat_result); | 10028 __ bind(&non_ascii_string_add_flat_result); |
9992 __ and_(r9, Immediate(kAsciiStringTag)); | 10029 __ and_(r9, Immediate(kAsciiStringTag)); |
9993 __ j(not_zero, &string_add_runtime); | 10030 __ j(not_zero, &string_add_runtime); |
9994 // Both strings are two byte strings. As they are short they are both | 10031 // Both strings are two byte strings. As they are short they are both |
9995 // flat. | 10032 // flat. |
9996 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime); | 10033 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime); |
9997 // rcx: result string | 10034 // rcx: result string |
9998 __ movq(rbx, rcx); | 10035 __ movq(rbx, rcx); |
9999 // Locate first character of result. | 10036 // Locate first character of result. |
10000 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 10037 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
10001 // Locate first character of first argument. | 10038 // Locate first character of first argument. |
10002 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); | 10039 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); |
10003 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 10040 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
10004 // rax: first char of first argument | 10041 // rax: first char of first argument |
10005 // rbx: result string | 10042 // rbx: result string |
10006 // rcx: first character of result | 10043 // rcx: first character of result |
10007 // rdx: second argument | 10044 // rdx: second argument |
10008 // rdi: length of first argument | 10045 // rdi: length of first argument |
10009 GenerateCopyCharacters(masm, rcx, rax, rdi, false); | 10046 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false); |
10010 // Locate first character of second argument. | 10047 // Locate first character of second argument. |
10011 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset)); | 10048 __ movl(rdi, FieldOperand(rdx, String::kLengthOffset)); |
10012 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 10049 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
10013 // rbx: result string | 10050 // rbx: result string |
10014 // rcx: next character of result | 10051 // rcx: next character of result |
10015 // rdx: first char of second argument | 10052 // rdx: first char of second argument |
10016 // rdi: length of second argument | 10053 // rdi: length of second argument |
10017 GenerateCopyCharacters(masm, rcx, rdx, rdi, false); | 10054 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false); |
10018 __ movq(rax, rbx); | 10055 __ movq(rax, rbx); |
10019 __ IncrementCounter(&Counters::string_add_native, 1); | 10056 __ IncrementCounter(&Counters::string_add_native, 1); |
10020 __ ret(2 * kPointerSize); | 10057 __ ret(2 * kPointerSize); |
10021 | 10058 |
10022 // Just jump to runtime to add the two strings. | 10059 // Just jump to runtime to add the two strings. |
10023 __ bind(&string_add_runtime); | 10060 __ bind(&string_add_runtime); |
10024 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10061 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
10025 } | 10062 } |
10026 | 10063 |
10027 | 10064 |
10028 void StringStubBase::GenerateCopyCharacters(MacroAssembler* masm, | 10065 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
10029 Register dest, | 10066 Register dest, |
10030 Register src, | 10067 Register src, |
10031 Register count, | 10068 Register count, |
10032 bool ascii) { | 10069 bool ascii) { |
10033 Label loop; | 10070 Label loop; |
10034 __ bind(&loop); | 10071 __ bind(&loop); |
10035 // This loop just copies one character at a time, as it is only used for very | 10072 // This loop just copies one character at a time, as it is only used for very |
10036 // short strings. | 10073 // short strings. |
10037 if (ascii) { | 10074 if (ascii) { |
10038 __ movb(kScratchRegister, Operand(src, 0)); | 10075 __ movb(kScratchRegister, Operand(src, 0)); |
10039 __ movb(Operand(dest, 0), kScratchRegister); | 10076 __ movb(Operand(dest, 0), kScratchRegister); |
10040 __ addq(src, Immediate(1)); | 10077 __ addq(src, Immediate(1)); |
10041 __ addq(dest, Immediate(1)); | 10078 __ addq(dest, Immediate(1)); |
10042 } else { | 10079 } else { |
10043 __ movzxwl(kScratchRegister, Operand(src, 0)); | 10080 __ movzxwl(kScratchRegister, Operand(src, 0)); |
10044 __ movw(Operand(dest, 0), kScratchRegister); | 10081 __ movw(Operand(dest, 0), kScratchRegister); |
10045 __ addq(src, Immediate(2)); | 10082 __ addq(src, Immediate(2)); |
10046 __ addq(dest, Immediate(2)); | 10083 __ addq(dest, Immediate(2)); |
10047 } | 10084 } |
10048 __ subl(count, Immediate(1)); | 10085 __ subl(count, Immediate(1)); |
10049 __ j(not_zero, &loop); | 10086 __ j(not_zero, &loop); |
10050 } | 10087 } |
10051 | 10088 |
10052 | 10089 |
10053 void StringStubBase::GenerateCopyCharactersREP(MacroAssembler* masm, | 10090 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, |
10054 Register dest, | 10091 Register dest, |
10055 Register src, | 10092 Register src, |
10056 Register count, | 10093 Register count, |
10057 bool ascii) { | 10094 bool ascii) { |
10058 // Copy characters using rep movs of doublewords. Align destination on 4 byte | 10095 // Copy characters using rep movs of doublewords. Align destination on 4 byte |
10059 // boundary before starting rep movs. Copy remaining characters after running | 10096 // boundary before starting rep movs. Copy remaining characters after running |
10060 // rep movs. | 10097 // rep movs. |
10061 ASSERT(dest.is(rdi)); // rep movs destination | 10098 ASSERT(dest.is(rdi)); // rep movs destination |
10062 ASSERT(src.is(rsi)); // rep movs source | 10099 ASSERT(src.is(rsi)); // rep movs source |
10063 ASSERT(count.is(rcx)); // rep movs count | 10100 ASSERT(count.is(rcx)); // rep movs count |
10064 | 10101 |
10065 // Nothing to do for zero characters. | 10102 // Nothing to do for zero characters. |
10066 Label done; | 10103 Label done; |
10067 __ testq(count, count); | 10104 __ testq(count, count); |
(...skipping 30 matching lines...) Expand all Loading... |
10098 __ movb(kScratchRegister, Operand(src, 0)); | 10135 __ movb(kScratchRegister, Operand(src, 0)); |
10099 __ movb(Operand(dest, 0), kScratchRegister); | 10136 __ movb(Operand(dest, 0), kScratchRegister); |
10100 __ addq(src, Immediate(1)); | 10137 __ addq(src, Immediate(1)); |
10101 __ addq(dest, Immediate(1)); | 10138 __ addq(dest, Immediate(1)); |
10102 __ subq(count, Immediate(1)); | 10139 __ subq(count, Immediate(1)); |
10103 __ j(not_zero, &loop); | 10140 __ j(not_zero, &loop); |
10104 | 10141 |
10105 __ bind(&done); | 10142 __ bind(&done); |
10106 } | 10143 } |
10107 | 10144 |
10108 void StringStubBase::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, | 10145 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, |
10109 Register c1, | 10146 Register c1, |
10110 Register c2, | 10147 Register c2, |
10111 Register scratch1, | 10148 Register scratch1, |
10112 Register scratch2, | 10149 Register scratch2, |
10113 Register scratch3, | 10150 Register scratch3, |
10114 Register scratch4, | 10151 Register scratch4, |
10115 Label* not_found) { | 10152 Label* not_found) { |
10116 // Register scratch3 is the general scratch register in this function. | 10153 // Register scratch3 is the general scratch register in this function. |
10117 Register scratch = scratch3; | 10154 Register scratch = scratch3; |
10118 | 10155 |
10119 // Make sure that both characters are not digits as such strings has a | 10156 // Make sure that both characters are not digits as such strings has a |
10120 // different hash algorithm. Don't try to look for these in the symbol table. | 10157 // different hash algorithm. Don't try to look for these in the symbol table. |
10121 Label not_array_index; | 10158 Label not_array_index; |
10122 __ movq(scratch, c1); | 10159 __ movq(scratch, c1); |
10123 __ subq(scratch, Immediate(static_cast<int>('0'))); | 10160 __ subq(scratch, Immediate(static_cast<int>('0'))); |
10124 __ cmpq(scratch, Immediate(static_cast<int>('9' - '0'))); | 10161 __ cmpq(scratch, Immediate(static_cast<int>('9' - '0'))); |
10125 __ j(above, ¬_array_index); | 10162 __ j(above, ¬_array_index); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10216 | 10253 |
10217 // Scratch register contains result when we fall through to here. | 10254 // Scratch register contains result when we fall through to here. |
10218 Register result = scratch; | 10255 Register result = scratch; |
10219 __ bind(&found_in_symbol_table); | 10256 __ bind(&found_in_symbol_table); |
10220 if (!result.is(rax)) { | 10257 if (!result.is(rax)) { |
10221 __ movq(rax, result); | 10258 __ movq(rax, result); |
10222 } | 10259 } |
10223 } | 10260 } |
10224 | 10261 |
10225 | 10262 |
10226 void StringStubBase::GenerateHashInit(MacroAssembler* masm, | 10263 void StringHelper::GenerateHashInit(MacroAssembler* masm, |
10227 Register hash, | 10264 Register hash, |
10228 Register character, | 10265 Register character, |
10229 Register scratch) { | 10266 Register scratch) { |
10230 // hash = character + (character << 10); | 10267 // hash = character + (character << 10); |
10231 __ movl(hash, character); | 10268 __ movl(hash, character); |
10232 __ shll(hash, Immediate(10)); | 10269 __ shll(hash, Immediate(10)); |
10233 __ addl(hash, character); | 10270 __ addl(hash, character); |
10234 // hash ^= hash >> 6; | 10271 // hash ^= hash >> 6; |
10235 __ movl(scratch, hash); | 10272 __ movl(scratch, hash); |
10236 __ sarl(scratch, Immediate(6)); | 10273 __ sarl(scratch, Immediate(6)); |
10237 __ xorl(hash, scratch); | 10274 __ xorl(hash, scratch); |
10238 } | 10275 } |
10239 | 10276 |
10240 | 10277 |
10241 void StringStubBase::GenerateHashAddCharacter(MacroAssembler* masm, | 10278 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, |
10242 Register hash, | 10279 Register hash, |
10243 Register character, | 10280 Register character, |
10244 Register scratch) { | 10281 Register scratch) { |
10245 // hash += character; | 10282 // hash += character; |
10246 __ addl(hash, character); | 10283 __ addl(hash, character); |
10247 // hash += hash << 10; | 10284 // hash += hash << 10; |
10248 __ movl(scratch, hash); | 10285 __ movl(scratch, hash); |
10249 __ shll(scratch, Immediate(10)); | 10286 __ shll(scratch, Immediate(10)); |
10250 __ addl(hash, scratch); | 10287 __ addl(hash, scratch); |
10251 // hash ^= hash >> 6; | 10288 // hash ^= hash >> 6; |
10252 __ movl(scratch, hash); | 10289 __ movl(scratch, hash); |
10253 __ sarl(scratch, Immediate(6)); | 10290 __ sarl(scratch, Immediate(6)); |
10254 __ xorl(hash, scratch); | 10291 __ xorl(hash, scratch); |
10255 } | 10292 } |
10256 | 10293 |
10257 | 10294 |
10258 void StringStubBase::GenerateHashGetHash(MacroAssembler* masm, | 10295 void StringHelper::GenerateHashGetHash(MacroAssembler* masm, |
10259 Register hash, | 10296 Register hash, |
10260 Register scratch) { | 10297 Register scratch) { |
10261 // hash += hash << 3; | 10298 // hash += hash << 3; |
10262 __ movl(scratch, hash); | 10299 __ movl(scratch, hash); |
10263 __ shll(scratch, Immediate(3)); | 10300 __ shll(scratch, Immediate(3)); |
10264 __ addl(hash, scratch); | 10301 __ addl(hash, scratch); |
10265 // hash ^= hash >> 11; | 10302 // hash ^= hash >> 11; |
10266 __ movl(scratch, hash); | 10303 __ movl(scratch, hash); |
10267 __ sarl(scratch, Immediate(11)); | 10304 __ sarl(scratch, Immediate(11)); |
10268 __ xorl(hash, scratch); | 10305 __ xorl(hash, scratch); |
10269 // hash += hash << 15; | 10306 // hash += hash << 15; |
10270 __ movl(scratch, hash); | 10307 __ movl(scratch, hash); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10327 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &runtime); | 10364 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &runtime); |
10328 | 10365 |
10329 // Get the two characters forming the sub string. | 10366 // Get the two characters forming the sub string. |
10330 __ SmiToInteger32(rdx, rdx); // From index is no longer smi. | 10367 __ SmiToInteger32(rdx, rdx); // From index is no longer smi. |
10331 __ movzxbq(rbx, FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize)); | 10368 __ movzxbq(rbx, FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize)); |
10332 __ movzxbq(rcx, | 10369 __ movzxbq(rcx, |
10333 FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize + 1)); | 10370 FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize + 1)); |
10334 | 10371 |
10335 // Try to lookup two character string in symbol table. | 10372 // Try to lookup two character string in symbol table. |
10336 Label make_two_character_string; | 10373 Label make_two_character_string; |
10337 GenerateTwoCharacterSymbolTableProbe(masm, rbx, rcx, rax, rdx, rdi, r14, | 10374 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
10338 &make_two_character_string); | 10375 masm, rbx, rcx, rax, rdx, rdi, r14, &make_two_character_string); |
10339 __ ret(3 * kPointerSize); | 10376 __ ret(3 * kPointerSize); |
10340 | 10377 |
10341 __ bind(&make_two_character_string); | 10378 __ bind(&make_two_character_string); |
10342 // Setup registers for allocating the two character string. | 10379 // Setup registers for allocating the two character string. |
10343 __ movq(rax, Operand(rsp, kStringOffset)); | 10380 __ movq(rax, Operand(rsp, kStringOffset)); |
10344 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 10381 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
10345 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 10382 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
10346 __ Set(rcx, 2); | 10383 __ Set(rcx, 2); |
10347 | 10384 |
10348 __ bind(&result_longer_than_two); | 10385 __ bind(&result_longer_than_two); |
(...skipping 20 matching lines...) Expand all Loading... |
10369 SmiIndex smi_as_index = masm->SmiToIndex(rbx, rbx, times_1); | 10406 SmiIndex smi_as_index = masm->SmiToIndex(rbx, rbx, times_1); |
10370 __ lea(rsi, Operand(rsi, smi_as_index.reg, smi_as_index.scale, | 10407 __ lea(rsi, Operand(rsi, smi_as_index.reg, smi_as_index.scale, |
10371 SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 10408 SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
10372 } | 10409 } |
10373 | 10410 |
10374 // rax: result string | 10411 // rax: result string |
10375 // rcx: result length | 10412 // rcx: result length |
10376 // rdx: original value of rsi | 10413 // rdx: original value of rsi |
10377 // rdi: first character of result | 10414 // rdi: first character of result |
10378 // rsi: character of sub string start | 10415 // rsi: character of sub string start |
10379 GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); | 10416 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); |
10380 __ movq(rsi, rdx); // Restore rsi. | 10417 __ movq(rsi, rdx); // Restore rsi. |
10381 __ IncrementCounter(&Counters::sub_string_native, 1); | 10418 __ IncrementCounter(&Counters::sub_string_native, 1); |
10382 __ ret(kArgumentsSize); | 10419 __ ret(kArgumentsSize); |
10383 | 10420 |
10384 __ bind(&non_ascii_flat); | 10421 __ bind(&non_ascii_flat); |
10385 // rax: string | 10422 // rax: string |
10386 // rbx: instance type & kStringRepresentationMask | kStringEncodingMask | 10423 // rbx: instance type & kStringRepresentationMask | kStringEncodingMask |
10387 // rcx: result string length | 10424 // rcx: result string length |
10388 // Check for sequential two byte string | 10425 // Check for sequential two byte string |
10389 __ cmpb(rbx, Immediate(kSeqStringTag | kTwoByteStringTag)); | 10426 __ cmpb(rbx, Immediate(kSeqStringTag | kTwoByteStringTag)); |
(...skipping 14 matching lines...) Expand all Loading... |
10404 SmiIndex smi_as_index = masm->SmiToIndex(rbx, rbx, times_2); | 10441 SmiIndex smi_as_index = masm->SmiToIndex(rbx, rbx, times_2); |
10405 __ lea(rsi, Operand(rsi, smi_as_index.reg, smi_as_index.scale, | 10442 __ lea(rsi, Operand(rsi, smi_as_index.reg, smi_as_index.scale, |
10406 SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 10443 SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
10407 } | 10444 } |
10408 | 10445 |
10409 // rax: result string | 10446 // rax: result string |
10410 // rcx: result length | 10447 // rcx: result length |
10411 // rdx: original value of rsi | 10448 // rdx: original value of rsi |
10412 // rdi: first character of result | 10449 // rdi: first character of result |
10413 // rsi: character of sub string start | 10450 // rsi: character of sub string start |
10414 GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); | 10451 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); |
10415 __ movq(rsi, rdx); // Restore esi. | 10452 __ movq(rsi, rdx); // Restore esi. |
10416 __ IncrementCounter(&Counters::sub_string_native, 1); | 10453 __ IncrementCounter(&Counters::sub_string_native, 1); |
10417 __ ret(kArgumentsSize); | 10454 __ ret(kArgumentsSize); |
10418 | 10455 |
10419 // Just jump to runtime to create the sub string. | 10456 // Just jump to runtime to create the sub string. |
10420 __ bind(&runtime); | 10457 __ bind(&runtime); |
10421 __ TailCallRuntime(Runtime::kSubString, 3, 1); | 10458 __ TailCallRuntime(Runtime::kSubString, 3, 1); |
10422 } | 10459 } |
10423 | 10460 |
10424 | 10461 |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10631 // Call the function from C++. | 10668 // Call the function from C++. |
10632 return FUNCTION_CAST<ModuloFunction>(buffer); | 10669 return FUNCTION_CAST<ModuloFunction>(buffer); |
10633 } | 10670 } |
10634 | 10671 |
10635 #endif | 10672 #endif |
10636 | 10673 |
10637 | 10674 |
10638 #undef __ | 10675 #undef __ |
10639 | 10676 |
10640 } } // namespace v8::internal | 10677 } } // namespace v8::internal |
OLD | NEW |