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/x87/codegen-x87.h" | 5 #include "src/x87/codegen-x87.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/heap/heap.h" | 10 #include "src/heap/heap.h" |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 } | 205 } |
206 | 206 |
207 | 207 |
208 #undef __ | 208 #undef __ |
209 | 209 |
210 // ------------------------------------------------------------------------- | 210 // ------------------------------------------------------------------------- |
211 // Code generators | 211 // Code generators |
212 | 212 |
213 #define __ ACCESS_MASM(masm) | 213 #define __ ACCESS_MASM(masm) |
214 | 214 |
215 | |
216 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | |
217 MacroAssembler* masm, | |
218 Register receiver, | |
219 Register key, | |
220 Register value, | |
221 Register target_map, | |
222 AllocationSiteMode mode, | |
223 Label* allocation_memento_found) { | |
224 Register scratch = edi; | |
225 DCHECK(!AreAliased(receiver, key, value, target_map, scratch)); | |
226 | |
227 if (mode == TRACK_ALLOCATION_SITE) { | |
228 DCHECK(allocation_memento_found != NULL); | |
229 __ JumpIfJSArrayHasAllocationMemento( | |
230 receiver, scratch, allocation_memento_found); | |
231 } | |
232 | |
233 // Set transitioned map. | |
234 __ mov(FieldOperand(receiver, HeapObject::kMapOffset), target_map); | |
235 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch, | |
236 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
237 } | |
238 | |
239 | |
240 void ElementsTransitionGenerator::GenerateSmiToDouble( | |
241 MacroAssembler* masm, | |
242 Register receiver, | |
243 Register key, | |
244 Register value, | |
245 Register target_map, | |
246 AllocationSiteMode mode, | |
247 Label* fail) { | |
248 // Return address is on the stack. | |
249 DCHECK(receiver.is(edx)); | |
250 DCHECK(key.is(ecx)); | |
251 DCHECK(value.is(eax)); | |
252 DCHECK(target_map.is(ebx)); | |
253 | |
254 Label loop, entry, convert_hole, gc_required, only_change_map; | |
255 | |
256 if (mode == TRACK_ALLOCATION_SITE) { | |
257 __ JumpIfJSArrayHasAllocationMemento(edx, edi, fail); | |
258 } | |
259 | |
260 // Check for empty arrays, which only require a map transition and no changes | |
261 // to the backing store. | |
262 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | |
263 __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array())); | |
264 __ j(equal, &only_change_map); | |
265 | |
266 __ push(eax); | |
267 __ push(ebx); | |
268 __ push(esi); | |
269 | |
270 __ mov(edi, FieldOperand(edi, FixedArray::kLengthOffset)); | |
271 | |
272 // Allocate new FixedDoubleArray. | |
273 // edx: receiver | |
274 // edi: length of source FixedArray (smi-tagged) | |
275 AllocationFlags flags = static_cast<AllocationFlags>(DOUBLE_ALIGNMENT); | |
276 __ Allocate(FixedDoubleArray::kHeaderSize, times_8, edi, | |
277 REGISTER_VALUE_IS_SMI, eax, ebx, no_reg, &gc_required, flags); | |
278 | |
279 // eax: destination FixedDoubleArray | |
280 // edi: number of elements | |
281 // edx: receiver | |
282 __ mov(FieldOperand(eax, HeapObject::kMapOffset), | |
283 Immediate(masm->isolate()->factory()->fixed_double_array_map())); | |
284 __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), edi); | |
285 __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset)); | |
286 // Replace receiver's backing store with newly created FixedDoubleArray. | |
287 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); | |
288 __ mov(ebx, eax); | |
289 __ RecordWriteField(edx, JSObject::kElementsOffset, ebx, edi, kDontSaveFPRegs, | |
290 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
291 | |
292 __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset)); | |
293 | |
294 // Prepare for conversion loop. | |
295 ExternalReference canonical_the_hole_nan_reference = | |
296 ExternalReference::address_of_the_hole_nan(); | |
297 __ jmp(&entry); | |
298 | |
299 // Call into runtime if GC is required. | |
300 __ bind(&gc_required); | |
301 | |
302 // Restore registers before jumping into runtime. | |
303 __ pop(esi); | |
304 __ pop(ebx); | |
305 __ pop(eax); | |
306 __ jmp(fail); | |
307 | |
308 // Convert and copy elements | |
309 // esi: source FixedArray | |
310 __ bind(&loop); | |
311 __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize)); | |
312 // ebx: current element from source | |
313 // edi: index of current element | |
314 __ JumpIfNotSmi(ebx, &convert_hole); | |
315 | |
316 // Normal smi, convert it to double and store. | |
317 __ SmiUntag(ebx); | |
318 __ push(ebx); | |
319 __ fild_s(Operand(esp, 0)); | |
320 __ pop(ebx); | |
321 __ fstp_d(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize)); | |
322 __ jmp(&entry); | |
323 | |
324 // Found hole, store hole_nan_as_double instead. | |
325 __ bind(&convert_hole); | |
326 | |
327 if (FLAG_debug_code) { | |
328 __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); | |
329 __ Assert(equal, kObjectFoundInSmiOnlyArray); | |
330 } | |
331 | |
332 __ fld_d(Operand::StaticVariable(canonical_the_hole_nan_reference)); | |
333 __ fstp_d(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize)); | |
334 | |
335 __ bind(&entry); | |
336 __ sub(edi, Immediate(Smi::FromInt(1))); | |
337 __ j(not_sign, &loop); | |
338 | |
339 // Restore registers. | |
340 __ pop(esi); | |
341 __ pop(ebx); | |
342 __ pop(eax); | |
343 | |
344 __ bind(&only_change_map); | |
345 // eax: value | |
346 // ebx: target map | |
347 // Set transitioned map. | |
348 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | |
349 __ RecordWriteField(edx, HeapObject::kMapOffset, ebx, edi, kDontSaveFPRegs, | |
350 OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
351 } | |
352 | |
353 | |
354 void ElementsTransitionGenerator::GenerateDoubleToObject( | |
355 MacroAssembler* masm, | |
356 Register receiver, | |
357 Register key, | |
358 Register value, | |
359 Register target_map, | |
360 AllocationSiteMode mode, | |
361 Label* fail) { | |
362 // Return address is on the stack. | |
363 DCHECK(receiver.is(edx)); | |
364 DCHECK(key.is(ecx)); | |
365 DCHECK(value.is(eax)); | |
366 DCHECK(target_map.is(ebx)); | |
367 | |
368 Label loop, entry, convert_hole, gc_required, only_change_map, success; | |
369 | |
370 if (mode == TRACK_ALLOCATION_SITE) { | |
371 __ JumpIfJSArrayHasAllocationMemento(edx, edi, fail); | |
372 } | |
373 | |
374 // Check for empty arrays, which only require a map transition and no changes | |
375 // to the backing store. | |
376 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | |
377 __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array())); | |
378 __ j(equal, &only_change_map); | |
379 | |
380 __ push(esi); | |
381 __ push(eax); | |
382 __ push(edx); | |
383 __ push(ebx); | |
384 | |
385 __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset)); | |
386 | |
387 // Allocate new FixedArray. | |
388 // ebx: length of source FixedDoubleArray (smi-tagged) | |
389 __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize)); | |
390 __ Allocate(edi, eax, esi, no_reg, &gc_required, NO_ALLOCATION_FLAGS); | |
391 | |
392 // eax: destination FixedArray | |
393 // ebx: number of elements | |
394 __ mov(FieldOperand(eax, HeapObject::kMapOffset), | |
395 Immediate(masm->isolate()->factory()->fixed_array_map())); | |
396 __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx); | |
397 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | |
398 | |
399 // Allocating heap numbers in the loop below can fail and cause a jump to | |
400 // gc_required. We can't leave a partly initialized FixedArray behind, | |
401 // so pessimistically fill it with holes now. | |
402 Label initialization_loop, initialization_loop_entry; | |
403 __ jmp(&initialization_loop_entry, Label::kNear); | |
404 __ bind(&initialization_loop); | |
405 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), | |
406 masm->isolate()->factory()->the_hole_value()); | |
407 __ bind(&initialization_loop_entry); | |
408 __ sub(ebx, Immediate(Smi::FromInt(1))); | |
409 __ j(not_sign, &initialization_loop); | |
410 | |
411 __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset)); | |
412 __ jmp(&entry); | |
413 | |
414 // ebx: target map | |
415 // edx: receiver | |
416 // Set transitioned map. | |
417 __ bind(&only_change_map); | |
418 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | |
419 __ RecordWriteField(edx, HeapObject::kMapOffset, ebx, edi, kDontSaveFPRegs, | |
420 OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
421 __ jmp(&success); | |
422 | |
423 // Call into runtime if GC is required. | |
424 __ bind(&gc_required); | |
425 __ pop(ebx); | |
426 __ pop(edx); | |
427 __ pop(eax); | |
428 __ pop(esi); | |
429 __ jmp(fail); | |
430 | |
431 // Box doubles into heap numbers. | |
432 // edi: source FixedDoubleArray | |
433 // eax: destination FixedArray | |
434 __ bind(&loop); | |
435 // ebx: index of current element (smi-tagged) | |
436 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | |
437 __ cmp(FieldOperand(edi, ebx, times_4, offset), Immediate(kHoleNanUpper32)); | |
438 __ j(equal, &convert_hole); | |
439 | |
440 // Non-hole double, copy value into a heap number. | |
441 __ AllocateHeapNumber(edx, esi, no_reg, &gc_required); | |
442 // edx: new heap number | |
443 __ mov(esi, FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize)); | |
444 __ mov(FieldOperand(edx, HeapNumber::kValueOffset), esi); | |
445 __ mov(esi, FieldOperand(edi, ebx, times_4, offset)); | |
446 __ mov(FieldOperand(edx, HeapNumber::kValueOffset + kPointerSize), esi); | |
447 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx); | |
448 __ mov(esi, ebx); | |
449 __ RecordWriteArray(eax, edx, esi, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | |
450 OMIT_SMI_CHECK); | |
451 __ jmp(&entry, Label::kNear); | |
452 | |
453 // Replace the-hole NaN with the-hole pointer. | |
454 __ bind(&convert_hole); | |
455 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), | |
456 masm->isolate()->factory()->the_hole_value()); | |
457 | |
458 __ bind(&entry); | |
459 __ sub(ebx, Immediate(Smi::FromInt(1))); | |
460 __ j(not_sign, &loop); | |
461 | |
462 __ pop(ebx); | |
463 __ pop(edx); | |
464 // ebx: target map | |
465 // edx: receiver | |
466 // Set transitioned map. | |
467 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | |
468 __ RecordWriteField(edx, HeapObject::kMapOffset, ebx, edi, kDontSaveFPRegs, | |
469 OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
470 // Replace receiver's backing store with newly created and filled FixedArray. | |
471 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); | |
472 __ RecordWriteField(edx, JSObject::kElementsOffset, eax, edi, kDontSaveFPRegs, | |
473 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
474 | |
475 // Restore registers. | |
476 __ pop(eax); | |
477 __ pop(esi); | |
478 | |
479 __ bind(&success); | |
480 } | |
481 | |
482 | |
483 void StringCharLoadGenerator::Generate(MacroAssembler* masm, | 215 void StringCharLoadGenerator::Generate(MacroAssembler* masm, |
484 Factory* factory, | 216 Factory* factory, |
485 Register string, | 217 Register string, |
486 Register index, | 218 Register index, |
487 Register result, | 219 Register result, |
488 Label* call_runtime) { | 220 Label* call_runtime) { |
489 // Fetch the instance type of the receiver into result register. | 221 // Fetch the instance type of the receiver into result register. |
490 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); | 222 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); |
491 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 223 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
492 | 224 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 CodePatcher patcher(isolate, sequence, young_length); | 373 CodePatcher patcher(isolate, sequence, young_length); |
642 patcher.masm()->call(stub->instruction_start(), RelocInfo::NONE32); | 374 patcher.masm()->call(stub->instruction_start(), RelocInfo::NONE32); |
643 } | 375 } |
644 } | 376 } |
645 | 377 |
646 | 378 |
647 } // namespace internal | 379 } // namespace internal |
648 } // namespace v8 | 380 } // namespace v8 |
649 | 381 |
650 #endif // V8_TARGET_ARCH_X87 | 382 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |