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

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

Issue 8404030: Version 3.7.1 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 1 month 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/assembler-arm-inl.h ('k') | src/arm/code-stubs-arm.h » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 79 __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
80 __ ldr(result, 80 __ ldr(result,
81 FieldMemOperand(result, GlobalObject::kGlobalContextOffset)); 81 FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
82 // Load the Array function from the global context. 82 // Load the Array function from the global context.
83 __ ldr(result, 83 __ ldr(result,
84 MemOperand(result, 84 MemOperand(result,
85 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); 85 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
86 } 86 }
87 87
88 88
89 // This constant has the same value as JSArray::kPreallocatedArrayElements and
90 // if JSArray::kPreallocatedArrayElements is changed handling of loop unfolding
91 // below should be reconsidered.
92 static const int kLoopUnfoldLimit = 4;
93
94
95 // Allocate an empty JSArray. The allocated array is put into the result 89 // Allocate an empty JSArray. The allocated array is put into the result
96 // register. An elements backing store is allocated with size initial_capacity 90 // register. An elements backing store is allocated with size initial_capacity
97 // and filled with the hole values. 91 // and filled with the hole values.
98 static void AllocateEmptyJSArray(MacroAssembler* masm, 92 static void AllocateEmptyJSArray(MacroAssembler* masm,
99 Register array_function, 93 Register array_function,
100 Register result, 94 Register result,
101 Register scratch1, 95 Register scratch1,
102 Register scratch2, 96 Register scratch2,
103 Register scratch3, 97 Register scratch3,
104 int initial_capacity,
105 Label* gc_required) { 98 Label* gc_required) {
106 ASSERT(initial_capacity > 0); 99 const int initial_capacity = JSArray::kPreallocatedArrayElements;
100 STATIC_ASSERT(initial_capacity >= 0);
107 // Load the initial map from the array function. 101 // Load the initial map from the array function.
108 __ ldr(scratch1, FieldMemOperand(array_function, 102 __ ldr(scratch1, FieldMemOperand(array_function,
109 JSFunction::kPrototypeOrInitialMapOffset)); 103 JSFunction::kPrototypeOrInitialMapOffset));
110 104
111 // Allocate the JSArray object together with space for a fixed array with the 105 // Allocate the JSArray object together with space for a fixed array with the
112 // requested elements. 106 // requested elements.
113 int size = JSArray::kSize + FixedArray::SizeFor(initial_capacity); 107 int size = JSArray::kSize + FixedArray::SizeFor(initial_capacity);
114 __ AllocateInNewSpace(size, 108 __ AllocateInNewSpace(size,
115 result, 109 result,
116 scratch2, 110 scratch2,
(...skipping 29 matching lines...) Expand all
146 // result: JSObject 140 // result: JSObject
147 // scratch1: elements array (untagged) 141 // scratch1: elements array (untagged)
148 // scratch2: start of next object 142 // scratch2: start of next object
149 __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex); 143 __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
150 ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); 144 ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
151 __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 145 __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
152 __ mov(scratch3, Operand(Smi::FromInt(initial_capacity))); 146 __ mov(scratch3, Operand(Smi::FromInt(initial_capacity)));
153 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 147 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
154 __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 148 __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
155 149
156 // Fill the FixedArray with the hole value. 150 // Fill the FixedArray with the hole value. Inline the code if short.
151 if (initial_capacity == 0) return;
157 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 152 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
158 ASSERT(initial_capacity <= kLoopUnfoldLimit);
159 __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); 153 __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
160 for (int i = 0; i < initial_capacity; i++) { 154 static const int kLoopUnfoldLimit = 4;
155 if (initial_capacity <= kLoopUnfoldLimit) {
156 for (int i = 0; i < initial_capacity; i++) {
157 __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
158 }
159 } else {
160 Label loop, entry;
161 __ add(scratch2, scratch1, Operand(initial_capacity * kPointerSize));
162 __ b(&entry);
163 __ bind(&loop);
161 __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 164 __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
165 __ bind(&entry);
166 __ cmp(scratch1, scratch2);
167 __ b(lt, &loop);
162 } 168 }
163 } 169 }
164 170
165 // Allocate a JSArray with the number of elements stored in a register. The 171 // Allocate a JSArray with the number of elements stored in a register. The
166 // register array_function holds the built-in Array function and the register 172 // register array_function holds the built-in Array function and the register
167 // array_size holds the size of the array as a smi. The allocated array is put 173 // array_size holds the size of the array as a smi. The allocated array is put
168 // into the result register and beginning and end of the FixedArray elements 174 // into the result register and beginning and end of the FixedArray elements
169 // storage is put into registers elements_array_storage and elements_array_end 175 // storage is put into registers elements_array_storage and elements_array_end
170 // (see below for when that is not the case). If the parameter fill_with_holes 176 // (see below for when that is not the case). If the parameter fill_with_holes
171 // is true the allocated elements backing store is filled with the hole values 177 // is true the allocated elements backing store is filled with the hole values
172 // otherwise it is left uninitialized. When the backing store is filled the 178 // otherwise it is left uninitialized. When the backing store is filled the
173 // register elements_array_storage is scratched. 179 // register elements_array_storage is scratched.
174 static void AllocateJSArray(MacroAssembler* masm, 180 static void AllocateJSArray(MacroAssembler* masm,
175 Register array_function, // Array function. 181 Register array_function, // Array function.
176 Register array_size, // As a smi. 182 Register array_size, // As a smi, cannot be 0.
177 Register result, 183 Register result,
178 Register elements_array_storage, 184 Register elements_array_storage,
179 Register elements_array_end, 185 Register elements_array_end,
180 Register scratch1, 186 Register scratch1,
181 Register scratch2, 187 Register scratch2,
182 bool fill_with_hole, 188 bool fill_with_hole,
183 Label* gc_required) { 189 Label* gc_required) {
184 Label not_empty, allocated;
185
186 // Load the initial map from the array function. 190 // Load the initial map from the array function.
187 __ ldr(elements_array_storage, 191 __ ldr(elements_array_storage,
188 FieldMemOperand(array_function, 192 FieldMemOperand(array_function,
189 JSFunction::kPrototypeOrInitialMapOffset)); 193 JSFunction::kPrototypeOrInitialMapOffset));
190 194
191 // Check whether an empty sized array is requested. 195 if (FLAG_debug_code) { // Assert that array size is not zero.
192 __ tst(array_size, array_size); 196 __ tst(array_size, array_size);
193 __ b(ne, &not_empty); 197 __ Assert(ne, "array size is unexpectedly 0");
194 198 }
195 // If an empty array is requested allocate a small elements array anyway. This
196 // keeps the code below free of special casing for the empty array.
197 int size = JSArray::kSize +
198 FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
199 __ AllocateInNewSpace(size,
200 result,
201 elements_array_end,
202 scratch1,
203 gc_required,
204 TAG_OBJECT);
205 __ jmp(&allocated);
206 199
207 // Allocate the JSArray object together with space for a FixedArray with the 200 // Allocate the JSArray object together with space for a FixedArray with the
208 // requested number of elements. 201 // requested number of elements.
209 __ bind(&not_empty);
210 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 202 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
211 __ mov(elements_array_end, 203 __ mov(elements_array_end,
212 Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize)); 204 Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize));
213 __ add(elements_array_end, 205 __ add(elements_array_end,
214 elements_array_end, 206 elements_array_end,
215 Operand(array_size, ASR, kSmiTagSize)); 207 Operand(array_size, ASR, kSmiTagSize));
216 __ AllocateInNewSpace( 208 __ AllocateInNewSpace(
217 elements_array_end, 209 elements_array_end,
218 result, 210 result,
219 scratch1, 211 scratch1,
220 scratch2, 212 scratch2,
221 gc_required, 213 gc_required,
222 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); 214 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
223 215
224 // Allocated the JSArray. Now initialize the fields except for the elements 216 // Allocated the JSArray. Now initialize the fields except for the elements
225 // array. 217 // array.
226 // result: JSObject 218 // result: JSObject
227 // elements_array_storage: initial map 219 // elements_array_storage: initial map
228 // array_size: size of array (smi) 220 // array_size: size of array (smi)
229 __ bind(&allocated);
230 __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset)); 221 __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
231 __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex); 222 __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
232 __ str(elements_array_storage, 223 __ str(elements_array_storage,
233 FieldMemOperand(result, JSArray::kPropertiesOffset)); 224 FieldMemOperand(result, JSArray::kPropertiesOffset));
234 // Field JSArray::kElementsOffset is initialized later. 225 // Field JSArray::kElementsOffset is initialized later.
235 __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset)); 226 __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset));
236 227
237 // Calculate the location of the elements array and set elements array member 228 // Calculate the location of the elements array and set elements array member
238 // of the JSArray. 229 // of the JSArray.
239 // result: JSObject 230 // result: JSObject
240 // array_size: size of array (smi) 231 // array_size: size of array (smi)
241 __ add(elements_array_storage, result, Operand(JSArray::kSize)); 232 __ add(elements_array_storage, result, Operand(JSArray::kSize));
242 __ str(elements_array_storage, 233 __ str(elements_array_storage,
243 FieldMemOperand(result, JSArray::kElementsOffset)); 234 FieldMemOperand(result, JSArray::kElementsOffset));
244 235
245 // Clear the heap tag on the elements array. 236 // Clear the heap tag on the elements array.
246 STATIC_ASSERT(kSmiTag == 0); 237 STATIC_ASSERT(kSmiTag == 0);
247 __ sub(elements_array_storage, 238 __ sub(elements_array_storage,
248 elements_array_storage, 239 elements_array_storage,
249 Operand(kHeapObjectTag)); 240 Operand(kHeapObjectTag));
250 // Initialize the fixed array and fill it with holes. FixedArray length is 241 // Initialize the fixed array and fill it with holes. FixedArray length is
251 // stored as a smi. 242 // stored as a smi.
252 // result: JSObject 243 // result: JSObject
253 // elements_array_storage: elements array (untagged) 244 // elements_array_storage: elements array (untagged)
254 // array_size: size of array (smi) 245 // array_size: size of array (smi)
255 __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex); 246 __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
256 ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); 247 ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
257 __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex)); 248 __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex));
258 STATIC_ASSERT(kSmiTag == 0); 249 STATIC_ASSERT(kSmiTag == 0);
259 __ tst(array_size, array_size);
260 // Length of the FixedArray is the number of pre-allocated elements if
261 // the actual JSArray has length 0 and the size of the JSArray for non-empty
262 // JSArrays. The length of a FixedArray is stored as a smi.
263 __ mov(array_size,
264 Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)),
265 LeaveCC,
266 eq);
267 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 250 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
268 __ str(array_size, 251 __ str(array_size,
269 MemOperand(elements_array_storage, kPointerSize, PostIndex)); 252 MemOperand(elements_array_storage, kPointerSize, PostIndex));
270 253
271 // Calculate elements array and elements array end. 254 // Calculate elements array and elements array end.
272 // result: JSObject 255 // result: JSObject
273 // elements_array_storage: elements array element storage 256 // elements_array_storage: elements array element storage
274 // array_size: smi-tagged size of elements array 257 // array_size: smi-tagged size of elements array
275 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 258 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
276 __ add(elements_array_end, 259 __ add(elements_array_end,
(...skipping 27 matching lines...) Expand all
304 // sp[0]: last argument 287 // sp[0]: last argument
305 // This function is used for both construct and normal calls of Array. The only 288 // This function is used for both construct and normal calls of Array. The only
306 // difference between handling a construct call and a normal call is that for a 289 // difference between handling a construct call and a normal call is that for a
307 // construct call the constructor function in r1 needs to be preserved for 290 // construct call the constructor function in r1 needs to be preserved for
308 // entering the generic code. In both cases argc in r0 needs to be preserved. 291 // entering the generic code. In both cases argc in r0 needs to be preserved.
309 // Both registers are preserved by this code so no need to differentiate between 292 // Both registers are preserved by this code so no need to differentiate between
310 // construct call and normal call. 293 // construct call and normal call.
311 static void ArrayNativeCode(MacroAssembler* masm, 294 static void ArrayNativeCode(MacroAssembler* masm,
312 Label* call_generic_code) { 295 Label* call_generic_code) {
313 Counters* counters = masm->isolate()->counters(); 296 Counters* counters = masm->isolate()->counters();
314 Label argc_one_or_more, argc_two_or_more; 297 Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array;
315 298
316 // Check for array construction with zero arguments or one. 299 // Check for array construction with zero arguments or one.
317 __ cmp(r0, Operand(0, RelocInfo::NONE)); 300 __ cmp(r0, Operand(0, RelocInfo::NONE));
318 __ b(ne, &argc_one_or_more); 301 __ b(ne, &argc_one_or_more);
319 302
320 // Handle construction of an empty array. 303 // Handle construction of an empty array.
304 __ bind(&empty_array);
321 AllocateEmptyJSArray(masm, 305 AllocateEmptyJSArray(masm,
322 r1, 306 r1,
323 r2, 307 r2,
324 r3, 308 r3,
325 r4, 309 r4,
326 r5, 310 r5,
327 JSArray::kPreallocatedArrayElements,
328 call_generic_code); 311 call_generic_code);
329 __ IncrementCounter(counters->array_function_native(), 1, r3, r4); 312 __ IncrementCounter(counters->array_function_native(), 1, r3, r4);
330 // Setup return value, remove receiver from stack and return. 313 // Setup return value, remove receiver from stack and return.
331 __ mov(r0, r2); 314 __ mov(r0, r2);
332 __ add(sp, sp, Operand(kPointerSize)); 315 __ add(sp, sp, Operand(kPointerSize));
333 __ Jump(lr); 316 __ Jump(lr);
334 317
335 // Check for one argument. Bail out if argument is not smi or if it is 318 // Check for one argument. Bail out if argument is not smi or if it is
336 // negative. 319 // negative.
337 __ bind(&argc_one_or_more); 320 __ bind(&argc_one_or_more);
338 __ cmp(r0, Operand(1)); 321 __ cmp(r0, Operand(1));
339 __ b(ne, &argc_two_or_more); 322 __ b(ne, &argc_two_or_more);
340 STATIC_ASSERT(kSmiTag == 0); 323 STATIC_ASSERT(kSmiTag == 0);
341 __ ldr(r2, MemOperand(sp)); // Get the argument from the stack. 324 __ ldr(r2, MemOperand(sp)); // Get the argument from the stack.
325 __ tst(r2, r2);
326 __ b(ne, &not_empty_array);
327 __ Drop(1); // Adjust stack.
328 __ mov(r0, Operand(0)); // Treat this as a call with argc of zero.
329 __ b(&empty_array);
330
331 __ bind(&not_empty_array);
342 __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC); 332 __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC);
343 __ b(ne, call_generic_code); 333 __ b(ne, call_generic_code);
344 334
345 // Handle construction of an empty array of a certain size. Bail out if size 335 // Handle construction of an empty array of a certain size. Bail out if size
346 // is too large to actually allocate an elements array. 336 // is too large to actually allocate an elements array.
347 STATIC_ASSERT(kSmiTag == 0); 337 STATIC_ASSERT(kSmiTag == 0);
348 __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize)); 338 __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
349 __ b(ge, call_generic_code); 339 __ b(ge, call_generic_code);
350 340
351 // r0: argc 341 // r0: argc
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 __ mov(cp, Operand(0, RelocInfo::NONE)); 1010 __ mov(cp, Operand(0, RelocInfo::NONE));
1021 1011
1022 // Enter an internal frame. 1012 // Enter an internal frame.
1023 { 1013 {
1024 FrameScope scope(masm, StackFrame::INTERNAL); 1014 FrameScope scope(masm, StackFrame::INTERNAL);
1025 1015
1026 // Set up the context from the function argument. 1016 // Set up the context from the function argument.
1027 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1017 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1028 1018
1029 // Set up the roots register. 1019 // Set up the roots register.
1030 ExternalReference roots_address = 1020 ExternalReference roots_array_start =
1031 ExternalReference::roots_address(masm->isolate()); 1021 ExternalReference::roots_array_start(masm->isolate());
1032 __ mov(r10, Operand(roots_address)); 1022 __ mov(r10, Operand(roots_array_start));
1033 1023
1034 // Push the function and the receiver onto the stack. 1024 // Push the function and the receiver onto the stack.
1035 __ push(r1); 1025 __ push(r1);
1036 __ push(r2); 1026 __ push(r2);
1037 1027
1038 // Copy arguments to the stack in a loop. 1028 // Copy arguments to the stack in a loop.
1039 // r1: function 1029 // r1: function
1040 // r3: argc 1030 // r3: argc
1041 // r4: argv, i.e. points to first arg 1031 // r4: argv, i.e. points to first arg
1042 Label loop, entry; 1032 Label loop, entry;
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after
1718 __ bind(&dont_adapt_arguments); 1708 __ bind(&dont_adapt_arguments);
1719 __ Jump(r3); 1709 __ Jump(r3);
1720 } 1710 }
1721 1711
1722 1712
1723 #undef __ 1713 #undef __
1724 1714
1725 } } // namespace v8::internal 1715 } } // namespace v8::internal
1726 1716
1727 #endif // V8_TARGET_ARCH_ARM 1717 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/assembler-arm-inl.h ('k') | src/arm/code-stubs-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698