Chromium Code Reviews| 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 |