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_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
481 it.Advance(); | 481 it.Advance(); |
482 if (it.Done()) { | 482 if (it.Done()) { |
483 __ j(not_equal, miss_label); | 483 __ j(not_equal, miss_label); |
484 break; | 484 break; |
485 } | 485 } |
486 __ j(equal, &do_store, Label::kNear); | 486 __ j(equal, &do_store, Label::kNear); |
487 } | 487 } |
488 __ bind(&do_store); | 488 __ bind(&do_store); |
489 } | 489 } |
490 } else if (representation.IsDouble()) { | 490 } else if (representation.IsDouble()) { |
491 FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor); | |
492 | |
491 Label do_store, heap_number; | 493 Label do_store, heap_number; |
492 __ AllocateHeapNumber(storage_reg, scratch1, slow, MUTABLE); | 494 if (!FLAG_unbox_double_fields || !index.is_inobject()) { |
495 __ AllocateHeapNumber(storage_reg, scratch1, slow, MUTABLE); | |
496 } | |
493 | 497 |
494 __ JumpIfNotSmi(value_reg, &heap_number); | 498 __ JumpIfNotSmi(value_reg, &heap_number); |
495 __ SmiToInteger32(scratch1, value_reg); | 499 __ SmiToInteger32(scratch1, value_reg); |
496 __ Cvtlsi2sd(xmm0, scratch1); | 500 __ Cvtlsi2sd(xmm0, scratch1); |
497 __ jmp(&do_store); | 501 __ jmp(&do_store); |
498 | 502 |
499 __ bind(&heap_number); | 503 __ bind(&heap_number); |
500 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 504 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
501 miss_label, DONT_DO_SMI_CHECK); | 505 miss_label, DONT_DO_SMI_CHECK); |
502 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 506 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
503 | 507 |
504 __ bind(&do_store); | 508 __ bind(&do_store); |
505 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 509 if (!FLAG_unbox_double_fields || !index.is_inobject()) { |
510 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | |
511 } | |
506 } | 512 } |
507 | 513 |
508 // Stub never generated for non-global objects that require access | 514 // Stub never generated for non-global objects that require access |
509 // checks. | 515 // checks. |
510 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 516 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
511 | 517 |
512 // Perform map transition for the receiver if necessary. | 518 // Perform map transition for the receiver if necessary. |
513 if (details.type() == FIELD && | 519 if (details.type() == FIELD && |
514 object->map()->unused_property_fields() == 0) { | 520 object->map()->unused_property_fields() == 0) { |
515 // The properties must be extended before we can store the value. | 521 // The properties must be extended before we can store the value. |
(...skipping 23 matching lines...) Expand all Loading... | |
539 kDontSaveFPRegs, | 545 kDontSaveFPRegs, |
540 OMIT_REMEMBERED_SET, | 546 OMIT_REMEMBERED_SET, |
541 OMIT_SMI_CHECK); | 547 OMIT_SMI_CHECK); |
542 | 548 |
543 if (details.type() == CONSTANT) { | 549 if (details.type() == CONSTANT) { |
544 ASSERT(value_reg.is(rax)); | 550 ASSERT(value_reg.is(rax)); |
545 __ ret(0); | 551 __ ret(0); |
546 return; | 552 return; |
547 } | 553 } |
548 | 554 |
549 int index = transition->instance_descriptors()->GetFieldIndex( | 555 FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor); |
Toon Verwaest
2014/07/29 15:02:09
Nice cleanup. What about porting this to other pla
Igor Sheludko
2014/10/30 14:23:44
Done.
| |
550 transition->LastAdded()); | |
551 | |
552 // Adjust for the number of properties stored in the object. Even in the | |
553 // face of a transition we can use the old map here because the size of the | |
554 // object and the number of in-object properties is not going to change. | |
555 index -= object->map()->inobject_properties(); | |
556 | 556 |
557 // TODO(verwaest): Share this code as a code stub. | 557 // TODO(verwaest): Share this code as a code stub. |
558 SmiCheck smi_check = representation.IsTagged() | 558 SmiCheck smi_check = representation.IsTagged() |
559 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 559 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
560 if (index < 0) { | 560 if (index.is_inobject()) { |
561 // Set the property straight into the object. | 561 // Set the property straight into the object. |
562 int offset = object->map()->instance_size() + (index * kPointerSize); | 562 if (FLAG_unbox_double_fields && representation.IsDouble()) { |
563 if (representation.IsDouble()) { | 563 __ movsd(FieldOperand(receiver_reg, index.offset()), xmm0); |
564 __ movp(FieldOperand(receiver_reg, offset), storage_reg); | 564 } else if (representation.IsDouble()) { |
565 __ movp(FieldOperand(receiver_reg, index.offset()), storage_reg); | |
565 } else { | 566 } else { |
566 __ movp(FieldOperand(receiver_reg, offset), value_reg); | 567 __ movp(FieldOperand(receiver_reg, index.offset()), value_reg); |
567 } | 568 } |
568 | 569 |
569 if (!representation.IsSmi()) { | 570 if ((!FLAG_unbox_double_fields || !representation.IsDouble()) && |
571 !representation.IsSmi()) { | |
570 // Update the write barrier for the array address. | 572 // Update the write barrier for the array address. |
571 if (!representation.IsDouble()) { | 573 if (!representation.IsDouble()) { |
572 __ movp(storage_reg, value_reg); | 574 __ movp(storage_reg, value_reg); |
573 } | 575 } |
574 __ RecordWriteField( | 576 __ RecordWriteField(receiver_reg, index.offset(), storage_reg, scratch1, |
575 receiver_reg, offset, storage_reg, scratch1, kDontSaveFPRegs, | 577 kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check); |
576 EMIT_REMEMBERED_SET, smi_check); | |
577 } | 578 } |
578 } else { | 579 } else { |
579 // Write to the properties array. | 580 // Write to the properties array. |
580 int offset = index * kPointerSize + FixedArray::kHeaderSize; | |
581 // Get the properties array (optimistically). | 581 // Get the properties array (optimistically). |
582 __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 582 __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
583 if (representation.IsDouble()) { | 583 if (representation.IsDouble()) { |
584 __ movp(FieldOperand(scratch1, offset), storage_reg); | 584 __ movp(FieldOperand(scratch1, index.offset()), storage_reg); |
585 } else { | 585 } else { |
586 __ movp(FieldOperand(scratch1, offset), value_reg); | 586 __ movp(FieldOperand(scratch1, index.offset()), value_reg); |
587 } | 587 } |
588 | 588 |
589 if (!representation.IsSmi()) { | 589 if (!representation.IsSmi()) { |
590 // Update the write barrier for the array address. | 590 // Update the write barrier for the array address. |
591 if (!representation.IsDouble()) { | 591 if (!representation.IsDouble()) { |
592 __ movp(storage_reg, value_reg); | 592 __ movp(storage_reg, value_reg); |
593 } | 593 } |
594 __ RecordWriteField( | 594 __ RecordWriteField(scratch1, index.offset(), storage_reg, receiver_reg, |
595 scratch1, offset, storage_reg, receiver_reg, kDontSaveFPRegs, | 595 kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check); |
596 EMIT_REMEMBERED_SET, smi_check); | |
597 } | 596 } |
598 } | 597 } |
599 | 598 |
600 // Return the value (register rax). | 599 // Return the value (register rax). |
601 ASSERT(value_reg.is(rax)); | 600 ASSERT(value_reg.is(rax)); |
602 __ ret(0); | 601 __ ret(0); |
603 } | 602 } |
604 | 603 |
605 | 604 |
606 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 605 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
(...skipping 28 matching lines...) Expand all Loading... | |
635 it.Advance(); | 634 it.Advance(); |
636 if (it.Done()) { | 635 if (it.Done()) { |
637 __ j(not_equal, miss_label); | 636 __ j(not_equal, miss_label); |
638 break; | 637 break; |
639 } | 638 } |
640 __ j(equal, &do_store, Label::kNear); | 639 __ j(equal, &do_store, Label::kNear); |
641 } | 640 } |
642 __ bind(&do_store); | 641 __ bind(&do_store); |
643 } | 642 } |
644 } else if (representation.IsDouble()) { | 643 } else if (representation.IsDouble()) { |
645 // Load the double storage. | 644 // Prepare value for storing. |
646 if (index.is_inobject()) { | |
647 __ movp(scratch1, FieldOperand(receiver_reg, index.offset())); | |
648 } else { | |
649 __ movp(scratch1, | |
650 FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | |
651 __ movp(scratch1, FieldOperand(scratch1, index.offset())); | |
652 } | |
653 | |
654 // Store the value into the storage. | |
655 Label do_store, heap_number; | 645 Label do_store, heap_number; |
656 __ JumpIfNotSmi(value_reg, &heap_number); | 646 __ JumpIfNotSmi(value_reg, &heap_number); |
657 __ SmiToInteger32(scratch2, value_reg); | 647 __ SmiToInteger32(scratch1, value_reg); |
658 __ Cvtlsi2sd(xmm0, scratch2); | 648 __ Cvtlsi2sd(xmm0, scratch1); |
659 __ jmp(&do_store); | 649 __ jmp(&do_store); |
660 | 650 |
661 __ bind(&heap_number); | 651 __ bind(&heap_number); |
662 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 652 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
663 miss_label, DONT_DO_SMI_CHECK); | 653 miss_label, DONT_DO_SMI_CHECK); |
664 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 654 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
655 | |
665 __ bind(&do_store); | 656 __ bind(&do_store); |
666 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); | 657 // Store it either to respective mutable box or directly to in-object field. |
658 Operand operand = FieldOperand(scratch1, HeapNumber::kValueOffset); | |
Toon Verwaest
2014/07/29 15:02:09
Arg this code is confusing. Can you please just se
Igor Sheludko
2014/10/30 14:23:44
Done.
| |
659 if (index.is_inobject()) { | |
660 if (FLAG_unbox_double_fields) { | |
661 operand = FieldOperand(receiver_reg, index.offset()); | |
662 } else { | |
663 __ movp(scratch1, FieldOperand(receiver_reg, index.offset())); | |
664 } | |
665 } else { | |
666 __ movp(scratch1, | |
667 FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | |
668 __ movp(scratch1, FieldOperand(scratch1, index.offset())); | |
669 } | |
670 __ movsd(operand, xmm0); | |
667 // Return the value (register rax). | 671 // Return the value (register rax). |
668 ASSERT(value_reg.is(rax)); | 672 ASSERT(value_reg.is(rax)); |
669 __ ret(0); | 673 __ ret(0); |
670 return; | 674 return; |
671 } | 675 } |
672 | 676 |
673 // TODO(verwaest): Share this code as a code stub. | 677 // TODO(verwaest): Share this code as a code stub. |
674 SmiCheck smi_check = representation.IsTagged() | 678 SmiCheck smi_check = representation.IsTagged() |
675 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 679 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
676 if (index.is_inobject()) { | 680 if (index.is_inobject()) { |
(...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1437 // ----------------------------------- | 1441 // ----------------------------------- |
1438 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1442 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1439 } | 1443 } |
1440 | 1444 |
1441 | 1445 |
1442 #undef __ | 1446 #undef __ |
1443 | 1447 |
1444 } } // namespace v8::internal | 1448 } } // namespace v8::internal |
1445 | 1449 |
1446 #endif // V8_TARGET_ARCH_X64 | 1450 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |