| 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 |