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 23 matching lines...) Expand all Loading... |
34 // SP : address of last argument in argument array. | 34 // SP : address of last argument in argument array. |
35 // SP + 4*S4 - 4 : address of first argument in argument array. | 35 // SP + 4*S4 - 4 : address of first argument in argument array. |
36 // SP + 4*S4 : address of return value. | 36 // SP + 4*S4 : address of return value. |
37 // S5 : address of the runtime function to call. | 37 // S5 : address of the runtime function to call. |
38 // S4 : number of arguments to the call. | 38 // S4 : number of arguments to the call. |
39 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 39 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
40 const intptr_t thread_offset = NativeArguments::thread_offset(); | 40 const intptr_t thread_offset = NativeArguments::thread_offset(); |
41 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); | 41 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); |
42 const intptr_t argv_offset = NativeArguments::argv_offset(); | 42 const intptr_t argv_offset = NativeArguments::argv_offset(); |
43 const intptr_t retval_offset = NativeArguments::retval_offset(); | 43 const intptr_t retval_offset = NativeArguments::retval_offset(); |
| 44 const intptr_t exitframe_last_param_slot_from_fp = 2; |
44 | 45 |
45 __ SetPrologueOffset(); | 46 __ SetPrologueOffset(); |
46 __ Comment("CallToRuntimeStub"); | 47 __ Comment("CallToRuntimeStub"); |
47 __ EnterStubFrame(); | 48 __ EnterStubFrame(); |
48 | 49 |
49 COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << S2)) != 0); | 50 COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << S6)) != 0); |
50 __ LoadIsolate(S2); | 51 __ LoadIsolate(S6); |
51 | 52 |
52 // Save exit frame information to enable stack walking as we are about | 53 // Save exit frame information to enable stack walking as we are about |
53 // to transition to Dart VM C++ code. | 54 // to transition to Dart VM C++ code. |
54 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset())); | 55 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset())); |
55 | 56 |
56 #if defined(DEBUG) | 57 #if defined(DEBUG) |
57 { Label ok; | 58 { Label ok; |
58 // Check that we are always entering from Dart code. | 59 // Check that we are always entering from Dart code. |
59 __ lw(T0, Address(S2, Isolate::vm_tag_offset())); | 60 __ lw(T0, Address(S6, Isolate::vm_tag_offset())); |
60 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); | 61 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); |
61 __ Stop("Not coming from Dart code."); | 62 __ Stop("Not coming from Dart code."); |
62 __ Bind(&ok); | 63 __ Bind(&ok); |
63 } | 64 } |
64 #endif | 65 #endif |
65 | 66 |
66 // Mark that the isolate is executing VM code. | 67 // Mark that the isolate is executing VM code. |
67 __ sw(S5, Address(S2, Isolate::vm_tag_offset())); | 68 __ sw(S5, Address(S6, Isolate::vm_tag_offset())); |
68 | 69 |
69 // Reserve space for arguments and align frame before entering C++ world. | 70 // Reserve space for arguments and align frame before entering C++ world. |
70 // NativeArguments are passed in registers. | 71 // NativeArguments are passed in registers. |
71 ASSERT(sizeof(NativeArguments) == 4 * kWordSize); | 72 ASSERT(sizeof(NativeArguments) == 4 * kWordSize); |
72 __ ReserveAlignedFrameSpace(4 * kWordSize); // Reserve space for arguments. | 73 __ ReserveAlignedFrameSpace(4 * kWordSize); // Reserve space for arguments. |
73 | 74 |
74 // Pass NativeArguments structure by value and call runtime. | 75 // Pass NativeArguments structure by value and call runtime. |
75 // Registers A0, A1, A2, and A3 are used. | 76 // Registers A0, A1, A2, and A3 are used. |
76 | 77 |
77 ASSERT(thread_offset == 0 * kWordSize); | 78 ASSERT(thread_offset == 0 * kWordSize); |
78 // Set thread in NativeArgs. | 79 // Set thread in NativeArgs. |
79 __ mov(A0, THR); | 80 __ mov(A0, THR); |
80 | 81 |
81 // There are no runtime calls to closures, so we do not need to set the tag | 82 // There are no runtime calls to closures, so we do not need to set the tag |
82 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. | 83 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. |
83 ASSERT(argc_tag_offset == 1 * kWordSize); | 84 ASSERT(argc_tag_offset == 1 * kWordSize); |
84 __ mov(A1, S4); // Set argc in NativeArguments. | 85 __ mov(A1, S4); // Set argc in NativeArguments. |
85 | 86 |
86 ASSERT(argv_offset == 2 * kWordSize); | 87 ASSERT(argv_offset == 2 * kWordSize); |
87 __ sll(A2, S4, 2); | 88 __ sll(A2, S4, 2); |
88 __ addu(A2, FP, A2); // Compute argv. | 89 __ addu(A2, FP, A2); // Compute argv. |
89 // Set argv in NativeArguments. | 90 // Set argv in NativeArguments. |
90 __ addiu(A2, A2, Immediate(kParamEndSlotFromFp * kWordSize)); | 91 __ addiu(A2, A2, Immediate(exitframe_last_param_slot_from_fp * kWordSize)); |
91 | 92 |
92 | 93 |
93 // Call runtime or redirection via simulator. | 94 // Call runtime or redirection via simulator. |
94 // We defensively always jalr through T9 because it is sometimes required by | 95 // We defensively always jalr through T9 because it is sometimes required by |
95 // the MIPS ABI. | 96 // the MIPS ABI. |
96 __ mov(T9, S5); | 97 __ mov(T9, S5); |
97 __ jalr(T9); | 98 __ jalr(T9); |
98 | 99 |
99 ASSERT(retval_offset == 3 * kWordSize); | 100 ASSERT(retval_offset == 3 * kWordSize); |
100 // Retval is next to 1st argument. | 101 // Retval is next to 1st argument. |
101 __ delay_slot()->addiu(A3, A2, Immediate(kWordSize)); | 102 __ delay_slot()->addiu(A3, A2, Immediate(kWordSize)); |
102 __ Comment("CallToRuntimeStub return"); | 103 __ Comment("CallToRuntimeStub return"); |
103 | 104 |
104 // Mark that the isolate is executing Dart code. | 105 // Mark that the isolate is executing Dart code. |
105 __ LoadImmediate(A2, VMTag::kDartTagId); | 106 __ LoadImmediate(A2, VMTag::kDartTagId); |
106 __ sw(A2, Address(S2, Isolate::vm_tag_offset())); | 107 __ sw(A2, Address(S6, Isolate::vm_tag_offset())); |
107 | 108 |
108 // Reset exit frame information in Isolate structure. | 109 // Reset exit frame information in Isolate structure. |
109 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset())); | 110 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset())); |
110 | 111 |
111 __ LeaveStubFrameAndReturn(); | 112 __ LeaveStubFrameAndReturn(); |
112 } | 113 } |
113 | 114 |
114 | 115 |
115 // Print the stop message. | 116 // Print the stop message. |
116 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { | 117 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { |
(...skipping 23 matching lines...) Expand all Loading... |
140 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { | 141 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { |
141 const intptr_t thread_offset = NativeArguments::thread_offset(); | 142 const intptr_t thread_offset = NativeArguments::thread_offset(); |
142 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); | 143 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); |
143 const intptr_t argv_offset = NativeArguments::argv_offset(); | 144 const intptr_t argv_offset = NativeArguments::argv_offset(); |
144 const intptr_t retval_offset = NativeArguments::retval_offset(); | 145 const intptr_t retval_offset = NativeArguments::retval_offset(); |
145 | 146 |
146 __ SetPrologueOffset(); | 147 __ SetPrologueOffset(); |
147 __ Comment("CallNativeCFunctionStub"); | 148 __ Comment("CallNativeCFunctionStub"); |
148 __ EnterStubFrame(); | 149 __ EnterStubFrame(); |
149 | 150 |
150 COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << S2)) != 0); | 151 COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << S6)) != 0); |
151 __ LoadIsolate(S2); | 152 __ LoadIsolate(S6); |
152 | 153 |
153 // Save exit frame information to enable stack walking as we are about | 154 // Save exit frame information to enable stack walking as we are about |
154 // to transition to native code. | 155 // to transition to native code. |
155 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset())); | 156 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset())); |
156 | 157 |
157 #if defined(DEBUG) | 158 #if defined(DEBUG) |
158 { Label ok; | 159 { Label ok; |
159 // Check that we are always entering from Dart code. | 160 // Check that we are always entering from Dart code. |
160 __ lw(T0, Address(S2, Isolate::vm_tag_offset())); | 161 __ lw(T0, Address(S6, Isolate::vm_tag_offset())); |
161 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); | 162 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); |
162 __ Stop("Not coming from Dart code."); | 163 __ Stop("Not coming from Dart code."); |
163 __ Bind(&ok); | 164 __ Bind(&ok); |
164 } | 165 } |
165 #endif | 166 #endif |
166 | 167 |
167 // Mark that the isolate is executing Native code. | 168 // Mark that the isolate is executing Native code. |
168 __ sw(T5, Address(S2, Isolate::vm_tag_offset())); | 169 __ sw(T5, Address(S6, Isolate::vm_tag_offset())); |
169 | 170 |
170 // Initialize NativeArguments structure and call native function. | 171 // Initialize NativeArguments structure and call native function. |
171 // Registers A0, A1, A2, and A3 are used. | 172 // Registers A0, A1, A2, and A3 are used. |
172 | 173 |
173 ASSERT(thread_offset == 0 * kWordSize); | 174 ASSERT(thread_offset == 0 * kWordSize); |
174 // Set thread in NativeArgs. | 175 // Set thread in NativeArgs. |
175 __ mov(A0, THR); | 176 __ mov(A0, THR); |
176 | 177 |
177 // There are no native calls to closures, so we do not need to set the tag | 178 // There are no native calls to closures, so we do not need to set the tag |
178 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. | 179 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. |
179 ASSERT(argc_tag_offset == 1 * kWordSize); | 180 ASSERT(argc_tag_offset == 1 * kWordSize); |
180 // Set argc in NativeArguments: A1 already contains argc. | 181 // Set argc in NativeArguments: A1 already contains argc. |
181 | 182 |
182 ASSERT(argv_offset == 2 * kWordSize); | 183 ASSERT(argv_offset == 2 * kWordSize); |
183 // Set argv in NativeArguments: A2 already contains argv. | 184 // Set argv in NativeArguments: A2 already contains argv. |
184 | 185 |
185 ASSERT(retval_offset == 3 * kWordSize); | 186 ASSERT(retval_offset == 3 * kWordSize); |
186 // Set retval in NativeArgs. | 187 __ addiu(A3, FP, Immediate(3 * kWordSize)); // Set retval in NativeArgs. |
187 __ addiu(A3, FP, Immediate(kCallerSpSlotFromFp * kWordSize)); | |
188 | 188 |
189 // Passing the structure by value as in runtime calls would require changing | 189 // Passing the structure by value as in runtime calls would require changing |
190 // Dart API for native functions. | 190 // Dart API for native functions. |
191 // For now, space is reserved on the stack and we pass a pointer to it. | 191 // For now, space is reserved on the stack and we pass a pointer to it. |
192 __ addiu(SP, SP, Immediate(-4 * kWordSize)); | 192 __ addiu(SP, SP, Immediate(-4 * kWordSize)); |
193 __ sw(A3, Address(SP, 3 * kWordSize)); | 193 __ sw(A3, Address(SP, 3 * kWordSize)); |
194 __ sw(A2, Address(SP, 2 * kWordSize)); | 194 __ sw(A2, Address(SP, 2 * kWordSize)); |
195 __ sw(A1, Address(SP, 1 * kWordSize)); | 195 __ sw(A1, Address(SP, 1 * kWordSize)); |
196 __ sw(A0, Address(SP, 0 * kWordSize)); | 196 __ sw(A0, Address(SP, 0 * kWordSize)); |
197 __ mov(A0, SP); // Pass the pointer to the NativeArguments. | 197 __ mov(A0, SP); // Pass the pointer to the NativeArguments. |
198 | 198 |
199 | 199 |
200 __ mov(A1, T5); // Pass the function entrypoint. | 200 __ mov(A1, T5); // Pass the function entrypoint. |
201 __ ReserveAlignedFrameSpace(2 * kWordSize); // Just passing A0, A1. | 201 __ ReserveAlignedFrameSpace(2 * kWordSize); // Just passing A0, A1. |
202 // Call native wrapper function or redirection via simulator. | 202 // Call native wrapper function or redirection via simulator. |
203 #if defined(USING_SIMULATOR) | 203 #if defined(USING_SIMULATOR) |
204 uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper); | 204 uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper); |
205 entry = Simulator::RedirectExternalReference( | 205 entry = Simulator::RedirectExternalReference( |
206 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); | 206 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); |
207 __ LoadImmediate(T9, entry); | 207 __ LoadImmediate(T9, entry); |
208 __ jalr(T9); | 208 __ jalr(T9); |
209 #else | 209 #else |
210 __ BranchLink(&NativeEntry::NativeCallWrapperLabel(), kNotPatchable); | 210 __ BranchLink(&NativeEntry::NativeCallWrapperLabel(), kNotPatchable); |
211 #endif | 211 #endif |
212 __ Comment("CallNativeCFunctionStub return"); | 212 __ Comment("CallNativeCFunctionStub return"); |
213 | 213 |
214 // Mark that the isolate is executing Dart code. | 214 // Mark that the isolate is executing Dart code. |
215 __ LoadImmediate(A2, VMTag::kDartTagId); | 215 __ LoadImmediate(A2, VMTag::kDartTagId); |
216 __ sw(A2, Address(S2, Isolate::vm_tag_offset())); | 216 __ sw(A2, Address(S6, Isolate::vm_tag_offset())); |
217 | 217 |
218 // Reset exit frame information in Isolate structure. | 218 // Reset exit frame information in Isolate structure. |
219 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset())); | 219 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset())); |
220 | 220 |
221 __ LeaveStubFrameAndReturn(); | 221 __ LeaveStubFrameAndReturn(); |
222 } | 222 } |
223 | 223 |
224 | 224 |
225 // Input parameters: | 225 // Input parameters: |
226 // RA : return address. | 226 // RA : return address. |
227 // SP : address of return value. | 227 // SP : address of return value. |
228 // T5 : address of the native function to call. | 228 // T5 : address of the native function to call. |
229 // A2 : address of first argument in argument array. | 229 // A2 : address of first argument in argument array. |
230 // A1 : argc_tag including number of arguments and function kind. | 230 // A1 : argc_tag including number of arguments and function kind. |
231 void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) { | 231 void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) { |
232 const intptr_t thread_offset = NativeArguments::thread_offset(); | 232 const intptr_t thread_offset = NativeArguments::thread_offset(); |
233 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); | 233 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); |
234 const intptr_t argv_offset = NativeArguments::argv_offset(); | 234 const intptr_t argv_offset = NativeArguments::argv_offset(); |
235 const intptr_t retval_offset = NativeArguments::retval_offset(); | 235 const intptr_t retval_offset = NativeArguments::retval_offset(); |
236 | 236 |
237 __ SetPrologueOffset(); | 237 __ SetPrologueOffset(); |
238 __ Comment("CallNativeCFunctionStub"); | 238 __ Comment("CallNativeCFunctionStub"); |
239 __ EnterStubFrame(); | 239 __ EnterStubFrame(); |
240 | 240 |
241 COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << S2)) != 0); | 241 COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << S6)) != 0); |
242 __ LoadIsolate(S2); | 242 __ LoadIsolate(S6); |
243 | 243 |
244 // Save exit frame information to enable stack walking as we are about | 244 // Save exit frame information to enable stack walking as we are about |
245 // to transition to native code. | 245 // to transition to native code. |
246 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset())); | 246 __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset())); |
247 | 247 |
248 #if defined(DEBUG) | 248 #if defined(DEBUG) |
249 { Label ok; | 249 { Label ok; |
250 // Check that we are always entering from Dart code. | 250 // Check that we are always entering from Dart code. |
251 __ lw(T0, Address(S2, Isolate::vm_tag_offset())); | 251 __ lw(T0, Address(S6, Isolate::vm_tag_offset())); |
252 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); | 252 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); |
253 __ Stop("Not coming from Dart code."); | 253 __ Stop("Not coming from Dart code."); |
254 __ Bind(&ok); | 254 __ Bind(&ok); |
255 } | 255 } |
256 #endif | 256 #endif |
257 | 257 |
258 // Mark that the isolate is executing Native code. | 258 // Mark that the isolate is executing Native code. |
259 __ sw(T5, Address(S2, Isolate::vm_tag_offset())); | 259 __ sw(T5, Address(S6, Isolate::vm_tag_offset())); |
260 | 260 |
261 // Initialize NativeArguments structure and call native function. | 261 // Initialize NativeArguments structure and call native function. |
262 // Registers A0, A1, A2, and A3 are used. | 262 // Registers A0, A1, A2, and A3 are used. |
263 | 263 |
264 ASSERT(thread_offset == 0 * kWordSize); | 264 ASSERT(thread_offset == 0 * kWordSize); |
265 // Set thread in NativeArgs. | 265 // Set thread in NativeArgs. |
266 __ mov(A0, THR); | 266 __ mov(A0, THR); |
267 | 267 |
268 // There are no native calls to closures, so we do not need to set the tag | 268 // There are no native calls to closures, so we do not need to set the tag |
269 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. | 269 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. |
270 ASSERT(argc_tag_offset == 1 * kWordSize); | 270 ASSERT(argc_tag_offset == 1 * kWordSize); |
271 // Set argc in NativeArguments: A1 already contains argc. | 271 // Set argc in NativeArguments: A1 already contains argc. |
272 | 272 |
273 ASSERT(argv_offset == 2 * kWordSize); | 273 ASSERT(argv_offset == 2 * kWordSize); |
274 // Set argv in NativeArguments: A2 already contains argv. | 274 // Set argv in NativeArguments: A2 already contains argv. |
275 | 275 |
276 ASSERT(retval_offset == 3 * kWordSize); | 276 ASSERT(retval_offset == 3 * kWordSize); |
277 // Set retval in NativeArgs. | 277 __ addiu(A3, FP, Immediate(3 * kWordSize)); // Set retval in NativeArgs. |
278 __ addiu(A3, FP, Immediate(kCallerSpSlotFromFp * kWordSize)); | |
279 | 278 |
280 // Passing the structure by value as in runtime calls would require changing | 279 // Passing the structure by value as in runtime calls would require changing |
281 // Dart API for native functions. | 280 // Dart API for native functions. |
282 // For now, space is reserved on the stack and we pass a pointer to it. | 281 // For now, space is reserved on the stack and we pass a pointer to it. |
283 __ addiu(SP, SP, Immediate(-4 * kWordSize)); | 282 __ addiu(SP, SP, Immediate(-4 * kWordSize)); |
284 __ sw(A3, Address(SP, 3 * kWordSize)); | 283 __ sw(A3, Address(SP, 3 * kWordSize)); |
285 __ sw(A2, Address(SP, 2 * kWordSize)); | 284 __ sw(A2, Address(SP, 2 * kWordSize)); |
286 __ sw(A1, Address(SP, 1 * kWordSize)); | 285 __ sw(A1, Address(SP, 1 * kWordSize)); |
287 __ sw(A0, Address(SP, 0 * kWordSize)); | 286 __ sw(A0, Address(SP, 0 * kWordSize)); |
288 __ mov(A0, SP); // Pass the pointer to the NativeArguments. | 287 __ mov(A0, SP); // Pass the pointer to the NativeArguments. |
289 | 288 |
290 __ ReserveAlignedFrameSpace(kWordSize); // Just passing A0. | 289 __ ReserveAlignedFrameSpace(kWordSize); // Just passing A0. |
291 | 290 |
292 // Call native function or redirection via simulator. | 291 // Call native function or redirection via simulator. |
293 | 292 |
294 // We defensively always jalr through T9 because it is sometimes required by | 293 // We defensively always jalr through T9 because it is sometimes required by |
295 // the MIPS ABI. | 294 // the MIPS ABI. |
296 __ mov(T9, T5); | 295 __ mov(T9, T5); |
297 __ jalr(T9); | 296 __ jalr(T9); |
298 __ Comment("CallNativeCFunctionStub return"); | 297 __ Comment("CallNativeCFunctionStub return"); |
299 | 298 |
300 // Mark that the isolate is executing Dart code. | 299 // Mark that the isolate is executing Dart code. |
301 __ LoadImmediate(A2, VMTag::kDartTagId); | 300 __ LoadImmediate(A2, VMTag::kDartTagId); |
302 __ sw(A2, Address(S2, Isolate::vm_tag_offset())); | 301 __ sw(A2, Address(S6, Isolate::vm_tag_offset())); |
303 | 302 |
304 // Reset exit frame information in Isolate structure. | 303 // Reset exit frame information in Isolate structure. |
305 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset())); | 304 __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset())); |
306 | 305 |
307 __ LeaveStubFrameAndReturn(); | 306 __ LeaveStubFrameAndReturn(); |
308 } | 307 } |
309 | 308 |
310 | 309 |
311 // Input parameters: | 310 // Input parameters: |
312 // S4: arguments descriptor array. | 311 // S4: arguments descriptor array. |
313 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 312 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
314 __ Comment("CallStaticFunctionStub"); | 313 __ Comment("CallStaticFunctionStub"); |
315 __ EnterStubFrame(); | 314 __ EnterStubFrame(); |
316 // Setup space on stack for return value and preserve arguments descriptor. | 315 // Setup space on stack for return value and preserve arguments descriptor. |
317 | 316 |
318 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 317 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
319 __ sw(S4, Address(SP, 1 * kWordSize)); | 318 __ sw(S4, Address(SP, 1 * kWordSize)); |
320 __ LoadObject(TMP, Object::null_object()); | 319 __ LoadObject(TMP, Object::null_object()); |
321 __ sw(TMP, Address(SP, 0 * kWordSize)); | 320 __ sw(TMP, Address(SP, 0 * kWordSize)); |
322 | 321 |
323 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); | 322 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); |
324 __ Comment("CallStaticFunctionStub return"); | 323 __ Comment("CallStaticFunctionStub return"); |
325 | 324 |
326 // Get Code object result and restore arguments descriptor array. | 325 // Get Code object result and restore arguments descriptor array. |
327 __ lw(CODE_REG, Address(SP, 0 * kWordSize)); | 326 __ lw(T0, Address(SP, 0 * kWordSize)); |
328 __ lw(S4, Address(SP, 1 * kWordSize)); | 327 __ lw(S4, Address(SP, 1 * kWordSize)); |
329 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 328 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
330 | 329 |
331 __ lw(T0, FieldAddress(CODE_REG, Code::entry_point_offset())); | 330 __ lw(T0, FieldAddress(T0, Code::entry_point_offset())); |
332 | 331 |
333 // Remove the stub frame as we are about to jump to the dart function. | 332 // Remove the stub frame as we are about to jump to the dart function. |
334 __ LeaveStubFrameAndReturn(T0); | 333 __ LeaveStubFrameAndReturn(T0); |
335 } | 334 } |
336 | 335 |
337 | 336 |
338 // Called from a static call only when an invalid code has been entered | 337 // Called from a static call only when an invalid code has been entered |
339 // (invalid because its function was optimized or deoptimized). | 338 // (invalid because its function was optimized or deoptimized). |
340 // S4: arguments descriptor array. | 339 // S4: arguments descriptor array. |
341 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 340 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
342 // Load code pointer to this stub from the thread: | |
343 // The one that is passed in, is not correct - it points to the code object | |
344 // that needs to be replaced. | |
345 __ lw(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset())); | |
346 // Create a stub frame as we are pushing some objects on the stack before | 341 // Create a stub frame as we are pushing some objects on the stack before |
347 // calling into the runtime. | 342 // calling into the runtime. |
| 343 __ Comment("FixCallersTarget"); |
348 __ EnterStubFrame(); | 344 __ EnterStubFrame(); |
349 // Setup space on stack for return value and preserve arguments descriptor. | 345 // Setup space on stack for return value and preserve arguments descriptor. |
350 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 346 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
351 __ sw(S4, Address(SP, 1 * kWordSize)); | 347 __ sw(S4, Address(SP, 1 * kWordSize)); |
352 __ LoadObject(TMP, Object::null_object()); | 348 __ LoadObject(TMP, Object::null_object()); |
353 __ sw(TMP, Address(SP, 0 * kWordSize)); | 349 __ sw(TMP, Address(SP, 0 * kWordSize)); |
354 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); | 350 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); |
355 // Get Code object result and restore arguments descriptor array. | 351 // Get Code object result and restore arguments descriptor array. |
356 __ lw(CODE_REG, Address(SP, 0 * kWordSize)); | 352 __ lw(T0, Address(SP, 0 * kWordSize)); |
357 __ lw(S4, Address(SP, 1 * kWordSize)); | 353 __ lw(S4, Address(SP, 1 * kWordSize)); |
358 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 354 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
359 | 355 |
360 // Jump to the dart function. | 356 // Jump to the dart function. |
361 __ lw(T0, FieldAddress(CODE_REG, Code::entry_point_offset())); | 357 __ lw(T0, FieldAddress(T0, Code::entry_point_offset())); |
362 | 358 |
363 // Remove the stub frame. | 359 // Remove the stub frame. |
364 __ LeaveStubFrameAndReturn(T0); | 360 __ LeaveStubFrameAndReturn(T0); |
365 } | 361 } |
366 | 362 |
367 | 363 |
368 // Called from object allocate instruction when the allocation stub has been | 364 // Called from object allocate instruction when the allocation stub has been |
369 // disabled. | 365 // disabled. |
370 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { | 366 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { |
371 // Load code pointer to this stub from the thread: | 367 __ Comment("FixAllocationStubTarget"); |
372 // The one that is passed in, is not correct - it points to the code object | |
373 // that needs to be replaced. | |
374 __ lw(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset())); | |
375 __ EnterStubFrame(); | 368 __ EnterStubFrame(); |
376 // Setup space on stack for return value. | 369 // Setup space on stack for return value. |
377 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 370 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
378 __ LoadObject(TMP, Object::null_object()); | 371 __ LoadObject(TMP, Object::null_object()); |
379 __ sw(TMP, Address(SP, 0 * kWordSize)); | 372 __ sw(TMP, Address(SP, 0 * kWordSize)); |
380 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); | 373 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); |
381 // Get Code object result. | 374 // Get Code object result. |
382 __ lw(CODE_REG, Address(SP, 0 * kWordSize)); | 375 __ lw(T0, Address(SP, 0 * kWordSize)); |
383 __ addiu(SP, SP, Immediate(1 * kWordSize)); | 376 __ addiu(SP, SP, Immediate(1 * kWordSize)); |
384 | 377 |
385 // Jump to the dart function. | 378 // Jump to the dart function. |
386 __ lw(T0, FieldAddress(CODE_REG, Code::entry_point_offset())); | 379 __ lw(T0, FieldAddress(T0, Code::entry_point_offset())); |
387 | 380 |
388 // Remove the stub frame. | 381 // Remove the stub frame. |
389 __ LeaveStubFrameAndReturn(T0); | 382 __ LeaveStubFrameAndReturn(T0); |
390 } | 383 } |
391 | 384 |
392 | 385 |
393 // Input parameters: | 386 // Input parameters: |
394 // A1: Smi-tagged argument count, may be zero. | 387 // A1: Smi-tagged argument count, may be zero. |
395 // FP[kParamEndSlotFromFp + 1]: Last argument. | 388 // FP[kParamEndSlotFromFp + 1]: Last argument. |
396 static void PushArgumentsArray(Assembler* assembler) { | 389 static void PushArgumentsArray(Assembler* assembler) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 // - Push all registers that can contain values. | 426 // - Push all registers that can contain values. |
434 // - Call C routine to copy the stack and saved registers into temporary buffer. | 427 // - Call C routine to copy the stack and saved registers into temporary buffer. |
435 // - Adjust caller's frame to correct unoptimized frame size. | 428 // - Adjust caller's frame to correct unoptimized frame size. |
436 // - Fill the unoptimized frame. | 429 // - Fill the unoptimized frame. |
437 // - Materialize objects that require allocation (e.g. Double instances). | 430 // - Materialize objects that require allocation (e.g. Double instances). |
438 // GC can occur only after frame is fully rewritten. | 431 // GC can occur only after frame is fully rewritten. |
439 // Stack after EnterFrame(...) below: | 432 // Stack after EnterFrame(...) below: |
440 // +------------------+ | 433 // +------------------+ |
441 // | Saved PP | <- TOS | 434 // | Saved PP | <- TOS |
442 // +------------------+ | 435 // +------------------+ |
443 // | Saved CODE_REG | | |
444 // +------------------+ | |
445 // | Saved FP | <- FP of stub | 436 // | Saved FP | <- FP of stub |
446 // +------------------+ | 437 // +------------------+ |
447 // | Saved LR | (deoptimization point) | 438 // | Saved LR | (deoptimization point) |
448 // +------------------+ | 439 // +------------------+ |
449 // | Saved CODE_REG | | 440 // | PC marker | |
450 // +------------------+ | 441 // +------------------+ |
451 // | ... | <- SP of optimized frame | 442 // | ... | <- SP of optimized frame |
452 // | 443 // |
453 // Parts of the code cannot GC, part of the code can GC. | 444 // Parts of the code cannot GC, part of the code can GC. |
454 static void GenerateDeoptimizationSequence(Assembler* assembler, | 445 static void GenerateDeoptimizationSequence(Assembler* assembler, |
455 DeoptStubKind kind) { | 446 bool preserve_result) { |
456 const intptr_t kPushedRegistersSize = | 447 const intptr_t kPushedRegistersSize = |
457 kNumberOfCpuRegisters * kWordSize + kNumberOfFRegisters * kWordSize; | 448 kNumberOfCpuRegisters * kWordSize + |
| 449 4 * kWordSize + // PP, FP, RA, PC marker. |
| 450 kNumberOfFRegisters * kWordSize; |
458 | 451 |
459 __ SetPrologueOffset(); | 452 __ SetPrologueOffset(); |
460 __ Comment("GenerateDeoptimizationSequence"); | 453 __ Comment("GenerateDeoptimizationSequence"); |
461 // DeoptimizeCopyFrame expects a Dart frame. | 454 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
462 __ EnterStubFrame(kPushedRegistersSize); | 455 // is no need to set the correct PC marker or load PP, since they get patched. |
| 456 __ addiu(SP, SP, Immediate(-kPushedRegistersSize * kWordSize)); |
| 457 __ sw(ZR, Address(SP, kPushedRegistersSize - 1 * kWordSize)); |
| 458 __ sw(RA, Address(SP, kPushedRegistersSize - 2 * kWordSize)); |
| 459 __ sw(FP, Address(SP, kPushedRegistersSize - 3 * kWordSize)); |
| 460 __ sw(PP, Address(SP, kPushedRegistersSize - 4 * kWordSize)); |
| 461 __ addiu(FP, SP, Immediate(kPushedRegistersSize - 3 * kWordSize)); |
| 462 |
| 463 __ LoadPoolPointer(); |
463 | 464 |
464 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry | 465 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
465 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. | 466 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
466 const intptr_t saved_result_slot_from_fp = | 467 const intptr_t saved_result_slot_from_fp = |
467 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - V0); | 468 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - V0); |
468 // Result in V0 is preserved as part of pushing all registers below. | 469 // Result in V0 is preserved as part of pushing all registers below. |
469 | 470 |
470 // Push registers in their enumeration order: lowest register number at | 471 // Push registers in their enumeration order: lowest register number at |
471 // lowest address. | 472 // lowest address. |
472 for (int i = 0; i < kNumberOfCpuRegisters; i++) { | 473 for (int i = 0; i < kNumberOfCpuRegisters; i++) { |
473 const int slot = kNumberOfCpuRegisters - i; | 474 const int slot = 4 + kNumberOfCpuRegisters - i; |
474 Register reg = static_cast<Register>(i); | 475 Register reg = static_cast<Register>(i); |
475 if (reg == CODE_REG) { | 476 __ sw(reg, Address(SP, kPushedRegistersSize - slot * kWordSize)); |
476 // Save the original value of CODE_REG pushed before invoking this stub | |
477 // instead of the value used to call this stub. | |
478 COMPILE_ASSERT(TMP < CODE_REG); // Assert TMP is pushed first. | |
479 __ lw(TMP, Address(FP, kCallerSpSlotFromFp * kWordSize)); | |
480 __ sw(TMP, Address(SP, kPushedRegistersSize - slot * kWordSize)); | |
481 } else { | |
482 __ sw(reg, Address(SP, kPushedRegistersSize - slot * kWordSize)); | |
483 } | |
484 } | 477 } |
485 for (int i = 0; i < kNumberOfFRegisters; i++) { | 478 for (int i = 0; i < kNumberOfFRegisters; i++) { |
486 // These go below the CPU registers. | 479 // These go below the CPU registers. |
487 const int slot = kNumberOfCpuRegisters + kNumberOfFRegisters - i; | 480 const int slot = 4 + kNumberOfCpuRegisters + kNumberOfFRegisters - i; |
488 FRegister reg = static_cast<FRegister>(i); | 481 FRegister reg = static_cast<FRegister>(i); |
489 __ swc1(reg, Address(SP, kPushedRegistersSize - slot * kWordSize)); | 482 __ swc1(reg, Address(SP, kPushedRegistersSize - slot * kWordSize)); |
490 } | 483 } |
491 | 484 |
492 __ mov(A0, SP); // Pass address of saved registers block. | 485 __ mov(A0, SP); // Pass address of saved registers block. |
493 __ LoadImmediate(A1, (kind == kLazyDeopt) ? 1 : 0); | |
494 __ ReserveAlignedFrameSpace(1 * kWordSize); | 486 __ ReserveAlignedFrameSpace(1 * kWordSize); |
495 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2); | 487 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1); |
496 // Result (V0) is stack-size (FP - SP) in bytes, incl. the return address. | 488 // Result (V0) is stack-size (FP - SP) in bytes, incl. the return address. |
497 | 489 |
498 const bool preserve_result = (kind == kLazyDeopt); | |
499 if (preserve_result) { | 490 if (preserve_result) { |
500 // Restore result into T1 temporarily. | 491 // Restore result into T1 temporarily. |
501 __ lw(T1, Address(FP, saved_result_slot_from_fp * kWordSize)); | 492 __ lw(T1, Address(FP, saved_result_slot_from_fp * kWordSize)); |
502 } | 493 } |
503 | 494 |
504 __ RestoreCodePointer(); | |
505 __ LeaveDartFrame(); | 495 __ LeaveDartFrame(); |
506 __ subu(SP, FP, V0); | 496 __ subu(SP, FP, V0); |
507 | 497 |
508 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there | 498 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
509 // is no need to set the correct PC marker or load PP, since they get patched. | 499 // is no need to set the correct PC marker or load PP, since they get patched. |
510 __ EnterStubFrame(); | 500 __ EnterStubFrame(); |
511 | 501 |
512 __ mov(A0, FP); // Get last FP address. | 502 __ mov(A0, FP); // Get last FP address. |
513 if (preserve_result) { | 503 if (preserve_result) { |
514 __ Push(T1); // Preserve result as first local. | 504 __ Push(T1); // Preserve result as first local. |
515 } | 505 } |
516 __ ReserveAlignedFrameSpace(1 * kWordSize); | 506 __ ReserveAlignedFrameSpace(1 * kWordSize); |
517 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); // Pass last FP in A0. | 507 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); // Pass last FP in A0. |
518 if (preserve_result) { | 508 if (preserve_result) { |
519 // Restore result into T1. | 509 // Restore result into T1. |
520 __ lw(T1, Address(FP, kFirstLocalSlotFromFp * kWordSize)); | 510 __ lw(T1, Address(FP, kFirstLocalSlotFromFp * kWordSize)); |
521 } | 511 } |
522 // Code above cannot cause GC. | 512 // Code above cannot cause GC. |
523 __ RestoreCodePointer(); | |
524 __ LeaveStubFrame(); | 513 __ LeaveStubFrame(); |
525 | 514 |
526 // Frame is fully rewritten at this point and it is safe to perform a GC. | 515 // Frame is fully rewritten at this point and it is safe to perform a GC. |
527 // Materialize any objects that were deferred by FillFrame because they | 516 // Materialize any objects that were deferred by FillFrame because they |
528 // require allocation. | 517 // require allocation. |
529 // Enter stub frame with loading PP. The caller's PP is not materialized yet. | 518 // Enter stub frame with loading PP. The caller's PP is not materialized yet. |
530 __ EnterStubFrame(); | 519 __ EnterStubFrame(); |
531 if (preserve_result) { | 520 if (preserve_result) { |
532 __ Push(T1); // Preserve result, it will be GC-d here. | 521 __ Push(T1); // Preserve result, it will be GC-d here. |
533 } | 522 } |
534 __ PushObject(Smi::ZoneHandle()); // Space for the result. | 523 __ PushObject(Smi::ZoneHandle()); // Space for the result. |
535 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0); | 524 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0); |
536 // Result tells stub how many bytes to remove from the expression stack | 525 // Result tells stub how many bytes to remove from the expression stack |
537 // of the bottom-most frame. They were used as materialization arguments. | 526 // of the bottom-most frame. They were used as materialization arguments. |
538 __ Pop(T1); | 527 __ Pop(T1); |
539 if (preserve_result) { | 528 if (preserve_result) { |
540 __ Pop(V0); // Restore result. | 529 __ Pop(V0); // Restore result. |
541 } | 530 } |
542 __ LeaveStubFrame(); | 531 __ LeaveStubFrame(); |
543 // Remove materialization arguments. | 532 // Remove materialization arguments. |
544 __ SmiUntag(T1); | 533 __ SmiUntag(T1); |
545 __ addu(SP, SP, T1); | 534 __ addu(SP, SP, T1); |
546 __ Ret(); | 535 __ Ret(); |
547 } | 536 } |
548 | 537 |
549 | 538 |
550 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { | 539 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { |
551 // Correct return address to point just after the call that is being | 540 // Correct return address to point just after the call that is being |
552 // deoptimized. | 541 // deoptimized. |
553 __ AddImmediate(RA, -CallPattern::kDeoptCallLengthInBytes); | 542 __ AddImmediate(RA, -CallPattern::kFixedLengthInBytes); |
554 // Push zap value instead of CODE_REG for lazy deopt. | 543 GenerateDeoptimizationSequence(assembler, true); // Preserve V0. |
555 __ LoadImmediate(TMP, 0xf1f1f1f1); | |
556 __ Push(TMP); | |
557 GenerateDeoptimizationSequence(assembler, kLazyDeopt); | |
558 } | 544 } |
559 | 545 |
560 | 546 |
561 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 547 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
562 GenerateDeoptimizationSequence(assembler, kEagerDeopt); | 548 GenerateDeoptimizationSequence(assembler, false); // Don't preserve V0. |
563 } | 549 } |
564 | 550 |
565 | 551 |
566 static void GenerateDispatcherCode(Assembler* assembler, | 552 static void GenerateDispatcherCode(Assembler* assembler, |
567 Label* call_target_function) { | 553 Label* call_target_function) { |
568 __ Comment("NoSuchMethodDispatch"); | 554 __ Comment("NoSuchMethodDispatch"); |
569 // When lazily generated invocation dispatchers are disabled, the | 555 // When lazily generated invocation dispatchers are disabled, the |
570 // miss-handler may return null. | 556 // miss-handler may return null. |
571 __ BranchNotEqual(T0, Object::null_object(), call_target_function); | 557 __ BranchNotEqual(T0, Object::null_object(), call_target_function); |
572 __ EnterStubFrame(); | 558 __ EnterStubFrame(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
622 __ sw(S5, Address(SP, 1 * kWordSize)); | 608 __ sw(S5, Address(SP, 1 * kWordSize)); |
623 __ sw(S4, Address(SP, 0 * kWordSize)); | 609 __ sw(S4, Address(SP, 0 * kWordSize)); |
624 | 610 |
625 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); | 611 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); |
626 | 612 |
627 __ lw(T0, Address(SP, 3 * kWordSize)); // Get result function. | 613 __ lw(T0, Address(SP, 3 * kWordSize)); // Get result function. |
628 __ lw(S4, Address(SP, 4 * kWordSize)); // Restore argument descriptor. | 614 __ lw(S4, Address(SP, 4 * kWordSize)); // Restore argument descriptor. |
629 __ lw(S5, Address(SP, 5 * kWordSize)); // Restore IC data. | 615 __ lw(S5, Address(SP, 5 * kWordSize)); // Restore IC data. |
630 __ addiu(SP, SP, Immediate(6 * kWordSize)); | 616 __ addiu(SP, SP, Immediate(6 * kWordSize)); |
631 | 617 |
632 __ RestoreCodePointer(); | |
633 __ LeaveStubFrame(); | 618 __ LeaveStubFrame(); |
634 | 619 |
635 if (!FLAG_lazy_dispatchers) { | 620 if (!FLAG_lazy_dispatchers) { |
636 Label call_target_function; | 621 Label call_target_function; |
637 GenerateDispatcherCode(assembler, &call_target_function); | 622 GenerateDispatcherCode(assembler, &call_target_function); |
638 __ Bind(&call_target_function); | 623 __ Bind(&call_target_function); |
639 } | 624 } |
640 | 625 |
641 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | |
642 __ lw(T2, FieldAddress(T0, Function::entry_point_offset())); | 626 __ lw(T2, FieldAddress(T0, Function::entry_point_offset())); |
643 __ jr(T2); | 627 __ jr(T2); |
644 } | 628 } |
645 | 629 |
646 | 630 |
647 // Called for inline allocation of arrays. | 631 // Called for inline allocation of arrays. |
648 // Input parameters: | 632 // Input parameters: |
649 // RA: return address. | 633 // RA: return address. |
650 // A1: Array length as Smi (must be preserved). | 634 // A1: Array length as Smi (must be preserved). |
651 // A0: array element type (either NULL or an instantiated type). | 635 // A0: array element type (either NULL or an instantiated type). |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 __ lw(A0, Address(SP, 0 * kWordSize)); | 773 __ lw(A0, Address(SP, 0 * kWordSize)); |
790 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 774 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
791 | 775 |
792 __ LeaveStubFrameAndReturn(); | 776 __ LeaveStubFrameAndReturn(); |
793 } | 777 } |
794 | 778 |
795 | 779 |
796 // Called when invoking Dart code from C++ (VM code). | 780 // Called when invoking Dart code from C++ (VM code). |
797 // Input parameters: | 781 // Input parameters: |
798 // RA : points to return address. | 782 // RA : points to return address. |
799 // A0 : code object of the Dart function to call. | 783 // A0 : entrypoint of the Dart function to call. |
800 // A1 : arguments descriptor array. | 784 // A1 : arguments descriptor array. |
801 // A2 : arguments array. | 785 // A2 : arguments array. |
802 // A3 : current thread. | 786 // A3 : current thread. |
803 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | 787 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
804 // Save frame pointer coming in. | 788 // Save frame pointer coming in. |
805 __ Comment("InvokeDartCodeStub"); | 789 __ Comment("InvokeDartCodeStub"); |
806 __ EnterFrame(); | 790 __ EnterFrame(); |
807 | 791 |
808 // Save new context and C++ ABI callee-saved registers. | 792 // Save new context and C++ ABI callee-saved registers. |
809 | 793 |
(...skipping 12 matching lines...) Expand all Loading... |
822 | 806 |
823 for (intptr_t i = kAbiFirstPreservedFpuReg; | 807 for (intptr_t i = kAbiFirstPreservedFpuReg; |
824 i <= kAbiLastPreservedFpuReg; i++) { | 808 i <= kAbiLastPreservedFpuReg; i++) { |
825 FRegister r = static_cast<FRegister>(i); | 809 FRegister r = static_cast<FRegister>(i); |
826 const intptr_t slot = | 810 const intptr_t slot = |
827 kAbiPreservedCpuRegCount + kPreservedSlots + i - | 811 kAbiPreservedCpuRegCount + kPreservedSlots + i - |
828 kAbiFirstPreservedFpuReg; | 812 kAbiFirstPreservedFpuReg; |
829 __ swc1(r, Address(SP, slot * kWordSize)); | 813 __ swc1(r, Address(SP, slot * kWordSize)); |
830 } | 814 } |
831 | 815 |
832 // We now load the pool pointer(PP) with a GC safe value as we are about | 816 // We now load the pool pointer(PP) as we are about to invoke dart code and we |
833 // to invoke dart code. | 817 // could potentially invoke some intrinsic functions which need the PP to be |
834 __ LoadImmediate(PP, 0); | 818 // set up. |
| 819 __ LoadPoolPointer(); |
835 | 820 |
836 // Set up THR, which caches the current thread in Dart code. | 821 // Set up THR, which caches the current thread in Dart code. |
837 if (THR != A3) { | 822 if (THR != A3) { |
838 __ mov(THR, A3); | 823 __ mov(THR, A3); |
839 } | 824 } |
840 __ LoadIsolate(T2); | 825 __ LoadIsolate(T2); |
841 | 826 |
842 // Save the current VMTag on the stack. | 827 // Save the current VMTag on the stack. |
843 __ lw(T1, Address(T2, Isolate::vm_tag_offset())); | 828 __ lw(T1, Address(T2, Isolate::vm_tag_offset())); |
844 __ sw(T1, Address(SP, 2 * kWordSize)); | 829 __ sw(T1, Address(SP, 2 * kWordSize)); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 __ Push(A3); | 868 __ Push(A3); |
884 __ addiu(A1, A1, Immediate(1)); | 869 __ addiu(A1, A1, Immediate(1)); |
885 __ BranchSignedLess(A1, T1, &push_arguments); | 870 __ BranchSignedLess(A1, T1, &push_arguments); |
886 __ delay_slot()->addiu(A2, A2, Immediate(kWordSize)); | 871 __ delay_slot()->addiu(A2, A2, Immediate(kWordSize)); |
887 | 872 |
888 __ Bind(&done_push_arguments); | 873 __ Bind(&done_push_arguments); |
889 | 874 |
890 // Call the Dart code entrypoint. | 875 // Call the Dart code entrypoint. |
891 // We are calling into Dart code, here, so there is no need to call through | 876 // We are calling into Dart code, here, so there is no need to call through |
892 // T9 to match the ABI. | 877 // T9 to match the ABI. |
893 __ lw(CODE_REG, Address(A0, VMHandles::kOffsetOfRawPtrInHandle)); | |
894 __ lw(A0, FieldAddress(CODE_REG, Code::entry_point_offset())); | |
895 __ jalr(A0); // S4 is the arguments descriptor array. | 878 __ jalr(A0); // S4 is the arguments descriptor array. |
896 __ Comment("InvokeDartCodeStub return"); | 879 __ Comment("InvokeDartCodeStub return"); |
897 | 880 |
898 // Get rid of arguments pushed on the stack. | 881 // Get rid of arguments pushed on the stack. |
899 __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize); | 882 __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize); |
900 | 883 |
901 __ LoadIsolate(S2); | 884 __ LoadIsolate(S6); |
902 | 885 |
903 // Restore the current VMTag from the stack. | 886 // Restore the current VMTag from the stack. |
904 __ lw(T1, Address(SP, 2 * kWordSize)); | 887 __ lw(T1, Address(SP, 2 * kWordSize)); |
905 __ sw(T1, Address(S2, Isolate::vm_tag_offset())); | 888 __ sw(T1, Address(S6, Isolate::vm_tag_offset())); |
906 | 889 |
907 // Restore the saved top resource and top exit frame info back into the | 890 // Restore the saved top resource and top exit frame info back into the |
908 // Isolate structure. Uses T0 as a temporary register for this. | 891 // Isolate structure. Uses T0 as a temporary register for this. |
909 __ lw(T0, Address(SP, 1 * kWordSize)); | 892 __ lw(T0, Address(SP, 1 * kWordSize)); |
910 __ sw(T0, Address(THR, Thread::top_resource_offset())); | 893 __ sw(T0, Address(THR, Thread::top_resource_offset())); |
911 __ lw(T0, Address(SP, 0 * kWordSize)); | 894 __ lw(T0, Address(SP, 0 * kWordSize)); |
912 __ sw(T0, Address(THR, Thread::top_exit_frame_info_offset())); | 895 __ sw(T0, Address(THR, Thread::top_exit_frame_info_offset())); |
913 | 896 |
914 // Restore C++ ABI callee-saved registers. | 897 // Restore C++ ABI callee-saved registers. |
915 for (int i = S0; i <= S7; i++) { | 898 for (int i = S0; i <= S7; i++) { |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 // Restore callee-saved registers, tear down frame. | 1101 // Restore callee-saved registers, tear down frame. |
1119 __ LeaveCallRuntimeFrame(); | 1102 __ LeaveCallRuntimeFrame(); |
1120 __ Ret(); | 1103 __ Ret(); |
1121 } | 1104 } |
1122 | 1105 |
1123 | 1106 |
1124 // Called for inline allocation of objects. | 1107 // Called for inline allocation of objects. |
1125 // Input parameters: | 1108 // Input parameters: |
1126 // RA : return address. | 1109 // RA : return address. |
1127 // SP + 0 : type arguments object (only if class is parameterized). | 1110 // SP + 0 : type arguments object (only if class is parameterized). |
1128 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1111 // Returns patch_code_pc offset where patching code for disabling the stub |
1129 const Class& cls) { | 1112 // has been generated (similar to regularly generated Dart code). |
| 1113 void StubCode::GenerateAllocationStubForClass( |
| 1114 Assembler* assembler, const Class& cls, |
| 1115 uword* entry_patch_offset, uword* patch_code_pc_offset) { |
1130 __ Comment("AllocationStubForClass"); | 1116 __ Comment("AllocationStubForClass"); |
| 1117 *entry_patch_offset = assembler->CodeSize(); |
1131 // The generated code is different if the class is parameterized. | 1118 // The generated code is different if the class is parameterized. |
1132 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; | 1119 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; |
1133 ASSERT(!is_cls_parameterized || | 1120 ASSERT(!is_cls_parameterized || |
1134 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); | 1121 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); |
1135 // kInlineInstanceSize is a constant used as a threshold for determining | 1122 // kInlineInstanceSize is a constant used as a threshold for determining |
1136 // when the object initialization should be done as a loop or as | 1123 // when the object initialization should be done as a loop or as |
1137 // straight line code. | 1124 // straight line code. |
1138 const int kInlineInstanceSize = 12; | 1125 const int kInlineInstanceSize = 12; |
1139 const intptr_t instance_size = cls.instance_size(); | 1126 const intptr_t instance_size = cls.instance_size(); |
1140 ASSERT(instance_size > 0); | 1127 ASSERT(instance_size > 0); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 __ sw(T7, Address(SP, 0 * kWordSize)); | 1230 __ sw(T7, Address(SP, 0 * kWordSize)); |
1244 } | 1231 } |
1245 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. | 1232 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. |
1246 __ Comment("AllocationStubForClass return"); | 1233 __ Comment("AllocationStubForClass return"); |
1247 // Pop result (newly allocated object). | 1234 // Pop result (newly allocated object). |
1248 __ lw(V0, Address(SP, 2 * kWordSize)); | 1235 __ lw(V0, Address(SP, 2 * kWordSize)); |
1249 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Pop arguments. | 1236 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Pop arguments. |
1250 // V0: new object | 1237 // V0: new object |
1251 // Restore the frame pointer and return. | 1238 // Restore the frame pointer and return. |
1252 __ LeaveStubFrameAndReturn(RA); | 1239 __ LeaveStubFrameAndReturn(RA); |
| 1240 *patch_code_pc_offset = assembler->CodeSize(); |
| 1241 __ BranchPatchable(*StubCode::FixAllocationStubTarget_entry()); |
1253 } | 1242 } |
1254 | 1243 |
1255 | 1244 |
1256 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1245 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
1257 // from the entry code of a dart function after an error in passed argument | 1246 // from the entry code of a dart function after an error in passed argument |
1258 // name or number is detected. | 1247 // name or number is detected. |
1259 // Input parameters: | 1248 // Input parameters: |
1260 // RA : return address. | 1249 // RA : return address. |
1261 // SP : address of last argument. | 1250 // SP : address of last argument. |
1262 // S4: arguments descriptor array. | 1251 // S4: arguments descriptor array. |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 __ CallRuntime(handle_ic_miss, num_args + 1); | 1551 __ CallRuntime(handle_ic_miss, num_args + 1); |
1563 __ Comment("NArgsCheckInlineCacheStub return"); | 1552 __ Comment("NArgsCheckInlineCacheStub return"); |
1564 // Pop returned function object into T3. | 1553 // Pop returned function object into T3. |
1565 // Restore arguments descriptor array and IC data array. | 1554 // Restore arguments descriptor array and IC data array. |
1566 __ lw(T3, Address(SP, (num_slots - 3) * kWordSize)); | 1555 __ lw(T3, Address(SP, (num_slots - 3) * kWordSize)); |
1567 __ lw(S4, Address(SP, (num_slots - 2) * kWordSize)); | 1556 __ lw(S4, Address(SP, (num_slots - 2) * kWordSize)); |
1568 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize)); | 1557 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize)); |
1569 // Remove the call arguments pushed earlier, including the IC data object | 1558 // Remove the call arguments pushed earlier, including the IC data object |
1570 // and the arguments descriptor array. | 1559 // and the arguments descriptor array. |
1571 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); | 1560 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); |
1572 if (range_collection_mode == kCollectRanges) { | |
1573 __ RestoreCodePointer(); | |
1574 } | |
1575 __ LeaveStubFrame(); | 1561 __ LeaveStubFrame(); |
1576 | 1562 |
1577 Label call_target_function; | 1563 Label call_target_function; |
1578 if (!FLAG_lazy_dispatchers) { | 1564 if (!FLAG_lazy_dispatchers) { |
1579 __ mov(T0, T3); | 1565 __ mov(T0, T3); |
1580 GenerateDispatcherCode(assembler, &call_target_function); | 1566 GenerateDispatcherCode(assembler, &call_target_function); |
1581 } else { | 1567 } else { |
1582 __ b(&call_target_function); | 1568 __ b(&call_target_function); |
1583 } | 1569 } |
1584 | 1570 |
(...skipping 27 matching lines...) Expand all Loading... |
1612 __ lw(T1, Address(SP, 1 * kWordSize)); | 1598 __ lw(T1, Address(SP, 1 * kWordSize)); |
1613 } | 1599 } |
1614 __ EnterStubFrame(); | 1600 __ EnterStubFrame(); |
1615 __ addiu(SP, SP, Immediate(- frame_size * kWordSize)); | 1601 __ addiu(SP, SP, Immediate(- frame_size * kWordSize)); |
1616 __ sw(RA, Address(SP, (frame_size - 1) * kWordSize)); // Return address. | 1602 __ sw(RA, Address(SP, (frame_size - 1) * kWordSize)); // Return address. |
1617 __ sw(S5, Address(SP, (frame_size - 2) * kWordSize)); // Preserve IC data. | 1603 __ sw(S5, Address(SP, (frame_size - 2) * kWordSize)); // Preserve IC data. |
1618 __ sw(T3, Address(SP, 0 * kWordSize)); | 1604 __ sw(T3, Address(SP, 0 * kWordSize)); |
1619 if (num_args == 2) { | 1605 if (num_args == 2) { |
1620 __ sw(T1, Address(SP, 1 * kWordSize)); | 1606 __ sw(T1, Address(SP, 1 * kWordSize)); |
1621 } | 1607 } |
1622 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | |
1623 __ jalr(T4); | 1608 __ jalr(T4); |
1624 __ lw(S5, Address(SP, (frame_size - 2) * kWordSize)); | 1609 __ lw(S5, Address(SP, (frame_size - 2) * kWordSize)); |
1625 __ lw(RA, Address(SP, (frame_size - 1) * kWordSize)); | 1610 __ lw(RA, Address(SP, (frame_size - 1) * kWordSize)); |
1626 Label done; | 1611 Label done; |
1627 __ UpdateRangeFeedback(V0, 2, S5, T1, &done); | 1612 __ UpdateRangeFeedback(V0, 2, S5, T1, &done); |
1628 __ Bind(&done); | 1613 __ Bind(&done); |
1629 __ addiu(SP, SP, Immediate(frame_size * kWordSize)); | 1614 __ addiu(SP, SP, Immediate(frame_size * kWordSize)); |
1630 __ RestoreCodePointer(); | |
1631 __ LeaveStubFrame(); | 1615 __ LeaveStubFrame(); |
1632 __ Ret(); | 1616 __ Ret(); |
1633 } else { | 1617 } else { |
1634 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | |
1635 __ jr(T4); | 1618 __ jr(T4); |
1636 } | 1619 } |
1637 | 1620 |
1638 // Call single step callback in debugger. | 1621 // Call single step callback in debugger. |
1639 if (FLAG_support_debugger && !optimized) { | 1622 if (FLAG_support_debugger && !optimized) { |
1640 __ Bind(&stepping); | 1623 __ Bind(&stepping); |
1641 __ EnterStubFrame(); | 1624 __ EnterStubFrame(); |
1642 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1625 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1643 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. | 1626 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. |
1644 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1627 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
1645 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1628 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1646 __ lw(RA, Address(SP, 0 * kWordSize)); | 1629 __ lw(RA, Address(SP, 0 * kWordSize)); |
1647 __ lw(S5, Address(SP, 1 * kWordSize)); | 1630 __ lw(S5, Address(SP, 1 * kWordSize)); |
1648 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1631 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
1649 __ RestoreCodePointer(); | |
1650 __ LeaveStubFrame(); | 1632 __ LeaveStubFrame(); |
1651 __ b(&done_stepping); | 1633 __ b(&done_stepping); |
1652 } | 1634 } |
1653 } | 1635 } |
1654 | 1636 |
1655 | 1637 |
1656 // Use inline cache data array to invoke the target or continue in inline | 1638 // Use inline cache data array to invoke the target or continue in inline |
1657 // cache miss handler. Stub for 1-argument check (receiver class). | 1639 // cache miss handler. Stub for 1-argument check (receiver class). |
1658 // RA: Return address. | 1640 // RA: Return address. |
1659 // S5: Inline cache data object. | 1641 // S5: Inline cache data object. |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1785 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); | 1767 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); |
1786 __ movz(T4, T7, CMPRES1); | 1768 __ movz(T4, T7, CMPRES1); |
1787 __ sw(T4, Address(T0, count_offset)); | 1769 __ sw(T4, Address(T0, count_offset)); |
1788 } | 1770 } |
1789 | 1771 |
1790 // Load arguments descriptor into S4. | 1772 // Load arguments descriptor into S4. |
1791 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1773 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
1792 | 1774 |
1793 // Get function and call it, if possible. | 1775 // Get function and call it, if possible. |
1794 __ lw(T0, Address(T0, target_offset)); | 1776 __ lw(T0, Address(T0, target_offset)); |
1795 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | |
1796 __ lw(T4, FieldAddress(T0, Function::entry_point_offset())); | 1777 __ lw(T4, FieldAddress(T0, Function::entry_point_offset())); |
1797 __ jr(T4); | 1778 __ jr(T4); |
1798 | 1779 |
1799 // Call single step callback in debugger. | 1780 // Call single step callback in debugger. |
1800 if (FLAG_support_debugger) { | 1781 if (FLAG_support_debugger) { |
1801 __ Bind(&stepping); | 1782 __ Bind(&stepping); |
1802 __ EnterStubFrame(); | 1783 __ EnterStubFrame(); |
1803 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1784 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1804 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. | 1785 __ sw(S5, Address(SP, 1 * kWordSize)); // Preserve IC data. |
1805 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1786 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
1806 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1787 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1807 __ lw(RA, Address(SP, 0 * kWordSize)); | 1788 __ lw(RA, Address(SP, 0 * kWordSize)); |
1808 __ lw(S5, Address(SP, 1 * kWordSize)); | 1789 __ lw(S5, Address(SP, 1 * kWordSize)); |
1809 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1790 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
1810 __ RestoreCodePointer(); | |
1811 __ LeaveStubFrame(); | 1791 __ LeaveStubFrame(); |
1812 __ b(&done_stepping); | 1792 __ b(&done_stepping); |
1813 } | 1793 } |
1814 } | 1794 } |
1815 | 1795 |
1816 | 1796 |
1817 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1797 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
1818 GenerateUsageCounterIncrement(assembler, T0); | 1798 GenerateUsageCounterIncrement(assembler, T0); |
1819 GenerateNArgsCheckInlineCacheStub( | 1799 GenerateNArgsCheckInlineCacheStub( |
1820 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, | 1800 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, |
(...skipping 19 matching lines...) Expand all Loading... |
1840 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data object. | 1820 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data object. |
1841 __ sw(S4, Address(SP, 1 * kWordSize)); // Preserve args descriptor array. | 1821 __ sw(S4, Address(SP, 1 * kWordSize)); // Preserve args descriptor array. |
1842 __ sw(T0, Address(SP, 0 * kWordSize)); // Pass function. | 1822 __ sw(T0, Address(SP, 0 * kWordSize)); // Pass function. |
1843 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1823 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
1844 __ lw(T0, Address(SP, 0 * kWordSize)); // Restore function. | 1824 __ lw(T0, Address(SP, 0 * kWordSize)); // Restore function. |
1845 __ lw(S4, Address(SP, 1 * kWordSize)); // Restore args descriptor array. | 1825 __ lw(S4, Address(SP, 1 * kWordSize)); // Restore args descriptor array. |
1846 __ lw(S5, Address(SP, 2 * kWordSize)); // Restore IC data array. | 1826 __ lw(S5, Address(SP, 2 * kWordSize)); // Restore IC data array. |
1847 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 1827 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
1848 __ LeaveStubFrame(); | 1828 __ LeaveStubFrame(); |
1849 | 1829 |
1850 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | |
1851 __ lw(T2, FieldAddress(T0, Function::entry_point_offset())); | 1830 __ lw(T2, FieldAddress(T0, Function::entry_point_offset())); |
1852 __ jr(T2); | 1831 __ jr(T2); |
1853 } | 1832 } |
1854 | 1833 |
1855 | 1834 |
1856 // S5: Contains an ICData. | 1835 // S5: Contains an ICData. |
1857 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { | 1836 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { |
1858 __ Comment("ICCallBreakpoint stub"); | 1837 __ Comment("ICCallBreakpoint stub"); |
1859 __ EnterStubFrame(); | 1838 __ EnterStubFrame(); |
1860 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1839 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1861 __ sw(S5, Address(SP, 1 * kWordSize)); | 1840 __ sw(S5, Address(SP, 1 * kWordSize)); |
1862 __ LoadObject(TMP, Object::null_object()); | 1841 __ LoadObject(TMP, Object::null_object()); |
1863 __ sw(TMP, Address(SP, 0 * kWordSize)); | 1842 __ sw(TMP, Address(SP, 0 * kWordSize)); |
1864 | 1843 |
1865 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1844 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1866 | 1845 |
1867 __ lw(S5, Address(SP, 1 * kWordSize)); | 1846 __ lw(S5, Address(SP, 1 * kWordSize)); |
1868 __ lw(CODE_REG, Address(SP, 0 * kWordSize)); | 1847 __ lw(T0, Address(SP, 0 * kWordSize)); |
1869 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1848 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
1870 __ LeaveStubFrame(); | 1849 __ LeaveStubFrame(); |
1871 __ lw(T0, FieldAddress(CODE_REG, Code::entry_point_offset())); | |
1872 __ jr(T0); | 1850 __ jr(T0); |
1873 } | 1851 } |
1874 | 1852 |
1875 | 1853 |
1876 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { | 1854 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { |
1877 __ Comment("RuntimeCallBreakpoint stub"); | 1855 __ Comment("RuntimeCallBreakpoint stub"); |
1878 __ EnterStubFrame(); | 1856 __ EnterStubFrame(); |
1879 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 1857 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
1880 __ LoadObject(TMP, Object::null_object()); | 1858 __ LoadObject(TMP, Object::null_object()); |
1881 __ sw(TMP, Address(SP, 0 * kWordSize)); | 1859 __ sw(TMP, Address(SP, 0 * kWordSize)); |
1882 | 1860 |
1883 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1861 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1884 | 1862 |
1885 __ lw(CODE_REG, Address(SP, 0 * kWordSize)); | 1863 __ lw(T0, Address(SP, 0 * kWordSize)); |
1886 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 1864 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
1887 __ LeaveStubFrame(); | 1865 __ LeaveStubFrame(); |
1888 __ lw(T0, FieldAddress(CODE_REG, Code::entry_point_offset())); | |
1889 __ jr(T0); | 1866 __ jr(T0); |
1890 } | 1867 } |
1891 | 1868 |
1892 | 1869 |
1893 // Called only from unoptimized code. All relevant registers have been saved. | 1870 // Called only from unoptimized code. All relevant registers have been saved. |
1894 // RA: return address. | 1871 // RA: return address. |
1895 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1872 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
1896 // Check single stepping. | 1873 // Check single stepping. |
1897 Label stepping, done_stepping; | 1874 Label stepping, done_stepping; |
1898 __ LoadIsolate(T0); | 1875 __ LoadIsolate(T0); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2069 __ Comment("OptimizeFunctionStub"); | 2046 __ Comment("OptimizeFunctionStub"); |
2070 __ EnterStubFrame(); | 2047 __ EnterStubFrame(); |
2071 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 2048 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
2072 __ sw(S4, Address(SP, 2 * kWordSize)); | 2049 __ sw(S4, Address(SP, 2 * kWordSize)); |
2073 // Setup space on stack for return value. | 2050 // Setup space on stack for return value. |
2074 __ LoadObject(TMP, Object::null_object()); | 2051 __ LoadObject(TMP, Object::null_object()); |
2075 __ sw(TMP, Address(SP, 1 * kWordSize)); | 2052 __ sw(TMP, Address(SP, 1 * kWordSize)); |
2076 __ sw(T0, Address(SP, 0 * kWordSize)); | 2053 __ sw(T0, Address(SP, 0 * kWordSize)); |
2077 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); | 2054 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
2078 __ Comment("OptimizeFunctionStub return"); | 2055 __ Comment("OptimizeFunctionStub return"); |
2079 __ lw(CODE_REG, Address(SP, 1 * kWordSize)); // Get Code object | 2056 __ lw(T0, Address(SP, 1 * kWordSize)); // Get Code object |
2080 __ lw(S4, Address(SP, 2 * kWordSize)); // Restore argument descriptor. | 2057 __ lw(S4, Address(SP, 2 * kWordSize)); // Restore argument descriptor. |
2081 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Discard argument. | 2058 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Discard argument. |
2082 | 2059 |
2083 __ lw(T0, FieldAddress(CODE_REG, Code::entry_point_offset())); | 2060 __ lw(T0, FieldAddress(T0, Code::entry_point_offset())); |
2084 __ LeaveStubFrameAndReturn(T0); | 2061 __ LeaveStubFrameAndReturn(T0); |
2085 __ break_(0); | 2062 __ break_(0); |
2086 } | 2063 } |
2087 | 2064 |
2088 | 2065 |
2089 // Does identical check (object references are equal or not equal) with special | 2066 // Does identical check (object references are equal or not equal) with special |
2090 // checks for boxed numbers. | 2067 // checks for boxed numbers. |
2091 // Returns: CMPRES1 is zero if equal, non-zero otherwise. | 2068 // Returns: CMPRES1 is zero if equal, non-zero otherwise. |
2092 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint | 2069 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint |
2093 // cannot contain a value that fits in Mint or Smi. | 2070 // cannot contain a value that fits in Mint or Smi. |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2194 | 2171 |
2195 // Call single step callback in debugger. | 2172 // Call single step callback in debugger. |
2196 if (FLAG_support_debugger) { | 2173 if (FLAG_support_debugger) { |
2197 __ Bind(&stepping); | 2174 __ Bind(&stepping); |
2198 __ EnterStubFrame(); | 2175 __ EnterStubFrame(); |
2199 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 2176 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
2200 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 2177 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
2201 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 2178 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
2202 __ lw(RA, Address(SP, 0 * kWordSize)); | 2179 __ lw(RA, Address(SP, 0 * kWordSize)); |
2203 __ addiu(SP, SP, Immediate(1 * kWordSize)); | 2180 __ addiu(SP, SP, Immediate(1 * kWordSize)); |
2204 __ RestoreCodePointer(); | |
2205 __ LeaveStubFrame(); | 2181 __ LeaveStubFrame(); |
2206 __ b(&done_stepping); | 2182 __ b(&done_stepping); |
2207 } | 2183 } |
2208 } | 2184 } |
2209 | 2185 |
2210 | 2186 |
2211 // Called from optimized code only. | 2187 // Called from optimized code only. |
2212 // SP + 4: left operand. | 2188 // SP + 4: left operand. |
2213 // SP + 0: right operand. | 2189 // SP + 0: right operand. |
2214 // Returns: CMPRES1 is zero if equal, non-zero otherwise. | 2190 // Returns: CMPRES1 is zero if equal, non-zero otherwise. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2255 | 2231 |
2256 __ Bind(&call_target_function); | 2232 __ Bind(&call_target_function); |
2257 // Call the target found in the cache. For a class id match, this is a | 2233 // Call the target found in the cache. For a class id match, this is a |
2258 // proper target for the given name and arguments descriptor. If the | 2234 // proper target for the given name and arguments descriptor. If the |
2259 // illegal class id was found, the target is a cache miss handler that can | 2235 // illegal class id was found, the target is a cache miss handler that can |
2260 // be invoked as a normal Dart function. | 2236 // be invoked as a normal Dart function. |
2261 __ sll(T1, T3, 2); | 2237 __ sll(T1, T3, 2); |
2262 __ addu(T1, T2, T1); | 2238 __ addu(T1, T2, T1); |
2263 __ lw(T0, FieldAddress(T1, base + kWordSize)); | 2239 __ lw(T0, FieldAddress(T1, base + kWordSize)); |
2264 | 2240 |
2265 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | |
2266 __ lw(target, FieldAddress(T0, Function::entry_point_offset())); | 2241 __ lw(target, FieldAddress(T0, Function::entry_point_offset())); |
2267 } | 2242 } |
2268 | 2243 |
2269 | 2244 |
2270 // Called from megamorphic calls. | 2245 // Called from megamorphic calls. |
2271 // T0: receiver. | 2246 // T0: receiver. |
2272 // T1: lookup cache. | 2247 // T1: lookup cache. |
2273 // Result: | 2248 // Result: |
2274 // T1: entry point. | 2249 // T1: entry point. |
2275 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2250 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2276 EmitMegamorphicLookup(assembler, T0, T1, T1); | 2251 EmitMegamorphicLookup(assembler, T0, T1, T1); |
2277 __ Ret(); | 2252 __ Ret(); |
2278 } | 2253 } |
2279 | 2254 |
2280 } // namespace dart | 2255 } // namespace dart |
2281 | 2256 |
2282 #endif // defined TARGET_ARCH_MIPS | 2257 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |