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

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

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fixed comments 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;
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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