| 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_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 __ lw(T2, FieldAddress(T0, Function::code_offset())); | 675 __ lw(T2, FieldAddress(T0, Function::code_offset())); |
| 676 __ lw(T2, FieldAddress(T2, Code::instructions_offset())); | 676 __ lw(T2, FieldAddress(T2, Code::instructions_offset())); |
| 677 __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag); | 677 __ AddImmediate(T2, Instructions::HeaderSize() - kHeapObjectTag); |
| 678 __ jr(T2); | 678 __ jr(T2); |
| 679 } | 679 } |
| 680 | 680 |
| 681 | 681 |
| 682 // Called for inline allocation of arrays. | 682 // Called for inline allocation of arrays. |
| 683 // Input parameters: | 683 // Input parameters: |
| 684 // RA: return address. | 684 // RA: return address. |
| 685 // A1: Array length as Smi. | 685 // A1: Array length as Smi (must be preserved). |
| 686 // A0: array element type (either NULL or an instantiated type). | 686 // A0: array element type (either NULL or an instantiated type). |
| 687 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved. | 687 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved. |
| 688 // The newly allocated object is returned in V0. | 688 // The newly allocated object is returned in V0. |
| 689 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 689 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 690 __ TraceSimMsg("AllocateArrayStub"); | 690 __ TraceSimMsg("AllocateArrayStub"); |
| 691 Label slow_case; | 691 Label slow_case; |
| 692 if (FLAG_inline_alloc) { | |
| 693 // Compute the size to be allocated, it is based on the array length | |
| 694 // and is computed as: | |
| 695 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | |
| 696 // Assert that length is a Smi. | |
| 697 __ andi(CMPRES1, A1, Immediate(kSmiTagMask)); | |
| 698 if (FLAG_use_slow_path) { | |
| 699 __ b(&slow_case); | |
| 700 } else { | |
| 701 __ bne(CMPRES1, ZR, &slow_case); | |
| 702 } | |
| 703 __ bltz(A1, &slow_case); | |
| 704 // Check for maximum allowed length. | |
| 705 const intptr_t max_len = | |
| 706 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); | |
| 707 __ BranchUnsignedGreater(A1, max_len, &slow_case); | |
| 708 | 692 |
| 709 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 693 // Compute the size to be allocated, it is based on the array length |
| 710 __ lw(T0, Address(T0, Isolate::heap_offset())); | 694 // and is computed as: |
| 711 __ lw(T0, Address(T0, Heap::new_space_offset())); | 695 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 696 __ mov(T3, A1); // Array length. |
| 712 | 697 |
| 713 // Calculate and align allocation size. | 698 // Check that length is a positive Smi. |
| 714 // Load new object start and calculate next object start. | 699 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); |
| 715 // A0: array element type. | 700 __ bne(CMPRES1, ZR, &slow_case); |
| 716 // A1: Array length as Smi. | 701 __ bltz(T3, &slow_case); |
| 717 // T0: Points to new space object. | |
| 718 __ lw(V0, Address(T0, Scavenger::top_offset())); | |
| 719 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | |
| 720 __ LoadImmediate(T3, fixed_size); | |
| 721 __ sll(TMP, A1, 1); // A1 is Smi. | |
| 722 __ addu(T3, T3, TMP); | |
| 723 ASSERT(kSmiTagShift == 1); | |
| 724 __ LoadImmediate(TMP, ~(kObjectAlignment - 1)); | |
| 725 __ and_(T3, T3, TMP); | |
| 726 | 702 |
| 727 __ AdduDetectOverflow(T2, T3, V0, CMPRES1); | 703 // Check for maximum allowed length. |
| 728 __ bltz(CMPRES1, &slow_case); // CMPRES1 < 0 on overflow. | 704 const intptr_t max_len = |
| 705 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); |
| 706 __ BranchUnsignedGreater(T3, max_len, &slow_case); |
| 729 | 707 |
| 730 // Check if the allocation fits into the remaining space. | 708 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 731 // V0: potential new object start. | 709 __ LoadImmediate(T2, fixed_size); |
| 732 // A0: array element type. | 710 __ sll(T3, T3, 1); // T3 is a Smi. |
| 733 // A1: array length as Smi. | 711 __ addu(T2, T2, T3); |
| 734 // T0: points to new space object. | 712 ASSERT(kSmiTagShift == 1); |
| 735 // T2: potential next object start. | 713 __ LoadImmediate(T3, ~(kObjectAlignment - 1)); |
| 736 // T3: array size. | 714 __ and_(T2, T2, T3); |
| 737 __ lw(CMPRES1, Address(T0, Scavenger::end_offset())); | |
| 738 __ BranchUnsignedGreaterEqual(T2, CMPRES1, &slow_case); | |
| 739 | 715 |
| 740 // Successfully allocated the object(s), now update top to point to | 716 // T2: Allocation size. |
| 741 // next object start and initialize the object. | |
| 742 // V0: potential new object start. | |
| 743 // T2: potential next object start. | |
| 744 // T0: Points to new space object. | |
| 745 __ sw(T2, Address(T0, Scavenger::top_offset())); | |
| 746 __ addiu(V0, V0, Immediate(kHeapObjectTag)); | |
| 747 // T1: Size of allocation in bytes. | |
| 748 __ subu(T1, T2, V0); | |
| 749 __ UpdateAllocationStatsWithSize(kArrayCid, T1, T5); | |
| 750 | 717 |
| 751 // V0: new object start as a tagged pointer. | 718 Isolate* isolate = Isolate::Current(); |
| 752 // A0: array element type. | 719 Heap* heap = isolate->heap(); |
| 753 // A1: Array length as Smi. | |
| 754 // T2: new object end address. | |
| 755 | 720 |
| 756 // Store the type argument field. | 721 __ LoadImmediate(T3, heap->TopAddress()); |
| 757 __ StoreIntoObjectNoBarrier( | 722 __ lw(T0, Address(T3, 0)); // Potential new object start. |
| 758 V0, | |
| 759 FieldAddress(V0, Array::type_arguments_offset()), | |
| 760 A0); | |
| 761 | 723 |
| 762 // Set the length field. | 724 __ AdduDetectOverflow(T1, T0, T2, CMPRES1); // Potential next object start. |
| 763 __ StoreIntoObjectNoBarrier( | 725 __ bltz(CMPRES1, &slow_case); // CMPRES1 < 0 on overflow. |
| 764 V0, | |
| 765 FieldAddress(V0, Array::length_offset()), | |
| 766 A1); | |
| 767 | 726 |
| 768 // Calculate the size tag. | 727 // Check if the allocation fits into the remaining space. |
| 769 // V0: new object start as a tagged pointer. | 728 // T0: potential new object start. |
| 770 // A1: Array length as Smi. | 729 // T1: potential next object start. |
| 771 // T2: new object end address. | 730 // T2: allocation size. |
| 772 // T3: array size. | 731 __ LoadImmediate(T4, heap->EndAddress()); |
| 732 __ lw(T4, Address(T4, 0)); |
| 733 __ BranchUnsignedGreaterEqual(T1, T4, &slow_case); |
| 734 |
| 735 // Successfully allocated the object(s), now update top to point to |
| 736 // next object start and initialize the object. |
| 737 __ sw(T1, Address(T3, 0)); |
| 738 __ addiu(T0, T0, Immediate(kHeapObjectTag)); |
| 739 __ UpdateAllocationStatsWithSize(kArrayCid, T2, T4); |
| 740 |
| 741 // Initialize the tags. |
| 742 // T0: new object start as a tagged pointer. |
| 743 // T1: new object end address. |
| 744 // T2: allocation size. |
| 745 { |
| 746 Label overflow, done; |
| 773 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 747 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 774 // If no size tag overflow, shift T3 left, else set T3 to zero. | 748 const Class& cls = Class::Handle(isolate->object_store()->array_class()); |
| 775 __ LoadImmediate(T4, RawObject::SizeTag::kMaxSizeTag); | 749 |
| 776 __ sltu(CMPRES1, T4, T3); // CMPRES1 = T4 < T3 ? 1 : 0 | 750 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); |
| 777 __ sll(TMP, T3, shift); // TMP = T3 << shift; | 751 __ b(&done); |
| 778 __ movz(T3, TMP, CMPRES1); // T3 = T4 >= T3 ? 0 : T3 | 752 __ delay_slot()->sll(T2, T2, shift); |
| 779 __ movn(T3, ZR, CMPRES1); // T3 = T4 < T3 ? TMP : T3 | 753 __ Bind(&overflow); |
| 754 __ mov(T2, ZR); |
| 755 __ Bind(&done); |
| 780 | 756 |
| 781 // Get the class index and insert it into the tags. | 757 // Get the class index and insert it into the tags. |
| 782 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(kArrayCid)); | 758 // T2: size and bit tags. |
| 783 __ or_(T3, T3, TMP); | 759 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id())); |
| 784 __ sw(T3, FieldAddress(V0, Array::tags_offset())); | 760 __ or_(T2, T2, TMP); |
| 761 __ sw(T2, FieldAddress(T0, Array::tags_offset())); // Store tags. |
| 762 } |
| 785 | 763 |
| 786 // Initialize all array elements to raw_null. | 764 // T0: new object start as a tagged pointer. |
| 787 // V0: new object start as a tagged pointer. | 765 // T1: new object end address. |
| 788 // T2: new object end address. | 766 // Store the type argument field. |
| 789 // A1: Array length as Smi. | 767 __ StoreIntoObjectNoBarrier(T0, |
| 790 __ AddImmediate(T3, V0, Array::data_offset() - kHeapObjectTag); | 768 FieldAddress(T0, Array::type_arguments_offset()), |
| 791 // T3: iterator which initially points to the start of the variable | 769 A0); |
| 792 // data area to be initialized. | |
| 793 | 770 |
| 794 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null())); | 771 // Set the length field. |
| 795 Label loop, loop_exit; | 772 __ StoreIntoObjectNoBarrier(T0, |
| 796 __ BranchUnsignedGreaterEqual(T3, T2, &loop_exit); | 773 FieldAddress(T0, Array::length_offset()), |
| 797 __ Bind(&loop); | 774 A1); |
| 798 __ addiu(T3, T3, Immediate(kWordSize)); | |
| 799 __ bne(T3, T2, &loop); | |
| 800 __ delay_slot()->sw(T7, Address(T3, -kWordSize)); | |
| 801 __ Bind(&loop_exit); | |
| 802 | 775 |
| 803 // Done allocating and initializing the array. | 776 __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null())); |
| 804 // V0: new object. | 777 // Initialize all array elements to raw_null. |
| 805 // A1: Array length as Smi (preserved for the caller.) | 778 // T0: new object start as a tagged pointer. |
| 806 __ Ret(); | 779 // T1: new object end address. |
| 807 } | 780 // T2: iterator which initially points to the start of the variable |
| 781 // data area to be initialized. |
| 782 // T7: null. |
| 783 __ AddImmediate(T2, T0, sizeof(RawArray) - kHeapObjectTag); |
| 784 |
| 785 Label done; |
| 786 Label init_loop; |
| 787 __ Bind(&init_loop); |
| 788 __ BranchUnsignedGreaterEqual(T2, T1, &done); |
| 789 __ sw(T7, Address(T2, 0)); |
| 790 __ b(&init_loop); |
| 791 __ delay_slot()->addiu(T2, T2, Immediate(kWordSize)); |
| 792 __ Bind(&done); |
| 793 |
| 794 __ Ret(); // Returns the newly allocated object in V0. |
| 795 __ delay_slot()->mov(V0, T0); |
| 808 | 796 |
| 809 // Unable to allocate the array using the fast inline code, just call | 797 // Unable to allocate the array using the fast inline code, just call |
| 810 // into the runtime. | 798 // into the runtime. |
| 811 __ Bind(&slow_case); | 799 __ Bind(&slow_case); |
| 812 // Create a stub frame as we are pushing some objects on the stack before | 800 // Create a stub frame as we are pushing some objects on the stack before |
| 813 // calling into the runtime. | 801 // calling into the runtime. |
| 814 __ EnterStubFrame(); | 802 __ EnterStubFrame(); |
| 815 // Setup space on stack for return value. | 803 // Setup space on stack for return value. |
| 816 // Push array length as Smi and element type. | 804 // Push array length as Smi and element type. |
| 817 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 805 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| (...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2103 const Register right = T0; | 2091 const Register right = T0; |
| 2104 __ lw(left, Address(SP, 1 * kWordSize)); | 2092 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2105 __ lw(right, Address(SP, 0 * kWordSize)); | 2093 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2106 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2094 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2107 __ Ret(); | 2095 __ Ret(); |
| 2108 } | 2096 } |
| 2109 | 2097 |
| 2110 } // namespace dart | 2098 } // namespace dart |
| 2111 | 2099 |
| 2112 #endif // defined TARGET_ARCH_MIPS | 2100 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |