| OLD | NEW |
| 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 Loading... |
| 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). |
| 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). |
| 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 Loading... |
| 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 |
| OLD | NEW |