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

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

Issue 1343373003: Revert "VM: New calling convention for generated code." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/stub_code_ia32.cc ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 23 matching lines...) Expand all
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_ia32.cc ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698