Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(348)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 1750017: Port string keyed load IC improvements (r4444) to x64. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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, &not_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(&not_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
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, &not_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(&not_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
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
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
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, &not_array_index); 10162 __ j(above, &not_array_index);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698