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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 391693002: In-object double fields unboxing (for 64-bit only). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 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
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698