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