OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3955 __ AssertString(r0); | 3955 __ AssertString(r0); |
3956 | 3956 |
3957 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); | 3957 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); |
3958 __ IndexFromHash(r0, r0); | 3958 __ IndexFromHash(r0, r0); |
3959 | 3959 |
3960 context()->Plug(r0); | 3960 context()->Plug(r0); |
3961 } | 3961 } |
3962 | 3962 |
3963 | 3963 |
3964 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { | 3964 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { |
3965 Label bailout, done, one_char_separator, long_separator, | 3965 Label bailout, done, one_char_separator, long_separator, non_trivial_array, |
3966 non_trivial_array, not_size_one_array, loop, | 3966 not_size_one_array, loop, empty_separator_loop, one_char_separator_loop, |
3967 empty_separator_loop, one_char_separator_loop, | |
3968 one_char_separator_loop_entry, long_separator_loop; | 3967 one_char_separator_loop_entry, long_separator_loop; |
3969 ZoneList<Expression*>* args = expr->arguments(); | 3968 ZoneList<Expression*>* args = expr->arguments(); |
3970 ASSERT(args->length() == 2); | 3969 ASSERT(args->length() == 2); |
3971 VisitForStackValue(args->at(1)); | 3970 VisitForStackValue(args->at(1)); |
3972 VisitForAccumulatorValue(args->at(0)); | 3971 VisitForAccumulatorValue(args->at(0)); |
3973 | 3972 |
3974 // All aliases of the same register have disjoint lifetimes. | 3973 // All aliases of the same register have disjoint lifetimes. |
3975 Register array = r0; | 3974 Register array = r0; |
3976 Register elements = no_reg; // Will be r0. | 3975 Register elements = no_reg; // Will be r0. |
3977 Register result = no_reg; // Will be r0. | 3976 Register result = no_reg; // Will be r0. |
3978 Register separator = r1; | 3977 Register separator = r1; |
3979 Register array_length = r2; | 3978 Register array_length = r2; |
3980 Register result_pos = no_reg; // Will be r2 | 3979 Register result_pos = no_reg; // Will be r2 |
3981 Register string_length = r3; | 3980 Register string_length = r3; |
3982 Register string = r4; | 3981 Register string = r4; |
3983 Register element = r5; | 3982 Register element = r5; |
3984 Register elements_end = r6; | 3983 Register elements_end = r6; |
3985 Register scratch1 = r7; | 3984 Register scratch = r9; |
3986 Register scratch2 = r9; | |
3987 | 3985 |
3988 // Separator operand is on the stack. | 3986 // Separator operand is on the stack. |
3989 __ pop(separator); | 3987 __ pop(separator); |
3990 | 3988 |
3991 // Check that the array is a JSArray. | 3989 // Check that the array is a JSArray. |
3992 __ JumpIfSmi(array, &bailout); | 3990 __ JumpIfSmi(array, &bailout); |
3993 __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE); | 3991 __ CompareObjectType(array, scratch, array_length, JS_ARRAY_TYPE); |
3994 __ b(ne, &bailout); | 3992 __ b(ne, &bailout); |
3995 | 3993 |
3996 // Check that the array has fast elements. | 3994 // Check that the array has fast elements. |
3997 __ CheckFastElements(scratch1, scratch2, &bailout); | 3995 __ CheckFastElements(scratch, array_length, &bailout); |
3998 | 3996 |
3999 // If the array has length zero, return the empty string. | 3997 // If the array has length zero, return the empty string. |
4000 __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset)); | 3998 __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset)); |
4001 __ SmiUntag(array_length, SetCC); | 3999 __ SmiUntag(array_length, SetCC); |
4002 __ b(ne, &non_trivial_array); | 4000 __ b(ne, &non_trivial_array); |
4003 __ LoadRoot(r0, Heap::kempty_stringRootIndex); | 4001 __ LoadRoot(r0, Heap::kempty_stringRootIndex); |
4004 __ b(&done); | 4002 __ b(&done); |
4005 | 4003 |
4006 __ bind(&non_trivial_array); | 4004 __ bind(&non_trivial_array); |
4007 | 4005 |
(...skipping 16 matching lines...) Expand all Loading... |
4024 // string_length: Accumulated sum of string lengths (smi). | 4022 // string_length: Accumulated sum of string lengths (smi). |
4025 // element: Current array element. | 4023 // element: Current array element. |
4026 // elements_end: Array end. | 4024 // elements_end: Array end. |
4027 if (generate_debug_code_) { | 4025 if (generate_debug_code_) { |
4028 __ cmp(array_length, Operand::Zero()); | 4026 __ cmp(array_length, Operand::Zero()); |
4029 __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin); | 4027 __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin); |
4030 } | 4028 } |
4031 __ bind(&loop); | 4029 __ bind(&loop); |
4032 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 4030 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
4033 __ JumpIfSmi(string, &bailout); | 4031 __ JumpIfSmi(string, &bailout); |
4034 __ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); | 4032 __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); |
4035 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 4033 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
4036 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); | 4034 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout); |
4037 __ ldr(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); | 4035 __ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); |
4038 __ add(string_length, string_length, Operand(scratch1), SetCC); | 4036 __ add(string_length, string_length, Operand(scratch), SetCC); |
4039 __ b(vs, &bailout); | 4037 __ b(vs, &bailout); |
4040 __ cmp(element, elements_end); | 4038 __ cmp(element, elements_end); |
4041 __ b(lt, &loop); | 4039 __ b(lt, &loop); |
4042 | 4040 |
4043 // If array_length is 1, return elements[0], a string. | 4041 // If array_length is 1, return elements[0], a string. |
4044 __ cmp(array_length, Operand(1)); | 4042 __ cmp(array_length, Operand(1)); |
4045 __ b(ne, ¬_size_one_array); | 4043 __ b(ne, ¬_size_one_array); |
4046 __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 4044 __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
4047 __ b(&done); | 4045 __ b(&done); |
4048 | 4046 |
4049 __ bind(¬_size_one_array); | 4047 __ bind(¬_size_one_array); |
4050 | 4048 |
4051 // Live values in registers: | 4049 // Live values in registers: |
4052 // separator: Separator string | 4050 // separator: Separator string |
4053 // array_length: Length of the array. | 4051 // array_length: Length of the array. |
4054 // string_length: Sum of string lengths (smi). | 4052 // string_length: Sum of string lengths (smi). |
4055 // elements: FixedArray of strings. | 4053 // elements: FixedArray of strings. |
4056 | 4054 |
4057 // Check that the separator is a flat ASCII string. | 4055 // Check that the separator is a flat ASCII string. |
4058 __ JumpIfSmi(separator, &bailout); | 4056 __ JumpIfSmi(separator, &bailout); |
4059 __ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); | 4057 __ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset)); |
4060 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 4058 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
4061 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); | 4059 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout); |
4062 | 4060 |
4063 // Add (separator length times array_length) - separator length to the | 4061 // Add (separator length times array_length) - separator length to the |
4064 // string_length to get the length of the result string. array_length is not | 4062 // string_length to get the length of the result string. array_length is not |
4065 // smi but the other values are, so the result is a smi | 4063 // smi but the other values are, so the result is a smi |
4066 __ ldr(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); | 4064 __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); |
4067 __ sub(string_length, string_length, Operand(scratch1)); | 4065 __ sub(string_length, string_length, Operand(scratch)); |
4068 __ smull(scratch2, ip, array_length, scratch1); | 4066 __ smull(scratch, ip, array_length, scratch); |
4069 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are | 4067 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are |
4070 // zero. | 4068 // zero. |
4071 __ cmp(ip, Operand::Zero()); | 4069 __ cmp(ip, Operand::Zero()); |
4072 __ b(ne, &bailout); | 4070 __ b(ne, &bailout); |
4073 __ tst(scratch2, Operand(0x80000000)); | 4071 __ tst(scratch, Operand(0x80000000)); |
4074 __ b(ne, &bailout); | 4072 __ b(ne, &bailout); |
4075 __ add(string_length, string_length, Operand(scratch2), SetCC); | 4073 __ add(string_length, string_length, Operand(scratch), SetCC); |
4076 __ b(vs, &bailout); | 4074 __ b(vs, &bailout); |
4077 __ SmiUntag(string_length); | 4075 __ SmiUntag(string_length); |
4078 | 4076 |
4079 // Get first element in the array to free up the elements register to be used | 4077 // Get first element in the array to free up the elements register to be used |
4080 // for the result. | 4078 // for the result. |
4081 __ add(element, | 4079 __ add(element, |
4082 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 4080 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
4083 result = elements; // End of live range for elements. | 4081 result = elements; // End of live range for elements. |
4084 elements = no_reg; | 4082 elements = no_reg; |
4085 // Live values in registers: | 4083 // Live values in registers: |
4086 // element: First array element | 4084 // element: First array element |
4087 // separator: Separator string | 4085 // separator: Separator string |
4088 // string_length: Length of result string (not smi) | 4086 // string_length: Length of result string (not smi) |
4089 // array_length: Length of the array. | 4087 // array_length: Length of the array. |
4090 __ AllocateAsciiString(result, | 4088 __ AllocateAsciiString(result, |
4091 string_length, | 4089 string_length, |
4092 scratch1, | 4090 scratch, |
4093 scratch2, | 4091 string, // used as scratch |
4094 elements_end, | 4092 elements_end, // used as scratch |
4095 &bailout); | 4093 &bailout); |
4096 // Prepare for looping. Set up elements_end to end of the array. Set | 4094 // Prepare for looping. Set up elements_end to end of the array. Set |
4097 // result_pos to the position of the result where to write the first | 4095 // result_pos to the position of the result where to write the first |
4098 // character. | 4096 // character. |
4099 __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); | 4097 __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); |
4100 result_pos = array_length; // End of live range for array_length. | 4098 result_pos = array_length; // End of live range for array_length. |
4101 array_length = no_reg; | 4099 array_length = no_reg; |
4102 __ add(result_pos, | 4100 __ add(result_pos, |
4103 result, | 4101 result, |
4104 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 4102 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
4105 | 4103 |
4106 // Check the length of the separator. | 4104 // Check the length of the separator. |
4107 __ ldr(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); | 4105 __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); |
4108 __ cmp(scratch1, Operand(Smi::FromInt(1))); | 4106 __ cmp(scratch, Operand(Smi::FromInt(1))); |
4109 __ b(eq, &one_char_separator); | 4107 __ b(eq, &one_char_separator); |
4110 __ b(gt, &long_separator); | 4108 __ b(gt, &long_separator); |
4111 | 4109 |
4112 // Empty separator case | 4110 // Empty separator case |
4113 __ bind(&empty_separator_loop); | 4111 __ bind(&empty_separator_loop); |
4114 // Live values in registers: | 4112 // Live values in registers: |
4115 // result_pos: the position to which we are currently copying characters. | 4113 // result_pos: the position to which we are currently copying characters. |
4116 // element: Current array element. | 4114 // element: Current array element. |
4117 // elements_end: Array end. | 4115 // elements_end: Array end. |
4118 | 4116 |
4119 // Copy next array element to the result. | 4117 // Copy next array element to the result. |
4120 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 4118 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
4121 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); | 4119 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); |
4122 __ SmiUntag(string_length); | 4120 __ SmiUntag(string_length); |
4123 __ add(string, | 4121 __ add(string, |
4124 string, | 4122 string, |
4125 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 4123 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
4126 __ CopyBytes(string, result_pos, string_length, scratch1); | 4124 __ CopyBytes(string, result_pos, string_length, scratch); |
4127 __ cmp(element, elements_end); | 4125 __ cmp(element, elements_end); |
4128 __ b(lt, &empty_separator_loop); // End while (element < elements_end). | 4126 __ b(lt, &empty_separator_loop); // End while (element < elements_end). |
4129 ASSERT(result.is(r0)); | 4127 ASSERT(result.is(r0)); |
4130 __ b(&done); | 4128 __ b(&done); |
4131 | 4129 |
4132 // One-character separator case | 4130 // One-character separator case |
4133 __ bind(&one_char_separator); | 4131 __ bind(&one_char_separator); |
4134 // Replace separator with its ASCII character value. | 4132 // Replace separator with its ASCII character value. |
4135 __ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); | 4133 __ ldrb(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); |
4136 // Jump into the loop after the code that copies the separator, so the first | 4134 // Jump into the loop after the code that copies the separator, so the first |
(...skipping 11 matching lines...) Expand all Loading... |
4148 __ strb(separator, MemOperand(result_pos, 1, PostIndex)); | 4146 __ strb(separator, MemOperand(result_pos, 1, PostIndex)); |
4149 | 4147 |
4150 // Copy next array element to the result. | 4148 // Copy next array element to the result. |
4151 __ bind(&one_char_separator_loop_entry); | 4149 __ bind(&one_char_separator_loop_entry); |
4152 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 4150 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
4153 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); | 4151 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); |
4154 __ SmiUntag(string_length); | 4152 __ SmiUntag(string_length); |
4155 __ add(string, | 4153 __ add(string, |
4156 string, | 4154 string, |
4157 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 4155 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
4158 __ CopyBytes(string, result_pos, string_length, scratch1); | 4156 __ CopyBytes(string, result_pos, string_length, scratch); |
4159 __ cmp(element, elements_end); | 4157 __ cmp(element, elements_end); |
4160 __ b(lt, &one_char_separator_loop); // End while (element < elements_end). | 4158 __ b(lt, &one_char_separator_loop); // End while (element < elements_end). |
4161 ASSERT(result.is(r0)); | 4159 ASSERT(result.is(r0)); |
4162 __ b(&done); | 4160 __ b(&done); |
4163 | 4161 |
4164 // Long separator case (separator is more than one character). Entry is at the | 4162 // Long separator case (separator is more than one character). Entry is at the |
4165 // label long_separator below. | 4163 // label long_separator below. |
4166 __ bind(&long_separator_loop); | 4164 __ bind(&long_separator_loop); |
4167 // Live values in registers: | 4165 // Live values in registers: |
4168 // result_pos: the position to which we are currently copying characters. | 4166 // result_pos: the position to which we are currently copying characters. |
4169 // element: Current array element. | 4167 // element: Current array element. |
4170 // elements_end: Array end. | 4168 // elements_end: Array end. |
4171 // separator: Separator string. | 4169 // separator: Separator string. |
4172 | 4170 |
4173 // Copy the separator to the result. | 4171 // Copy the separator to the result. |
4174 __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset)); | 4172 __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset)); |
4175 __ SmiUntag(string_length); | 4173 __ SmiUntag(string_length); |
4176 __ add(string, | 4174 __ add(string, |
4177 separator, | 4175 separator, |
4178 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 4176 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
4179 __ CopyBytes(string, result_pos, string_length, scratch1); | 4177 __ CopyBytes(string, result_pos, string_length, scratch); |
4180 | 4178 |
4181 __ bind(&long_separator); | 4179 __ bind(&long_separator); |
4182 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); | 4180 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); |
4183 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); | 4181 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); |
4184 __ SmiUntag(string_length); | 4182 __ SmiUntag(string_length); |
4185 __ add(string, | 4183 __ add(string, |
4186 string, | 4184 string, |
4187 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 4185 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
4188 __ CopyBytes(string, result_pos, string_length, scratch1); | 4186 __ CopyBytes(string, result_pos, string_length, scratch); |
4189 __ cmp(element, elements_end); | 4187 __ cmp(element, elements_end); |
4190 __ b(lt, &long_separator_loop); // End while (element < elements_end). | 4188 __ b(lt, &long_separator_loop); // End while (element < elements_end). |
4191 ASSERT(result.is(r0)); | 4189 ASSERT(result.is(r0)); |
4192 __ b(&done); | 4190 __ b(&done); |
4193 | 4191 |
4194 __ bind(&bailout); | 4192 __ bind(&bailout); |
4195 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 4193 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
4196 __ bind(&done); | 4194 __ bind(&done); |
4197 context()->Plug(r0); | 4195 context()->Plug(r0); |
4198 } | 4196 } |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4983 Memory::uint32_at(interrupt_address_pointer)); | 4981 Memory::uint32_at(interrupt_address_pointer)); |
4984 return INTERRUPT; | 4982 return INTERRUPT; |
4985 } | 4983 } |
4986 } | 4984 } |
4987 #endif // DEBUG | 4985 #endif // DEBUG |
4988 | 4986 |
4989 | 4987 |
4990 } } // namespace v8::internal | 4988 } } // namespace v8::internal |
4991 | 4989 |
4992 #endif // V8_TARGET_ARCH_ARM | 4990 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |