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

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

Issue 1769014: Port string keyed load IC improvements (r4444) to ARM. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 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/arm/codegen-arm.h ('k') | src/arm/ic-arm.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 3932 matching lines...) Expand 10 before | Expand all | Expand 10 after
3943 3943
3944 // Generates the Math.sqrt method - currently just calls runtime. 3944 // Generates the Math.sqrt method - currently just calls runtime.
3945 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { 3945 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
3946 ASSERT(args->length() == 1); 3946 ASSERT(args->length() == 1);
3947 Load(args->at(0)); 3947 Load(args->at(0));
3948 frame_->CallRuntime(Runtime::kMath_sqrt, 1); 3948 frame_->CallRuntime(Runtime::kMath_sqrt, 1);
3949 frame_->EmitPush(r0); 3949 frame_->EmitPush(r0);
3950 } 3950 }
3951 3951
3952 3952
3953 // This should generate code that performs a charCodeAt() call or returns 3953 // This generates code that performs a charCodeAt() call or returns
3954 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 3954 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
3955 // It is not yet implemented on ARM, so it always goes to the slow case. 3955 // It can handle flat, 8 and 16 bit characters and cons strings where the
3956 // answer is found in the left hand branch of the cons. The slow case will
3957 // flatten the string, which will ensure that the answer is in the left hand
3958 // side the next time around.
3956 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3959 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
3957 VirtualFrame::SpilledScope spilled_scope(frame_); 3960 VirtualFrame::SpilledScope spilled_scope(frame_);
3958 ASSERT(args->length() == 2); 3961 ASSERT(args->length() == 2);
3959 Comment(masm_, "[ GenerateFastCharCodeAt"); 3962 Comment(masm_, "[ GenerateFastCharCodeAt");
3960 3963
3961 LoadAndSpill(args->at(0)); 3964 LoadAndSpill(args->at(0));
3962 LoadAndSpill(args->at(1)); 3965 LoadAndSpill(args->at(1));
3963 frame_->EmitPop(r0); // Index. 3966 frame_->EmitPop(r1); // Index.
3964 frame_->EmitPop(r1); // String. 3967 frame_->EmitPop(r2); // String.
3965 3968
3966 Label slow, end, not_a_flat_string, ascii_string, try_again_with_new_string; 3969 Label slow_case;
3970 Label exit;
3971 StringHelper::GenerateFastCharCodeAt(masm_,
3972 r2,
3973 r1,
3974 r3,
3975 r0,
3976 &slow_case,
3977 &slow_case,
3978 &slow_case,
3979 &slow_case);
3980 __ jmp(&exit);
3967 3981
3968 __ tst(r1, Operand(kSmiTagMask)); 3982 __ bind(&slow_case);
3969 __ b(eq, &slow); // The 'string' was a Smi. 3983 // Move the undefined value into the result register, which will
3970 3984 // trigger the slow case.
3971 ASSERT(kSmiTag == 0);
3972 __ tst(r0, Operand(kSmiTagMask | 0x80000000u));
3973 __ b(ne, &slow); // The index was negative or not a Smi.
3974
3975 __ bind(&try_again_with_new_string);
3976 __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE);
3977 __ b(ge, &slow);
3978
3979 // Now r2 has the string type.
3980 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset));
3981 // Now r3 has the length of the string. Compare with the index.
3982 __ cmp(r3, Operand(r0, LSR, kSmiTagSize));
3983 __ b(le, &slow);
3984
3985 // Here we know the index is in range. Check that string is sequential.
3986 ASSERT_EQ(0, kSeqStringTag);
3987 __ tst(r2, Operand(kStringRepresentationMask));
3988 __ b(ne, &not_a_flat_string);
3989
3990 // Check whether it is an ASCII string.
3991 ASSERT_EQ(0, kTwoByteStringTag);
3992 __ tst(r2, Operand(kStringEncodingMask));
3993 __ b(ne, &ascii_string);
3994
3995 // 2-byte string. We can add without shifting since the Smi tag size is the
3996 // log2 of the number of bytes in a two-byte character.
3997 ASSERT_EQ(1, kSmiTagSize);
3998 ASSERT_EQ(0, kSmiShiftSize);
3999 __ add(r1, r1, Operand(r0));
4000 __ ldrh(r0, FieldMemOperand(r1, SeqTwoByteString::kHeaderSize));
4001 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
4002 __ jmp(&end);
4003
4004 __ bind(&ascii_string);
4005 __ add(r1, r1, Operand(r0, LSR, kSmiTagSize));
4006 __ ldrb(r0, FieldMemOperand(r1, SeqAsciiString::kHeaderSize));
4007 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
4008 __ jmp(&end);
4009
4010 __ bind(&not_a_flat_string);
4011 __ and_(r2, r2, Operand(kStringRepresentationMask));
4012 __ cmp(r2, Operand(kConsStringTag));
4013 __ b(ne, &slow);
4014
4015 // ConsString.
4016 // Check that the right hand side is the empty string (ie if this is really a
4017 // flat string in a cons string). If that is not the case we would rather go
4018 // to the runtime system now, to flatten the string.
4019 __ ldr(r2, FieldMemOperand(r1, ConsString::kSecondOffset));
4020 __ LoadRoot(r3, Heap::kEmptyStringRootIndex);
4021 __ cmp(r2, Operand(r3));
4022 __ b(ne, &slow);
4023
4024 // Get the first of the two strings.
4025 __ ldr(r1, FieldMemOperand(r1, ConsString::kFirstOffset));
4026 __ jmp(&try_again_with_new_string);
4027
4028 __ bind(&slow);
4029 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 3985 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
4030 3986
4031 __ bind(&end); 3987 __ bind(&exit);
4032 frame_->EmitPush(r0); 3988 frame_->EmitPush(r0);
4033 } 3989 }
4034 3990
4035 3991
4036 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { 3992 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) {
4037 Comment(masm_, "[ GenerateCharFromCode"); 3993 Comment(masm_, "[ GenerateCharFromCode");
4038 ASSERT(args->length() == 1); 3994 ASSERT(args->length() == 1);
4039 3995
3996 Register code = r1;
3997 Register scratch = ip;
3998 Register result = r0;
3999
4040 LoadAndSpill(args->at(0)); 4000 LoadAndSpill(args->at(0));
4041 frame_->EmitPop(r0); 4001 frame_->EmitPop(code);
4042 4002
4043 JumpTarget slow_case; 4003 StringHelper::GenerateCharFromCode(masm_,
4044 JumpTarget exit; 4004 code,
4045 4005 scratch,
4046 // Fast case of Heap::LookupSingleCharacterStringFromCode. 4006 result,
4047 ASSERT(kSmiTag == 0); 4007 CALL_FUNCTION);
4048 ASSERT(kSmiShiftSize == 0); 4008 frame_->EmitPush(result);
4049 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
4050 __ tst(r0, Operand(kSmiTagMask |
4051 ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
4052 slow_case.Branch(nz);
4053
4054 ASSERT(kSmiTag == 0);
4055 __ mov(r1, Operand(Factory::single_character_string_cache()));
4056 __ add(r1, r1, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
4057 __ ldr(r1, MemOperand(r1, FixedArray::kHeaderSize - kHeapObjectTag));
4058 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
4059 __ cmp(r1, ip);
4060 slow_case.Branch(eq);
4061
4062 frame_->EmitPush(r1);
4063 exit.Jump();
4064
4065 slow_case.Bind();
4066 frame_->EmitPush(r0);
4067 frame_->CallRuntime(Runtime::kCharFromCode, 1);
4068 frame_->EmitPush(r0);
4069
4070 exit.Bind();
4071 } 4009 }
4072 4010
4073 4011
4074 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 4012 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
4075 VirtualFrame::SpilledScope spilled_scope(frame_); 4013 VirtualFrame::SpilledScope spilled_scope(frame_);
4076 ASSERT(args->length() == 1); 4014 ASSERT(args->length() == 1);
4077 LoadAndSpill(args->at(0)); 4015 LoadAndSpill(args->at(0));
4078 JumpTarget answer; 4016 JumpTarget answer;
4079 // We need the CC bits to come out as not_equal in the case where the 4017 // We need the CC bits to come out as not_equal in the case where the
4080 // object is a smi. This can't be done with the usual test opcode so 4018 // object is a smi. This can't be done with the usual test opcode so
(...skipping 4662 matching lines...) Expand 10 before | Expand all | Expand 10 after
8743 // stubs the never NaN NaN condition is only taken into account if the 8681 // stubs the never NaN NaN condition is only taken into account if the
8744 // condition is equals. 8682 // condition is equals.
8745 ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 13)); 8683 ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 13));
8746 return ConditionField::encode(static_cast<unsigned>(cc_) >> 28) 8684 return ConditionField::encode(static_cast<unsigned>(cc_) >> 28)
8747 | StrictField::encode(strict_) 8685 | StrictField::encode(strict_)
8748 | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false) 8686 | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
8749 | IncludeNumberCompareField::encode(include_number_compare_); 8687 | IncludeNumberCompareField::encode(include_number_compare_);
8750 } 8688 }
8751 8689
8752 8690
8753 void StringStubBase::GenerateCopyCharacters(MacroAssembler* masm, 8691 void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm,
8754 Register dest, 8692 Register object,
8755 Register src, 8693 Register index,
8756 Register count, 8694 Register scratch,
8757 Register scratch, 8695 Register result,
8758 bool ascii) { 8696 Label* receiver_not_string,
8697 Label* index_not_smi,
8698 Label* index_out_of_range,
8699 Label* slow_case) {
8700 Label not_a_flat_string;
8701 Label try_again_with_new_string;
8702 Label ascii_string;
8703 Label got_char_code;
8704
8705 // If the receiver is a smi trigger the non-string case.
8706 __ BranchOnSmi(object, receiver_not_string);
8707
8708 // Fetch the instance type of the receiver into result register.
8709 __ ldr(result, FieldMemOperand(object, HeapObject::kMapOffset));
8710 __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
8711 // If the receiver is not a string trigger the non-string case.
8712 __ tst(result, Operand(kIsNotStringMask));
8713 __ b(ne, receiver_not_string);
8714
8715 // If the index is non-smi trigger the non-smi case.
8716 __ BranchOnNotSmi(index, index_not_smi);
8717
8718 // Check for index out of range.
8719 __ ldr(scratch, FieldMemOperand(object, String::kLengthOffset));
8720 // Now scratch has the length of the string. Compare with the index.
8721 __ cmp(scratch, Operand(index, LSR, kSmiTagSize));
8722 __ b(ls, index_out_of_range);
8723
8724 __ bind(&try_again_with_new_string);
8725 // ----------- S t a t e -------------
8726 // -- object : string to access
8727 // -- result : instance type of the string
8728 // -- scratch : non-negative index < length
8729 // -----------------------------------
8730
8731 // We need special handling for non-flat strings.
8732 ASSERT_EQ(0, kSeqStringTag);
8733 __ tst(result, Operand(kStringRepresentationMask));
8734 __ b(ne, &not_a_flat_string);
8735
8736 // Check for 1-byte or 2-byte string.
8737 ASSERT_EQ(0, kTwoByteStringTag);
8738 __ tst(result, Operand(kStringEncodingMask));
8739 __ b(ne, &ascii_string);
8740
8741 // 2-byte string. We can add without shifting since the Smi tag size is the
8742 // log2 of the number of bytes in a two-byte character.
8743 ASSERT_EQ(1, kSmiTagSize);
8744 ASSERT_EQ(0, kSmiShiftSize);
8745 __ add(scratch, object, Operand(index));
8746 __ ldrh(result, FieldMemOperand(scratch, SeqTwoByteString::kHeaderSize));
8747 __ jmp(&got_char_code);
8748
8749 // Handle non-flat strings.
8750 __ bind(&not_a_flat_string);
8751 __ and_(result, result, Operand(kStringRepresentationMask));
8752 __ cmp(result, Operand(kConsStringTag));
8753 __ b(ne, slow_case);
8754
8755 // ConsString.
8756 // Check whether the right hand side is the empty string (i.e. if
8757 // this is really a flat string in a cons string). If that is not
8758 // the case we would rather go to the runtime system now to flatten
8759 // the string.
8760 __ ldr(result, FieldMemOperand(object, ConsString::kSecondOffset));
8761 __ LoadRoot(scratch, Heap::kEmptyStringRootIndex);
8762 __ cmp(result, Operand(scratch));
8763 __ b(ne, slow_case);
8764
8765 // Get the first of the two strings and load its instance type.
8766 __ ldr(object, FieldMemOperand(object, ConsString::kFirstOffset));
8767 __ ldr(result, FieldMemOperand(object, HeapObject::kMapOffset));
8768 __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
8769 __ jmp(&try_again_with_new_string);
8770
8771 // ASCII string.
8772 __ bind(&ascii_string);
8773 __ add(scratch, object, Operand(index, LSR, kSmiTagSize));
8774 __ ldrb(result, FieldMemOperand(scratch, SeqAsciiString::kHeaderSize));
8775
8776 __ bind(&got_char_code);
8777 __ mov(result, Operand(result, LSL, kSmiTagSize));
8778 }
8779
8780
8781 void StringHelper::GenerateCharFromCode(MacroAssembler* masm,
8782 Register code,
8783 Register scratch,
8784 Register result,
8785 InvokeFlag flag) {
8786 ASSERT(!code.is(result));
8787
8788 Label slow_case;
8789 Label exit;
8790
8791 // Fast case of Heap::LookupSingleCharacterStringFromCode.
8792 ASSERT(kSmiTag == 0);
8793 ASSERT(kSmiShiftSize == 0);
8794 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
8795 __ tst(code, Operand(kSmiTagMask |
8796 ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
8797 __ b(nz, &slow_case);
8798
8799 ASSERT(kSmiTag == 0);
8800 __ mov(result, Operand(Factory::single_character_string_cache()));
8801 __ add(result, result, Operand(code, LSL, kPointerSizeLog2 - kSmiTagSize));
8802 __ ldr(result, MemOperand(result, FixedArray::kHeaderSize - kHeapObjectTag));
8803 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
8804 __ cmp(result, scratch);
8805 __ b(eq, &slow_case);
8806 __ b(&exit);
8807
8808 __ bind(&slow_case);
8809 if (flag == CALL_FUNCTION) {
8810 __ push(code);
8811 __ CallRuntime(Runtime::kCharFromCode, 1);
8812 if (!result.is(r0)) {
8813 __ mov(result, r0);
8814 }
8815 } else {
8816 ASSERT(flag == JUMP_FUNCTION);
8817 ASSERT(result.is(r0));
8818 __ push(code);
8819 __ TailCallRuntime(Runtime::kCharFromCode, 1, 1);
8820 }
8821
8822 __ bind(&exit);
8823 if (flag == JUMP_FUNCTION) {
8824 ASSERT(result.is(r0));
8825 __ Ret();
8826 }
8827 }
8828
8829
8830 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
8831 Register dest,
8832 Register src,
8833 Register count,
8834 Register scratch,
8835 bool ascii) {
8759 Label loop; 8836 Label loop;
8760 Label done; 8837 Label done;
8761 // This loop just copies one character at a time, as it is only used for very 8838 // This loop just copies one character at a time, as it is only used for very
8762 // short strings. 8839 // short strings.
8763 if (!ascii) { 8840 if (!ascii) {
8764 __ add(count, count, Operand(count), SetCC); 8841 __ add(count, count, Operand(count), SetCC);
8765 } else { 8842 } else {
8766 __ cmp(count, Operand(0)); 8843 __ cmp(count, Operand(0));
8767 } 8844 }
8768 __ b(eq, &done); 8845 __ b(eq, &done);
(...skipping 10 matching lines...) Expand all
8779 __ bind(&done); 8856 __ bind(&done);
8780 } 8857 }
8781 8858
8782 8859
8783 enum CopyCharactersFlags { 8860 enum CopyCharactersFlags {
8784 COPY_ASCII = 1, 8861 COPY_ASCII = 1,
8785 DEST_ALWAYS_ALIGNED = 2 8862 DEST_ALWAYS_ALIGNED = 2
8786 }; 8863 };
8787 8864
8788 8865
8789 void StringStubBase::GenerateCopyCharactersLong(MacroAssembler* masm, 8866 void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
8790 Register dest, 8867 Register dest,
8791 Register src, 8868 Register src,
8792 Register count, 8869 Register count,
8793 Register scratch1, 8870 Register scratch1,
8794 Register scratch2, 8871 Register scratch2,
8795 Register scratch3, 8872 Register scratch3,
8796 Register scratch4, 8873 Register scratch4,
8797 Register scratch5, 8874 Register scratch5,
8798 int flags) { 8875 int flags) {
8799 bool ascii = (flags & COPY_ASCII) != 0; 8876 bool ascii = (flags & COPY_ASCII) != 0;
8800 bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; 8877 bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0;
8801 8878
8802 if (dest_always_aligned && FLAG_debug_code) { 8879 if (dest_always_aligned && FLAG_debug_code) {
8803 // Check that destination is actually word aligned if the flag says 8880 // Check that destination is actually word aligned if the flag says
8804 // that it is. 8881 // that it is.
8805 __ tst(dest, Operand(kPointerAlignmentMask)); 8882 __ tst(dest, Operand(kPointerAlignmentMask));
8806 __ Check(eq, "Destination of copy not aligned."); 8883 __ Check(eq, "Destination of copy not aligned.");
8807 } 8884 }
8808 8885
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
8922 __ cmp(dest, Operand(limit)); 8999 __ cmp(dest, Operand(limit));
8923 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt); 9000 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt);
8924 __ b(ge, &done); 9001 __ b(ge, &done);
8925 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); 9002 __ strb(scratch1, MemOperand(dest, 1, PostIndex));
8926 __ b(&byte_loop); 9003 __ b(&byte_loop);
8927 9004
8928 __ bind(&done); 9005 __ bind(&done);
8929 } 9006 }
8930 9007
8931 9008
8932 void StringStubBase::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, 9009 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
8933 Register c1, 9010 Register c1,
8934 Register c2, 9011 Register c2,
8935 Register scratch1, 9012 Register scratch1,
8936 Register scratch2, 9013 Register scratch2,
8937 Register scratch3, 9014 Register scratch3,
8938 Register scratch4, 9015 Register scratch4,
8939 Register scratch5, 9016 Register scratch5,
8940 Label* not_found) { 9017 Label* not_found) {
8941 // Register scratch3 is the general scratch register in this function. 9018 // Register scratch3 is the general scratch register in this function.
8942 Register scratch = scratch3; 9019 Register scratch = scratch3;
8943 9020
8944 // Make sure that both characters are not digits as such strings has a 9021 // Make sure that both characters are not digits as such strings has a
8945 // different hash algorithm. Don't try to look for these in the symbol table. 9022 // different hash algorithm. Don't try to look for these in the symbol table.
8946 Label not_array_index; 9023 Label not_array_index;
8947 __ sub(scratch, c1, Operand(static_cast<int>('0'))); 9024 __ sub(scratch, c1, Operand(static_cast<int>('0')));
8948 __ cmp(scratch, Operand(static_cast<int>('9' - '0'))); 9025 __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
8949 __ b(hi, &not_array_index); 9026 __ b(hi, &not_array_index);
8950 __ sub(scratch, c2, Operand(static_cast<int>('0'))); 9027 __ sub(scratch, c2, Operand(static_cast<int>('0')));
8951 __ cmp(scratch, Operand(static_cast<int>('9' - '0'))); 9028 __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
8952 9029
8953 // If check failed combine both characters into single halfword. 9030 // If check failed combine both characters into single halfword.
8954 // This is required by the contract of the method: code at the 9031 // This is required by the contract of the method: code at the
8955 // not_found branch expects this combination in c1 register 9032 // not_found branch expects this combination in c1 register
8956 __ orr(c1, c1, Operand(c2, LSL, kBitsPerByte), LeaveCC, ls); 9033 __ orr(c1, c1, Operand(c2, LSL, kBitsPerByte), LeaveCC, ls);
8957 __ b(ls, not_found); 9034 __ b(ls, not_found);
8958 9035
8959 __ bind(&not_array_index); 9036 __ bind(&not_array_index);
8960 // Calculate the two character string hash. 9037 // Calculate the two character string hash.
8961 Register hash = scratch1; 9038 Register hash = scratch1;
8962 GenerateHashInit(masm, hash, c1); 9039 StringHelper::GenerateHashInit(masm, hash, c1);
8963 GenerateHashAddCharacter(masm, hash, c2); 9040 StringHelper::GenerateHashAddCharacter(masm, hash, c2);
8964 GenerateHashGetHash(masm, hash); 9041 StringHelper::GenerateHashGetHash(masm, hash);
8965 9042
8966 // Collect the two characters in a register. 9043 // Collect the two characters in a register.
8967 Register chars = c1; 9044 Register chars = c1;
8968 __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte)); 9045 __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte));
8969 9046
8970 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. 9047 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
8971 // hash: hash of two character string. 9048 // hash: hash of two character string.
8972 9049
8973 // Load symbol table 9050 // Load symbol table
8974 // Load address of first element of the symbol table. 9051 // Load address of first element of the symbol table.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
9048 // No matching 2 character string found by probing. 9125 // No matching 2 character string found by probing.
9049 __ jmp(not_found); 9126 __ jmp(not_found);
9050 9127
9051 // Scratch register contains result when we fall through to here. 9128 // Scratch register contains result when we fall through to here.
9052 Register result = scratch; 9129 Register result = scratch;
9053 __ bind(&found_in_symbol_table); 9130 __ bind(&found_in_symbol_table);
9054 __ Move(r0, result); 9131 __ Move(r0, result);
9055 } 9132 }
9056 9133
9057 9134
9058 void StringStubBase::GenerateHashInit(MacroAssembler* masm, 9135 void StringHelper::GenerateHashInit(MacroAssembler* masm,
9059 Register hash, 9136 Register hash,
9060 Register character) { 9137 Register character) {
9061 // hash = character + (character << 10); 9138 // hash = character + (character << 10);
9062 __ add(hash, character, Operand(character, LSL, 10)); 9139 __ add(hash, character, Operand(character, LSL, 10));
9063 // hash ^= hash >> 6; 9140 // hash ^= hash >> 6;
9064 __ eor(hash, hash, Operand(hash, ASR, 6)); 9141 __ eor(hash, hash, Operand(hash, ASR, 6));
9065 } 9142 }
9066 9143
9067 9144
9068 void StringStubBase::GenerateHashAddCharacter(MacroAssembler* masm, 9145 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
9069 Register hash, 9146 Register hash,
9070 Register character) { 9147 Register character) {
9071 // hash += character; 9148 // hash += character;
9072 __ add(hash, hash, Operand(character)); 9149 __ add(hash, hash, Operand(character));
9073 // hash += hash << 10; 9150 // hash += hash << 10;
9074 __ add(hash, hash, Operand(hash, LSL, 10)); 9151 __ add(hash, hash, Operand(hash, LSL, 10));
9075 // hash ^= hash >> 6; 9152 // hash ^= hash >> 6;
9076 __ eor(hash, hash, Operand(hash, ASR, 6)); 9153 __ eor(hash, hash, Operand(hash, ASR, 6));
9077 } 9154 }
9078 9155
9079 9156
9080 void StringStubBase::GenerateHashGetHash(MacroAssembler* masm, 9157 void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
9081 Register hash) { 9158 Register hash) {
9082 // hash += hash << 3; 9159 // hash += hash << 3;
9083 __ add(hash, hash, Operand(hash, LSL, 3)); 9160 __ add(hash, hash, Operand(hash, LSL, 3));
9084 // hash ^= hash >> 11; 9161 // hash ^= hash >> 11;
9085 __ eor(hash, hash, Operand(hash, ASR, 11)); 9162 __ eor(hash, hash, Operand(hash, ASR, 11));
9086 // hash += hash << 15; 9163 // hash += hash << 15;
9087 __ add(hash, hash, Operand(hash, LSL, 15), SetCC); 9164 __ add(hash, hash, Operand(hash, LSL, 15), SetCC);
9088 9165
9089 // if (hash == 0) hash = 27; 9166 // if (hash == 0) hash = 27;
9090 __ mov(hash, Operand(27), LeaveCC, nz); 9167 __ mov(hash, Operand(27), LeaveCC, nz);
9091 } 9168 }
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
9198 __ b(gt, &result_longer_than_two); 9275 __ b(gt, &result_longer_than_two);
9199 9276
9200 // Sub string of length 2 requested. 9277 // Sub string of length 2 requested.
9201 // Get the two characters forming the sub string. 9278 // Get the two characters forming the sub string.
9202 __ add(r5, r5, Operand(r3)); 9279 __ add(r5, r5, Operand(r3));
9203 __ ldrb(r3, FieldMemOperand(r5, SeqAsciiString::kHeaderSize)); 9280 __ ldrb(r3, FieldMemOperand(r5, SeqAsciiString::kHeaderSize));
9204 __ ldrb(r4, FieldMemOperand(r5, SeqAsciiString::kHeaderSize + 1)); 9281 __ ldrb(r4, FieldMemOperand(r5, SeqAsciiString::kHeaderSize + 1));
9205 9282
9206 // Try to lookup two character string in symbol table. 9283 // Try to lookup two character string in symbol table.
9207 Label make_two_character_string; 9284 Label make_two_character_string;
9208 GenerateTwoCharacterSymbolTableProbe(masm, r3, r4, r1, r5, r6, r7, r9, 9285 StringHelper::GenerateTwoCharacterSymbolTableProbe(
9209 &make_two_character_string); 9286 masm, r3, r4, r1, r5, r6, r7, r9, &make_two_character_string);
9210 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); 9287 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
9211 __ add(sp, sp, Operand(3 * kPointerSize)); 9288 __ add(sp, sp, Operand(3 * kPointerSize));
9212 __ Ret(); 9289 __ Ret();
9213 9290
9214 // r2: result string length. 9291 // r2: result string length.
9215 // r3: two characters combined into halfword in little endian byte order. 9292 // r3: two characters combined into halfword in little endian byte order.
9216 __ bind(&make_two_character_string); 9293 __ bind(&make_two_character_string);
9217 __ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime); 9294 __ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime);
9218 __ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); 9295 __ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
9219 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); 9296 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
(...skipping 13 matching lines...) Expand all
9233 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9310 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9234 // Locate 'from' character of string. 9311 // Locate 'from' character of string.
9235 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9312 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9236 __ add(r5, r5, Operand(r6, ASR, 1)); 9313 __ add(r5, r5, Operand(r6, ASR, 1));
9237 9314
9238 // r0: result string. 9315 // r0: result string.
9239 // r1: first character of result string. 9316 // r1: first character of result string.
9240 // r2: result string length. 9317 // r2: result string length.
9241 // r5: first character of sub string to copy. 9318 // r5: first character of sub string to copy.
9242 ASSERT_EQ(0, SeqAsciiString::kHeaderSize & kObjectAlignmentMask); 9319 ASSERT_EQ(0, SeqAsciiString::kHeaderSize & kObjectAlignmentMask);
9243 GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, 9320 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
9244 COPY_ASCII | DEST_ALWAYS_ALIGNED); 9321 COPY_ASCII | DEST_ALWAYS_ALIGNED);
9245 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); 9322 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
9246 __ add(sp, sp, Operand(3 * kPointerSize)); 9323 __ add(sp, sp, Operand(3 * kPointerSize));
9247 __ Ret(); 9324 __ Ret();
9248 9325
9249 __ bind(&non_ascii_flat); 9326 __ bind(&non_ascii_flat);
9250 // r2: result string length. 9327 // r2: result string length.
9251 // r5: string. 9328 // r5: string.
9252 // r6: from offset (smi) 9329 // r6: from offset (smi)
9253 // Check for flat two byte string. 9330 // Check for flat two byte string.
9254 9331
9255 // Allocate the result. 9332 // Allocate the result.
9256 __ AllocateTwoByteString(r0, r2, r1, r3, r4, &runtime); 9333 __ AllocateTwoByteString(r0, r2, r1, r3, r4, &runtime);
9257 9334
9258 // r0: result string. 9335 // r0: result string.
9259 // r2: result string length. 9336 // r2: result string length.
9260 // r5: string. 9337 // r5: string.
9261 // Locate first character of result. 9338 // Locate first character of result.
9262 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 9339 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
9263 // Locate 'from' character of string. 9340 // Locate 'from' character of string.
9264 __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 9341 __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
9265 // As "from" is a smi it is 2 times the value which matches the size of a two 9342 // As "from" is a smi it is 2 times the value which matches the size of a two
9266 // byte character. 9343 // byte character.
9267 __ add(r5, r5, Operand(r6)); 9344 __ add(r5, r5, Operand(r6));
9268 9345
9269 // r0: result string. 9346 // r0: result string.
9270 // r1: first character of result. 9347 // r1: first character of result.
9271 // r2: result length. 9348 // r2: result length.
9272 // r5: first character of string to copy. 9349 // r5: first character of string to copy.
9273 ASSERT_EQ(0, SeqTwoByteString::kHeaderSize & kObjectAlignmentMask); 9350 ASSERT_EQ(0, SeqTwoByteString::kHeaderSize & kObjectAlignmentMask);
9274 GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, 9351 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
9275 DEST_ALWAYS_ALIGNED); 9352 DEST_ALWAYS_ALIGNED);
9276 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); 9353 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
9277 __ add(sp, sp, Operand(3 * kPointerSize)); 9354 __ add(sp, sp, Operand(3 * kPointerSize));
9278 __ Ret(); 9355 __ Ret();
9279 9356
9280 // Just jump to runtime to create the sub string. 9357 // Just jump to runtime to create the sub string.
9281 __ bind(&runtime); 9358 __ bind(&runtime);
9282 __ TailCallRuntime(Runtime::kSubString, 3, 1); 9359 __ TailCallRuntime(Runtime::kSubString, 3, 1);
9283 } 9360 }
9284 9361
9285 9362
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
9449 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, 9526 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7,
9450 &string_add_runtime); 9527 &string_add_runtime);
9451 9528
9452 // Get the two characters forming the sub string. 9529 // Get the two characters forming the sub string.
9453 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); 9530 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
9454 __ ldrb(r3, FieldMemOperand(r1, SeqAsciiString::kHeaderSize)); 9531 __ ldrb(r3, FieldMemOperand(r1, SeqAsciiString::kHeaderSize));
9455 9532
9456 // Try to lookup two character string in symbol table. If it is not found 9533 // Try to lookup two character string in symbol table. If it is not found
9457 // just allocate a new one. 9534 // just allocate a new one.
9458 Label make_two_character_string; 9535 Label make_two_character_string;
9459 GenerateTwoCharacterSymbolTableProbe(masm, r2, r3, r6, r7, r4, r5, r9, 9536 StringHelper::GenerateTwoCharacterSymbolTableProbe(
9460 &make_two_character_string); 9537 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string);
9461 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); 9538 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
9462 __ add(sp, sp, Operand(2 * kPointerSize)); 9539 __ add(sp, sp, Operand(2 * kPointerSize));
9463 __ Ret(); 9540 __ Ret();
9464 9541
9465 __ bind(&make_two_character_string); 9542 __ bind(&make_two_character_string);
9466 // Resulting string has length 2 and first chars of two strings 9543 // Resulting string has length 2 and first chars of two strings
9467 // are combined into single halfword in r2 register. 9544 // are combined into single halfword in r2 register.
9468 // So we can fill resulting string without two loops by a single 9545 // So we can fill resulting string without two loops by a single
9469 // halfword store instruction (which assumes that processor is 9546 // halfword store instruction (which assumes that processor is
9470 // in a little endian mode) 9547 // in a little endian mode)
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
9559 // Locate first character of result. 9636 // Locate first character of result.
9560 __ add(r6, r7, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9637 __ add(r6, r7, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9561 // Locate first character of first argument. 9638 // Locate first character of first argument.
9562 __ add(r0, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9639 __ add(r0, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9563 // r0: first character of first string. 9640 // r0: first character of first string.
9564 // r1: second string. 9641 // r1: second string.
9565 // r2: length of first string. 9642 // r2: length of first string.
9566 // r3: length of second string. 9643 // r3: length of second string.
9567 // r6: first character of result. 9644 // r6: first character of result.
9568 // r7: result string. 9645 // r7: result string.
9569 GenerateCopyCharacters(masm, r6, r0, r2, r4, true); 9646 StringHelper::GenerateCopyCharacters(masm, r6, r0, r2, r4, true);
9570 9647
9571 // Load second argument and locate first character. 9648 // Load second argument and locate first character.
9572 __ add(r1, r1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9649 __ add(r1, r1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9573 // r1: first character of second string. 9650 // r1: first character of second string.
9574 // r3: length of second string. 9651 // r3: length of second string.
9575 // r6: next character of result. 9652 // r6: next character of result.
9576 // r7: result string. 9653 // r7: result string.
9577 GenerateCopyCharacters(masm, r6, r1, r3, r4, true); 9654 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true);
9578 __ mov(r0, Operand(r7)); 9655 __ mov(r0, Operand(r7));
9579 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); 9656 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
9580 __ add(sp, sp, Operand(2 * kPointerSize)); 9657 __ add(sp, sp, Operand(2 * kPointerSize));
9581 __ Ret(); 9658 __ Ret();
9582 9659
9583 __ bind(&non_ascii_string_add_flat_result); 9660 __ bind(&non_ascii_string_add_flat_result);
9584 // Both strings are sequential two byte strings. 9661 // Both strings are sequential two byte strings.
9585 // r0: first string. 9662 // r0: first string.
9586 // r1: second string. 9663 // r1: second string.
9587 // r2: length of first string. 9664 // r2: length of first string.
(...skipping 10 matching lines...) Expand all
9598 __ add(r6, r7, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 9675 __ add(r6, r7, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
9599 // Locate first character of first argument. 9676 // Locate first character of first argument.
9600 __ add(r0, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 9677 __ add(r0, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
9601 9678
9602 // r0: first character of first string. 9679 // r0: first character of first string.
9603 // r1: second string. 9680 // r1: second string.
9604 // r2: length of first string. 9681 // r2: length of first string.
9605 // r3: length of second string. 9682 // r3: length of second string.
9606 // r6: first character of result. 9683 // r6: first character of result.
9607 // r7: result string. 9684 // r7: result string.
9608 GenerateCopyCharacters(masm, r6, r0, r2, r4, false); 9685 StringHelper::GenerateCopyCharacters(masm, r6, r0, r2, r4, false);
9609 9686
9610 // Locate first character of second argument. 9687 // Locate first character of second argument.
9611 __ add(r1, r1, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 9688 __ add(r1, r1, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
9612 9689
9613 // r1: first character of second string. 9690 // r1: first character of second string.
9614 // r3: length of second string. 9691 // r3: length of second string.
9615 // r6: next character of result (after copy of first string). 9692 // r6: next character of result (after copy of first string).
9616 // r7: result string. 9693 // r7: result string.
9617 GenerateCopyCharacters(masm, r6, r1, r3, r4, false); 9694 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false);
9618 9695
9619 __ mov(r0, Operand(r7)); 9696 __ mov(r0, Operand(r7));
9620 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); 9697 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
9621 __ add(sp, sp, Operand(2 * kPointerSize)); 9698 __ add(sp, sp, Operand(2 * kPointerSize));
9622 __ Ret(); 9699 __ Ret();
9623 9700
9624 // Just jump to runtime to add the two strings. 9701 // Just jump to runtime to add the two strings.
9625 __ bind(&string_add_runtime); 9702 __ bind(&string_add_runtime);
9626 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 9703 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
9627 } 9704 }
9628 9705
9629 9706
9630 #undef __ 9707 #undef __
9631 9708
9632 } } // namespace v8::internal 9709 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698