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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 8383002: Handle COW-arrays correctly when converting smi->double fast elements. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 2 months 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/x64/code-stubs-x64.cc ('k') | test/mjsunit/elements-transition.js » ('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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 void ElementsTransitionGenerator::GenerateSmiOnlyToDouble( 175 void ElementsTransitionGenerator::GenerateSmiOnlyToDouble(
176 MacroAssembler* masm, Label* fail) { 176 MacroAssembler* masm, Label* fail) {
177 // ----------- S t a t e ------------- 177 // ----------- S t a t e -------------
178 // -- rax : value 178 // -- rax : value
179 // -- rbx : target map 179 // -- rbx : target map
180 // -- rcx : key 180 // -- rcx : key
181 // -- rdx : receiver 181 // -- rdx : receiver
182 // -- rsp[0] : return address 182 // -- rsp[0] : return address
183 // ----------------------------------- 183 // -----------------------------------
184 // The fail label is not actually used since we do not allocate. 184 // The fail label is not actually used since we do not allocate.
185 Label allocated, cow_array;
186
187 // Check backing store for COW-ness. If the negative case, we do not have to
188 // allocate a new array, since FixedArray and FixedDoubleArray do not differ
189 // in size.
190 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
191 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset));
192 __ CompareRoot(FieldOperand(r8, HeapObject::kMapOffset),
193 Heap::kFixedCOWArrayMapRootIndex);
194 __ j(equal, &cow_array);
195 __ movq(r14, r8); // Destination array equals source array.
196
197 __ bind(&allocated);
198 // r8 : source FixedArray
199 // r9 : elements array length
200 // r14: destination FixedDoubleArray
201 // Set backing store's map
202 __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
203 __ movq(FieldOperand(r14, HeapObject::kMapOffset), rdi);
185 204
186 // Set transitioned map. 205 // Set transitioned map.
187 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); 206 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
188 __ RecordWriteField(rdx, 207 __ RecordWriteField(rdx,
189 HeapObject::kMapOffset, 208 HeapObject::kMapOffset,
190 rbx, 209 rbx,
191 rdi, 210 rdi,
192 kDontSaveFPRegs, 211 kDontSaveFPRegs,
193 EMIT_REMEMBERED_SET, 212 EMIT_REMEMBERED_SET,
194 OMIT_SMI_CHECK); 213 OMIT_SMI_CHECK);
195 // Set backing store's map
196 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
197 __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
198 __ movq(FieldOperand(r8, HeapObject::kMapOffset), rdi);
199 214
200 // Convert smis to doubles and holes to hole NaNs. Since FixedArray and 215 // Convert smis to doubles and holes to hole NaNs. In the non-COW case the
201 // FixedDoubleArray do not differ in size, we do not allocate a new array. 216 // length does not have to be set since we still use the exact same field
danno 2011/10/24 15:01:47 Or even simpler: NaNs. The Array's length remains
217 // for length.
202 STATIC_ASSERT(FixedDoubleArray::kLengthOffset == FixedArray::kLengthOffset); 218 STATIC_ASSERT(FixedDoubleArray::kLengthOffset == FixedArray::kLengthOffset);
203 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); 219 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
204 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); 220
205 // r8 : elements array
206 // r9 : elements array length
207 Label loop, entry, convert_hole; 221 Label loop, entry, convert_hole;
208 __ movq(r15, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE); 222 __ movq(r15, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE);
209 // r15: the-hole NaN 223 // r15: the-hole NaN
210 __ jmp(&entry); 224 __ jmp(&entry);
225
226 // Allocate new array if the source array is a COW array.
227 __ bind(&cow_array);
228 __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize));
229 __ AllocateInNewSpace(rdi, r14, r11, r15, fail, TAG_OBJECT);
230 // Set receiver's backing store.
231 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r14);
232 __ movq(r11, r14);
233 __ RecordWriteField(rdx,
234 JSObject::kElementsOffset,
235 r11,
236 r15,
237 kDontSaveFPRegs,
238 EMIT_REMEMBERED_SET,
239 OMIT_SMI_CHECK);
240 // Set backing store's length.
241 __ Integer32ToSmi(r11, r9);
242 __ movq(FieldOperand(r14, FixedDoubleArray::kLengthOffset), r11);
243 __ jmp(&allocated);
244
245 // Conversion loop.
211 __ bind(&loop); 246 __ bind(&loop);
212 __ decq(r9); 247 __ decq(r9);
213 __ movq(rbx, 248 __ movq(rbx,
214 FieldOperand(r8, r9, times_8, FixedArray::kHeaderSize)); 249 FieldOperand(r8, r9, times_8, FixedArray::kHeaderSize));
215 // r9 : current element's index 250 // r9 : current element's index
216 // rbx: current element (smi-tagged) 251 // rbx: current element (smi-tagged)
217 __ JumpIfNotSmi(rbx, &convert_hole); 252 __ JumpIfNotSmi(rbx, &convert_hole);
218 __ SmiToInteger32(rbx, rbx); 253 __ SmiToInteger32(rbx, rbx);
219 __ cvtlsi2sd(xmm0, rbx); 254 __ cvtlsi2sd(xmm0, rbx);
220 __ movsd(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize), 255 __ movsd(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize),
221 xmm0); 256 xmm0);
222 __ jmp(&entry); 257 __ jmp(&entry);
223 __ bind(&convert_hole); 258 __ bind(&convert_hole);
224 __ movq(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize), r15); 259 __ movq(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), r15);
225 __ bind(&entry); 260 __ bind(&entry);
226 __ testq(r9, r9); 261 __ testq(r9, r9);
227 __ j(not_zero, &loop); 262 __ j(not_zero, &loop);
228 } 263 }
229 264
230 265
231 void ElementsTransitionGenerator::GenerateDoubleToObject( 266 void ElementsTransitionGenerator::GenerateDoubleToObject(
232 MacroAssembler* masm, Label* fail) { 267 MacroAssembler* masm, Label* fail) {
233 // ----------- S t a t e ------------- 268 // ----------- S t a t e -------------
234 // -- rax : value 269 // -- rax : value
235 // -- rbx : target map 270 // -- rbx : target map
236 // -- rcx : key 271 // -- rcx : key
237 // -- rdx : receiver 272 // -- rdx : receiver
238 // -- rsp[0] : return address 273 // -- rsp[0] : return address
239 // ----------------------------------- 274 // -----------------------------------
240 Label loop, entry, convert_hole, gc_required; 275 Label loop, entry, convert_hole, gc_required;
241 __ push(rax); 276 __ push(rax);
242 277
243 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); 278 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
244 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); 279 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset));
245 // r8 : source FixedDoubleArray 280 // r8 : source FixedDoubleArray
246 // r9 : number of elements 281 // r9 : number of elements
247 __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize)); 282 __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize));
248 __ AllocateInNewSpace(rdi, rax, r14, r15, &gc_required, TAG_OBJECT); 283 __ AllocateInNewSpace(rdi, r11, r14, r15, &gc_required, TAG_OBJECT);
249 // rax: destination FixedArray 284 // r11: destination FixedArray
250 __ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex); 285 __ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex);
251 __ movq(FieldOperand(rax, HeapObject::kMapOffset), rdi); 286 __ movq(FieldOperand(r11, HeapObject::kMapOffset), rdi);
252 __ Integer32ToSmi(r14, r9); 287 __ Integer32ToSmi(r14, r9);
253 __ movq(FieldOperand(rax, FixedArray::kLengthOffset), r14); 288 __ movq(FieldOperand(r11, FixedArray::kLengthOffset), r14);
254 289
255 // Prepare for conversion loop. 290 // Prepare for conversion loop.
256 __ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE); 291 __ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE);
257 __ LoadRoot(rdi, Heap::kTheHoleValueRootIndex); 292 __ LoadRoot(rdi, Heap::kTheHoleValueRootIndex);
258 // rsi: the-hole NaN 293 // rsi: the-hole NaN
259 // rdi: pointer to the-hole 294 // rdi: pointer to the-hole
260 __ jmp(&entry); 295 __ jmp(&entry);
261 296
262 // Call into runtime if GC is required. 297 // Call into runtime if GC is required.
263 __ bind(&gc_required); 298 __ bind(&gc_required);
264 __ pop(rax); 299 __ pop(rax);
265 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 300 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
266 __ jmp(fail); 301 __ jmp(fail);
267 302
268 // Box doubles into heap numbers. 303 // Box doubles into heap numbers.
269 __ bind(&loop); 304 __ bind(&loop);
270 __ decq(r9); 305 __ decq(r9);
271 __ movq(r14, FieldOperand(r8, 306 __ movq(r14, FieldOperand(r8,
272 r9, 307 r9,
273 times_pointer_size, 308 times_pointer_size,
274 FixedDoubleArray::kHeaderSize)); 309 FixedDoubleArray::kHeaderSize));
275 // r9 : current element's index 310 // r9 : current element's index
276 // r14: current element 311 // r14: current element
277 __ cmpq(r14, rsi); 312 __ cmpq(r14, rsi);
278 __ j(equal, &convert_hole); 313 __ j(equal, &convert_hole);
279 314
280 // Non-hole double, copy value into a heap number. 315 // Non-hole double, copy value into a heap number.
281 __ AllocateHeapNumber(r11, r15, &gc_required); 316 __ AllocateHeapNumber(rax, r15, &gc_required);
282 // r11: new heap number 317 // rax: new heap number
283 __ movq(FieldOperand(r11, HeapNumber::kValueOffset), r14); 318 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), r14);
284 __ movq(FieldOperand(rax, 319 __ movq(FieldOperand(r11,
285 r9, 320 r9,
286 times_pointer_size, 321 times_pointer_size,
287 FixedArray::kHeaderSize), 322 FixedArray::kHeaderSize),
288 r11); 323 rax);
289 __ movq(r15, r9); 324 __ movq(r15, r9);
290 __ RecordWriteArray(rax, 325 __ RecordWriteArray(r11,
291 r11, 326 rax,
292 r15, 327 r15,
293 kDontSaveFPRegs, 328 kDontSaveFPRegs,
294 EMIT_REMEMBERED_SET, 329 EMIT_REMEMBERED_SET,
295 OMIT_SMI_CHECK); 330 OMIT_SMI_CHECK);
296 __ jmp(&entry, Label::kNear); 331 __ jmp(&entry, Label::kNear);
297 332
298 // Replace the-hole NaN with the-hole pointer. 333 // Replace the-hole NaN with the-hole pointer.
299 __ bind(&convert_hole); 334 __ bind(&convert_hole);
300 __ movq(FieldOperand(rax, 335 __ movq(FieldOperand(r11,
301 r9, 336 r9,
302 times_pointer_size, 337 times_pointer_size,
303 FixedArray::kHeaderSize), 338 FixedArray::kHeaderSize),
304 rdi); 339 rdi);
305 340
306 __ bind(&entry); 341 __ bind(&entry);
307 __ testq(r9, r9); 342 __ testq(r9, r9);
308 __ j(not_zero, &loop); 343 __ j(not_zero, &loop);
309 344
310 // Set transitioned map. 345 // Set transitioned map.
311 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); 346 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
312 __ RecordWriteField(rdx, 347 __ RecordWriteField(rdx,
313 HeapObject::kMapOffset, 348 HeapObject::kMapOffset,
314 rbx, 349 rbx,
315 rdi, 350 rdi,
316 kDontSaveFPRegs, 351 kDontSaveFPRegs,
317 EMIT_REMEMBERED_SET, 352 EMIT_REMEMBERED_SET,
318 OMIT_SMI_CHECK); 353 OMIT_SMI_CHECK);
319 // Replace receiver's backing store with newly created and filled FixedArray. 354 // Replace receiver's backing store with newly created and filled FixedArray.
320 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rax); 355 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r11);
321 __ RecordWriteField(rdx, 356 __ RecordWriteField(rdx,
322 JSObject::kElementsOffset, 357 JSObject::kElementsOffset,
323 rax, 358 r11,
324 rdi, 359 r15,
325 kDontSaveFPRegs, 360 kDontSaveFPRegs,
326 EMIT_REMEMBERED_SET, 361 EMIT_REMEMBERED_SET,
327 OMIT_SMI_CHECK); 362 OMIT_SMI_CHECK);
328 __ pop(rax); 363 __ pop(rax);
329 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 364 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
330 } 365 }
331 366
332 #undef __ 367 #undef __
333 368
334 } } // namespace v8::internal 369 } } // namespace v8::internal
335 370
336 #endif // V8_TARGET_ARCH_X64 371 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | test/mjsunit/elements-transition.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698