| 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 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved. | 263 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved. |
| 264 // The newly allocated object is returned in V0. | 264 // The newly allocated object is returned in V0. |
| 265 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 265 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 266 __ TraceSimMsg("AllocateArrayStub"); | 266 __ TraceSimMsg("AllocateArrayStub"); |
| 267 Label slow_case; | 267 Label slow_case; |
| 268 if (FLAG_inline_alloc) { | 268 if (FLAG_inline_alloc) { |
| 269 // Compute the size to be allocated, it is based on the array length | 269 // Compute the size to be allocated, it is based on the array length |
| 270 // and is computed as: | 270 // and is computed as: |
| 271 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 271 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 272 // Assert that length is a Smi. | 272 // Assert that length is a Smi. |
| 273 __ andi(CMPRES, A1, Immediate(kSmiTagMask)); |
| 273 if (FLAG_use_slow_path) { | 274 if (FLAG_use_slow_path) { |
| 274 __ b(&slow_case); | 275 __ b(&slow_case); |
| 275 } else { | 276 } else { |
| 276 __ andi(CMPRES, A1, Immediate(kSmiTagMask)); | |
| 277 __ bne(CMPRES, ZR, &slow_case); | 277 __ bne(CMPRES, ZR, &slow_case); |
| 278 } | 278 } |
| 279 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 279 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
| 280 __ lw(T0, Address(T0, Isolate::heap_offset())); | 280 __ lw(T0, Address(T0, Isolate::heap_offset())); |
| 281 __ lw(T0, Address(T0, Heap::new_space_offset())); | 281 __ lw(T0, Address(T0, Heap::new_space_offset())); |
| 282 | 282 |
| 283 // Calculate and align allocation size. | 283 // Calculate and align allocation size. |
| 284 // Load new object start and calculate next object start. | 284 // Load new object start and calculate next object start. |
| 285 // A0: array element type. | 285 // A0: array element type. |
| 286 // A1: Array length as Smi. | 286 // A1: Array length as Smi. |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 // Stack: | 527 // Stack: |
| 528 // TOS + 0: Argument array. | 528 // TOS + 0: Argument array. |
| 529 // TOS + 1: Arguments descriptor array. | 529 // TOS + 1: Arguments descriptor array. |
| 530 // TOS + 2: Place for result from the call. | 530 // TOS + 2: Place for result from the call. |
| 531 // TOS + 3: Saved FP of previous frame. | 531 // TOS + 3: Saved FP of previous frame. |
| 532 // TOS + 4: Dart code return address | 532 // TOS + 4: Dart code return address |
| 533 // TOS + 5: PC marker (0 for stub). | 533 // TOS + 5: PC marker (0 for stub). |
| 534 // TOS + 6: Last argument of caller. | 534 // TOS + 6: Last argument of caller. |
| 535 // .... | 535 // .... |
| 536 __ CallRuntime(kInvokeNonClosureRuntimeEntry); | 536 __ CallRuntime(kInvokeNonClosureRuntimeEntry); |
| 537 // Remove arguments. | 537 __ lw(V0, Address(SP, 2 * kWordSize)); // Get result into V0. |
| 538 __ Drop(2); | 538 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Remove arguments. |
| 539 __ Pop(V0); // Get result into R0. | |
| 540 | 539 |
| 541 // Remove the stub frame as we are about to return. | 540 // Remove the stub frame as we are about to return. |
| 542 __ LeaveStubFrame(); | 541 __ LeaveStubFrame(); |
| 543 __ Ret(); | 542 __ Ret(); |
| 544 } | 543 } |
| 545 | 544 |
| 546 | 545 |
| 547 // Called when invoking Dart code from C++ (VM code). | 546 // Called when invoking Dart code from C++ (VM code). |
| 548 // Input parameters: | 547 // Input parameters: |
| 549 // RA : points to return address. | 548 // RA : points to return address. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 } | 654 } |
| 656 __ lw(A3, Address(SP)); | 655 __ lw(A3, Address(SP)); |
| 657 __ addiu(SP, SP, Immediate((3 + kAbiPreservedCpuRegCount) * kWordSize)); | 656 __ addiu(SP, SP, Immediate((3 + kAbiPreservedCpuRegCount) * kWordSize)); |
| 658 | 657 |
| 659 // Restore the frame pointer and return. | 658 // Restore the frame pointer and return. |
| 660 __ LeaveStubFrame(); | 659 __ LeaveStubFrame(); |
| 661 __ Ret(); | 660 __ Ret(); |
| 662 } | 661 } |
| 663 | 662 |
| 664 | 663 |
| 664 // Called for inline allocation of contexts. |
| 665 // Input: |
| 666 // T1: number of context variables. |
| 667 // Output: |
| 668 // V0: new allocated RawContext object. |
| 665 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 669 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 666 __ Unimplemented("AllocateContext stub"); | 670 if (FLAG_inline_alloc) { |
| 671 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 672 Label slow_case; |
| 673 Heap* heap = Isolate::Current()->heap(); |
| 674 // First compute the rounded instance size. |
| 675 // T1: number of context variables. |
| 676 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; |
| 677 __ LoadImmediate(T2, fixed_size); |
| 678 __ sll(T0, T1, 2); |
| 679 __ addu(T2, T2, T0); |
| 680 ASSERT(kSmiTagShift == 1); |
| 681 __ LoadImmediate(T0, ~((kObjectAlignment) - 1)); |
| 682 __ and_(T2, T2, T0); |
| 683 |
| 684 // Now allocate the object. |
| 685 // T1: number of context variables. |
| 686 // T2: object size. |
| 687 __ LoadImmediate(T5, heap->TopAddress()); |
| 688 __ lw(V0, Address(T5, 0)); |
| 689 __ addu(T3, T2, V0); |
| 690 |
| 691 // Check if the allocation fits into the remaining space. |
| 692 // V0: potential new object. |
| 693 // T1: number of context variables. |
| 694 // T2: object size. |
| 695 // T3: potential next object start. |
| 696 __ LoadImmediate(TMP1, heap->EndAddress()); |
| 697 __ lw(TMP1, Address(TMP1, 0)); |
| 698 if (FLAG_use_slow_path) { |
| 699 __ b(&slow_case); |
| 700 } else { |
| 701 __ BranchGreaterEqual(T3, TMP1, &slow_case); |
| 702 } |
| 703 |
| 704 // Successfully allocated the object, now update top to point to |
| 705 // next object start and initialize the object. |
| 706 // V0: new object. |
| 707 // T1: number of context variables. |
| 708 // T2: object size. |
| 709 // T3: next object start. |
| 710 __ sw(T3, Address(T5, 0)); |
| 711 __ addiu(V0, V0, Immediate(kHeapObjectTag)); |
| 712 |
| 713 // Calculate the size tag. |
| 714 // V0: new object. |
| 715 // T1: number of context variables. |
| 716 // T2: object size. |
| 717 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; |
| 718 __ LoadImmediate(TMP1, RawObject::SizeTag::kMaxSizeTag); |
| 719 __ sltu(CMPRES, TMP1, T2); // CMPRES = T2 > TMP1 ? 1 : 0. |
| 720 __ movn(T2, ZR, CMPRES); // T2 = CMPRES != 0 ? 0 : T2. |
| 721 __ sll(TMP1, T2, shift); // TMP2 = T2 << shift. |
| 722 __ movz(T2, TMP1, CMPRES); // T2 = CMPRES == 0 ? TMP1 : T2. |
| 723 |
| 724 // Get the class index and insert it into the tags. |
| 725 // T2: size and bit tags. |
| 726 __ LoadImmediate(TMP1, RawObject::ClassIdTag::encode(context_class.id())); |
| 727 __ or_(T2, T2, TMP1); |
| 728 __ sw(T2, FieldAddress(V0, Context::tags_offset())); |
| 729 |
| 730 // Setup up number of context variables field. |
| 731 // V0: new object. |
| 732 // T1: number of context variables as integer value (not object). |
| 733 __ sw(T1, FieldAddress(V0, Context::num_variables_offset())); |
| 734 |
| 735 // Setup isolate field. |
| 736 // Load Isolate pointer from Context structure into R2. |
| 737 // V0: new object. |
| 738 // T1: number of context variables. |
| 739 __ lw(T2, FieldAddress(CTX, Context::isolate_offset())); |
| 740 // T2: isolate, not an object. |
| 741 __ sw(T2, FieldAddress(V0, Context::isolate_offset())); |
| 742 |
| 743 // Setup the parent field. |
| 744 // V0: new object. |
| 745 // T1: number of context variables. |
| 746 __ LoadImmediate(T2, reinterpret_cast<intptr_t>(Object::null())); |
| 747 __ sw(T2, FieldAddress(V0, Context::parent_offset())); |
| 748 |
| 749 // Initialize the context variables. |
| 750 // V0: new object. |
| 751 // T1: number of context variables. |
| 752 // T2: raw null. |
| 753 Label loop, loop_test; |
| 754 __ AddImmediate(T3, V0, Context::variable_offset(0) - kHeapObjectTag); |
| 755 __ b(&loop_test); |
| 756 __ delay_slot()->sll(T1, T1, 2); |
| 757 __ Bind(&loop); |
| 758 __ addu(TMP1, T3, T1); |
| 759 __ sw(T2, Address(TMP1)); |
| 760 __ Bind(&loop_test); |
| 761 __ addiu(T1, T1, Immediate(-kWordSize)); |
| 762 __ bne(T1, ZR, &loop); // Loop if R1 not zero. |
| 763 |
| 764 // Done allocating and initializing the context. |
| 765 // V0: new object. |
| 766 __ Ret(); |
| 767 |
| 768 __ Bind(&slow_case); |
| 769 } |
| 770 // Create a stub frame as we are pushing some objects on the stack before |
| 771 // calling into the runtime. |
| 772 __ EnterStubFrame(); |
| 773 // Setup space on stack for return value. |
| 774 __ LoadImmediate(T2, reinterpret_cast<intptr_t>(Object::null())); |
| 775 __ SmiTag(T1); |
| 776 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 777 __ sw(T2, Address(SP, 1 * kWordSize)); |
| 778 __ sw(T1, Address(SP, 0 * kWordSize)); |
| 779 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context. |
| 780 __ lw(V0, Address(SP, 1 * kWordSize)); // Get the new context. |
| 781 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Pop argument and return. |
| 782 |
| 783 // V0: new object |
| 784 // Restore the frame pointer. |
| 785 __ LeaveStubFrame(); |
| 786 __ Ret(); |
| 667 } | 787 } |
| 668 | 788 |
| 669 | 789 |
| 670 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); | 790 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); |
| 671 | 791 |
| 672 | 792 |
| 673 // Helper stub to implement Assembler::StoreIntoObject. | 793 // Helper stub to implement Assembler::StoreIntoObject. |
| 674 // Input parameters: | 794 // Input parameters: |
| 675 // T0: Address (i.e. object) being stored into. | 795 // T0: Address (i.e. object) being stored into. |
| 676 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { | 796 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 &no_instantiator); | 880 &no_instantiator); |
| 761 __ delay_slot()->mov(T4, T3); | 881 __ delay_slot()->mov(T4, T3); |
| 762 __ AddImmediate(T3, type_args_size); | 882 __ AddImmediate(T3, type_args_size); |
| 763 __ Bind(&no_instantiator); | 883 __ Bind(&no_instantiator); |
| 764 // T4: potential new object end and, if T4 != T3, potential new | 884 // T4: potential new object end and, if T4 != T3, potential new |
| 765 // InstantiatedTypeArguments object start. | 885 // InstantiatedTypeArguments object start. |
| 766 } | 886 } |
| 767 // Check if the allocation fits into the remaining space. | 887 // Check if the allocation fits into the remaining space. |
| 768 // T2: potential new object start. | 888 // T2: potential new object start. |
| 769 // T3: potential next object start. | 889 // T3: potential next object start. |
| 890 __ LoadImmediate(TMP1, heap->EndAddress()); |
| 891 __ lw(TMP1, Address(TMP1)); |
| 770 if (FLAG_use_slow_path) { | 892 if (FLAG_use_slow_path) { |
| 771 __ b(&slow_case); | 893 __ b(&slow_case); |
| 772 } else { | 894 } else { |
| 773 __ LoadImmediate(TMP1, heap->EndAddress()); | |
| 774 __ lw(TMP1, Address(TMP1)); | |
| 775 __ BranchGreaterEqual(T3, TMP1, &slow_case); | 895 __ BranchGreaterEqual(T3, TMP1, &slow_case); |
| 776 } | 896 } |
| 777 | 897 |
| 778 // Successfully allocated the object(s), now update top to point to | 898 // Successfully allocated the object(s), now update top to point to |
| 779 // next object start and initialize the object. | 899 // next object start and initialize the object. |
| 780 __ sw(T3, Address(T5)); | 900 __ sw(T3, Address(T5)); |
| 781 | 901 |
| 782 if (is_cls_parameterized) { | 902 if (is_cls_parameterized) { |
| 783 // Initialize the type arguments field in the object. | 903 // Initialize the type arguments field in the object. |
| 784 // T2: new object start. | 904 // T2: new object start. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 __ Bind(&slow_case); | 987 __ Bind(&slow_case); |
| 868 } | 988 } |
| 869 if (is_cls_parameterized) { | 989 if (is_cls_parameterized) { |
| 870 __ lw(T1, Address(SP, 1 * kWordSize)); | 990 __ lw(T1, Address(SP, 1 * kWordSize)); |
| 871 __ lw(T0, Address(SP, 0 * kWordSize)); | 991 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 872 } | 992 } |
| 873 // Create a stub frame as we are pushing some objects on the stack before | 993 // Create a stub frame as we are pushing some objects on the stack before |
| 874 // calling into the runtime. | 994 // calling into the runtime. |
| 875 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. | 995 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. |
| 876 __ LoadImmediate(T2, reinterpret_cast<intptr_t>(Object::null())); | 996 __ LoadImmediate(T2, reinterpret_cast<intptr_t>(Object::null())); |
| 877 __ Push(T2); // Setup space on stack for return value. | 997 __ LoadObject(TMP1, cls); |
| 878 __ PushObject(cls); // Push class of object to be allocated. | 998 |
| 999 __ addiu(SP, SP, Immediate(-4 * kWordSize)); |
| 1000 __ sw(T2, Address(SP, 3 * kWordSize)); // Space on stack for return value. |
| 1001 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Class of object to be allocated. |
| 1002 |
| 879 if (is_cls_parameterized) { | 1003 if (is_cls_parameterized) { |
| 880 // Push type arguments of object to be allocated and of instantiator. | 1004 // Push type arguments of object to be allocated and of instantiator. |
| 881 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | |
| 882 __ sw(T1, Address(SP, 1 * kWordSize)); | 1005 __ sw(T1, Address(SP, 1 * kWordSize)); |
| 883 __ sw(T0, Address(SP, 0 * kWordSize)); | 1006 __ sw(T0, Address(SP, 0 * kWordSize)); |
| 884 } else { | 1007 } else { |
| 885 // Push null type arguments and kNoInstantiator. | 1008 // Push null type arguments and kNoInstantiator. |
| 886 __ LoadImmediate(T1, Smi::RawValue(StubCode::kNoInstantiator)); | 1009 __ LoadImmediate(T1, Smi::RawValue(StubCode::kNoInstantiator)); |
| 887 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | |
| 888 __ sw(T2, Address(SP, 1 * kWordSize)); | 1010 __ sw(T2, Address(SP, 1 * kWordSize)); |
| 889 __ sw(T1, Address(SP, 0 * kWordSize)); | 1011 __ sw(T1, Address(SP, 0 * kWordSize)); |
| 890 } | 1012 } |
| 891 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. | 1013 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. |
| 892 __ TraceSimMsg("AllocationStubForClass return"); | 1014 __ TraceSimMsg("AllocationStubForClass return"); |
| 893 __ Drop(3); // Pop arguments. | 1015 // Pop result (newly allocated object). |
| 894 __ Pop(V0); // Pop result (newly allocated object). | 1016 __ lw(V0, Address(SP, 3 * kWordSize)); |
| 1017 __ addiu(SP, SP, Immediate(4 * kWordSize)); // Pop arguments. |
| 895 // V0: new object | 1018 // V0: new object |
| 896 // Restore the frame pointer. | 1019 // Restore the frame pointer. |
| 897 __ LeaveStubFrame(true); | 1020 __ LeaveStubFrame(true); |
| 898 __ Ret(); | 1021 __ Ret(); |
| 899 } | 1022 } |
| 900 | 1023 |
| 901 | 1024 |
| 902 // Called for inline allocation of closures. | 1025 // Called for inline allocation of closures. |
| 903 // Input parameters: | 1026 // Input parameters: |
| 904 // RA: return address. | 1027 // RA: return address. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 928 __ lw(T2, Address(T5)); | 1051 __ lw(T2, Address(T5)); |
| 929 __ AddImmediate(T3, T2, closure_size); | 1052 __ AddImmediate(T3, T2, closure_size); |
| 930 if (is_implicit_instance_closure) { | 1053 if (is_implicit_instance_closure) { |
| 931 __ mov(T4, T3); // T4: new context address. | 1054 __ mov(T4, T3); // T4: new context address. |
| 932 __ AddImmediate(T3, context_size); | 1055 __ AddImmediate(T3, context_size); |
| 933 } | 1056 } |
| 934 // Check if the allocation fits into the remaining space. | 1057 // Check if the allocation fits into the remaining space. |
| 935 // T2: potential new closure object. | 1058 // T2: potential new closure object. |
| 936 // T3: address of top of heap. | 1059 // T3: address of top of heap. |
| 937 // T4: potential new context object (only if is_implicit_closure). | 1060 // T4: potential new context object (only if is_implicit_closure). |
| 1061 __ LoadImmediate(TMP1, heap->EndAddress()); |
| 1062 __ lw(TMP1, Address(TMP1)); |
| 938 if (FLAG_use_slow_path) { | 1063 if (FLAG_use_slow_path) { |
| 939 __ b(&slow_case); | 1064 __ b(&slow_case); |
| 940 } else { | 1065 } else { |
| 941 __ LoadImmediate(TMP1, heap->EndAddress()); | |
| 942 __ lw(TMP1, Address(TMP1)); | |
| 943 __ BranchGreaterEqual(T3, TMP1, &slow_case); | 1066 __ BranchGreaterEqual(T3, TMP1, &slow_case); |
| 944 } | 1067 } |
| 945 | 1068 |
| 946 // Successfully allocated the object, now update top to point to | 1069 // Successfully allocated the object, now update top to point to |
| 947 // next object start and initialize the object. | 1070 // next object start and initialize the object. |
| 948 __ sw(T3, Address(T5)); | 1071 __ sw(T3, Address(T5)); |
| 949 | 1072 |
| 950 // T2: new closure object. | 1073 // T2: new closure object. |
| 951 // T4: new context object (only if is_implicit_closure). | 1074 // T4: new context object (only if is_implicit_closure). |
| 952 // Set the tags. | 1075 // Set the tags. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 | 1132 |
| 1010 // Done allocating and initializing the instance. | 1133 // Done allocating and initializing the instance. |
| 1011 // V0: new object. | 1134 // V0: new object. |
| 1012 __ addiu(V0, T2, Immediate(kHeapObjectTag)); | 1135 __ addiu(V0, T2, Immediate(kHeapObjectTag)); |
| 1013 __ LeaveStubFrame(true); | 1136 __ LeaveStubFrame(true); |
| 1014 __ Ret(); | 1137 __ Ret(); |
| 1015 | 1138 |
| 1016 __ Bind(&slow_case); | 1139 __ Bind(&slow_case); |
| 1017 } | 1140 } |
| 1018 | 1141 |
| 1142 // If it's an implicit static closure we need 2 stack slots. Otherwise, |
| 1143 // If it's an implicit instance closure we need 4 stack slots, o/w only 3. |
| 1144 int num_slots = 2; |
| 1145 if (!is_implicit_static_closure) { |
| 1146 num_slots = is_implicit_instance_closure ? 4 : 3; |
| 1147 } |
| 1148 __ addiu(SP, SP, Immediate(-num_slots * kWordSize)); |
| 1019 __ LoadImmediate(V0, reinterpret_cast<intptr_t>(Object::null())); | 1149 __ LoadImmediate(V0, reinterpret_cast<intptr_t>(Object::null())); |
| 1020 __ Push(V0); // Setup space on stack for return value. | 1150 __ LoadObject(TMP1, func); |
| 1021 __ PushObject(func); | 1151 // Setup space on stack for return value. |
| 1152 __ sw(V0, Address(SP, (num_slots - 1) * kWordSize)); |
| 1153 __ sw(TMP1, Address(SP, (num_slots - 2) * kWordSize)); |
| 1022 if (is_implicit_static_closure) { | 1154 if (is_implicit_static_closure) { |
| 1023 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry); | 1155 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry); |
| 1024 __ TraceSimMsg("AllocationStubForClosure return"); | 1156 __ TraceSimMsg("AllocationStubForClosure return"); |
| 1025 } else { | 1157 } else { |
| 1026 if (is_implicit_instance_closure) { | 1158 if (is_implicit_instance_closure) { |
| 1027 __ lw(T1, Address(FP, kReceiverFPOffset)); | 1159 __ lw(T1, Address(FP, kReceiverFPOffset)); |
| 1028 __ Push(T1); // Receiver. | 1160 __ sw(T1, Address(SP, (num_slots - 3) * kWordSize)); // Receiver. |
| 1161 __ sw(V0, Address(SP, (num_slots - 4) * kWordSize)); // Push null. |
| 1029 } | 1162 } |
| 1030 if (has_type_arguments) { | 1163 if (has_type_arguments) { |
| 1031 __ lw(V0, Address(FP, kTypeArgumentsFPOffset)); | 1164 __ lw(V0, Address(FP, kTypeArgumentsFPOffset)); |
| 1165 // Push type arguments of closure. |
| 1166 __ sw(V0, Address(SP, (num_slots - 3) * kWordSize)); |
| 1032 } | 1167 } |
| 1033 __ Push(V0); // Push type arguments of closure to be allocated or null. | |
| 1034 | 1168 |
| 1035 if (is_implicit_instance_closure) { | 1169 if (is_implicit_instance_closure) { |
| 1036 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry); | 1170 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry); |
| 1037 __ TraceSimMsg("AllocationStubForClosure return"); | 1171 __ TraceSimMsg("AllocationStubForClosure return"); |
| 1038 __ Drop(2); | |
| 1039 } else { | 1172 } else { |
| 1040 ASSERT(func.IsNonImplicitClosureFunction()); | 1173 ASSERT(func.IsNonImplicitClosureFunction()); |
| 1041 __ CallRuntime(kAllocateClosureRuntimeEntry); | 1174 __ CallRuntime(kAllocateClosureRuntimeEntry); |
| 1042 __ TraceSimMsg("AllocationStubForClosure return"); | 1175 __ TraceSimMsg("AllocationStubForClosure return"); |
| 1043 __ Drop(1); // Pop argument (type arguments of object). | |
| 1044 } | 1176 } |
| 1045 } | 1177 } |
| 1046 __ Drop(1); // Pop function object. | 1178 __ lw(V0, Address(SP, (num_slots - 1) * kWordSize)); // Pop function object. |
| 1047 __ Pop(V0); | 1179 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); |
| 1180 |
| 1048 // V0: new object | 1181 // V0: new object |
| 1049 // Restore the frame pointer. | 1182 // Restore the frame pointer. |
| 1050 __ LeaveStubFrame(true); | 1183 __ LeaveStubFrame(true); |
| 1051 __ Ret(); | 1184 __ Ret(); |
| 1052 } | 1185 } |
| 1053 | 1186 |
| 1054 | 1187 |
| 1055 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1188 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1056 __ Unimplemented("CallNoSuchMethodFunction stub"); | 1189 __ Unimplemented("CallNoSuchMethodFunction stub"); |
| 1057 } | 1190 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1187 // T1: argument_count - 1 (smi). | 1320 // T1: argument_count - 1 (smi). |
| 1188 __ sll(T1, T1, 1); // T1 is Smi. | 1321 __ sll(T1, T1, 1); // T1 is Smi. |
| 1189 __ addu(T1, SP, T1); | 1322 __ addu(T1, SP, T1); |
| 1190 // T1: address of receiver. | 1323 // T1: address of receiver. |
| 1191 // Create a stub frame as we are pushing some objects on the stack before | 1324 // Create a stub frame as we are pushing some objects on the stack before |
| 1192 // calling into the runtime. | 1325 // calling into the runtime. |
| 1193 __ EnterStubFrame(); | 1326 __ EnterStubFrame(); |
| 1194 __ LoadImmediate(T3, reinterpret_cast<intptr_t>(Object::null())); | 1327 __ LoadImmediate(T3, reinterpret_cast<intptr_t>(Object::null())); |
| 1195 // Preserve IC data object and arguments descriptor array and | 1328 // Preserve IC data object and arguments descriptor array and |
| 1196 // setup space on stack for result (target code object). | 1329 // setup space on stack for result (target code object). |
| 1197 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1330 int num_slots = num_args + 5; |
| 1198 __ sw(S5, Address(SP, 2 * kWordSize)); | 1331 __ addiu(SP, SP, Immediate(-num_slots * kWordSize)); |
| 1199 __ sw(S4, Address(SP, 1 * kWordSize)); | 1332 __ sw(S5, Address(SP, (num_slots - 1) * kWordSize)); |
| 1200 __ sw(T3, Address(SP, 0 * kWordSize)); | 1333 __ sw(S4, Address(SP, (num_slots - 2) * kWordSize)); |
| 1334 __ sw(T3, Address(SP, (num_slots - 3) * kWordSize)); |
| 1201 // Push call arguments. | 1335 // Push call arguments. |
| 1202 for (intptr_t i = 0; i < num_args; i++) { | 1336 for (intptr_t i = 0; i < num_args; i++) { |
| 1203 __ lw(TMP, Address(T1, -i * kWordSize)); | 1337 __ lw(TMP1, Address(T1, -i * kWordSize)); |
| 1204 __ Push(TMP); | 1338 __ sw(TMP1, Address(SP, (num_slots - i - 4) * kWordSize)); |
| 1205 } | 1339 } |
| 1206 // Pass IC data object and arguments descriptor array. | 1340 // Pass IC data object and arguments descriptor array. |
| 1207 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1341 __ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize)); |
| 1208 __ sw(S5, Address(SP, 1 * kWordSize)); | 1342 __ sw(S4, Address(SP, (num_slots - num_args - 5) * kWordSize)); |
| 1209 __ sw(S4, Address(SP, 0 * kWordSize)); | |
| 1210 | 1343 |
| 1211 if (num_args == 1) { | 1344 if (num_args == 1) { |
| 1212 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); | 1345 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1213 } else if (num_args == 2) { | 1346 } else if (num_args == 2) { |
| 1214 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); | 1347 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| 1215 } else if (num_args == 3) { | 1348 } else if (num_args == 3) { |
| 1216 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); | 1349 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); |
| 1217 } else { | 1350 } else { |
| 1218 UNIMPLEMENTED(); | 1351 UNIMPLEMENTED(); |
| 1219 } | 1352 } |
| 1220 __ TraceSimMsg("NArgsCheckInlineCacheStub return"); | 1353 __ TraceSimMsg("NArgsCheckInlineCacheStub return"); |
| 1354 // Pop returned code object into T3 (null if not found). |
| 1355 // Restore arguments descriptor array and IC data array. |
| 1356 __ lw(T3, Address(SP, (num_slots - 3) * kWordSize)); |
| 1357 __ lw(S4, Address(SP, (num_slots - 2) * kWordSize)); |
| 1358 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize)); |
| 1221 // Remove the call arguments pushed earlier, including the IC data object | 1359 // Remove the call arguments pushed earlier, including the IC data object |
| 1222 // and the arguments descriptor array. | 1360 // and the arguments descriptor array. |
| 1223 __ Drop(num_args + 2); | 1361 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); |
| 1224 // Pop returned code object into T3 (null if not found). | |
| 1225 // Restore arguments descriptor array and IC data array. | |
| 1226 __ lw(T3, Address(SP, 0 * kWordSize)); | |
| 1227 __ lw(S4, Address(SP, 1 * kWordSize)); | |
| 1228 __ lw(S5, Address(SP, 2 * kWordSize)); | |
| 1229 __ addiu(SP, SP, Immediate(3 * kWordSize)); | |
| 1230 __ LeaveStubFrame(); | 1362 __ LeaveStubFrame(); |
| 1231 Label call_target_function; | 1363 Label call_target_function; |
| 1232 __ BranchNotEqual(T3, reinterpret_cast<intptr_t>(Object::null()), | 1364 __ BranchNotEqual(T3, reinterpret_cast<intptr_t>(Object::null()), |
| 1233 &call_target_function); | 1365 &call_target_function); |
| 1234 // NoSuchMethod or closure. | 1366 // NoSuchMethod or closure. |
| 1235 // Mark IC call that it may be a closure call that does not collect | 1367 // Mark IC call that it may be a closure call that does not collect |
| 1236 // type feedback. | 1368 // type feedback. |
| 1237 __ LoadImmediate(TMP2, 1); | 1369 __ LoadImmediate(TMP2, 1); |
| 1238 __ Branch(&StubCode::InstanceFunctionLookupLabel()); | 1370 __ Branch(&StubCode::InstanceFunctionLookupLabel()); |
| 1239 __ delay_slot()->sb(TMP2, FieldAddress(S5, ICData::is_closure_call_offset())); | 1371 __ delay_slot()->sb(TMP2, FieldAddress(S5, ICData::is_closure_call_offset())); |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1597 __ Bind(&done); | 1729 __ Bind(&done); |
| 1598 __ lw(T0, Address(SP, 0 * kWordSize)); | 1730 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 1599 __ lw(T1, Address(SP, 1 * kWordSize)); | 1731 __ lw(T1, Address(SP, 1 * kWordSize)); |
| 1600 __ Ret(); | 1732 __ Ret(); |
| 1601 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); | 1733 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); |
| 1602 } | 1734 } |
| 1603 | 1735 |
| 1604 } // namespace dart | 1736 } // namespace dart |
| 1605 | 1737 |
| 1606 #endif // defined TARGET_ARCH_MIPS | 1738 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |