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_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 3805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3816 | 3816 |
3817 __ AssertString(r0); | 3817 __ AssertString(r0); |
3818 | 3818 |
3819 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); | 3819 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); |
3820 __ IndexFromHash(r0, r0); | 3820 __ IndexFromHash(r0, r0); |
3821 | 3821 |
3822 context()->Plug(r0); | 3822 context()->Plug(r0); |
3823 } | 3823 } |
3824 | 3824 |
3825 | 3825 |
3826 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { | 3826 void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) { |
3827 Label bailout, done, one_char_separator, long_separator, non_trivial_array, | 3827 Label bailout, done, one_char_separator, long_separator, non_trivial_array, |
3828 not_size_one_array, loop, empty_separator_loop, one_char_separator_loop, | 3828 not_size_one_array, loop, empty_separator_loop, one_char_separator_loop, |
3829 one_char_separator_loop_entry, long_separator_loop; | 3829 one_char_separator_loop_entry, long_separator_loop; |
3830 ZoneList<Expression*>* args = expr->arguments(); | 3830 ZoneList<Expression*>* args = expr->arguments(); |
3831 DCHECK(args->length() == 2); | 3831 DCHECK(args->length() == 2); |
3832 VisitForStackValue(args->at(1)); | 3832 VisitForStackValue(args->at(1)); |
3833 VisitForAccumulatorValue(args->at(0)); | 3833 VisitForAccumulatorValue(args->at(0)); |
3834 | 3834 |
3835 // All aliases of the same register have disjoint lifetimes. | 3835 // All aliases of the same register have disjoint lifetimes. |
3836 Register array = r0; | 3836 Register array = r0; |
(...skipping 26 matching lines...) Expand all Loading... |
3863 __ LoadRoot(r0, Heap::kempty_stringRootIndex); | 3863 __ LoadRoot(r0, Heap::kempty_stringRootIndex); |
3864 __ b(&done); | 3864 __ b(&done); |
3865 | 3865 |
3866 __ bind(&non_trivial_array); | 3866 __ bind(&non_trivial_array); |
3867 | 3867 |
3868 // Get the FixedArray containing array's elements. | 3868 // Get the FixedArray containing array's elements. |
3869 elements = array; | 3869 elements = array; |
3870 __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset)); | 3870 __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset)); |
3871 array = no_reg; // End of array's live range. | 3871 array = no_reg; // End of array's live range. |
3872 | 3872 |
3873 // Check that all array elements are sequential ASCII strings, and | 3873 // Check that all array elements are sequential one-byte strings, and |
3874 // accumulate the sum of their lengths, as a smi-encoded value. | 3874 // accumulate the sum of their lengths, as a smi-encoded value. |
3875 __ mov(string_length, Operand::Zero()); | 3875 __ mov(string_length, Operand::Zero()); |
3876 __ add(element, | 3876 __ add(element, |
3877 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 3877 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
3878 __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); | 3878 __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); |
3879 // Loop condition: while (element < elements_end). | 3879 // Loop condition: while (element < elements_end). |
3880 // Live values in registers: | 3880 // Live values in registers: |
3881 // elements: Fixed array of strings. | 3881 // elements: Fixed array of strings. |
3882 // array_length: Length of the fixed array of strings (not smi) | 3882 // array_length: Length of the fixed array of strings (not smi) |
3883 // separator: Separator string | 3883 // separator: Separator string |
3884 // string_length: Accumulated sum of string lengths (smi). | 3884 // string_length: Accumulated sum of string lengths (smi). |
3885 // element: Current array element. | 3885 // element: Current array element. |
3886 // elements_end: Array end. | 3886 // elements_end: Array end. |
3887 if (generate_debug_code_) { | 3887 if (generate_debug_code_) { |
3888 __ cmp(array_length, Operand::Zero()); | 3888 __ cmp(array_length, Operand::Zero()); |
3889 __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin); | 3889 __ Assert(gt, kNoEmptyArraysHereInEmitFastOneByteArrayJoin); |
3890 } | 3890 } |
3891 __ bind(&loop); | 3891 __ bind(&loop); |
3892 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 3892 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
3893 __ JumpIfSmi(string, &bailout); | 3893 __ JumpIfSmi(string, &bailout); |
3894 __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); | 3894 __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); |
3895 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 3895 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
3896 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout); | 3896 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch, scratch, &bailout); |
3897 __ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); | 3897 __ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); |
3898 __ add(string_length, string_length, Operand(scratch), SetCC); | 3898 __ add(string_length, string_length, Operand(scratch), SetCC); |
3899 __ b(vs, &bailout); | 3899 __ b(vs, &bailout); |
3900 __ cmp(element, elements_end); | 3900 __ cmp(element, elements_end); |
3901 __ b(lt, &loop); | 3901 __ b(lt, &loop); |
3902 | 3902 |
3903 // If array_length is 1, return elements[0], a string. | 3903 // If array_length is 1, return elements[0], a string. |
3904 __ cmp(array_length, Operand(1)); | 3904 __ cmp(array_length, Operand(1)); |
3905 __ b(ne, ¬_size_one_array); | 3905 __ b(ne, ¬_size_one_array); |
3906 __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 3906 __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
3907 __ b(&done); | 3907 __ b(&done); |
3908 | 3908 |
3909 __ bind(¬_size_one_array); | 3909 __ bind(¬_size_one_array); |
3910 | 3910 |
3911 // Live values in registers: | 3911 // Live values in registers: |
3912 // separator: Separator string | 3912 // separator: Separator string |
3913 // array_length: Length of the array. | 3913 // array_length: Length of the array. |
3914 // string_length: Sum of string lengths (smi). | 3914 // string_length: Sum of string lengths (smi). |
3915 // elements: FixedArray of strings. | 3915 // elements: FixedArray of strings. |
3916 | 3916 |
3917 // Check that the separator is a flat ASCII string. | 3917 // Check that the separator is a flat one-byte string. |
3918 __ JumpIfSmi(separator, &bailout); | 3918 __ JumpIfSmi(separator, &bailout); |
3919 __ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset)); | 3919 __ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset)); |
3920 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 3920 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
3921 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout); | 3921 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch, scratch, &bailout); |
3922 | 3922 |
3923 // Add (separator length times array_length) - separator length to the | 3923 // Add (separator length times array_length) - separator length to the |
3924 // string_length to get the length of the result string. array_length is not | 3924 // string_length to get the length of the result string. array_length is not |
3925 // smi but the other values are, so the result is a smi | 3925 // smi but the other values are, so the result is a smi |
3926 __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); | 3926 __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); |
3927 __ sub(string_length, string_length, Operand(scratch)); | 3927 __ sub(string_length, string_length, Operand(scratch)); |
3928 __ smull(scratch, ip, array_length, scratch); | 3928 __ smull(scratch, ip, array_length, scratch); |
3929 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are | 3929 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are |
3930 // zero. | 3930 // zero. |
3931 __ cmp(ip, Operand::Zero()); | 3931 __ cmp(ip, Operand::Zero()); |
3932 __ b(ne, &bailout); | 3932 __ b(ne, &bailout); |
3933 __ tst(scratch, Operand(0x80000000)); | 3933 __ tst(scratch, Operand(0x80000000)); |
3934 __ b(ne, &bailout); | 3934 __ b(ne, &bailout); |
3935 __ add(string_length, string_length, Operand(scratch), SetCC); | 3935 __ add(string_length, string_length, Operand(scratch), SetCC); |
3936 __ b(vs, &bailout); | 3936 __ b(vs, &bailout); |
3937 __ SmiUntag(string_length); | 3937 __ SmiUntag(string_length); |
3938 | 3938 |
3939 // Get first element in the array to free up the elements register to be used | 3939 // Get first element in the array to free up the elements register to be used |
3940 // for the result. | 3940 // for the result. |
3941 __ add(element, | 3941 __ add(element, |
3942 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 3942 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
3943 result = elements; // End of live range for elements. | 3943 result = elements; // End of live range for elements. |
3944 elements = no_reg; | 3944 elements = no_reg; |
3945 // Live values in registers: | 3945 // Live values in registers: |
3946 // element: First array element | 3946 // element: First array element |
3947 // separator: Separator string | 3947 // separator: Separator string |
3948 // string_length: Length of result string (not smi) | 3948 // string_length: Length of result string (not smi) |
3949 // array_length: Length of the array. | 3949 // array_length: Length of the array. |
3950 __ AllocateAsciiString(result, | 3950 __ AllocateOneByteString(result, string_length, scratch, |
3951 string_length, | 3951 string, // used as scratch |
3952 scratch, | 3952 elements_end, // used as scratch |
3953 string, // used as scratch | 3953 &bailout); |
3954 elements_end, // used as scratch | |
3955 &bailout); | |
3956 // Prepare for looping. Set up elements_end to end of the array. Set | 3954 // Prepare for looping. Set up elements_end to end of the array. Set |
3957 // result_pos to the position of the result where to write the first | 3955 // result_pos to the position of the result where to write the first |
3958 // character. | 3956 // character. |
3959 __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); | 3957 __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); |
3960 result_pos = array_length; // End of live range for array_length. | 3958 result_pos = array_length; // End of live range for array_length. |
3961 array_length = no_reg; | 3959 array_length = no_reg; |
3962 __ add(result_pos, | 3960 __ add(result_pos, |
3963 result, | 3961 result, |
3964 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3962 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3965 | 3963 |
(...skipping 18 matching lines...) Expand all Loading... |
3984 string, | 3982 string, |
3985 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3983 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3986 __ CopyBytes(string, result_pos, string_length, scratch); | 3984 __ CopyBytes(string, result_pos, string_length, scratch); |
3987 __ cmp(element, elements_end); | 3985 __ cmp(element, elements_end); |
3988 __ b(lt, &empty_separator_loop); // End while (element < elements_end). | 3986 __ b(lt, &empty_separator_loop); // End while (element < elements_end). |
3989 DCHECK(result.is(r0)); | 3987 DCHECK(result.is(r0)); |
3990 __ b(&done); | 3988 __ b(&done); |
3991 | 3989 |
3992 // One-character separator case | 3990 // One-character separator case |
3993 __ bind(&one_char_separator); | 3991 __ bind(&one_char_separator); |
3994 // Replace separator with its ASCII character value. | 3992 // Replace separator with its one-byte character value. |
3995 __ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); | 3993 __ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); |
3996 // Jump into the loop after the code that copies the separator, so the first | 3994 // Jump into the loop after the code that copies the separator, so the first |
3997 // element is not preceded by a separator | 3995 // element is not preceded by a separator |
3998 __ jmp(&one_char_separator_loop_entry); | 3996 __ jmp(&one_char_separator_loop_entry); |
3999 | 3997 |
4000 __ bind(&one_char_separator_loop); | 3998 __ bind(&one_char_separator_loop); |
4001 // Live values in registers: | 3999 // Live values in registers: |
4002 // result_pos: the position to which we are currently copying characters. | 4000 // result_pos: the position to which we are currently copying characters. |
4003 // element: Current array element. | 4001 // element: Current array element. |
4004 // elements_end: Array end. | 4002 // elements_end: Array end. |
4005 // separator: Single separator ASCII char (in lower byte). | 4003 // separator: Single separator one-byte char (in lower byte). |
4006 | 4004 |
4007 // Copy the separator character to the result. | 4005 // Copy the separator character to the result. |
4008 __ strb(separator, MemOperand(result_pos, 1, PostIndex)); | 4006 __ strb(separator, MemOperand(result_pos, 1, PostIndex)); |
4009 | 4007 |
4010 // Copy next array element to the result. | 4008 // Copy next array element to the result. |
4011 __ bind(&one_char_separator_loop_entry); | 4009 __ bind(&one_char_separator_loop_entry); |
4012 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 4010 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
4013 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); | 4011 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); |
4014 __ SmiUntag(string_length); | 4012 __ SmiUntag(string_length); |
4015 __ add(string, | 4013 __ add(string, |
(...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4927 | 4925 |
4928 DCHECK(interrupt_address == | 4926 DCHECK(interrupt_address == |
4929 isolate->builtins()->OsrAfterStackCheck()->entry()); | 4927 isolate->builtins()->OsrAfterStackCheck()->entry()); |
4930 return OSR_AFTER_STACK_CHECK; | 4928 return OSR_AFTER_STACK_CHECK; |
4931 } | 4929 } |
4932 | 4930 |
4933 | 4931 |
4934 } } // namespace v8::internal | 4932 } } // namespace v8::internal |
4935 | 4933 |
4936 #endif // V8_TARGET_ARCH_ARM | 4934 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |