| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
| 8 | 8 |
| 9 // Note on Mips implementation: | 9 // Note on Mips implementation: |
| 10 // | 10 // |
| (...skipping 3817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3828 | 3828 |
| 3829 __ AssertString(v0); | 3829 __ AssertString(v0); |
| 3830 | 3830 |
| 3831 __ lw(v0, FieldMemOperand(v0, String::kHashFieldOffset)); | 3831 __ lw(v0, FieldMemOperand(v0, String::kHashFieldOffset)); |
| 3832 __ IndexFromHash(v0, v0); | 3832 __ IndexFromHash(v0, v0); |
| 3833 | 3833 |
| 3834 context()->Plug(v0); | 3834 context()->Plug(v0); |
| 3835 } | 3835 } |
| 3836 | 3836 |
| 3837 | 3837 |
| 3838 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { | 3838 void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) { |
| 3839 Label bailout, done, one_char_separator, long_separator, | 3839 Label bailout, done, one_char_separator, long_separator, |
| 3840 non_trivial_array, not_size_one_array, loop, | 3840 non_trivial_array, not_size_one_array, loop, |
| 3841 empty_separator_loop, one_char_separator_loop, | 3841 empty_separator_loop, one_char_separator_loop, |
| 3842 one_char_separator_loop_entry, long_separator_loop; | 3842 one_char_separator_loop_entry, long_separator_loop; |
| 3843 ZoneList<Expression*>* args = expr->arguments(); | 3843 ZoneList<Expression*>* args = expr->arguments(); |
| 3844 DCHECK(args->length() == 2); | 3844 DCHECK(args->length() == 2); |
| 3845 VisitForStackValue(args->at(1)); | 3845 VisitForStackValue(args->at(1)); |
| 3846 VisitForAccumulatorValue(args->at(0)); | 3846 VisitForAccumulatorValue(args->at(0)); |
| 3847 | 3847 |
| 3848 // All aliases of the same register have disjoint lifetimes. | 3848 // All aliases of the same register have disjoint lifetimes. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3878 __ LoadRoot(v0, Heap::kempty_stringRootIndex); | 3878 __ LoadRoot(v0, Heap::kempty_stringRootIndex); |
| 3879 __ Branch(&done); | 3879 __ Branch(&done); |
| 3880 | 3880 |
| 3881 __ bind(&non_trivial_array); | 3881 __ bind(&non_trivial_array); |
| 3882 | 3882 |
| 3883 // Get the FixedArray containing array's elements. | 3883 // Get the FixedArray containing array's elements. |
| 3884 elements = array; | 3884 elements = array; |
| 3885 __ lw(elements, FieldMemOperand(array, JSArray::kElementsOffset)); | 3885 __ lw(elements, FieldMemOperand(array, JSArray::kElementsOffset)); |
| 3886 array = no_reg; // End of array's live range. | 3886 array = no_reg; // End of array's live range. |
| 3887 | 3887 |
| 3888 // Check that all array elements are sequential ASCII strings, and | 3888 // Check that all array elements are sequential one-byte strings, and |
| 3889 // accumulate the sum of their lengths, as a smi-encoded value. | 3889 // accumulate the sum of their lengths, as a smi-encoded value. |
| 3890 __ mov(string_length, zero_reg); | 3890 __ mov(string_length, zero_reg); |
| 3891 __ Addu(element, | 3891 __ Addu(element, |
| 3892 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 3892 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 3893 __ sll(elements_end, array_length, kPointerSizeLog2); | 3893 __ sll(elements_end, array_length, kPointerSizeLog2); |
| 3894 __ Addu(elements_end, element, elements_end); | 3894 __ Addu(elements_end, element, elements_end); |
| 3895 // Loop condition: while (element < elements_end). | 3895 // Loop condition: while (element < elements_end). |
| 3896 // Live values in registers: | 3896 // Live values in registers: |
| 3897 // elements: Fixed array of strings. | 3897 // elements: Fixed array of strings. |
| 3898 // array_length: Length of the fixed array of strings (not smi) | 3898 // array_length: Length of the fixed array of strings (not smi) |
| 3899 // separator: Separator string | 3899 // separator: Separator string |
| 3900 // string_length: Accumulated sum of string lengths (smi). | 3900 // string_length: Accumulated sum of string lengths (smi). |
| 3901 // element: Current array element. | 3901 // element: Current array element. |
| 3902 // elements_end: Array end. | 3902 // elements_end: Array end. |
| 3903 if (generate_debug_code_) { | 3903 if (generate_debug_code_) { |
| 3904 __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin, | 3904 __ Assert(gt, kNoEmptyArraysHereInEmitFastOneByteArrayJoin, array_length, |
| 3905 array_length, Operand(zero_reg)); | 3905 Operand(zero_reg)); |
| 3906 } | 3906 } |
| 3907 __ bind(&loop); | 3907 __ bind(&loop); |
| 3908 __ lw(string, MemOperand(element)); | 3908 __ lw(string, MemOperand(element)); |
| 3909 __ Addu(element, element, kPointerSize); | 3909 __ Addu(element, element, kPointerSize); |
| 3910 __ JumpIfSmi(string, &bailout); | 3910 __ JumpIfSmi(string, &bailout); |
| 3911 __ lw(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); | 3911 __ lw(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 3912 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 3912 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 3913 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); | 3913 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout); |
| 3914 __ lw(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); | 3914 __ lw(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); |
| 3915 __ AdduAndCheckForOverflow(string_length, string_length, scratch1, scratch3); | 3915 __ AdduAndCheckForOverflow(string_length, string_length, scratch1, scratch3); |
| 3916 __ BranchOnOverflow(&bailout, scratch3); | 3916 __ BranchOnOverflow(&bailout, scratch3); |
| 3917 __ Branch(&loop, lt, element, Operand(elements_end)); | 3917 __ Branch(&loop, lt, element, Operand(elements_end)); |
| 3918 | 3918 |
| 3919 // If array_length is 1, return elements[0], a string. | 3919 // If array_length is 1, return elements[0], a string. |
| 3920 __ Branch(¬_size_one_array, ne, array_length, Operand(1)); | 3920 __ Branch(¬_size_one_array, ne, array_length, Operand(1)); |
| 3921 __ lw(v0, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 3921 __ lw(v0, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 3922 __ Branch(&done); | 3922 __ Branch(&done); |
| 3923 | 3923 |
| 3924 __ bind(¬_size_one_array); | 3924 __ bind(¬_size_one_array); |
| 3925 | 3925 |
| 3926 // Live values in registers: | 3926 // Live values in registers: |
| 3927 // separator: Separator string | 3927 // separator: Separator string |
| 3928 // array_length: Length of the array. | 3928 // array_length: Length of the array. |
| 3929 // string_length: Sum of string lengths (smi). | 3929 // string_length: Sum of string lengths (smi). |
| 3930 // elements: FixedArray of strings. | 3930 // elements: FixedArray of strings. |
| 3931 | 3931 |
| 3932 // Check that the separator is a flat ASCII string. | 3932 // Check that the separator is a flat one-byte string. |
| 3933 __ JumpIfSmi(separator, &bailout); | 3933 __ JumpIfSmi(separator, &bailout); |
| 3934 __ lw(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); | 3934 __ lw(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); |
| 3935 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 3935 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 3936 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); | 3936 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout); |
| 3937 | 3937 |
| 3938 // Add (separator length times array_length) - separator length to the | 3938 // Add (separator length times array_length) - separator length to the |
| 3939 // string_length to get the length of the result string. array_length is not | 3939 // string_length to get the length of the result string. array_length is not |
| 3940 // smi but the other values are, so the result is a smi. | 3940 // smi but the other values are, so the result is a smi. |
| 3941 __ lw(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); | 3941 __ lw(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); |
| 3942 __ Subu(string_length, string_length, Operand(scratch1)); | 3942 __ Subu(string_length, string_length, Operand(scratch1)); |
| 3943 __ Mul(scratch3, scratch2, array_length, scratch1); | 3943 __ Mul(scratch3, scratch2, array_length, scratch1); |
| 3944 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are | 3944 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are |
| 3945 // zero. | 3945 // zero. |
| 3946 __ Branch(&bailout, ne, scratch3, Operand(zero_reg)); | 3946 __ Branch(&bailout, ne, scratch3, Operand(zero_reg)); |
| 3947 __ And(scratch3, scratch2, Operand(0x80000000)); | 3947 __ And(scratch3, scratch2, Operand(0x80000000)); |
| 3948 __ Branch(&bailout, ne, scratch3, Operand(zero_reg)); | 3948 __ Branch(&bailout, ne, scratch3, Operand(zero_reg)); |
| 3949 __ AdduAndCheckForOverflow(string_length, string_length, scratch2, scratch3); | 3949 __ AdduAndCheckForOverflow(string_length, string_length, scratch2, scratch3); |
| 3950 __ BranchOnOverflow(&bailout, scratch3); | 3950 __ BranchOnOverflow(&bailout, scratch3); |
| 3951 __ SmiUntag(string_length); | 3951 __ SmiUntag(string_length); |
| 3952 | 3952 |
| 3953 // Get first element in the array to free up the elements register to be used | 3953 // Get first element in the array to free up the elements register to be used |
| 3954 // for the result. | 3954 // for the result. |
| 3955 __ Addu(element, | 3955 __ Addu(element, |
| 3956 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 3956 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 3957 result = elements; // End of live range for elements. | 3957 result = elements; // End of live range for elements. |
| 3958 elements = no_reg; | 3958 elements = no_reg; |
| 3959 // Live values in registers: | 3959 // Live values in registers: |
| 3960 // element: First array element | 3960 // element: First array element |
| 3961 // separator: Separator string | 3961 // separator: Separator string |
| 3962 // string_length: Length of result string (not smi) | 3962 // string_length: Length of result string (not smi) |
| 3963 // array_length: Length of the array. | 3963 // array_length: Length of the array. |
| 3964 __ AllocateAsciiString(result, | 3964 __ AllocateOneByteString(result, string_length, scratch1, scratch2, |
| 3965 string_length, | 3965 elements_end, &bailout); |
| 3966 scratch1, | |
| 3967 scratch2, | |
| 3968 elements_end, | |
| 3969 &bailout); | |
| 3970 // Prepare for looping. Set up elements_end to end of the array. Set | 3966 // Prepare for looping. Set up elements_end to end of the array. Set |
| 3971 // result_pos to the position of the result where to write the first | 3967 // result_pos to the position of the result where to write the first |
| 3972 // character. | 3968 // character. |
| 3973 __ sll(elements_end, array_length, kPointerSizeLog2); | 3969 __ sll(elements_end, array_length, kPointerSizeLog2); |
| 3974 __ Addu(elements_end, element, elements_end); | 3970 __ Addu(elements_end, element, elements_end); |
| 3975 result_pos = array_length; // End of live range for array_length. | 3971 result_pos = array_length; // End of live range for array_length. |
| 3976 array_length = no_reg; | 3972 array_length = no_reg; |
| 3977 __ Addu(result_pos, | 3973 __ Addu(result_pos, |
| 3978 result, | 3974 result, |
| 3979 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3975 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3998 __ SmiUntag(string_length); | 3994 __ SmiUntag(string_length); |
| 3999 __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); | 3995 __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
| 4000 __ CopyBytes(string, result_pos, string_length, scratch1); | 3996 __ CopyBytes(string, result_pos, string_length, scratch1); |
| 4001 // End while (element < elements_end). | 3997 // End while (element < elements_end). |
| 4002 __ Branch(&empty_separator_loop, lt, element, Operand(elements_end)); | 3998 __ Branch(&empty_separator_loop, lt, element, Operand(elements_end)); |
| 4003 DCHECK(result.is(v0)); | 3999 DCHECK(result.is(v0)); |
| 4004 __ Branch(&done); | 4000 __ Branch(&done); |
| 4005 | 4001 |
| 4006 // One-character separator case. | 4002 // One-character separator case. |
| 4007 __ bind(&one_char_separator); | 4003 __ bind(&one_char_separator); |
| 4008 // Replace separator with its ASCII character value. | 4004 // Replace separator with its one-byte character value. |
| 4009 __ lbu(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); | 4005 __ lbu(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); |
| 4010 // Jump into the loop after the code that copies the separator, so the first | 4006 // Jump into the loop after the code that copies the separator, so the first |
| 4011 // element is not preceded by a separator. | 4007 // element is not preceded by a separator. |
| 4012 __ jmp(&one_char_separator_loop_entry); | 4008 __ jmp(&one_char_separator_loop_entry); |
| 4013 | 4009 |
| 4014 __ bind(&one_char_separator_loop); | 4010 __ bind(&one_char_separator_loop); |
| 4015 // Live values in registers: | 4011 // Live values in registers: |
| 4016 // result_pos: the position to which we are currently copying characters. | 4012 // result_pos: the position to which we are currently copying characters. |
| 4017 // element: Current array element. | 4013 // element: Current array element. |
| 4018 // elements_end: Array end. | 4014 // elements_end: Array end. |
| 4019 // separator: Single separator ASCII char (in lower byte). | 4015 // separator: Single separator one-byte char (in lower byte). |
| 4020 | 4016 |
| 4021 // Copy the separator character to the result. | 4017 // Copy the separator character to the result. |
| 4022 __ sb(separator, MemOperand(result_pos)); | 4018 __ sb(separator, MemOperand(result_pos)); |
| 4023 __ Addu(result_pos, result_pos, 1); | 4019 __ Addu(result_pos, result_pos, 1); |
| 4024 | 4020 |
| 4025 // Copy next array element to the result. | 4021 // Copy next array element to the result. |
| 4026 __ bind(&one_char_separator_loop_entry); | 4022 __ bind(&one_char_separator_loop_entry); |
| 4027 __ lw(string, MemOperand(element)); | 4023 __ lw(string, MemOperand(element)); |
| 4028 __ Addu(element, element, kPointerSize); | 4024 __ Addu(element, element, kPointerSize); |
| 4029 __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); | 4025 __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); |
| (...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4877 Assembler::target_address_at(pc_immediate_load_address)) == | 4873 Assembler::target_address_at(pc_immediate_load_address)) == |
| 4878 reinterpret_cast<uint32_t>( | 4874 reinterpret_cast<uint32_t>( |
| 4879 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4875 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4880 return OSR_AFTER_STACK_CHECK; | 4876 return OSR_AFTER_STACK_CHECK; |
| 4881 } | 4877 } |
| 4882 | 4878 |
| 4883 | 4879 |
| 4884 } } // namespace v8::internal | 4880 } } // namespace v8::internal |
| 4885 | 4881 |
| 4886 #endif // V8_TARGET_ARCH_MIPS | 4882 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |