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 3932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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, ¬_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(¬_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 Loading... |
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, ¬_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(¬_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 Loading... |
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 Loading... |
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, ¬_array_index); | 9026 __ b(hi, ¬_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(¬_array_index); | 9036 __ bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |