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

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

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month 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
« no previous file with comments | « runtime/vm/stub_code_ia32_test.cc ('k') | runtime/vm/stub_code_mips_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_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"
11 #include "vm/dart_entry.h" 11 #include "vm/dart_entry.h"
12 #include "vm/flow_graph_compiler.h" 12 #include "vm/flow_graph_compiler.h"
13 #include "vm/heap.h" 13 #include "vm/heap.h"
14 #include "vm/instructions.h" 14 #include "vm/instructions.h"
15 #include "vm/object_store.h" 15 #include "vm/object_store.h"
16 #include "vm/stack_frame.h" 16 #include "vm/stack_frame.h"
17 #include "vm/stub_code.h" 17 #include "vm/stub_code.h"
18 #include "vm/tags.h" 18 #include "vm/tags.h"
19 19
20 #define __ assembler-> 20 #define __ assembler->
21 21
22 namespace dart { 22 namespace dart {
23 23
24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); 24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
25 DEFINE_FLAG(bool, use_slow_path, false, 25 DEFINE_FLAG(bool,
26 "Set to true for debugging & verifying the slow paths."); 26 use_slow_path,
27 false,
28 "Set to true for debugging & verifying the slow paths.");
27 DECLARE_FLAG(bool, trace_optimized_ic_calls); 29 DECLARE_FLAG(bool, trace_optimized_ic_calls);
28 30
29 // Input parameters: 31 // Input parameters:
30 // RA : return address. 32 // RA : return address.
31 // SP : address of last argument in argument array. 33 // SP : address of last argument in argument array.
32 // SP + 4*S4 - 4 : address of first argument in argument array. 34 // SP + 4*S4 - 4 : address of first argument in argument array.
33 // SP + 4*S4 : address of return value. 35 // SP + 4*S4 : address of return value.
34 // S5 : address of the runtime function to call. 36 // S5 : address of the runtime function to call.
35 // S4 : number of arguments to the call. 37 // S4 : number of arguments to the call.
36 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { 38 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
37 const intptr_t thread_offset = NativeArguments::thread_offset(); 39 const intptr_t thread_offset = NativeArguments::thread_offset();
38 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 40 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
39 const intptr_t argv_offset = NativeArguments::argv_offset(); 41 const intptr_t argv_offset = NativeArguments::argv_offset();
40 const intptr_t retval_offset = NativeArguments::retval_offset(); 42 const intptr_t retval_offset = NativeArguments::retval_offset();
41 43
42 __ SetPrologueOffset(); 44 __ SetPrologueOffset();
43 __ Comment("CallToRuntimeStub"); 45 __ Comment("CallToRuntimeStub");
44 __ EnterStubFrame(); 46 __ EnterStubFrame();
45 47
46 // Save exit frame information to enable stack walking as we are about 48 // Save exit frame information to enable stack walking as we are about
47 // to transition to Dart VM C++ code. 49 // to transition to Dart VM C++ code.
48 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset())); 50 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset()));
49 51
50 #if defined(DEBUG) 52 #if defined(DEBUG)
51 { Label ok; 53 {
54 Label ok;
52 // Check that we are always entering from Dart code. 55 // Check that we are always entering from Dart code.
53 __ lw(T0, Assembler::VMTagAddress()); 56 __ lw(T0, Assembler::VMTagAddress());
54 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); 57 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok);
55 __ Stop("Not coming from Dart code."); 58 __ Stop("Not coming from Dart code.");
56 __ Bind(&ok); 59 __ Bind(&ok);
57 } 60 }
58 #endif 61 #endif
59 62
60 // Mark that the thread is executing VM code. 63 // Mark that the thread is executing VM code.
61 __ sw(S5, Assembler::VMTagAddress()); 64 __ sw(S5, Assembler::VMTagAddress());
(...skipping 21 matching lines...) Expand all
83 // Set argv in NativeArguments. 86 // Set argv in NativeArguments.
84 __ addiu(A2, A2, Immediate(kParamEndSlotFromFp * kWordSize)); 87 __ addiu(A2, A2, Immediate(kParamEndSlotFromFp * kWordSize));
85 88
86 89
87 // Call runtime or redirection via simulator. 90 // Call runtime or redirection via simulator.
88 // We defensively always jalr through T9 because it is sometimes required by 91 // We defensively always jalr through T9 because it is sometimes required by
89 // the MIPS ABI. 92 // the MIPS ABI.
90 __ mov(T9, S5); 93 __ mov(T9, S5);
91 __ jalr(T9); 94 __ jalr(T9);
92 95
93 ASSERT(retval_offset == 3 * kWordSize); 96 ASSERT(retval_offset == 3 * kWordSize);
94 // Retval is next to 1st argument. 97 // Retval is next to 1st argument.
95 __ delay_slot()->addiu(A3, A2, Immediate(kWordSize)); 98 __ delay_slot()->addiu(A3, A2, Immediate(kWordSize));
96 __ Comment("CallToRuntimeStub return"); 99 __ Comment("CallToRuntimeStub return");
97 100
98 // Mark that the thread is executing Dart code. 101 // Mark that the thread is executing Dart code.
99 __ LoadImmediate(A2, VMTag::kDartTagId); 102 __ LoadImmediate(A2, VMTag::kDartTagId);
100 __ sw(A2, Assembler::VMTagAddress()); 103 __ sw(A2, Assembler::VMTagAddress());
101 104
102 // Reset exit frame information in Isolate structure. 105 // Reset exit frame information in Isolate structure.
103 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset())); 106 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset()));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 142
140 __ SetPrologueOffset(); 143 __ SetPrologueOffset();
141 __ Comment("CallNativeCFunctionStub"); 144 __ Comment("CallNativeCFunctionStub");
142 __ EnterStubFrame(); 145 __ EnterStubFrame();
143 146
144 // Save exit frame information to enable stack walking as we are about 147 // Save exit frame information to enable stack walking as we are about
145 // to transition to native code. 148 // to transition to native code.
146 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset())); 149 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset()));
147 150
148 #if defined(DEBUG) 151 #if defined(DEBUG)
149 { Label ok; 152 {
153 Label ok;
150 // Check that we are always entering from Dart code. 154 // Check that we are always entering from Dart code.
151 __ lw(T0, Assembler::VMTagAddress()); 155 __ lw(T0, Assembler::VMTagAddress());
152 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); 156 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok);
153 __ Stop("Not coming from Dart code."); 157 __ Stop("Not coming from Dart code.");
154 __ Bind(&ok); 158 __ Bind(&ok);
155 } 159 }
156 #endif 160 #endif
157 161
158 // Mark that the thread is executing native code. 162 // Mark that the thread is executing native code.
159 __ sw(T5, Assembler::VMTagAddress()); 163 __ sw(T5, Assembler::VMTagAddress());
(...skipping 21 matching lines...) Expand all
181 // Dart API for native functions. 185 // Dart API for native functions.
182 // For now, space is reserved on the stack and we pass a pointer to it. 186 // For now, space is reserved on the stack and we pass a pointer to it.
183 __ addiu(SP, SP, Immediate(-4 * kWordSize)); 187 __ addiu(SP, SP, Immediate(-4 * kWordSize));
184 __ sw(A3, Address(SP, 3 * kWordSize)); 188 __ sw(A3, Address(SP, 3 * kWordSize));
185 __ sw(A2, Address(SP, 2 * kWordSize)); 189 __ sw(A2, Address(SP, 2 * kWordSize));
186 __ sw(A1, Address(SP, 1 * kWordSize)); 190 __ sw(A1, Address(SP, 1 * kWordSize));
187 __ sw(A0, Address(SP, 0 * kWordSize)); 191 __ sw(A0, Address(SP, 0 * kWordSize));
188 __ mov(A0, SP); // Pass the pointer to the NativeArguments. 192 __ mov(A0, SP); // Pass the pointer to the NativeArguments.
189 193
190 194
191 __ mov(A1, T5); // Pass the function entrypoint. 195 __ mov(A1, T5); // Pass the function entrypoint.
192 __ ReserveAlignedFrameSpace(2 * kWordSize); // Just passing A0, A1. 196 __ ReserveAlignedFrameSpace(2 * kWordSize); // Just passing A0, A1.
193 197
194 // Call native wrapper function or redirection via simulator. 198 // Call native wrapper function or redirection via simulator.
195 __ lw(T9, Address(THR, Thread::native_call_wrapper_entry_point_offset())); 199 __ lw(T9, Address(THR, Thread::native_call_wrapper_entry_point_offset()));
196 __ jalr(T9); 200 __ jalr(T9);
197 __ Comment("CallNativeCFunctionStub return"); 201 __ Comment("CallNativeCFunctionStub return");
198 202
199 // Mark that the thread is executing Dart code. 203 // Mark that the thread is executing Dart code.
200 __ LoadImmediate(A2, VMTag::kDartTagId); 204 __ LoadImmediate(A2, VMTag::kDartTagId);
201 __ sw(A2, Assembler::VMTagAddress()); 205 __ sw(A2, Assembler::VMTagAddress());
(...skipping 19 matching lines...) Expand all
221 225
222 __ SetPrologueOffset(); 226 __ SetPrologueOffset();
223 __ Comment("CallNativeCFunctionStub"); 227 __ Comment("CallNativeCFunctionStub");
224 __ EnterStubFrame(); 228 __ EnterStubFrame();
225 229
226 // Save exit frame information to enable stack walking as we are about 230 // Save exit frame information to enable stack walking as we are about
227 // to transition to native code. 231 // to transition to native code.
228 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset())); 232 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset()));
229 233
230 #if defined(DEBUG) 234 #if defined(DEBUG)
231 { Label ok; 235 {
236 Label ok;
232 // Check that we are always entering from Dart code. 237 // Check that we are always entering from Dart code.
233 __ lw(T0, Assembler::VMTagAddress()); 238 __ lw(T0, Assembler::VMTagAddress());
234 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); 239 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok);
235 __ Stop("Not coming from Dart code."); 240 __ Stop("Not coming from Dart code.");
236 __ Bind(&ok); 241 __ Bind(&ok);
237 } 242 }
238 #endif 243 #endif
239 244
240 // Mark that the thread is executing native code. 245 // Mark that the thread is executing native code.
241 __ sw(T5, Assembler::VMTagAddress()); 246 __ sw(T5, Assembler::VMTagAddress());
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 } 471 }
467 } 472 }
468 for (int i = 0; i < kNumberOfFRegisters; i++) { 473 for (int i = 0; i < kNumberOfFRegisters; i++) {
469 // These go below the CPU registers. 474 // These go below the CPU registers.
470 const int slot = kNumberOfCpuRegisters + kNumberOfFRegisters - i; 475 const int slot = kNumberOfCpuRegisters + kNumberOfFRegisters - i;
471 FRegister reg = static_cast<FRegister>(i); 476 FRegister reg = static_cast<FRegister>(i);
472 __ swc1(reg, Address(SP, kPushedRegistersSize - slot * kWordSize)); 477 __ swc1(reg, Address(SP, kPushedRegistersSize - slot * kWordSize));
473 } 478 }
474 479
475 __ mov(A0, SP); // Pass address of saved registers block. 480 __ mov(A0, SP); // Pass address of saved registers block.
476 bool is_lazy = (kind == kLazyDeoptFromReturn) || 481 bool is_lazy =
477 (kind == kLazyDeoptFromThrow); 482 (kind == kLazyDeoptFromReturn) || (kind == kLazyDeoptFromThrow);
478 __ LoadImmediate(A1, is_lazy ? 1 : 0); 483 __ LoadImmediate(A1, is_lazy ? 1 : 0);
479 __ ReserveAlignedFrameSpace(1 * kWordSize); 484 __ ReserveAlignedFrameSpace(1 * kWordSize);
480 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2); 485 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
481 // Result (V0) is stack-size (FP - SP) in bytes, incl. the return address. 486 // Result (V0) is stack-size (FP - SP) in bytes, incl. the return address.
482 487
483 if (kind == kLazyDeoptFromReturn) { 488 if (kind == kLazyDeoptFromReturn) {
484 // Restore result into T1 temporarily. 489 // Restore result into T1 temporarily.
485 __ lw(T1, Address(FP, saved_result_slot_from_fp * kWordSize)); 490 __ lw(T1, Address(FP, saved_result_slot_from_fp * kWordSize));
486 } else if (kind == kLazyDeoptFromThrow) { 491 } else if (kind == kLazyDeoptFromThrow) {
487 // Restore result into T1 temporarily. 492 // Restore result into T1 temporarily.
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 __ LoadImmediate(T3, ~(kObjectAlignment - 1)); 701 __ LoadImmediate(T3, ~(kObjectAlignment - 1));
697 __ and_(T2, T2, T3); 702 __ and_(T2, T2, T3);
698 703
699 // T2: Allocation size. 704 // T2: Allocation size.
700 705
701 Heap::Space space = Heap::kNew; 706 Heap::Space space = Heap::kNew;
702 __ lw(T3, Address(THR, Thread::heap_offset())); 707 __ lw(T3, Address(THR, Thread::heap_offset()));
703 // Potential new object start. 708 // Potential new object start.
704 __ lw(T0, Address(T3, Heap::TopOffset(space))); 709 __ lw(T0, Address(T3, Heap::TopOffset(space)));
705 710
706 __ addu(T1, T0, T2); // Potential next object start. 711 __ addu(T1, T0, T2); // Potential next object start.
707 __ BranchUnsignedLess(T1, T0, &slow_case); // Branch on unsigned overflow. 712 __ BranchUnsignedLess(T1, T0, &slow_case); // Branch on unsigned overflow.
708 713
709 // Check if the allocation fits into the remaining space. 714 // Check if the allocation fits into the remaining space.
710 // T0: potential new object start. 715 // T0: potential new object start.
711 // T1: potential next object start. 716 // T1: potential next object start.
712 // T2: allocation size. 717 // T2: allocation size.
713 // T3: heap. 718 // T3: heap.
714 __ lw(T4, Address(T3, Heap::EndOffset(space))); 719 __ lw(T4, Address(T3, Heap::EndOffset(space)));
715 __ BranchUnsignedGreaterEqual(T1, T4, &slow_case); 720 __ BranchUnsignedGreaterEqual(T1, T4, &slow_case);
716 721
717 // Successfully allocated the object(s), now update top to point to 722 // Successfully allocated the object(s), now update top to point to
718 // next object start and initialize the object. 723 // next object start and initialize the object.
719 // T3: heap. 724 // T3: heap.
720 __ sw(T1, Address(T3, Heap::TopOffset(space))); 725 __ sw(T1, Address(T3, Heap::TopOffset(space)));
721 __ addiu(T0, T0, Immediate(kHeapObjectTag)); 726 __ addiu(T0, T0, Immediate(kHeapObjectTag));
722 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, T2, T4, space)); 727 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, T2, T4, space));
723 728
724 // Initialize the tags. 729 // Initialize the tags.
725 // T0: new object start as a tagged pointer. 730 // T0: new object start as a tagged pointer.
726 // T1: new object end address. 731 // T1: new object end address.
727 // T2: allocation size. 732 // T2: allocation size.
728 { 733 {
729 Label overflow, done; 734 Label overflow, done;
730 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; 735 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
731 736
732 __ BranchUnsignedGreater( 737 __ BranchUnsignedGreater(T2, Immediate(RawObject::SizeTag::kMaxSizeTag),
733 T2, Immediate(RawObject::SizeTag::kMaxSizeTag), &overflow); 738 &overflow);
734 __ b(&done); 739 __ b(&done);
735 __ delay_slot()->sll(T2, T2, shift); 740 __ delay_slot()->sll(T2, T2, shift);
736 __ Bind(&overflow); 741 __ Bind(&overflow);
737 __ mov(T2, ZR); 742 __ mov(T2, ZR);
738 __ Bind(&done); 743 __ Bind(&done);
739 744
740 // Get the class index and insert it into the tags. 745 // Get the class index and insert it into the tags.
741 // T2: size and bit tags. 746 // T2: size and bit tags.
742 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); 747 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));
743 __ or_(T2, T2, TMP); 748 __ or_(T2, T2, TMP);
744 __ sw(T2, FieldAddress(T0, Array::tags_offset())); // Store tags. 749 __ sw(T2, FieldAddress(T0, Array::tags_offset())); // Store tags.
745 } 750 }
746 751
747 // T0: new object start as a tagged pointer. 752 // T0: new object start as a tagged pointer.
748 // T1: new object end address. 753 // T1: new object end address.
749 // Store the type argument field. 754 // Store the type argument field.
750 __ StoreIntoObjectNoBarrier(T0, 755 __ StoreIntoObjectNoBarrier(
751 FieldAddress(T0, Array::type_arguments_offset()), 756 T0, FieldAddress(T0, Array::type_arguments_offset()), A0);
752 A0);
753 757
754 // Set the length field. 758 // Set the length field.
755 __ StoreIntoObjectNoBarrier(T0, 759 __ StoreIntoObjectNoBarrier(T0, FieldAddress(T0, Array::length_offset()), A1);
756 FieldAddress(T0, Array::length_offset()),
757 A1);
758 760
759 __ LoadObject(T7, Object::null_object()); 761 __ LoadObject(T7, Object::null_object());
760 // Initialize all array elements to raw_null. 762 // Initialize all array elements to raw_null.
761 // T0: new object start as a tagged pointer. 763 // T0: new object start as a tagged pointer.
762 // T1: new object end address. 764 // T1: new object end address.
763 // T2: iterator which initially points to the start of the variable 765 // T2: iterator which initially points to the start of the variable
764 // data area to be initialized. 766 // data area to be initialized.
765 // T7: null. 767 // T7: null.
766 __ AddImmediate(T2, T0, sizeof(RawArray) - kHeapObjectTag); 768 __ AddImmediate(T2, T0, sizeof(RawArray) - kHeapObjectTag);
767 769
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 817
816 // Push code object to PC marker slot. 818 // Push code object to PC marker slot.
817 __ lw(TMP, Address(A3, Thread::invoke_dart_code_stub_offset())); 819 __ lw(TMP, Address(A3, Thread::invoke_dart_code_stub_offset()));
818 __ Push(TMP); 820 __ Push(TMP);
819 821
820 // Save new context and C++ ABI callee-saved registers. 822 // Save new context and C++ ABI callee-saved registers.
821 823
822 // The saved vm tag, top resource, and top exit frame info. 824 // The saved vm tag, top resource, and top exit frame info.
823 const intptr_t kPreservedSlots = 3; 825 const intptr_t kPreservedSlots = 3;
824 const intptr_t kPreservedRegSpace = 826 const intptr_t kPreservedRegSpace =
825 kWordSize * (kAbiPreservedCpuRegCount + kAbiPreservedFpuRegCount + 827 kWordSize *
826 kPreservedSlots); 828 (kAbiPreservedCpuRegCount + kAbiPreservedFpuRegCount + kPreservedSlots);
827 829
828 __ addiu(SP, SP, Immediate(-kPreservedRegSpace)); 830 __ addiu(SP, SP, Immediate(-kPreservedRegSpace));
829 for (int i = S0; i <= S7; i++) { 831 for (int i = S0; i <= S7; i++) {
830 Register r = static_cast<Register>(i); 832 Register r = static_cast<Register>(i);
831 const intptr_t slot = i - S0 + kPreservedSlots; 833 const intptr_t slot = i - S0 + kPreservedSlots;
832 __ sw(r, Address(SP, slot * kWordSize)); 834 __ sw(r, Address(SP, slot * kWordSize));
833 } 835 }
834 836
835 for (intptr_t i = kAbiFirstPreservedFpuReg; 837 for (intptr_t i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg;
836 i <= kAbiLastPreservedFpuReg; i++) { 838 i++) {
837 FRegister r = static_cast<FRegister>(i); 839 FRegister r = static_cast<FRegister>(i);
838 const intptr_t slot = 840 const intptr_t slot = kAbiPreservedCpuRegCount + kPreservedSlots + i -
839 kAbiPreservedCpuRegCount + kPreservedSlots + i - 841 kAbiFirstPreservedFpuReg;
840 kAbiFirstPreservedFpuReg;
841 __ swc1(r, Address(SP, slot * kWordSize)); 842 __ swc1(r, Address(SP, slot * kWordSize));
842 } 843 }
843 844
844 // We now load the pool pointer(PP) with a GC safe value as we are about 845 // We now load the pool pointer(PP) with a GC safe value as we are about
845 // to invoke dart code. 846 // to invoke dart code.
846 __ LoadImmediate(PP, 0); 847 __ LoadImmediate(PP, 0);
847 848
848 // Set up THR, which caches the current thread in Dart code. 849 // Set up THR, which caches the current thread in Dart code.
849 if (THR != A3) { 850 if (THR != A3) {
850 __ mov(THR, A3); 851 __ mov(THR, A3);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
921 __ lw(T0, Address(SP, 0 * kWordSize)); 922 __ lw(T0, Address(SP, 0 * kWordSize));
922 __ sw(T0, Address(THR, Thread::top_exit_frame_info_offset())); 923 __ sw(T0, Address(THR, Thread::top_exit_frame_info_offset()));
923 924
924 // Restore C++ ABI callee-saved registers. 925 // Restore C++ ABI callee-saved registers.
925 for (int i = S0; i <= S7; i++) { 926 for (int i = S0; i <= S7; i++) {
926 Register r = static_cast<Register>(i); 927 Register r = static_cast<Register>(i);
927 const intptr_t slot = i - S0 + kPreservedSlots; 928 const intptr_t slot = i - S0 + kPreservedSlots;
928 __ lw(r, Address(SP, slot * kWordSize)); 929 __ lw(r, Address(SP, slot * kWordSize));
929 } 930 }
930 931
931 for (intptr_t i = kAbiFirstPreservedFpuReg; 932 for (intptr_t i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg;
932 i <= kAbiLastPreservedFpuReg; i++) { 933 i++) {
933 FRegister r = static_cast<FRegister>(i); 934 FRegister r = static_cast<FRegister>(i);
934 const intptr_t slot = 935 const intptr_t slot = kAbiPreservedCpuRegCount + kPreservedSlots + i -
935 kAbiPreservedCpuRegCount + kPreservedSlots + i - 936 kAbiFirstPreservedFpuReg;
936 kAbiFirstPreservedFpuReg;
937 __ lwc1(r, Address(SP, slot * kWordSize)); 937 __ lwc1(r, Address(SP, slot * kWordSize));
938 } 938 }
939 939
940 __ addiu(SP, SP, Immediate(kPreservedRegSpace)); 940 __ addiu(SP, SP, Immediate(kPreservedRegSpace));
941 941
942 // Restore the frame pointer and return. 942 // Restore the frame pointer and return.
943 __ LeaveFrameAndReturn(); 943 __ LeaveFrameAndReturn();
944 } 944 }
945 945
946 946
947 // Called for inline allocation of contexts. 947 // Called for inline allocation of contexts.
948 // Input: 948 // Input:
949 // T1: number of context variables. 949 // T1: number of context variables.
950 // Output: 950 // Output:
951 // V0: new allocated RawContext object. 951 // V0: new allocated RawContext object.
952 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { 952 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
953 __ Comment("AllocateContext"); 953 __ Comment("AllocateContext");
954 if (FLAG_inline_alloc) { 954 if (FLAG_inline_alloc) {
955 Label slow_case; 955 Label slow_case;
956 // First compute the rounded instance size. 956 // First compute the rounded instance size.
957 // T1: number of context variables. 957 // T1: number of context variables.
958 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; 958 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1;
959 __ LoadImmediate(T2, fixed_size); 959 __ LoadImmediate(T2, fixed_size);
960 __ sll(T0, T1, 2); 960 __ sll(T0, T1, 2);
961 __ addu(T2, T2, T0); 961 __ addu(T2, T2, T0);
962 ASSERT(kSmiTagShift == 1); 962 ASSERT(kSmiTagShift == 1);
963 __ LoadImmediate(T0, ~((kObjectAlignment) - 1)); 963 __ LoadImmediate(T0, ~((kObjectAlignment)-1));
964 __ and_(T2, T2, T0); 964 __ and_(T2, T2, T0);
965 965
966 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kContextCid, T4, &slow_case)); 966 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kContextCid, T4, &slow_case));
967 // Now allocate the object. 967 // Now allocate the object.
968 // T1: number of context variables. 968 // T1: number of context variables.
969 // T2: object size. 969 // T2: object size.
970 const intptr_t cid = kContextCid; 970 const intptr_t cid = kContextCid;
971 Heap::Space space = Heap::kNew; 971 Heap::Space space = Heap::kNew;
972 __ lw(T5, Address(THR, Thread::heap_offset())); 972 __ lw(T5, Address(THR, Thread::heap_offset()));
973 __ lw(V0, Address(T5, Heap::TopOffset(space))); 973 __ lw(V0, Address(T5, Heap::TopOffset(space)));
(...skipping 23 matching lines...) Expand all
997 __ addiu(V0, V0, Immediate(kHeapObjectTag)); 997 __ addiu(V0, V0, Immediate(kHeapObjectTag));
998 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, T2, T5, space)); 998 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, T2, T5, space));
999 999
1000 // Calculate the size tag. 1000 // Calculate the size tag.
1001 // V0: new object. 1001 // V0: new object.
1002 // T1: number of context variables. 1002 // T1: number of context variables.
1003 // T2: object size. 1003 // T2: object size.
1004 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; 1004 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
1005 __ LoadImmediate(TMP, RawObject::SizeTag::kMaxSizeTag); 1005 __ LoadImmediate(TMP, RawObject::SizeTag::kMaxSizeTag);
1006 __ sltu(CMPRES1, TMP, T2); // CMPRES1 = T2 > TMP ? 1 : 0. 1006 __ sltu(CMPRES1, TMP, T2); // CMPRES1 = T2 > TMP ? 1 : 0.
1007 __ movn(T2, ZR, CMPRES1); // T2 = CMPRES1 != 0 ? 0 : T2. 1007 __ movn(T2, ZR, CMPRES1); // T2 = CMPRES1 != 0 ? 0 : T2.
1008 __ sll(TMP, T2, shift); // TMP = T2 << shift. 1008 __ sll(TMP, T2, shift); // TMP = T2 << shift.
1009 __ movz(T2, TMP, CMPRES1); // T2 = CMPRES1 == 0 ? TMP : T2. 1009 __ movz(T2, TMP, CMPRES1); // T2 = CMPRES1 == 0 ? TMP : T2.
1010 1010
1011 // Get the class index and insert it into the tags. 1011 // Get the class index and insert it into the tags.
1012 // T2: size and bit tags. 1012 // T2: size and bit tags.
1013 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); 1013 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));
1014 __ or_(T2, T2, TMP); 1014 __ or_(T2, T2, TMP);
1015 __ sw(T2, FieldAddress(V0, Context::tags_offset())); 1015 __ sw(T2, FieldAddress(V0, Context::tags_offset()));
1016 1016
1017 // Setup up number of context variables field. 1017 // Setup up number of context variables field.
1018 // V0: new object. 1018 // V0: new object.
(...skipping 27 matching lines...) Expand all
1046 // Create a stub frame as we are pushing some objects on the stack before 1046 // Create a stub frame as we are pushing some objects on the stack before
1047 // calling into the runtime. 1047 // calling into the runtime.
1048 __ EnterStubFrame(); 1048 __ EnterStubFrame();
1049 // Setup space on stack for return value. 1049 // Setup space on stack for return value.
1050 __ SmiTag(T1); 1050 __ SmiTag(T1);
1051 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1051 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1052 __ LoadObject(TMP, Object::null_object()); 1052 __ LoadObject(TMP, Object::null_object());
1053 __ sw(TMP, Address(SP, 1 * kWordSize)); // Store null. 1053 __ sw(TMP, Address(SP, 1 * kWordSize)); // Store null.
1054 __ sw(T1, Address(SP, 0 * kWordSize)); 1054 __ sw(T1, Address(SP, 0 * kWordSize));
1055 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. 1055 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context.
1056 __ lw(V0, Address(SP, 1 * kWordSize)); // Get the new context. 1056 __ lw(V0, Address(SP, 1 * kWordSize)); // Get the new context.
1057 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Pop argument and return. 1057 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Pop argument and return.
1058 1058
1059 // V0: new object 1059 // V0: new object
1060 // Restore the frame pointer. 1060 // Restore the frame pointer.
1061 __ LeaveStubFrameAndReturn(); 1061 __ LeaveStubFrameAndReturn();
1062 } 1062 }
1063 1063
1064 1064
1065 // Helper stub to implement Assembler::StoreIntoObject. 1065 // Helper stub to implement Assembler::StoreIntoObject.
1066 // Input parameters: 1066 // Input parameters:
1067 // T0: Address (i.e. object) being stored into. 1067 // T0: Address (i.e. object) being stored into.
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 1197
1198 // Initialize the remaining words of the object. 1198 // Initialize the remaining words of the object.
1199 // T2: new object start. 1199 // T2: new object start.
1200 // T3: next object start. 1200 // T3: next object start.
1201 // T1: new object type arguments (if is_cls_parameterized). 1201 // T1: new object type arguments (if is_cls_parameterized).
1202 // First try inlining the initialization without a loop. 1202 // First try inlining the initialization without a loop.
1203 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1203 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1204 // Check if the object contains any non-header fields. 1204 // Check if the object contains any non-header fields.
1205 // Small objects are initialized using a consecutive set of writes. 1205 // Small objects are initialized using a consecutive set of writes.
1206 for (intptr_t current_offset = Instance::NextFieldOffset(); 1206 for (intptr_t current_offset = Instance::NextFieldOffset();
1207 current_offset < instance_size; 1207 current_offset < instance_size; current_offset += kWordSize) {
1208 current_offset += kWordSize) {
1209 __ sw(T7, Address(T2, current_offset)); 1208 __ sw(T7, Address(T2, current_offset));
1210 } 1209 }
1211 } else { 1210 } else {
1212 __ addiu(T4, T2, Immediate(Instance::NextFieldOffset())); 1211 __ addiu(T4, T2, Immediate(Instance::NextFieldOffset()));
1213 // Loop until the whole object is initialized. 1212 // Loop until the whole object is initialized.
1214 // T2: new object. 1213 // T2: new object.
1215 // T3: next object start. 1214 // T3: next object start.
1216 // T4: next word to be initialized. 1215 // T4: next word to be initialized.
1217 // T1: new object type arguments (if is_cls_parameterized). 1216 // T1: new object type arguments (if is_cls_parameterized).
1218 Label loop, loop_exit; 1217 Label loop, loop_exit;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1306 // function and not the top-scope function. 1305 // function and not the top-scope function.
1307 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { 1306 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
1308 __ Comment("OptimizedUsageCounterIncrement"); 1307 __ Comment("OptimizedUsageCounterIncrement");
1309 Register ic_reg = S5; 1308 Register ic_reg = S5;
1310 Register func_reg = T0; 1309 Register func_reg = T0;
1311 if (FLAG_trace_optimized_ic_calls) { 1310 if (FLAG_trace_optimized_ic_calls) {
1312 __ EnterStubFrame(); 1311 __ EnterStubFrame();
1313 __ addiu(SP, SP, Immediate(-4 * kWordSize)); 1312 __ addiu(SP, SP, Immediate(-4 * kWordSize));
1314 __ sw(T0, Address(SP, 3 * kWordSize)); 1313 __ sw(T0, Address(SP, 3 * kWordSize));
1315 __ sw(S5, Address(SP, 2 * kWordSize)); 1314 __ sw(S5, Address(SP, 2 * kWordSize));
1316 __ sw(ic_reg, Address(SP, 1 * kWordSize)); // Argument. 1315 __ sw(ic_reg, Address(SP, 1 * kWordSize)); // Argument.
1317 __ sw(func_reg, Address(SP, 0 * kWordSize)); // Argument. 1316 __ sw(func_reg, Address(SP, 0 * kWordSize)); // Argument.
1318 __ CallRuntime(kTraceICCallRuntimeEntry, 2); 1317 __ CallRuntime(kTraceICCallRuntimeEntry, 2);
1319 __ lw(S5, Address(SP, 2 * kWordSize)); 1318 __ lw(S5, Address(SP, 2 * kWordSize));
1320 __ lw(T0, Address(SP, 3 * kWordSize)); 1319 __ lw(T0, Address(SP, 3 * kWordSize));
1321 __ addiu(SP, SP, Immediate(4 * kWordSize)); // Discard argument; 1320 __ addiu(SP, SP, Immediate(4 * kWordSize)); // Discard argument;
1322 __ LeaveStubFrame(); 1321 __ LeaveStubFrame();
1323 } 1322 }
1324 __ lw(T7, FieldAddress(func_reg, Function::usage_counter_offset())); 1323 __ lw(T7, FieldAddress(func_reg, Function::usage_counter_offset()));
1325 __ addiu(T7, T7, Immediate(1)); 1324 __ addiu(T7, T7, Immediate(1));
1326 __ sw(T7, FieldAddress(func_reg, Function::usage_counter_offset())); 1325 __ sw(T7, FieldAddress(func_reg, Function::usage_counter_offset()));
(...skipping 27 matching lines...) Expand all
1354 Label* not_smi_or_overflow) { 1353 Label* not_smi_or_overflow) {
1355 __ Comment("Fast Smi op"); 1354 __ Comment("Fast Smi op");
1356 ASSERT(num_args == 2); 1355 ASSERT(num_args == 2);
1357 __ lw(T0, Address(SP, 0 * kWordSize)); // Left. 1356 __ lw(T0, Address(SP, 0 * kWordSize)); // Left.
1358 __ lw(T1, Address(SP, 1 * kWordSize)); // Right. 1357 __ lw(T1, Address(SP, 1 * kWordSize)); // Right.
1359 __ or_(CMPRES1, T0, T1); 1358 __ or_(CMPRES1, T0, T1);
1360 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask)); 1359 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask));
1361 __ bne(CMPRES1, ZR, not_smi_or_overflow); 1360 __ bne(CMPRES1, ZR, not_smi_or_overflow);
1362 switch (kind) { 1361 switch (kind) {
1363 case Token::kADD: { 1362 case Token::kADD: {
1364 __ AdduDetectOverflow(V0, T1, T0, CMPRES1); // Add. 1363 __ AdduDetectOverflow(V0, T1, T0, CMPRES1); // Add.
1365 __ bltz(CMPRES1, not_smi_or_overflow); // Fall through on overflow. 1364 __ bltz(CMPRES1, not_smi_or_overflow); // Fall through on overflow.
1366 break; 1365 break;
1367 } 1366 }
1368 case Token::kSUB: { 1367 case Token::kSUB: {
1369 __ SubuDetectOverflow(V0, T1, T0, CMPRES1); // Subtract. 1368 __ SubuDetectOverflow(V0, T1, T0, CMPRES1); // Subtract.
1370 __ bltz(CMPRES1, not_smi_or_overflow); // Fall through on overflow. 1369 __ bltz(CMPRES1, not_smi_or_overflow); // Fall through on overflow.
1371 break; 1370 break;
1372 } 1371 }
1373 case Token::kEQ: { 1372 case Token::kEQ: {
1374 Label true_label, done; 1373 Label true_label, done;
1375 __ beq(T1, T0, &true_label); 1374 __ beq(T1, T0, &true_label);
1376 __ LoadObject(V0, Bool::False()); 1375 __ LoadObject(V0, Bool::False());
1377 __ b(&done); 1376 __ b(&done);
1378 __ Bind(&true_label); 1377 __ Bind(&true_label);
1379 __ LoadObject(V0, Bool::True()); 1378 __ LoadObject(V0, Bool::True());
1380 __ Bind(&done); 1379 __ Bind(&done);
1381 break; 1380 break;
1382 } 1381 }
1383 default: UNIMPLEMENTED(); 1382 default:
1383 UNIMPLEMENTED();
1384 } 1384 }
1385 // S5: IC data object (preserved). 1385 // S5: IC data object (preserved).
1386 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); 1386 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset()));
1387 // T0: ic_data_array with check entries: classes and target functions. 1387 // T0: ic_data_array with check entries: classes and target functions.
1388 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); 1388 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag);
1389 // T0: points directly to the first ic data array element. 1389 // T0: points directly to the first ic data array element.
1390 #if defined(DEBUG) 1390 #if defined(DEBUG)
1391 // Check that first entry is for Smi/Smi. 1391 // Check that first entry is for Smi/Smi.
1392 Label error, ok; 1392 Label error, ok;
1393 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid)); 1393 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid));
1394 __ lw(T4, Address(T0)); 1394 __ lw(T4, Address(T0));
1395 __ BranchNotEqual(T4, Immediate(imm_smi_cid), &error); 1395 __ BranchNotEqual(T4, Immediate(imm_smi_cid), &error);
1396 __ lw(T4, Address(T0, kWordSize)); 1396 __ lw(T4, Address(T0, kWordSize));
1397 __ BranchEqual(T4, Immediate(imm_smi_cid), &ok); 1397 __ BranchEqual(T4, Immediate(imm_smi_cid), &ok);
1398 __ Bind(&error); 1398 __ Bind(&error);
1399 __ Stop("Incorrect IC data"); 1399 __ Stop("Incorrect IC data");
(...skipping 26 matching lines...) Expand all
1426 // - Match not found -> jump to IC miss. 1426 // - Match not found -> jump to IC miss.
1427 void StubCode::GenerateNArgsCheckInlineCacheStub( 1427 void StubCode::GenerateNArgsCheckInlineCacheStub(
1428 Assembler* assembler, 1428 Assembler* assembler,
1429 intptr_t num_args, 1429 intptr_t num_args,
1430 const RuntimeEntry& handle_ic_miss, 1430 const RuntimeEntry& handle_ic_miss,
1431 Token::Kind kind, 1431 Token::Kind kind,
1432 bool optimized) { 1432 bool optimized) {
1433 __ Comment("NArgsCheckInlineCacheStub"); 1433 __ Comment("NArgsCheckInlineCacheStub");
1434 ASSERT(num_args > 0); 1434 ASSERT(num_args > 0);
1435 #if defined(DEBUG) 1435 #if defined(DEBUG)
1436 { Label ok; 1436 {
1437 Label ok;
1437 // Check that the IC data array has NumArgsTested() == num_args. 1438 // Check that the IC data array has NumArgsTested() == num_args.
1438 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1439 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1439 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); 1440 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset()));
1440 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1441 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1441 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); 1442 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask()));
1442 __ BranchEqual(T0, Immediate(num_args), &ok); 1443 __ BranchEqual(T0, Immediate(num_args), &ok);
1443 __ Stop("Incorrect stub for IC data"); 1444 __ Stop("Incorrect stub for IC data");
1444 __ Bind(&ok); 1445 __ Bind(&ok);
1445 } 1446 }
1446 #endif // DEBUG 1447 #endif // DEBUG
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1503 // T3: next argument class ID (smi). 1504 // T3: next argument class ID (smi).
1504 __ lw(T4, Address(T0, i * kWordSize)); 1505 __ lw(T4, Address(T0, i * kWordSize));
1505 // T4: next class ID to check (smi). 1506 // T4: next class ID to check (smi).
1506 } 1507 }
1507 if (i < (num_args - 1)) { 1508 if (i < (num_args - 1)) {
1508 __ bne(T3, T4, &update); // Continue. 1509 __ bne(T3, T4, &update); // Continue.
1509 } else { 1510 } else {
1510 // Last check, all checks before matched. 1511 // Last check, all checks before matched.
1511 Label skip; 1512 Label skip;
1512 __ bne(T3, T4, &skip); 1513 __ bne(T3, T4, &skip);
1513 __ b(&found); // Break. 1514 __ b(&found); // Break.
1514 __ delay_slot()->mov(RA, T2); // Restore return address if found. 1515 __ delay_slot()->mov(RA, T2); // Restore return address if found.
1515 __ Bind(&skip); 1516 __ Bind(&skip);
1516 } 1517 }
1517 } 1518 }
1518 __ Bind(&update); 1519 __ Bind(&update);
1519 // Reload receiver class ID. It has not been destroyed when num_args == 1. 1520 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1520 if (num_args > 1) { 1521 if (num_args > 1) {
1521 __ sll(T3, T1, 1); 1522 __ sll(T3, T1, 1);
1522 __ addu(T3, T3, SP); 1523 __ addu(T3, T3, SP);
1523 __ lw(T3, Address(T3)); 1524 __ lw(T3, Address(T3));
1524 __ LoadTaggedClassIdMayBeSmi(T3, T3); 1525 __ LoadTaggedClassIdMayBeSmi(T3, T3);
1525 } 1526 }
1526 1527
1527 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1528 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1528 __ AddImmediate(T0, entry_size); // Next entry. 1529 __ AddImmediate(T0, entry_size); // Next entry.
1529 __ lw(T4, Address(T0)); // Next class ID. 1530 __ lw(T4, Address(T0)); // Next class ID.
1530 1531
1531 __ Bind(&test); 1532 __ Bind(&test);
1532 __ BranchNotEqual(T4, Immediate(Smi::RawValue(kIllegalCid)), &loop); // Done? 1533 __ BranchNotEqual(T4, Immediate(Smi::RawValue(kIllegalCid)), &loop); // Done?
1533 1534
1534 __ Comment("IC miss"); 1535 __ Comment("IC miss");
1535 // Restore return address. 1536 // Restore return address.
1536 __ mov(RA, T2); 1537 __ mov(RA, T2);
1537 1538
1538 // Compute address of arguments (first read number of arguments from 1539 // Compute address of arguments (first read number of arguments from
1539 // arguments descriptor array and then compute address on the stack). 1540 // arguments descriptor array and then compute address on the stack).
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 // RA: Return address. 1629 // RA: Return address.
1629 // S5: Inline cache data object. 1630 // S5: Inline cache data object.
1630 // Inline cache data object structure: 1631 // Inline cache data object structure:
1631 // 0: function-name 1632 // 0: function-name
1632 // 1: N, number of arguments checked. 1633 // 1: N, number of arguments checked.
1633 // 2 .. (length - 1): group of checks, each check containing: 1634 // 2 .. (length - 1): group of checks, each check containing:
1634 // - N classes. 1635 // - N classes.
1635 // - 1 target function. 1636 // - 1 target function.
1636 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1637 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1637 GenerateUsageCounterIncrement(assembler, T0); 1638 GenerateUsageCounterIncrement(assembler, T0);
1638 GenerateNArgsCheckInlineCacheStub(assembler, 1, 1639 GenerateNArgsCheckInlineCacheStub(
1639 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); 1640 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1640 } 1641 }
1641 1642
1642 1643
1643 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1644 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1644 GenerateUsageCounterIncrement(assembler, T0); 1645 GenerateUsageCounterIncrement(assembler, T0);
1645 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1646 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1646 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); 1647 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1648 Token::kILLEGAL);
1647 } 1649 }
1648 1650
1649 1651
1650 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { 1652 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
1651 GenerateUsageCounterIncrement(assembler, T0); 1653 GenerateUsageCounterIncrement(assembler, T0);
1652 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1654 GenerateNArgsCheckInlineCacheStub(
1653 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD); 1655 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
1654 } 1656 }
1655 1657
1656 1658
1657 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { 1659 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
1658 GenerateUsageCounterIncrement(assembler, T0); 1660 GenerateUsageCounterIncrement(assembler, T0);
1659 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1661 GenerateNArgsCheckInlineCacheStub(
1660 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); 1662 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
1661 } 1663 }
1662 1664
1663 1665
1664 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { 1666 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
1665 GenerateUsageCounterIncrement(assembler, T0); 1667 GenerateUsageCounterIncrement(assembler, T0);
1666 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1668 GenerateNArgsCheckInlineCacheStub(
1667 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); 1669 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
1668 } 1670 }
1669 1671
1670 1672
1671 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( 1673 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1672 Assembler* assembler) { 1674 Assembler* assembler) {
1673 GenerateOptimizedUsageCounterIncrement(assembler); 1675 GenerateOptimizedUsageCounterIncrement(assembler);
1674 GenerateNArgsCheckInlineCacheStub(assembler, 1, 1676 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1675 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, 1677 kInlineCacheMissHandlerOneArgRuntimeEntry,
1676 true /* optimized */); 1678 Token::kILLEGAL, true /* optimized */);
1677 } 1679 }
1678 1680
1679 1681
1680 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( 1682 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
1681 Assembler* assembler) { 1683 Assembler* assembler) {
1682 GenerateOptimizedUsageCounterIncrement(assembler); 1684 GenerateOptimizedUsageCounterIncrement(assembler);
1683 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1685 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1684 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, 1686 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1685 true /* optimized */); 1687 Token::kILLEGAL, true /* optimized */);
1686 } 1688 }
1687 1689
1688 1690
1689 // Intermediary stub between a static call and its target. ICData contains 1691 // Intermediary stub between a static call and its target. ICData contains
1690 // the target function and the call count. 1692 // the target function and the call count.
1691 // S5: ICData 1693 // S5: ICData
1692 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1694 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1693 GenerateUsageCounterIncrement(assembler, T0); 1695 GenerateUsageCounterIncrement(assembler, T0);
1694 __ Comment("UnoptimizedStaticCallStub"); 1696 __ Comment("UnoptimizedStaticCallStub");
1695 #if defined(DEBUG) 1697 #if defined(DEBUG)
1696 { Label ok; 1698 {
1699 Label ok;
1697 // Check that the IC data array has NumArgsTested() == 0. 1700 // Check that the IC data array has NumArgsTested() == 0.
1698 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1701 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1699 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); 1702 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset()));
1700 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1703 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1701 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); 1704 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask()));
1702 __ beq(T0, ZR, &ok); 1705 __ beq(T0, ZR, &ok);
1703 __ Stop("Incorrect IC data for unoptimized static call"); 1706 __ Stop("Incorrect IC data for unoptimized static call");
1704 __ Bind(&ok); 1707 __ Bind(&ok);
1705 } 1708 }
1706 #endif // DEBUG 1709 #endif // DEBUG
(...skipping 19 matching lines...) Expand all
1726 // Increment count for this call. 1729 // Increment count for this call.
1727 __ lw(T4, Address(T0, count_offset)); 1730 __ lw(T4, Address(T0, count_offset));
1728 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); 1731 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6);
1729 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. 1732 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow.
1730 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); 1733 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue));
1731 __ movz(T4, T7, CMPRES1); 1734 __ movz(T4, T7, CMPRES1);
1732 __ sw(T4, Address(T0, count_offset)); 1735 __ sw(T4, Address(T0, count_offset));
1733 } 1736 }
1734 1737
1735 // Load arguments descriptor into S4. 1738 // Load arguments descriptor into S4.
1736 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); 1739 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
1737 1740
1738 // Get function and call it, if possible. 1741 // Get function and call it, if possible.
1739 __ lw(T0, Address(T0, target_offset)); 1742 __ lw(T0, Address(T0, target_offset));
1740 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); 1743 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset()));
1741 __ lw(T4, FieldAddress(T0, Function::entry_point_offset())); 1744 __ lw(T4, FieldAddress(T0, Function::entry_point_offset()));
1742 __ jr(T4); 1745 __ jr(T4);
1743 1746
1744 // Call single step callback in debugger. 1747 // Call single step callback in debugger.
1745 if (FLAG_support_debugger) { 1748 if (FLAG_support_debugger) {
1746 __ Bind(&stepping); 1749 __ Bind(&stepping);
(...skipping 14 matching lines...) Expand all
1761 1764
1762 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { 1765 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
1763 GenerateUsageCounterIncrement(assembler, T0); 1766 GenerateUsageCounterIncrement(assembler, T0);
1764 GenerateNArgsCheckInlineCacheStub( 1767 GenerateNArgsCheckInlineCacheStub(
1765 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); 1768 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1766 } 1769 }
1767 1770
1768 1771
1769 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1772 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1770 GenerateUsageCounterIncrement(assembler, T0); 1773 GenerateUsageCounterIncrement(assembler, T0);
1771 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1774 GenerateNArgsCheckInlineCacheStub(
1772 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); 1775 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1773 } 1776 }
1774 1777
1775 1778
1776 // Stub for compiling a function and jumping to the compiled code. 1779 // Stub for compiling a function and jumping to the compiled code.
1777 // S5: IC-Data (for methods). 1780 // S5: IC-Data (for methods).
1778 // S4: Arguments descriptor. 1781 // S4: Arguments descriptor.
1779 // T0: Function. 1782 // T0: Function.
1780 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1783 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1781 __ EnterStubFrame(); 1784 __ EnterStubFrame();
1782 __ addiu(SP, SP, Immediate(-3 * kWordSize)); 1785 __ addiu(SP, SP, Immediate(-3 * kWordSize));
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1864 // Result in V0: null -> not found, otherwise result (true or false). 1867 // Result in V0: null -> not found, otherwise result (true or false).
1865 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { 1868 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
1866 __ Comment("SubtypeNTestCacheStub"); 1869 __ Comment("SubtypeNTestCacheStub");
1867 ASSERT((1 <= n) && (n <= 3)); 1870 ASSERT((1 <= n) && (n <= 3));
1868 if (n > 1) { 1871 if (n > 1) {
1869 // Get instance type arguments. 1872 // Get instance type arguments.
1870 __ LoadClass(T0, A0); 1873 __ LoadClass(T0, A0);
1871 // Compute instance type arguments into T1. 1874 // Compute instance type arguments into T1.
1872 Label has_no_type_arguments; 1875 Label has_no_type_arguments;
1873 __ LoadObject(T1, Object::null_object()); 1876 __ LoadObject(T1, Object::null_object());
1874 __ lw(T2, FieldAddress(T0, 1877 __ lw(T2, FieldAddress(
1875 Class::type_arguments_field_offset_in_words_offset())); 1878 T0, Class::type_arguments_field_offset_in_words_offset()));
1876 __ BranchEqual( 1879 __ BranchEqual(T2, Immediate(Class::kNoTypeArguments),
1877 T2, Immediate(Class::kNoTypeArguments), &has_no_type_arguments); 1880 &has_no_type_arguments);
1878 __ sll(T2, T2, 2); 1881 __ sll(T2, T2, 2);
1879 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4 1882 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4
1880 __ lw(T1, FieldAddress(T2, 0)); 1883 __ lw(T1, FieldAddress(T2, 0));
1881 __ Bind(&has_no_type_arguments); 1884 __ Bind(&has_no_type_arguments);
1882 } 1885 }
1883 __ LoadClassId(T0, A0); 1886 __ LoadClassId(T0, A0);
1884 // A0: instance. 1887 // A0: instance.
1885 // A1: instantiator type arguments or NULL. 1888 // A1: instantiator type arguments or NULL.
1886 // A2: SubtypeTestCache. 1889 // A2: SubtypeTestCache.
1887 // T0: instance class id. 1890 // T0: instance class id.
(...skipping 21 matching lines...) Expand all
1909 __ beq(T3, T0, &found); 1912 __ beq(T3, T0, &found);
1910 } else { 1913 } else {
1911 __ bne(T3, T0, &next_iteration); 1914 __ bne(T3, T0, &next_iteration);
1912 __ lw(T3, 1915 __ lw(T3,
1913 Address(T2, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); 1916 Address(T2, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
1914 if (n == 2) { 1917 if (n == 2) {
1915 __ beq(T3, T1, &found); 1918 __ beq(T3, T1, &found);
1916 } else { 1919 } else {
1917 __ bne(T3, T1, &next_iteration); 1920 __ bne(T3, T1, &next_iteration);
1918 __ lw(T3, Address(T2, kWordSize * 1921 __ lw(T3, Address(T2, kWordSize *
1919 SubtypeTestCache::kInstantiatorTypeArguments)); 1922 SubtypeTestCache::kInstantiatorTypeArguments));
1920 __ beq(T3, A1, &found); 1923 __ beq(T3, A1, &found);
1921 } 1924 }
1922 } 1925 }
1923 __ Bind(&next_iteration); 1926 __ Bind(&next_iteration);
1924 __ b(&loop); 1927 __ b(&loop);
1925 __ delay_slot()->addiu(T2, T2, 1928 __ delay_slot()->addiu(
1926 Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); 1929 T2, T2, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength));
1927 // Fall through to not found. 1930 // Fall through to not found.
1928 __ Bind(&not_found); 1931 __ Bind(&not_found);
1929 __ Ret(); 1932 __ Ret();
1930 __ delay_slot()->mov(V0, T7); 1933 __ delay_slot()->mov(V0, T7);
1931 1934
1932 __ Bind(&found); 1935 __ Bind(&found);
1933 __ Ret(); 1936 __ Ret();
1934 __ delay_slot()->lw(V0, 1937 __ delay_slot()->lw(V0,
1935 Address(T2, kWordSize * SubtypeTestCache::kTestResult)); 1938 Address(T2, kWordSize * SubtypeTestCache::kTestResult));
1936 } 1939 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1985 // A3: error object. 1988 // A3: error object.
1986 // SP + 4*kWordSize: address of stacktrace object. 1989 // SP + 4*kWordSize: address of stacktrace object.
1987 // SP + 5*kWordSize: address of thread. 1990 // SP + 5*kWordSize: address of thread.
1988 // Does not return. 1991 // Does not return.
1989 void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) { 1992 void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
1990 ASSERT(kExceptionObjectReg == V0); 1993 ASSERT(kExceptionObjectReg == V0);
1991 ASSERT(kStackTraceObjectReg == V1); 1994 ASSERT(kStackTraceObjectReg == V1);
1992 __ mov(V0, A3); // Exception object. 1995 __ mov(V0, A3); // Exception object.
1993 // MIPS ABI reserves stack space for all arguments. The StackTrace object is 1996 // MIPS ABI reserves stack space for all arguments. The StackTrace object is
1994 // the last of five arguments, so it is first pushed on the stack. 1997 // the last of five arguments, so it is first pushed on the stack.
1995 __ lw(V1, Address(SP, 4 * kWordSize)); // StackTrace object. 1998 __ lw(V1, Address(SP, 4 * kWordSize)); // StackTrace object.
1996 __ mov(FP, A2); // Frame_pointer. 1999 __ mov(FP, A2); // Frame_pointer.
1997 __ lw(THR, Address(SP, 5 * kWordSize)); // Thread. 2000 __ lw(THR, Address(SP, 5 * kWordSize)); // Thread.
1998 // Set tag. 2001 // Set tag.
1999 __ LoadImmediate(A2, VMTag::kDartTagId); 2002 __ LoadImmediate(A2, VMTag::kDartTagId);
2000 __ sw(A2, Assembler::VMTagAddress()); 2003 __ sw(A2, Assembler::VMTagAddress());
2001 // Clear top exit frame. 2004 // Clear top exit frame.
2002 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset())); 2005 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset()));
2003 // Restore pool pointer. 2006 // Restore pool pointer.
2004 __ RestoreCodePointer(); 2007 __ RestoreCodePointer();
2005 __ LoadPoolPointer(); 2008 __ LoadPoolPointer();
2006 __ jr(A0); // Jump to the exception handler code. 2009 __ jr(A0); // Jump to the exception handler code.
2007 __ delay_slot()->mov(SP, A1); // Stack pointer. 2010 __ delay_slot()->mov(SP, A1); // Stack pointer.
2008 } 2011 }
2009 2012
2010 2013
2011 // Calls to the runtime to optimize the given function. 2014 // Calls to the runtime to optimize the given function.
2012 // T0: function to be reoptimized. 2015 // T0: function to be reoptimized.
2013 // S4: argument descriptor (preserved). 2016 // S4: argument descriptor (preserved).
2014 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 2017 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
2015 __ Comment("OptimizeFunctionStub"); 2018 __ Comment("OptimizeFunctionStub");
2016 __ EnterStubFrame(); 2019 __ EnterStubFrame();
2017 __ addiu(SP, SP, Immediate(-3 * kWordSize)); 2020 __ addiu(SP, SP, Immediate(-3 * kWordSize));
2018 __ sw(S4, Address(SP, 2 * kWordSize)); 2021 __ sw(S4, Address(SP, 2 * kWordSize));
2019 // Setup space on stack for return value. 2022 // Setup space on stack for return value.
2020 __ sw(ZR, Address(SP, 1 * kWordSize)); 2023 __ sw(ZR, Address(SP, 1 * kWordSize));
2021 __ sw(T0, Address(SP, 0 * kWordSize)); 2024 __ sw(T0, Address(SP, 0 * kWordSize));
2022 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); 2025 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
2023 __ Comment("OptimizeFunctionStub return"); 2026 __ Comment("OptimizeFunctionStub return");
2024 __ lw(T0, Address(SP, 1 * kWordSize)); // Get Function object 2027 __ lw(T0, Address(SP, 1 * kWordSize)); // Get Function object
2025 __ lw(S4, Address(SP, 2 * kWordSize)); // Restore argument descriptor. 2028 __ lw(S4, Address(SP, 2 * kWordSize)); // Restore argument descriptor.
2026 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Discard argument. 2029 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Discard argument.
2027 2030
2028 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); 2031 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset()));
2029 __ lw(T1, FieldAddress(T0, Function::entry_point_offset())); 2032 __ lw(T1, FieldAddress(T0, Function::entry_point_offset()));
2030 __ LeaveStubFrameAndReturn(T1); 2033 __ LeaveStubFrameAndReturn(T1);
2031 __ break_(0); 2034 __ break_(0);
2032 } 2035 }
2033 2036
2034 2037
2035 // Does identical check (object references are equal or not equal) with special 2038 // Does identical check (object references are equal or not equal) with special
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
2378 } 2381 }
2379 2382
2380 2383
2381 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { 2384 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
2382 __ break_(0); 2385 __ break_(0);
2383 } 2386 }
2384 2387
2385 } // namespace dart 2388 } // namespace dart
2386 2389
2387 #endif // defined TARGET_ARCH_MIPS 2390 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_ia32_test.cc ('k') | runtime/vm/stub_code_mips_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698