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

Side by Side Diff: runtime/vm/stub_code_ia32.cc

Issue 284013002: Improve performance of stubcode based array allocation moving stub to isolate specific area. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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 (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 592
593 __ movl(EBX, FieldAddress(EAX, Function::code_offset())); 593 __ movl(EBX, FieldAddress(EAX, Function::code_offset()));
594 __ movl(EBX, FieldAddress(EBX, Code::instructions_offset())); 594 __ movl(EBX, FieldAddress(EBX, Code::instructions_offset()));
595 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 595 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
596 __ jmp(EBX); 596 __ jmp(EBX);
597 } 597 }
598 598
599 599
600 // Called for inline allocation of arrays. 600 // Called for inline allocation of arrays.
601 // Input parameters: 601 // Input parameters:
602 // EDX : Array length as Smi. 602 // EDX : Array length as Smi. (must be preserved)
zra 2014/05/15 16:20:26 missing . at end of comment.
srdjan 2014/05/15 16:52:34 Done.
603 // ECX : array element type (either NULL or an instantiated type). 603 // ECX : array element type (either NULL or an instantiated type).
604 // Uses EAX, EBX, ECX, EDI as temporary registers. 604 // Uses EAX, EBX, ECX, EDI as temporary registers.
605 // NOTE: EDX cannot be clobbered here as the caller relies on it being saved.
606 // The newly allocated object is returned in EAX. 605 // The newly allocated object is returned in EAX.
607 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { 606 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
608 Label slow_case; 607 Label slow_case;
609 const Immediate& raw_null = 608 const Immediate& raw_null =
610 Immediate(reinterpret_cast<intptr_t>(Object::null())); 609 Immediate(reinterpret_cast<intptr_t>(Object::null()));
611 610
612 if (FLAG_inline_alloc) { 611 // Compute the size to be allocated, it is based on the array length
613 // Compute the size to be allocated, it is based on the array length 612 // and is computed as:
614 // and is computed as: 613 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
615 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). 614 // Assert that length is a Smi.
616 // Assert that length is a Smi. 615 __ testl(EDX, Immediate(kSmiTagMask));
617 __ testl(EDX, Immediate(kSmiTagMask)); 616 if (FLAG_use_slow_path) {
618 if (FLAG_use_slow_path) { 617 __ jmp(&slow_case);
619 __ jmp(&slow_case); 618 } else {
620 } else { 619 __ j(NOT_ZERO, &slow_case);
621 __ j(NOT_ZERO, &slow_case); 620 }
622 } 621 __ cmpl(EDX, Immediate(0));
623 __ cmpl(EDX, Immediate(0)); 622 __ j(LESS, &slow_case);
624 __ j(LESS, &slow_case);
625 623
626 // Check for maximum allowed length. 624 // Check for maximum allowed length.
627 const Immediate& max_len = 625 const Immediate& max_len =
628 Immediate(reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements))); 626 Immediate(reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)));
629 __ cmpl(EDX, max_len); 627 __ cmpl(EDX, max_len);
630 __ j(GREATER, &slow_case); 628 __ j(GREATER, &slow_case);
631 629
632 __ movl(EDI, FieldAddress(CTX, Context::isolate_offset())); 630 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
633 __ movl(EDI, Address(EDI, Isolate::heap_offset())); 631 __ leal(EDI, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi.
634 __ movl(EDI, Address(EDI, Heap::new_space_offset())); 632 ASSERT(kSmiTagShift == 1);
633 __ andl(EDI, Immediate(-kObjectAlignment));
635 634
636 // Calculate and align allocation size. 635 // ECX: array element type.
637 // Load new object start and calculate next object start. 636 // EDX: array length as Smi.
638 // ECX: array element type. 637 // EDI: allocation size.
639 // EDX: Array length as Smi.
640 // EDI: Points to new space object.
641 __ movl(EAX, Address(EDI, Scavenger::top_offset()));
642 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
643 __ leal(EBX, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi.
644 ASSERT(kSmiTagShift == 1);
645 __ andl(EBX, Immediate(-kObjectAlignment));
646 638
647 // Check for overflow. 639 Isolate* isolate = Isolate::Current();
648 __ addl(EBX, EAX); 640 Heap* heap = isolate->heap();
649 __ j(CARRY, &slow_case);
650 641
651 // Check if the allocation fits into the remaining space. 642 __ movl(EAX, Address::Absolute(heap->TopAddress()));
652 // EAX: potential new object start. 643 __ movl(EBX, EAX);
653 // EBX: potential next object start.
654 // ECX: array element type.
655 // EDX: Array length as Smi.
656 // EDI: Points to new space object.
657 __ cmpl(EBX, Address(EDI, Scavenger::end_offset()));
658 __ j(ABOVE_EQUAL, &slow_case);
659 644
660 // Successfully allocated the object(s), now update top to point to 645 // EDI: allocation size.
661 // next object start and initialize the object. 646 __ addl(EBX, EDI);
662 // EAX: potential new object start. 647 __ j(CARRY, &slow_case);
663 // EBX: potential next object start.
664 // EDX: Array length as Smi.
665 // EDI: Points to new space object.
666 __ movl(Address(EDI, Scavenger::top_offset()), EBX);
667 __ addl(EAX, Immediate(kHeapObjectTag));
668 // EDI: Size of allocation in bytes.
669 __ movl(EDI, EBX);
670 __ subl(EDI, EAX);
671 __ UpdateAllocationStatsWithSize(kArrayCid, EDI, kNoRegister);
672 648
673 // EAX: new object start as a tagged pointer. 649 // Check if the allocation fits into the remaining space.
674 // EBX: new object end address. 650 // EAX: potential new object start.
675 // ECX: array element type. 651 // EBX: potential next object start.
676 // EDX: Array length as Smi. 652 // EDI: allocation size.
653 // ECX: array element type.
654 // EDX: array length as Smi).
655 __ cmpl(EBX, Address::Absolute(heap->EndAddress()));
656 __ j(ABOVE_EQUAL, &slow_case);
677 657
678 // Store the type argument field. 658 // Successfully allocated the object(s), now update top to point to
679 __ StoreIntoObjectNoBarrier( 659 // next object start and initialize the object.
680 EAX, 660 __ movl(Address::Absolute(heap->TopAddress()), EBX);
681 FieldAddress(EAX, Array::type_arguments_offset()), 661 __ addl(EAX, Immediate(kHeapObjectTag));
682 ECX); 662 __ UpdateAllocationStatsWithSize(kArrayCid, EDI, kNoRegister);
683 663
684 // Set the length field. 664 // Initialize the tags.
685 __ StoreIntoObjectNoBarrier( 665 // EAX: new object start as a tagged pointer.
686 EAX, 666 // EBX: new object end address.
687 FieldAddress(EAX, Array::length_offset()), 667 // EDI: allocation size.
688 EDX); 668 // ECX: array element type.
669 // EDX: array length as Smi.
670 {
671 Label size_tag_overflow, done;
672 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag));
673 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
674 __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));
675 __ jmp(&done, Assembler::kNearJump);
689 676
690 // Calculate the size tag. 677 __ Bind(&size_tag_overflow);
691 // EAX: new object start as a tagged pointer. 678 __ movl(EDI, Immediate(0));
692 // EBX: new object end address.
693 // EDX: Array length as Smi.
694 {
695 Label size_tag_overflow, done;
696 __ leal(ECX, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi.
697 ASSERT(kSmiTagShift == 1);
698 __ andl(ECX, Immediate(-kObjectAlignment));
699 __ cmpl(ECX, Immediate(RawObject::SizeTag::kMaxSizeTag));
700 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
701 __ shll(ECX, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));
702 __ jmp(&done);
703
704 __ Bind(&size_tag_overflow);
705 __ movl(ECX, Immediate(0));
706 __ Bind(&done);
707
708 // Get the class index and insert it into the tags.
709 __ orl(ECX, Immediate(RawObject::ClassIdTag::encode(kArrayCid)));
710 __ movl(FieldAddress(EAX, Array::tags_offset()), ECX);
711 }
712
713 // Initialize all array elements to raw_null.
714 // EAX: new object start as a tagged pointer.
715 // EBX: new object end address.
716 // EDX: Array length as Smi.
717 __ leal(ECX, FieldAddress(EAX, Array::data_offset()));
718 // ECX: iterator which initially points to the start of the variable
719 // data area to be initialized.
720 Label done;
721 Label init_loop;
722 __ Bind(&init_loop);
723 __ cmpl(ECX, EBX);
724 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
725 // TODO(cshapiro): StoreIntoObjectNoBarrier
726 __ movl(Address(ECX, 0), raw_null);
727 __ addl(ECX, Immediate(kWordSize));
728 __ jmp(&init_loop, Assembler::kNearJump);
729 __ Bind(&done); 679 __ Bind(&done);
730 680
731 // Done allocating and initializing the array. 681 // Get the class index and insert it into the tags.
732 // EAX: new object. 682 const Class& cls = Class::Handle(isolate->object_store()->array_class());
733 // EDX: Array length as Smi (preserved for the caller.) 683 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cls.id())));
734 __ ret(); 684 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags.
735 } 685 }
686 // EAX: new object start as a tagged pointer.
687 // EBX: new object end address.
688 // ECX: array element type.
689 // EDX: Array length as Smi (preserved).
690 // Store the type argument field.
691 __ StoreIntoObjectNoBarrier(EAX,
692 FieldAddress(EAX, Array::type_arguments_offset()),
693 ECX);
694
695 // Set the length field.
696 __ StoreIntoObjectNoBarrier(EAX,
697 FieldAddress(EAX, Array::length_offset()),
698 EDX);
699
700 // Initialize all array elements to raw_null.
701 // EAX: new object start as a tagged pointer.
702 // EBX: new object end address.
703 // EDI: iterator which initially points to the start of the variable
704 // data area to be initialized.
705 // ECX: array element type.
706 // EDX: array length as Smi.
707 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray)));
708 Label done;
709 Label init_loop;
710 __ Bind(&init_loop);
711 __ cmpl(EDI, EBX);
712 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
713 __ movl(Address(EDI, 0), raw_null);
714 __ addl(EDI, Immediate(kWordSize));
715 __ jmp(&init_loop, Assembler::kNearJump);
716 __ Bind(&done);
717 __ ret(); // returns the newly allocated object in EAX.
736 718
737 // Unable to allocate the array using the fast inline code, just call 719 // Unable to allocate the array using the fast inline code, just call
738 // into the runtime. 720 // into the runtime.
739 __ Bind(&slow_case); 721 __ Bind(&slow_case);
740 // Create a stub frame as we are pushing some objects on the stack before 722 // Create a stub frame as we are pushing some objects on the stack before
741 // calling into the runtime. 723 // calling into the runtime.
742 __ EnterStubFrame(); 724 __ EnterStubFrame();
743 __ pushl(raw_null); // Setup space on stack for return value. 725 __ pushl(raw_null); // Setup space on stack for return value.
744 __ pushl(EDX); // Array length as Smi. 726 __ pushl(EDX); // Array length as Smi.
745 __ pushl(ECX); // Element type. 727 __ pushl(ECX); // Element type.
746 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); 728 __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
747 __ popl(EAX); // Pop element type argument. 729 __ popl(EAX); // Pop element type argument.
748 __ popl(EDX); // Pop array length argument. 730 __ popl(EDX); // Pop array length argument. (preserved)
zra 2014/05/15 16:20:26 ditto
srdjan 2014/05/15 16:52:34 Done.
749 __ popl(EAX); // Pop return value from return slot. 731 __ popl(EAX); // Pop return value from return slot.
750 __ LeaveFrame(); 732 __ LeaveFrame();
751 __ ret(); 733 __ ret();
752 } 734 }
753 735
754 736
755 // Called when invoking dart code from C++ (VM code). 737 // Called when invoking dart code from C++ (VM code).
756 // Input parameters: 738 // Input parameters:
757 // ESP : points to return address. 739 // ESP : points to return address.
758 // ESP + 4 : entrypoint of the dart function to call. 740 // ESP + 4 : entrypoint of the dart function to call.
(...skipping 1166 matching lines...) Expand 10 before | Expand all | Expand 10 after
1925 const Register temp = ECX; 1907 const Register temp = ECX;
1926 __ movl(left, Address(ESP, 2 * kWordSize)); 1908 __ movl(left, Address(ESP, 2 * kWordSize));
1927 __ movl(right, Address(ESP, 1 * kWordSize)); 1909 __ movl(right, Address(ESP, 1 * kWordSize));
1928 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); 1910 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
1929 __ ret(); 1911 __ ret();
1930 } 1912 }
1931 1913
1932 } // namespace dart 1914 } // namespace dart
1933 1915
1934 #endif // defined TARGET_ARCH_IA32 1916 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698