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

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

Issue 269343010: Adds single-precision and SIMD load/store to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/simulator_arm64.cc ('k') | tests/co19/co19-runtime.status » ('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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
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 26 matching lines...) Expand all
37 const intptr_t isolate_offset = NativeArguments::isolate_offset(); 37 const intptr_t isolate_offset = NativeArguments::isolate_offset();
38 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 38 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
39 const intptr_t argv_offset = NativeArguments::argv_offset(); 39 const intptr_t argv_offset = NativeArguments::argv_offset();
40 const intptr_t retval_offset = NativeArguments::retval_offset(); 40 const intptr_t retval_offset = NativeArguments::retval_offset();
41 const intptr_t exitframe_last_param_slot_from_fp = 1; 41 const intptr_t exitframe_last_param_slot_from_fp = 1;
42 42
43 __ SetPrologueOffset(); 43 __ SetPrologueOffset();
44 __ Comment("CallToRuntimeStub"); 44 __ Comment("CallToRuntimeStub");
45 __ EnterFrame(0); 45 __ EnterFrame(0);
46 46
47 // Load current Isolate pointer from Context structure into A0. 47 // Load current Isolate pointer from Context structure into R0.
48 __ LoadFieldFromOffset(R0, CTX, Context::isolate_offset()); 48 __ LoadFieldFromOffset(R0, CTX, Context::isolate_offset(), kNoPP);
49 49
50 // Save exit frame information to enable stack walking as we are about 50 // Save exit frame information to enable stack walking as we are about
51 // to transition to Dart VM C++ code. 51 // to transition to Dart VM C++ code.
52 __ mov(TMP, SP); // Can't directly store SP. 52 __ mov(TMP, SP); // Can't directly store SP.
53 __ StoreToOffset(TMP, R0, Isolate::top_exit_frame_info_offset()); 53 __ StoreToOffset(TMP, R0, Isolate::top_exit_frame_info_offset(), kNoPP);
54 54
55 // Save current Context pointer into Isolate structure. 55 // Save current Context pointer into Isolate structure.
56 __ StoreToOffset(CTX, R0, Isolate::top_context_offset()); 56 __ StoreToOffset(CTX, R0, Isolate::top_context_offset(), kNoPP);
57 57
58 // Cache Isolate pointer into CTX while executing runtime code. 58 // Cache Isolate pointer into CTX while executing runtime code.
59 __ mov(CTX, R0); 59 __ mov(CTX, R0);
60 60
61 #if defined(DEBUG) 61 #if defined(DEBUG)
62 { Label ok; 62 { Label ok;
63 // Check that we are always entering from Dart code. 63 // Check that we are always entering from Dart code.
64 __ LoadFromOffset(R8, R0, Isolate::vm_tag_offset()); 64 __ LoadFromOffset(R8, R0, Isolate::vm_tag_offset(), kNoPP);
65 __ CompareImmediate(R8, VMTag::kScriptTagId, kNoPP); 65 __ CompareImmediate(R8, VMTag::kScriptTagId, kNoPP);
66 __ b(&ok, EQ); 66 __ b(&ok, EQ);
67 __ Stop("Not coming from Dart code."); 67 __ Stop("Not coming from Dart code.");
68 __ Bind(&ok); 68 __ Bind(&ok);
69 } 69 }
70 #endif 70 #endif
71 71
72 // Mark that the isolate is executing VM code. 72 // Mark that the isolate is executing VM code.
73 __ StoreToOffset(R5, R0, Isolate::vm_tag_offset()); 73 __ StoreToOffset(R5, R0, Isolate::vm_tag_offset(), kNoPP);
74 74
75 // Reserve space for arguments and align frame before entering C++ world. 75 // Reserve space for arguments and align frame before entering C++ world.
76 // NativeArguments are passed in registers. 76 // NativeArguments are passed in registers.
77 __ Comment("align stack"); 77 __ Comment("align stack");
78 ASSERT(sizeof(NativeArguments) == 4 * kWordSize); 78 ASSERT(sizeof(NativeArguments) == 4 * kWordSize);
79 __ ReserveAlignedFrameSpace(4 * kWordSize); // Reserve space for arguments. 79 __ ReserveAlignedFrameSpace(4 * kWordSize); // Reserve space for arguments.
80 80
81 // Pass NativeArguments structure by value and call runtime. 81 // Pass NativeArguments structure by value and call runtime.
82 // Registers R0, R1, R2, and R3 are used. 82 // Registers R0, R1, R2, and R3 are used.
83 83
(...skipping 16 matching lines...) Expand all
100 __ AddImmediate(R3, R2, kWordSize, kNoPP); 100 __ AddImmediate(R3, R2, kWordSize, kNoPP);
101 101
102 // TODO(zra): Check that the ABI allows calling through this register. 102 // TODO(zra): Check that the ABI allows calling through this register.
103 __ blr(R5); 103 __ blr(R5);
104 104
105 // Retval is next to 1st argument. 105 // Retval is next to 1st argument.
106 __ Comment("CallToRuntimeStub return"); 106 __ Comment("CallToRuntimeStub return");
107 107
108 // Mark that the isolate is executing Dart code. 108 // Mark that the isolate is executing Dart code.
109 __ LoadImmediate(R2, VMTag::kScriptTagId, kNoPP); 109 __ LoadImmediate(R2, VMTag::kScriptTagId, kNoPP);
110 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset()); 110 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset(), kNoPP);
111 111
112 // Reset exit frame information in Isolate structure. 112 // Reset exit frame information in Isolate structure.
113 __ StoreToOffset(ZR, CTX, Isolate::top_exit_frame_info_offset()); 113 __ StoreToOffset(ZR, CTX, Isolate::top_exit_frame_info_offset(), kNoPP);
114 114
115 // Load Context pointer from Isolate structure into A2. 115 // Load Context pointer from Isolate structure into A2.
116 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset()); 116 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset(), kNoPP);
117 117
118 // Load null. 118 // Load null.
119 __ LoadObject(TMP, Object::null_object(), PP); 119 __ LoadObject(TMP, Object::null_object(), PP);
120 120
121 // Reset Context pointer in Isolate structure. 121 // Reset Context pointer in Isolate structure.
122 __ StoreToOffset(TMP, CTX, Isolate::top_context_offset()); 122 __ StoreToOffset(TMP, CTX, Isolate::top_context_offset(), kNoPP);
123 123
124 // Cache Context pointer into CTX while executing Dart code. 124 // Cache Context pointer into CTX while executing Dart code.
125 __ mov(CTX, R2); 125 __ mov(CTX, R2);
126 126
127 __ LeaveFrame(); 127 __ LeaveFrame();
128 __ ret(); 128 __ ret();
129 } 129 }
130 130
131 131
132 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { 132 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
133 __ Stop("GeneratePrintStopMessageStub"); 133 __ Stop("GeneratePrintStopMessageStub");
134 } 134 }
135 135
136 136
137 // Input parameters: 137 // Input parameters:
138 // LR : return address. 138 // LR : return address.
139 // SP : address of return value. 139 // SP : address of return value.
140 // R5 : address of the native function to call. 140 // R5 : address of the native function to call.
141 // R2 : address of first argument in argument array. 141 // R2 : address of first argument in argument array.
142 // R1 : argc_tag including number of arguments and function kind. 142 // R1 : argc_tag including number of arguments and function kind.
143 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { 143 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) {
144 const intptr_t isolate_offset = NativeArguments::isolate_offset(); 144 const intptr_t isolate_offset = NativeArguments::isolate_offset();
145 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 145 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
146 const intptr_t argv_offset = NativeArguments::argv_offset(); 146 const intptr_t argv_offset = NativeArguments::argv_offset();
147 const intptr_t retval_offset = NativeArguments::retval_offset(); 147 const intptr_t retval_offset = NativeArguments::retval_offset();
148 148
149 __ EnterFrame(0); 149 __ EnterFrame(0);
150 150
151 // Load current Isolate pointer from Context structure into R0. 151 // Load current Isolate pointer from Context structure into R0.
152 __ LoadFieldFromOffset(R0, CTX, Context::isolate_offset()); 152 __ LoadFieldFromOffset(R0, CTX, Context::isolate_offset(), kNoPP);
153 153
154 // 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
155 // to transition to native code. 155 // to transition to native code.
156 __ mov(TMP, SP); 156 __ mov(TMP, SP);
157 __ StoreToOffset(TMP, R0, Isolate::top_exit_frame_info_offset()); 157 __ StoreToOffset(TMP, R0, Isolate::top_exit_frame_info_offset(), kNoPP);
158 158
159 // Save current Context pointer into Isolate structure. 159 // Save current Context pointer into Isolate structure.
160 __ StoreToOffset(CTX, R0, Isolate::top_context_offset()); 160 __ StoreToOffset(CTX, R0, Isolate::top_context_offset(), kNoPP);
161 161
162 // Cache Isolate pointer into CTX while executing native code. 162 // Cache Isolate pointer into CTX while executing native code.
163 __ mov(CTX, R0); 163 __ mov(CTX, R0);
164 164
165 #if defined(DEBUG) 165 #if defined(DEBUG)
166 { Label ok; 166 { Label ok;
167 // Check that we are always entering from Dart code. 167 // Check that we are always entering from Dart code.
168 __ LoadFromOffset(R6, CTX, Isolate::vm_tag_offset()); 168 __ LoadFromOffset(R6, CTX, Isolate::vm_tag_offset(), kNoPP);
169 __ CompareImmediate(R6, VMTag::kScriptTagId, kNoPP); 169 __ CompareImmediate(R6, VMTag::kScriptTagId, kNoPP);
170 __ b(&ok, EQ); 170 __ b(&ok, EQ);
171 __ Stop("Not coming from Dart code."); 171 __ Stop("Not coming from Dart code.");
172 __ Bind(&ok); 172 __ Bind(&ok);
173 } 173 }
174 #endif 174 #endif
175 175
176 // Mark that the isolate is executing Native code. 176 // Mark that the isolate is executing Native code.
177 __ StoreToOffset(R5, CTX, Isolate::vm_tag_offset()); 177 __ StoreToOffset(R5, CTX, Isolate::vm_tag_offset(), kNoPP);
178 178
179 // Reserve space for the native arguments structure passed on the stack (the 179 // Reserve space for the native arguments structure passed on the stack (the
180 // outgoing pointer parameter to the native arguments structure is passed in 180 // outgoing pointer parameter to the native arguments structure is passed in
181 // R0) and align frame before entering the C++ world. 181 // R0) and align frame before entering the C++ world.
182 __ ReserveAlignedFrameSpace(sizeof(NativeArguments)); 182 __ ReserveAlignedFrameSpace(sizeof(NativeArguments));
183 183
184 // Initialize NativeArguments structure and call native function. 184 // Initialize NativeArguments structure and call native function.
185 // Registers R0, R1, R2, and R3 are used. 185 // Registers R0, R1, R2, and R3 are used.
186 186
187 ASSERT(isolate_offset == 0 * kWordSize); 187 ASSERT(isolate_offset == 0 * kWordSize);
188 // Set isolate in NativeArgs: R0 already contains CTX. 188 // Set isolate in NativeArgs: R0 already contains CTX.
189 189
190 // There are no native calls to closures, so we do not need to set the tag 190 // There are no native calls to closures, so we do not need to set the tag
191 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 191 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
192 ASSERT(argc_tag_offset == 1 * kWordSize); 192 ASSERT(argc_tag_offset == 1 * kWordSize);
193 // Set argc in NativeArguments: R1 already contains argc. 193 // Set argc in NativeArguments: R1 already contains argc.
194 194
195 ASSERT(argv_offset == 2 * kWordSize); 195 ASSERT(argv_offset == 2 * kWordSize);
196 // Set argv in NativeArguments: R2 already contains argv. 196 // Set argv in NativeArguments: R2 already contains argv.
197 197
198 // Set retval in NativeArgs. 198 // Set retval in NativeArgs.
199 ASSERT(retval_offset == 3 * kWordSize); 199 ASSERT(retval_offset == 3 * kWordSize);
200 __ AddImmediate(R3, FP, 2 * kWordSize, kNoPP); 200 __ AddImmediate(R3, FP, 2 * kWordSize, kNoPP);
201 201
202 // TODO(regis): Should we pass the structure by value as in runtime calls? 202 // TODO(regis): Should we pass the structure by value as in runtime calls?
203 // It would require changing Dart API for native functions. 203 // It would require changing Dart API for native functions.
204 // For now, space is reserved on the stack and we pass a pointer to it. 204 // For now, space is reserved on the stack and we pass a pointer to it.
205 __ StoreToOffset(R0, SP, isolate_offset); 205 __ StoreToOffset(R0, SP, isolate_offset, kNoPP);
206 __ StoreToOffset(R1, SP, argc_tag_offset); 206 __ StoreToOffset(R1, SP, argc_tag_offset, kNoPP);
207 __ StoreToOffset(R2, SP, argv_offset); 207 __ StoreToOffset(R2, SP, argv_offset, kNoPP);
208 __ StoreToOffset(R3, SP, retval_offset); 208 __ StoreToOffset(R3, SP, retval_offset, kNoPP);
209 __ mov(R0, SP); // Pass the pointer to the NativeArguments. 209 __ mov(R0, SP); // Pass the pointer to the NativeArguments.
210 210
211 // Call native function (setsup scope if not leaf function). 211 // Call native function (setsup scope if not leaf function).
212 Label leaf_call; 212 Label leaf_call;
213 Label done; 213 Label done;
214 __ TestImmediate(R1, NativeArguments::AutoSetupScopeMask(), kNoPP); 214 __ TestImmediate(R1, NativeArguments::AutoSetupScopeMask(), kNoPP);
215 __ b(&leaf_call, EQ); 215 __ b(&leaf_call, EQ);
216 216
217 __ mov(R1, R5); // Pass the function entrypoint to call. 217 __ mov(R1, R5); // Pass the function entrypoint to call.
218 // Call native function invocation wrapper or redirection via simulator. 218 // Call native function invocation wrapper or redirection via simulator.
219 #if defined(USING_SIMULATOR) 219 #if defined(USING_SIMULATOR)
220 uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper); 220 uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper);
221 entry = Simulator::RedirectExternalReference( 221 entry = Simulator::RedirectExternalReference(
222 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); 222 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
223 __ LoadImmediate(R2, entry, kNoPP); 223 __ LoadImmediate(R2, entry, kNoPP);
224 __ blr(R2); 224 __ blr(R2);
225 #else 225 #else
226 __ BranchLink(&NativeEntry::NativeCallWrapperLabel()); 226 __ BranchLink(&NativeEntry::NativeCallWrapperLabel());
227 #endif 227 #endif
228 __ b(&done); 228 __ b(&done);
229 229
230 __ Bind(&leaf_call); 230 __ Bind(&leaf_call);
231 // Call native function or redirection via simulator. 231 // Call native function or redirection via simulator.
232 __ blr(R5); 232 __ blr(R5);
233 233
234 __ Bind(&done); 234 __ Bind(&done);
235 235
236 // Mark that the isolate is executing Dart code. 236 // Mark that the isolate is executing Dart code.
237 __ LoadImmediate(R2, VMTag::kScriptTagId, kNoPP); 237 __ LoadImmediate(R2, VMTag::kScriptTagId, kNoPP);
238 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset()); 238 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset(), kNoPP);
239 239
240 // Reset exit frame information in Isolate structure. 240 // Reset exit frame information in Isolate structure.
241 __ StoreToOffset(ZR, CTX, Isolate::top_exit_frame_info_offset()); 241 __ StoreToOffset(ZR, CTX, Isolate::top_exit_frame_info_offset(), kNoPP);
242 242
243 // Load Context pointer from Isolate structure into R2. 243 // Load Context pointer from Isolate structure into R2.
244 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset()); 244 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset(), kNoPP);
245 245
246 // Reset Context pointer in Isolate structure. 246 // Reset Context pointer in Isolate structure.
247 __ LoadObject(R3, Object::null_object(), PP); 247 __ LoadObject(R3, Object::null_object(), PP);
248 __ StoreToOffset(R3, CTX, Isolate::top_context_offset()); 248 __ StoreToOffset(R3, CTX, Isolate::top_context_offset(), kNoPP);
249 249
250 // Cache Context pointer into CTX while executing Dart code. 250 // Cache Context pointer into CTX while executing Dart code.
251 __ mov(CTX, R2); 251 __ mov(CTX, R2);
252 252
253 __ LeaveFrame(); 253 __ LeaveFrame();
254 __ ret(); 254 __ ret();
255 } 255 }
256 256
257 257
258 // Input parameters: 258 // Input parameters:
259 // LR : return address. 259 // LR : return address.
260 // SP : address of return value. 260 // SP : address of return value.
261 // R5 : address of the native function to call. 261 // R5 : address of the native function to call.
262 // R2 : address of first argument in argument array. 262 // R2 : address of first argument in argument array.
263 // R1 : argc_tag including number of arguments and function kind. 263 // R1 : argc_tag including number of arguments and function kind.
264 void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) { 264 void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) {
265 const intptr_t isolate_offset = NativeArguments::isolate_offset(); 265 const intptr_t isolate_offset = NativeArguments::isolate_offset();
266 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 266 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
267 const intptr_t argv_offset = NativeArguments::argv_offset(); 267 const intptr_t argv_offset = NativeArguments::argv_offset();
268 const intptr_t retval_offset = NativeArguments::retval_offset(); 268 const intptr_t retval_offset = NativeArguments::retval_offset();
269 269
270 __ EnterFrame(0); 270 __ EnterFrame(0);
271 271
272 // Load current Isolate pointer from Context structure into R0. 272 // Load current Isolate pointer from Context structure into R0.
273 __ LoadFieldFromOffset(R0, CTX, Context::isolate_offset()); 273 __ LoadFieldFromOffset(R0, CTX, Context::isolate_offset(), kNoPP);
274 274
275 // Save exit frame information to enable stack walking as we are about 275 // Save exit frame information to enable stack walking as we are about
276 // to transition to native code. 276 // to transition to native code.
277 __ mov(TMP, SP); // Can't store SP directly, first copy to TMP. 277 __ mov(TMP, SP); // Can't store SP directly, first copy to TMP.
278 __ StoreToOffset(TMP, R0, Isolate::top_exit_frame_info_offset()); 278 __ StoreToOffset(TMP, R0, Isolate::top_exit_frame_info_offset(), kNoPP);
279 279
280 // Save current Context pointer into Isolate structure. 280 // Save current Context pointer into Isolate structure.
281 __ StoreToOffset(CTX, R0, Isolate::top_context_offset()); 281 __ StoreToOffset(CTX, R0, Isolate::top_context_offset(), kNoPP);
282 282
283 // Cache Isolate pointer into CTX while executing native code. 283 // Cache Isolate pointer into CTX while executing native code.
284 __ mov(CTX, R0); 284 __ mov(CTX, R0);
285 285
286 #if defined(DEBUG) 286 #if defined(DEBUG)
287 { Label ok; 287 { Label ok;
288 // Check that we are always entering from Dart code. 288 // Check that we are always entering from Dart code.
289 __ LoadFromOffset(R6, CTX, Isolate::vm_tag_offset()); 289 __ LoadFromOffset(R6, CTX, Isolate::vm_tag_offset(), kNoPP);
290 __ CompareImmediate(R6, VMTag::kScriptTagId, kNoPP); 290 __ CompareImmediate(R6, VMTag::kScriptTagId, kNoPP);
291 __ b(&ok, EQ); 291 __ b(&ok, EQ);
292 __ Stop("Not coming from Dart code."); 292 __ Stop("Not coming from Dart code.");
293 __ Bind(&ok); 293 __ Bind(&ok);
294 } 294 }
295 #endif 295 #endif
296 296
297 // Mark that the isolate is executing Native code. 297 // Mark that the isolate is executing Native code.
298 __ StoreToOffset(R5, CTX, Isolate::vm_tag_offset()); 298 __ StoreToOffset(R5, CTX, Isolate::vm_tag_offset(), kNoPP);
299 299
300 // Reserve space for the native arguments structure passed on the stack (the 300 // Reserve space for the native arguments structure passed on the stack (the
301 // outgoing pointer parameter to the native arguments structure is passed in 301 // outgoing pointer parameter to the native arguments structure is passed in
302 // R0) and align frame before entering the C++ world. 302 // R0) and align frame before entering the C++ world.
303 __ ReserveAlignedFrameSpace(sizeof(NativeArguments)); 303 __ ReserveAlignedFrameSpace(sizeof(NativeArguments));
304 304
305 // Initialize NativeArguments structure and call native function. 305 // Initialize NativeArguments structure and call native function.
306 // Registers R0, R1, R2, and R3 are used. 306 // Registers R0, R1, R2, and R3 are used.
307 307
308 ASSERT(isolate_offset == 0 * kWordSize); 308 ASSERT(isolate_offset == 0 * kWordSize);
309 // Set isolate in NativeArgs: R0 already contains CTX. 309 // Set isolate in NativeArgs: R0 already contains CTX.
310 310
311 // There are no native calls to closures, so we do not need to set the tag 311 // There are no native calls to closures, so we do not need to set the tag
312 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 312 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
313 ASSERT(argc_tag_offset == 1 * kWordSize); 313 ASSERT(argc_tag_offset == 1 * kWordSize);
314 // Set argc in NativeArguments: R1 already contains argc. 314 // Set argc in NativeArguments: R1 already contains argc.
315 315
316 ASSERT(argv_offset == 2 * kWordSize); 316 ASSERT(argv_offset == 2 * kWordSize);
317 // Set argv in NativeArguments: R2 already contains argv. 317 // Set argv in NativeArguments: R2 already contains argv.
318 318
319 // Set retval in NativeArgs. 319 // Set retval in NativeArgs.
320 ASSERT(retval_offset == 3 * kWordSize); 320 ASSERT(retval_offset == 3 * kWordSize);
321 __ AddImmediate(R3, FP, 2 * kWordSize, kNoPP); 321 __ AddImmediate(R3, FP, 2 * kWordSize, kNoPP);
322 322
323 // TODO(regis): Should we pass the structure by value as in runtime calls? 323 // TODO(regis): Should we pass the structure by value as in runtime calls?
324 // It would require changing Dart API for native functions. 324 // It would require changing Dart API for native functions.
325 // For now, space is reserved on the stack and we pass a pointer to it. 325 // For now, space is reserved on the stack and we pass a pointer to it.
326 __ StoreToOffset(R0, SP, isolate_offset); 326 __ StoreToOffset(R0, SP, isolate_offset, kNoPP);
327 __ StoreToOffset(R1, SP, argc_tag_offset); 327 __ StoreToOffset(R1, SP, argc_tag_offset, kNoPP);
328 __ StoreToOffset(R2, SP, argv_offset); 328 __ StoreToOffset(R2, SP, argv_offset, kNoPP);
329 __ StoreToOffset(R3, SP, retval_offset); 329 __ StoreToOffset(R3, SP, retval_offset, kNoPP);
330 __ mov(R0, SP); // Pass the pointer to the NativeArguments. 330 __ mov(R0, SP); // Pass the pointer to the NativeArguments.
331 331
332 // Call native function or redirection via simulator. 332 // Call native function or redirection via simulator.
333 __ blr(R5); 333 __ blr(R5);
334 334
335 // Mark that the isolate is executing Dart code. 335 // Mark that the isolate is executing Dart code.
336 __ LoadImmediate(R2, VMTag::kScriptTagId, kNoPP); 336 __ LoadImmediate(R2, VMTag::kScriptTagId, kNoPP);
337 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset()); 337 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset(), kNoPP);
338 338
339 // Reset exit frame information in Isolate structure. 339 // Reset exit frame information in Isolate structure.
340 __ StoreToOffset(ZR, CTX, Isolate::top_exit_frame_info_offset()); 340 __ StoreToOffset(ZR, CTX, Isolate::top_exit_frame_info_offset(), kNoPP);
341 341
342 // Load Context pointer from Isolate structure into R2. 342 // Load Context pointer from Isolate structure into R2.
343 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset()); 343 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset(), kNoPP);
344 344
345 // Reset Context pointer in Isolate structure. 345 // Reset Context pointer in Isolate structure.
346 __ LoadObject(R3, Object::null_object(), PP); 346 __ LoadObject(R3, Object::null_object(), PP);
347 __ StoreToOffset(R3, CTX, Isolate::top_context_offset()); 347 __ StoreToOffset(R3, CTX, Isolate::top_context_offset(), kNoPP);
348 348
349 // Cache Context pointer into CTX while executing Dart code. 349 // Cache Context pointer into CTX while executing Dart code.
350 __ mov(CTX, R2); 350 __ mov(CTX, R2);
351 351
352 __ LeaveFrame(); 352 __ LeaveFrame();
353 __ ret(); 353 __ ret();
354 } 354 }
355 355
356 356
357 // Input parameters: 357 // Input parameters:
358 // R4: arguments descriptor array. 358 // R4: arguments descriptor array.
359 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 359 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
360 // Create a stub frame as we are pushing some objects on the stack before 360 // Create a stub frame as we are pushing some objects on the stack before
361 // calling into the runtime. 361 // calling into the runtime.
362 __ EnterStubFrame(); 362 __ EnterStubFrame();
363 // Setup space on stack for return value and preserve arguments descriptor. 363 // Setup space on stack for return value and preserve arguments descriptor.
364 __ Push(R4); 364 __ Push(R4);
365 __ PushObject(Object::null_object(), PP); 365 __ PushObject(Object::null_object(), PP);
366 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); 366 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
367 // Get Code object result and restore arguments descriptor array. 367 // Get Code object result and restore arguments descriptor array.
368 __ Pop(R0); 368 __ Pop(R0);
369 __ Pop(R4); 369 __ Pop(R4);
370 // Remove the stub frame. 370 // Remove the stub frame.
371 __ LeaveStubFrame(); 371 __ LeaveStubFrame();
372 // Jump to the dart function. 372 // Jump to the dart function.
373 __ LoadFieldFromOffset(R0, R0, Code::instructions_offset()); 373 __ LoadFieldFromOffset(R0, R0, Code::instructions_offset(), kNoPP);
374 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); 374 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
375 __ br(R0); 375 __ br(R0);
376 } 376 }
377 377
378 378
379 // Called from a static call only when an invalid code has been entered 379 // Called from a static call only when an invalid code has been entered
380 // (invalid because its function was optimized or deoptimized). 380 // (invalid because its function was optimized or deoptimized).
381 // R4: arguments descriptor array. 381 // R4: arguments descriptor array.
382 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 382 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
383 // Create a stub frame as we are pushing some objects on the stack before 383 // Create a stub frame as we are pushing some objects on the stack before
384 // calling into the runtime. 384 // calling into the runtime.
385 __ EnterStubFrame(); 385 __ EnterStubFrame();
386 // Setup space on stack for return value and preserve arguments descriptor. 386 // Setup space on stack for return value and preserve arguments descriptor.
387 __ Push(R4); 387 __ Push(R4);
388 __ PushObject(Object::null_object(), PP); 388 __ PushObject(Object::null_object(), PP);
389 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); 389 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
390 // Get Code object result and restore arguments descriptor array. 390 // Get Code object result and restore arguments descriptor array.
391 __ Pop(R0); 391 __ Pop(R0);
392 __ Pop(R4); 392 __ Pop(R4);
393 // Remove the stub frame. 393 // Remove the stub frame.
394 __ LeaveStubFrame(); 394 __ LeaveStubFrame();
395 // Jump to the dart function. 395 // Jump to the dart function.
396 __ LoadFieldFromOffset(R0, R0, Code::instructions_offset()); 396 __ LoadFieldFromOffset(R0, R0, Code::instructions_offset(), kNoPP);
397 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); 397 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
398 __ br(R0); 398 __ br(R0);
399 } 399 }
400 400
401 401
402 // Input parameters: 402 // Input parameters:
403 // R2: smi-tagged argument count, may be zero. 403 // R2: smi-tagged argument count, may be zero.
404 // FP[kParamEndSlotFromFp + 1]: last argument. 404 // FP[kParamEndSlotFromFp + 1]: last argument.
405 static void PushArgumentsArray(Assembler* assembler) { 405 static void PushArgumentsArray(Assembler* assembler) {
406 // Allocate array to store arguments of caller. 406 // Allocate array to store arguments of caller.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 __ PushDouble(vreg); 490 __ PushDouble(vreg);
491 } 491 }
492 492
493 __ mov(R0, SP); // Pass address of saved registers block. 493 __ mov(R0, SP); // Pass address of saved registers block.
494 __ ReserveAlignedFrameSpace(0); 494 __ ReserveAlignedFrameSpace(0);
495 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1); 495 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1);
496 // Result (R0) is stack-size (FP - SP) in bytes. 496 // Result (R0) is stack-size (FP - SP) in bytes.
497 497
498 if (preserve_result) { 498 if (preserve_result) {
499 // Restore result into R1 temporarily. 499 // Restore result into R1 temporarily.
500 __ LoadFromOffset(R1, FP, saved_result_slot_from_fp * kWordSize); 500 __ LoadFromOffset(R1, FP, saved_result_slot_from_fp * kWordSize, kNoPP);
501 } 501 }
502 502
503 // There is a Dart Frame on the stack. We must restore PP and leave frame. 503 // There is a Dart Frame on the stack. We must restore PP and leave frame.
504 __ LeaveDartFrame(); 504 __ LeaveDartFrame();
505 __ sub(TMP, FP, Operand(R0)); 505 __ sub(TMP, FP, Operand(R0));
506 __ mov(SP, TMP); 506 __ mov(SP, TMP);
507 507
508 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 508 // 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. 509 // is no need to set the correct PC marker or load PP, since they get patched.
510 __ EnterFrame(0); 510 __ EnterFrame(0);
511 __ Push(ZR); 511 __ Push(ZR);
512 __ TagAndPushPP(); 512 __ TagAndPushPP();
513 513
514 if (preserve_result) { 514 if (preserve_result) {
515 __ Push(R1); // Preserve result as first local. 515 __ Push(R1); // Preserve result as first local.
516 } 516 }
517 __ ReserveAlignedFrameSpace(0); 517 __ ReserveAlignedFrameSpace(0);
518 __ mov(R0, FP); // Pass last FP as parameter in R0. 518 __ mov(R0, FP); // Pass last FP as parameter in R0.
519 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); 519 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
520 if (preserve_result) { 520 if (preserve_result) {
521 // Restore result into R1. 521 // Restore result into R1.
522 __ LoadFromOffset(R1, FP, kFirstLocalSlotFromFp * kWordSize); 522 __ LoadFromOffset(R1, FP, kFirstLocalSlotFromFp * kWordSize, kNoPP);
523 } 523 }
524 // Code above cannot cause GC. 524 // Code above cannot cause GC.
525 // There is a Dart Frame on the stack. We must restore PP and leave frame. 525 // There is a Dart Frame on the stack. We must restore PP and leave frame.
526 __ LeaveDartFrame(); 526 __ LeaveDartFrame();
527 527
528 // Frame is fully rewritten at this point and it is safe to perform a GC. 528 // Frame is fully rewritten at this point and it is safe to perform a GC.
529 // Materialize any objects that were deferred by FillFrame because they 529 // Materialize any objects that were deferred by FillFrame because they
530 // require allocation. 530 // require allocation.
531 __ EnterStubFrame(); 531 __ EnterStubFrame();
532 if (preserve_result) { 532 if (preserve_result) {
(...skipping 28 matching lines...) Expand all
561 561
562 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 562 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
563 GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0. 563 GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0.
564 } 564 }
565 565
566 566
567 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 567 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
568 __ EnterStubFrame(); 568 __ EnterStubFrame();
569 569
570 // Load the receiver. 570 // Load the receiver.
571 __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset()); 571 __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset(), kNoPP);
572 __ add(TMP, FP, Operand(R2, LSL, 2)); // R2 is Smi. 572 __ add(TMP, FP, Operand(R2, LSL, 2)); // R2 is Smi.
573 __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize); 573 __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize, kNoPP);
574 574
575 // Preserve IC data and arguments descriptor. 575 // Preserve IC data and arguments descriptor.
576 __ Push(R5); 576 __ Push(R5);
577 __ Push(R4); 577 __ Push(R4);
578 578
579 // Push space for the return value. 579 // Push space for the return value.
580 // Push the receiver. 580 // Push the receiver.
581 // Push IC data object. 581 // Push IC data object.
582 // Push arguments descriptor array. 582 // Push arguments descriptor array.
583 __ PushObject(Object::null_object(), PP); 583 __ PushObject(Object::null_object(), PP);
584 __ Push(R6); 584 __ Push(R6);
585 __ Push(R5); 585 __ Push(R5);
586 __ Push(R4); 586 __ Push(R4);
587 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); 587 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
588 // Remove arguments. 588 // Remove arguments.
589 __ Drop(3); 589 __ Drop(3);
590 __ Pop(R0); // Get result into R0 (target function). 590 __ Pop(R0); // Get result into R0 (target function).
591 591
592 // Restore IC data and arguments descriptor. 592 // Restore IC data and arguments descriptor.
593 __ Pop(R4); 593 __ Pop(R4);
594 __ Pop(R5); 594 __ Pop(R5);
595 595
596 __ LeaveStubFrame(); 596 __ LeaveStubFrame();
597 597
598 // Tail-call to target function. 598 // Tail-call to target function.
599 __ LoadFieldFromOffset(R2, R0, Function::code_offset()); 599 __ LoadFieldFromOffset(R2, R0, Function::code_offset(), kNoPP);
600 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset()); 600 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), kNoPP);
601 __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP); 601 __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP);
602 __ br(R2); 602 __ br(R2);
603 } 603 }
604 604
605 605
606 // Called for inline allocation of arrays. 606 // Called for inline allocation of arrays.
607 // Input parameters: 607 // Input parameters:
608 // LR: return address. 608 // LR: return address.
609 // R2: array length as Smi. 609 // R2: array length as Smi.
610 // R1: array element type (either NULL or an instantiated type). 610 // R1: array element type (either NULL or an instantiated type).
611 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved. 611 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved.
612 // The newly allocated object is returned in R0. 612 // The newly allocated object is returned in R0.
613 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { 613 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
614 Label slow_case; 614 Label slow_case;
615 if (FLAG_inline_alloc) { 615 if (FLAG_inline_alloc) {
616 // Compute the size to be allocated, it is based on the array length 616 // Compute the size to be allocated, it is based on the array length
617 // and is computed as: 617 // and is computed as:
618 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). 618 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
619 // Assert that length is a Smi. 619 // Assert that length is a Smi.
620 __ tsti(R2, kSmiTagMask); 620 __ tsti(R2, kSmiTagMask);
621 if (FLAG_use_slow_path) { 621 if (FLAG_use_slow_path) {
622 __ b(&slow_case); 622 __ b(&slow_case);
623 } else { 623 } else {
624 __ b(&slow_case, NE); 624 __ b(&slow_case, NE);
625 } 625 }
626 __ LoadFieldFromOffset(R8, CTX, Context::isolate_offset()); 626 __ LoadFieldFromOffset(R8, CTX, Context::isolate_offset(), kNoPP);
627 __ LoadFromOffset(R8, R8, Isolate::heap_offset()); 627 __ LoadFromOffset(R8, R8, Isolate::heap_offset(), kNoPP);
628 __ LoadFromOffset(R8, R8, Heap::new_space_offset()); 628 __ LoadFromOffset(R8, R8, Heap::new_space_offset(), kNoPP);
629 629
630 // Calculate and align allocation size. 630 // Calculate and align allocation size.
631 // Load new object start and calculate next object start. 631 // Load new object start and calculate next object start.
632 // R1: array element type. 632 // R1: array element type.
633 // R2: array length as Smi. 633 // R2: array length as Smi.
634 // R8: points to new space object. 634 // R8: points to new space object.
635 __ LoadFromOffset(R0, R8, Scavenger::top_offset()); 635 __ LoadFromOffset(R0, R8, Scavenger::top_offset(), kNoPP);
636 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; 636 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
637 __ LoadImmediate(R3, fixed_size, kNoPP); 637 __ LoadImmediate(R3, fixed_size, kNoPP);
638 __ add(R3, R3, Operand(R2, LSL, 2)); // R2 is Smi. 638 __ add(R3, R3, Operand(R2, LSL, 2)); // R2 is Smi.
639 ASSERT(kSmiTagShift == 1); 639 ASSERT(kSmiTagShift == 1);
640 __ andi(R3, R3, ~(kObjectAlignment - 1)); 640 __ andi(R3, R3, ~(kObjectAlignment - 1));
641 __ add(R7, R3, Operand(R0)); 641 __ add(R7, R3, Operand(R0));
642 642
643 // Check if the allocation fits into the remaining space. 643 // Check if the allocation fits into the remaining space.
644 // R0: potential new object start. 644 // R0: potential new object start.
645 // R1: array element type. 645 // R1: array element type.
646 // R2: array length as Smi. 646 // R2: array length as Smi.
647 // R3: array size. 647 // R3: array size.
648 // R7: potential next object start. 648 // R7: potential next object start.
649 // R8: points to new space object. 649 // R8: points to new space object.
650 __ LoadFromOffset(TMP, R8, Scavenger::end_offset()); 650 __ LoadFromOffset(TMP, R8, Scavenger::end_offset(), kNoPP);
651 __ CompareRegisters(R7, TMP); 651 __ CompareRegisters(R7, TMP);
652 __ b(&slow_case, CS); // Branch if unsigned higher or equal. 652 __ b(&slow_case, CS); // Branch if unsigned higher or equal.
653 653
654 // Successfully allocated the object(s), now update top to point to 654 // Successfully allocated the object(s), now update top to point to
655 // next object start and initialize the object. 655 // next object start and initialize the object.
656 // R0: potential new object start. 656 // R0: potential new object start.
657 // R3: array size. 657 // R3: array size.
658 // R7: potential next object start. 658 // R7: potential next object start.
659 // R8: Points to new space object. 659 // R8: Points to new space object.
660 __ StoreToOffset(R7, R8, Scavenger::top_offset()); 660 __ StoreToOffset(R7, R8, Scavenger::top_offset(), kNoPP);
661 __ add(R0, R0, Operand(kHeapObjectTag)); 661 __ add(R0, R0, Operand(kHeapObjectTag));
662 __ UpdateAllocationStatsWithSize(kArrayCid, R3, R8, kNoPP); 662 __ UpdateAllocationStatsWithSize(kArrayCid, R3, R8, kNoPP);
663 663
664 // R0: new object start as a tagged pointer. 664 // R0: new object start as a tagged pointer.
665 // R1: array element type. 665 // R1: array element type.
666 // R2: array length as Smi. 666 // R2: array length as Smi.
667 // R3: array size. 667 // R3: array size.
668 // R7: new object end address. 668 // R7: new object end address.
669 669
670 // Store the type argument field. 670 // Store the type argument field.
671 __ StoreIntoObjectNoBarrier( 671 __ StoreIntoObjectOffsetNoBarrier(
672 R0, 672 R0, Array::type_arguments_offset(), R1, PP);
673 FieldAddress(R0, Array::type_arguments_offset()),
674 R1);
675 673
676 // Set the length field. 674 // Set the length field.
677 __ StoreIntoObjectNoBarrier( 675 __ StoreIntoObjectOffsetNoBarrier(R0, Array::length_offset(), R2, PP);
678 R0,
679 FieldAddress(R0, Array::length_offset()),
680 R2);
681 676
682 // Calculate the size tag. 677 // Calculate the size tag.
683 // R0: new object start as a tagged pointer. 678 // R0: new object start as a tagged pointer.
684 // R2: array length as Smi. 679 // R2: array length as Smi.
685 // R3: array size. 680 // R3: array size.
686 // R7: new object end address. 681 // R7: new object end address.
687 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; 682 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
688 __ CompareImmediate(R3, RawObject::SizeTag::kMaxSizeTag, kNoPP); 683 __ CompareImmediate(R3, RawObject::SizeTag::kMaxSizeTag, kNoPP);
689 // If no size tag overflow, shift R1 left, else set R1 to zero. 684 // If no size tag overflow, shift R1 left, else set R1 to zero.
690 __ Lsl(TMP, R3, shift); 685 __ Lsl(TMP, R3, shift);
691 __ csel(R1, TMP, R1, LS); 686 __ csel(R1, TMP, R1, LS);
692 __ csel(R1, ZR, R1, HI); 687 __ csel(R1, ZR, R1, HI);
693 688
694 // Get the class index and insert it into the tags. 689 // Get the class index and insert it into the tags.
695 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(kArrayCid), kNoPP); 690 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(kArrayCid), kNoPP);
696 __ orr(R1, R1, Operand(TMP)); 691 __ orr(R1, R1, Operand(TMP));
697 __ StoreFieldToOffset(R1, R0, Array::tags_offset()); 692 __ StoreFieldToOffset(R1, R0, Array::tags_offset(), kNoPP);
698 693
699 // Initialize all array elements to raw_null. 694 // Initialize all array elements to raw_null.
700 // R0: new object start as a tagged pointer. 695 // R0: new object start as a tagged pointer.
701 // R7: new object end address. 696 // R7: new object end address.
702 // R2: array length as Smi. 697 // R2: array length as Smi.
703 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag, kNoPP); 698 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag, kNoPP);
704 // R1: iterator which initially points to the start of the variable 699 // R1: iterator which initially points to the start of the variable
705 // data area to be initialized. 700 // data area to be initialized.
706 __ LoadObject(TMP, Object::null_object(), PP); 701 __ LoadObject(TMP, Object::null_object(), PP);
707 Label loop, done; 702 Label loop, done;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 // set up. 777 // set up.
783 __ LoadPoolPointer(PP); 778 __ LoadPoolPointer(PP);
784 779
785 // The new Context structure contains a pointer to the current Isolate 780 // The new Context structure contains a pointer to the current Isolate
786 // structure. Cache the Context pointer in the CTX register so that it is 781 // structure. Cache the Context pointer in the CTX register so that it is
787 // available in generated code and calls to Isolate::Current() need not be 782 // available in generated code and calls to Isolate::Current() need not be
788 // done. The assumption is that this register will never be clobbered by 783 // done. The assumption is that this register will never be clobbered by
789 // compiled or runtime stub code. 784 // compiled or runtime stub code.
790 785
791 // Cache the new Context pointer into CTX while executing Dart code. 786 // Cache the new Context pointer into CTX while executing Dart code.
792 __ LoadFromOffset(CTX, R3, VMHandles::kOffsetOfRawPtrInHandle); 787 __ LoadFromOffset(CTX, R3, VMHandles::kOffsetOfRawPtrInHandle, PP);
793 788
794 // Load Isolate pointer from Context structure into temporary register R4. 789 // Load Isolate pointer from Context structure into temporary register R4.
795 __ LoadFieldFromOffset(R5, CTX, Context::isolate_offset()); 790 __ LoadFieldFromOffset(R5, CTX, Context::isolate_offset(), PP);
796 791
797 // Save the current VMTag on the stack. 792 // Save the current VMTag on the stack.
798 ASSERT(kSavedVMTagSlotFromEntryFp == -20); 793 ASSERT(kSavedVMTagSlotFromEntryFp == -20);
799 __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset()); 794 __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset(), PP);
800 __ Push(R4); 795 __ Push(R4);
801 796
802 // Mark that the isolate is executing Dart code. 797 // Mark that the isolate is executing Dart code.
803 __ LoadImmediate(R6, VMTag::kScriptTagId, PP); 798 __ LoadImmediate(R6, VMTag::kScriptTagId, PP);
804 __ StoreToOffset(R6, R5, Isolate::vm_tag_offset()); 799 __ StoreToOffset(R6, R5, Isolate::vm_tag_offset(), PP);
805 800
806 // Save the top exit frame info. Use R6 as a temporary register. 801 // Save the top exit frame info. Use R6 as a temporary register.
807 // StackFrameIterator reads the top exit frame info saved in this frame. 802 // StackFrameIterator reads the top exit frame info saved in this frame.
808 __ LoadFromOffset(R6, R5, Isolate::top_exit_frame_info_offset()); 803 __ LoadFromOffset(R6, R5, Isolate::top_exit_frame_info_offset(), PP);
809 __ StoreToOffset(ZR, R5, Isolate::top_exit_frame_info_offset()); 804 __ StoreToOffset(ZR, R5, Isolate::top_exit_frame_info_offset(), PP);
810 805
811 // Save the old Context pointer. Use R4 as a temporary register. 806 // Save the old Context pointer. Use R4 as a temporary register.
812 // Note that VisitObjectPointers will find this saved Context pointer during 807 // Note that VisitObjectPointers will find this saved Context pointer during
813 // GC marking, since it traverses any information between SP and 808 // GC marking, since it traverses any information between SP and
814 // FP - kExitLinkSlotFromEntryFp. 809 // FP - kExitLinkSlotFromEntryFp.
815 // EntryFrame::SavedContext reads the context saved in this frame. 810 // EntryFrame::SavedContext reads the context saved in this frame.
816 __ LoadFromOffset(R4, R5, Isolate::top_context_offset()); 811 __ LoadFromOffset(R4, R5, Isolate::top_context_offset(), PP);
817 812
818 // The constants kSavedContextSlotFromEntryFp and 813 // The constants kSavedContextSlotFromEntryFp and
819 // kExitLinkSlotFromEntryFp must be kept in sync with the code below. 814 // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
820 ASSERT(kExitLinkSlotFromEntryFp == -21); 815 ASSERT(kExitLinkSlotFromEntryFp == -21);
821 ASSERT(kSavedContextSlotFromEntryFp == -22); 816 ASSERT(kSavedContextSlotFromEntryFp == -22);
822 __ Push(R6); 817 __ Push(R6);
823 __ Push(R4); 818 __ Push(R4);
824 819
825 // Load arguments descriptor array into R4, which is passed to Dart code. 820 // Load arguments descriptor array into R4, which is passed to Dart code.
826 __ LoadFromOffset(R4, R1, VMHandles::kOffsetOfRawPtrInHandle); 821 __ LoadFromOffset(R4, R1, VMHandles::kOffsetOfRawPtrInHandle, PP);
827 822
828 // Load number of arguments into S5. 823 // Load number of arguments into S5.
829 __ LoadFieldFromOffset(R5, R4, ArgumentsDescriptor::count_offset()); 824 __ LoadFieldFromOffset(R5, R4, ArgumentsDescriptor::count_offset(), PP);
830 __ SmiUntag(R5); 825 __ SmiUntag(R5);
831 826
832 // Compute address of 'arguments array' data area into R2. 827 // Compute address of 'arguments array' data area into R2.
833 __ LoadFromOffset(R2, R2, VMHandles::kOffsetOfRawPtrInHandle); 828 __ LoadFromOffset(R2, R2, VMHandles::kOffsetOfRawPtrInHandle, PP);
834 __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag, PP); 829 __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag, PP);
835 830
836 // Set up arguments for the Dart call. 831 // Set up arguments for the Dart call.
837 Label push_arguments; 832 Label push_arguments;
838 Label done_push_arguments; 833 Label done_push_arguments;
839 __ cmp(R5, Operand(0)); 834 __ cmp(R5, Operand(0));
840 __ b(&done_push_arguments, EQ); // check if there are arguments. 835 __ b(&done_push_arguments, EQ); // check if there are arguments.
841 __ LoadImmediate(R1, 0, PP); 836 __ LoadImmediate(R1, 0, PP);
842 __ Bind(&push_arguments); 837 __ Bind(&push_arguments);
843 __ ldr(R3, Address(R2)); 838 __ ldr(R3, Address(R2));
844 __ Push(R3); 839 __ Push(R3);
845 __ add(R1, R1, Operand(1)); 840 __ add(R1, R1, Operand(1));
846 __ add(R2, R2, Operand(kWordSize)); 841 __ add(R2, R2, Operand(kWordSize));
847 __ cmp(R1, Operand(R5)); 842 __ cmp(R1, Operand(R5));
848 __ b(&push_arguments, LT); 843 __ b(&push_arguments, LT);
849 __ Bind(&done_push_arguments); 844 __ Bind(&done_push_arguments);
850 845
851 // Call the Dart code entrypoint. 846 // Call the Dart code entrypoint.
852 __ blr(R0); // R4 is the arguments descriptor array. 847 __ blr(R0); // R4 is the arguments descriptor array.
853 __ Comment("InvokeDartCodeStub return"); 848 __ Comment("InvokeDartCodeStub return");
854 849
855 // Read the saved new Context pointer. 850 // Read the saved new Context pointer.
856 __ LoadFromOffset(CTX, FP, kNewContextOffsetFromFp); 851 __ LoadFromOffset(CTX, FP, kNewContextOffsetFromFp, PP);
857 __ LoadFromOffset(CTX, CTX, VMHandles::kOffsetOfRawPtrInHandle); 852 __ LoadFromOffset(CTX, CTX, VMHandles::kOffsetOfRawPtrInHandle, PP);
858 853
859 // Get rid of arguments pushed on the stack. 854 // Get rid of arguments pushed on the stack.
860 __ AddImmediate(SP, FP, kSavedContextSlotFromEntryFp * kWordSize, PP); 855 __ AddImmediate(SP, FP, kSavedContextSlotFromEntryFp * kWordSize, PP);
861 856
862 // Load Isolate pointer from Context structure into CTX. Drop Context. 857 // Load Isolate pointer from Context structure into CTX. Drop Context.
863 __ LoadFieldFromOffset(CTX, CTX, Context::isolate_offset()); 858 __ LoadFieldFromOffset(CTX, CTX, Context::isolate_offset(), PP);
864 859
865 // Restore the current VMTag from the stack. 860 // Restore the current VMTag from the stack.
866 __ ldr(R4, Address(SP, 2 * kWordSize)); 861 __ ldr(R4, Address(SP, 2 * kWordSize));
867 __ StoreToOffset(R4, CTX, Isolate::vm_tag_offset()); 862 __ StoreToOffset(R4, CTX, Isolate::vm_tag_offset(), PP);
868 863
869 // Restore the saved Context pointer into the Isolate structure. 864 // Restore the saved Context pointer into the Isolate structure.
870 // Uses R4 as a temporary register for this. 865 // Uses R4 as a temporary register for this.
871 // Restore the saved top exit frame info back into the Isolate structure. 866 // Restore the saved top exit frame info back into the Isolate structure.
872 // Uses R6 as a temporary register for this. 867 // Uses R6 as a temporary register for this.
873 __ Pop(R4); 868 __ Pop(R4);
874 __ Pop(R6); 869 __ Pop(R6);
875 __ StoreToOffset(R4, CTX, Isolate::top_context_offset()); 870 __ StoreToOffset(R4, CTX, Isolate::top_context_offset(), PP);
876 __ StoreToOffset(R6, CTX, Isolate::top_exit_frame_info_offset()); 871 __ StoreToOffset(R6, CTX, Isolate::top_exit_frame_info_offset(), PP);
877 872
878 __ Pop(R3); 873 __ Pop(R3);
879 __ Pop(R4); 874 __ Pop(R4);
880 875
881 // Restore the bottom 64-bits of callee-saved V registers. 876 // Restore the bottom 64-bits of callee-saved V registers.
882 for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) { 877 for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
883 const VRegister r = static_cast<VRegister>(i); 878 const VRegister r = static_cast<VRegister>(i);
884 __ PushDouble(r); 879 __ PushDouble(r);
885 } 880 }
886 881
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 // If no size tag overflow, shift R2 left, else set R2 to zero. 951 // If no size tag overflow, shift R2 left, else set R2 to zero.
957 __ Lsl(TMP, R2, shift); 952 __ Lsl(TMP, R2, shift);
958 __ csel(R2, TMP, R2, LS); 953 __ csel(R2, TMP, R2, LS);
959 __ csel(R2, ZR, R2, HI); 954 __ csel(R2, ZR, R2, HI);
960 955
961 // Get the class index and insert it into the tags. 956 // Get the class index and insert it into the tags.
962 // R2: size and bit tags. 957 // R2: size and bit tags.
963 __ LoadImmediate( 958 __ LoadImmediate(
964 TMP, RawObject::ClassIdTag::encode(context_class.id()), kNoPP); 959 TMP, RawObject::ClassIdTag::encode(context_class.id()), kNoPP);
965 __ orr(R2, R2, Operand(TMP)); 960 __ orr(R2, R2, Operand(TMP));
966 __ StoreFieldToOffset(R2, R0, Context::tags_offset()); 961 __ StoreFieldToOffset(R2, R0, Context::tags_offset(), kNoPP);
967 962
968 // Setup up number of context variables field. 963 // Setup up number of context variables field.
969 // R0: new object. 964 // R0: new object.
970 // R1: number of context variables as integer value (not object). 965 // R1: number of context variables as integer value (not object).
971 __ StoreFieldToOffset(R1, R0, Context::num_variables_offset()); 966 __ StoreFieldToOffset(R1, R0, Context::num_variables_offset(), kNoPP);
972 967
973 // Setup isolate field. 968 // Setup isolate field.
974 // Load Isolate pointer from Context structure into R2. 969 // Load Isolate pointer from Context structure into R2.
975 // R0: new object. 970 // R0: new object.
976 // R1: number of context variables. 971 // R1: number of context variables.
977 __ LoadFieldFromOffset(R2, CTX, Context::isolate_offset()); 972 __ LoadFieldFromOffset(R2, CTX, Context::isolate_offset(), kNoPP);
978 // R2: isolate, not an object. 973 // R2: isolate, not an object.
979 __ StoreFieldToOffset(R2, R0, Context::isolate_offset()); 974 __ StoreFieldToOffset(R2, R0, Context::isolate_offset(), kNoPP);
980 975
981 // Setup the parent field. 976 // Setup the parent field.
982 // R0: new object. 977 // R0: new object.
983 // R1: number of context variables. 978 // R1: number of context variables.
984 __ LoadObject(R2, Object::null_object(), PP); 979 __ LoadObject(R2, Object::null_object(), PP);
985 __ StoreFieldToOffset(R2, R0, Context::parent_offset()); 980 __ StoreFieldToOffset(R2, R0, Context::parent_offset(), kNoPP);
986 981
987 // Initialize the context variables. 982 // Initialize the context variables.
988 // R0: new object. 983 // R0: new object.
989 // R1: number of context variables. 984 // R1: number of context variables.
990 // R2: raw null. 985 // R2: raw null.
991 Label loop, done; 986 Label loop, done;
992 __ AddImmediate( 987 __ AddImmediate(
993 R3, R0, Context::variable_offset(0) - kHeapObjectTag, kNoPP); 988 R3, R0, Context::variable_offset(0) - kHeapObjectTag, kNoPP);
994 __ Bind(&loop); 989 __ Bind(&loop);
995 __ subs(R1, R1, Operand(1)); 990 __ subs(R1, R1, Operand(1));
(...skipping 27 matching lines...) Expand all
1023 1018
1024 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); 1019 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate);
1025 1020
1026 // Helper stub to implement Assembler::StoreIntoObject. 1021 // Helper stub to implement Assembler::StoreIntoObject.
1027 // Input parameters: 1022 // Input parameters:
1028 // R0: Address being stored 1023 // R0: Address being stored
1029 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { 1024 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
1030 Label add_to_buffer; 1025 Label add_to_buffer;
1031 // Check whether this object has already been remembered. Skip adding to the 1026 // Check whether this object has already been remembered. Skip adding to the
1032 // store buffer if the object is in the store buffer already. 1027 // store buffer if the object is in the store buffer already.
1033 __ LoadFieldFromOffset(TMP, R0, Object::tags_offset()); 1028 __ LoadFieldFromOffset(TMP, R0, Object::tags_offset(), kNoPP);
1034 __ tsti(TMP, 1 << RawObject::kRememberedBit); 1029 __ tsti(TMP, 1 << RawObject::kRememberedBit);
1035 __ b(&add_to_buffer, EQ); 1030 __ b(&add_to_buffer, EQ);
1036 __ ret(); 1031 __ ret();
1037 1032
1038 __ Bind(&add_to_buffer); 1033 __ Bind(&add_to_buffer);
1039 // Save values being destroyed. 1034 // Save values being destroyed.
1040 __ Push(R1); 1035 __ Push(R1);
1041 __ Push(R2); 1036 __ Push(R2);
1042 __ Push(R3); 1037 __ Push(R3);
1043 1038
1044 __ orri(R2, TMP, 1 << RawObject::kRememberedBit); 1039 __ orri(R2, TMP, 1 << RawObject::kRememberedBit);
1045 __ StoreFieldToOffset(R2, R0, Object::tags_offset()); 1040 __ StoreFieldToOffset(R2, R0, Object::tags_offset(), kNoPP);
1046 1041
1047 // Load the isolate out of the context. 1042 // Load the isolate out of the context.
1048 // Spilled: R1, R2, R3. 1043 // Spilled: R1, R2, R3.
1049 // R0: address being stored. 1044 // R0: address being stored.
1050 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset()); 1045 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset(), kNoPP);
1051 1046
1052 // Load the StoreBuffer block out of the isolate. Then load top_ out of the 1047 // Load the StoreBuffer block out of the isolate. Then load top_ out of the
1053 // StoreBufferBlock and add the address to the pointers_. 1048 // StoreBufferBlock and add the address to the pointers_.
1054 // R1: isolate. 1049 // R1: isolate.
1055 __ LoadFromOffset(R1, R1, Isolate::store_buffer_offset()); 1050 __ LoadFromOffset(R1, R1, Isolate::store_buffer_offset(), kNoPP);
1056 __ LoadFromOffset(R2, R1, StoreBufferBlock::top_offset(), kUnsignedWord); 1051 __ LoadFromOffset(R2, R1, StoreBufferBlock::top_offset(),
1052 kNoPP, kUnsignedWord);
1057 __ add(R3, R1, Operand(R2, LSL, 3)); 1053 __ add(R3, R1, Operand(R2, LSL, 3));
1058 __ StoreToOffset(R0, R3, StoreBufferBlock::pointers_offset()); 1054 __ StoreToOffset(R0, R3, StoreBufferBlock::pointers_offset(), kNoPP);
1059 1055
1060 // Increment top_ and check for overflow. 1056 // Increment top_ and check for overflow.
1061 // R2: top_. 1057 // R2: top_.
1062 // R1: StoreBufferBlock. 1058 // R1: StoreBufferBlock.
1063 Label L; 1059 Label L;
1064 __ add(R2, R2, Operand(1)); 1060 __ add(R2, R2, Operand(1));
1065 __ StoreToOffset(R2, R1, StoreBufferBlock::top_offset(), kUnsignedWord); 1061 __ StoreToOffset(R2, R1, StoreBufferBlock::top_offset(),
1062 kNoPP, kUnsignedWord);
1066 __ CompareImmediate(R2, StoreBufferBlock::kSize, kNoPP); 1063 __ CompareImmediate(R2, StoreBufferBlock::kSize, kNoPP);
1067 // Restore values. 1064 // Restore values.
1068 __ Pop(R3); 1065 __ Pop(R3);
1069 __ Pop(R2); 1066 __ Pop(R2);
1070 __ Pop(R1); 1067 __ Pop(R1);
1071 __ b(&L, EQ); 1068 __ b(&L, EQ);
1072 __ ret(); 1069 __ ret();
1073 1070
1074 // Handle overflow: Call the runtime leaf function. 1071 // Handle overflow: Call the runtime leaf function.
1075 __ Bind(&L); 1072 __ Bind(&L);
1076 // Setup frame, push callee-saved registers. 1073 // Setup frame, push callee-saved registers.
1077 1074
1078 __ EnterCallRuntimeFrame(0 * kWordSize); 1075 __ EnterCallRuntimeFrame(0 * kWordSize);
1079 __ LoadFieldFromOffset(R0, CTX, Context::isolate_offset()); 1076 __ LoadFieldFromOffset(R0, CTX, Context::isolate_offset(), kNoPP);
1080 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); 1077 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
1081 // Restore callee-saved registers, tear down frame. 1078 // Restore callee-saved registers, tear down frame.
1082 __ LeaveCallRuntimeFrame(); 1079 __ LeaveCallRuntimeFrame();
1083 __ ret(); 1080 __ ret();
1084 } 1081 }
1085 1082
1086 1083
1087 // Called for inline allocation of objects. 1084 // Called for inline allocation of objects.
1088 // Input parameters: 1085 // Input parameters:
1089 // LR : return address. 1086 // LR : return address.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 1126
1130 // R2: new object start. 1127 // R2: new object start.
1131 // R3: next object start. 1128 // R3: next object start.
1132 // R1: new object type arguments (if is_cls_parameterized). 1129 // R1: new object type arguments (if is_cls_parameterized).
1133 // Set the tags. 1130 // Set the tags.
1134 uword tags = 0; 1131 uword tags = 0;
1135 tags = RawObject::SizeTag::update(instance_size, tags); 1132 tags = RawObject::SizeTag::update(instance_size, tags);
1136 ASSERT(cls.id() != kIllegalCid); 1133 ASSERT(cls.id() != kIllegalCid);
1137 tags = RawObject::ClassIdTag::update(cls.id(), tags); 1134 tags = RawObject::ClassIdTag::update(cls.id(), tags);
1138 __ LoadImmediate(R0, tags, kNoPP); 1135 __ LoadImmediate(R0, tags, kNoPP);
1139 __ StoreToOffset(R0, R2, Instance::tags_offset()); 1136 __ StoreToOffset(R0, R2, Instance::tags_offset(), kNoPP);
1140 1137
1141 // Initialize the remaining words of the object. 1138 // Initialize the remaining words of the object.
1142 __ LoadObject(R0, Object::null_object(), PP); 1139 __ LoadObject(R0, Object::null_object(), PP);
1143 1140
1144 // R0: raw null. 1141 // R0: raw null.
1145 // R2: new object start. 1142 // R2: new object start.
1146 // R3: next object start. 1143 // R3: next object start.
1147 // R1: new object type arguments (if is_cls_parameterized). 1144 // R1: new object type arguments (if is_cls_parameterized).
1148 // First try inlining the initialization without a loop. 1145 // First try inlining the initialization without a loop.
1149 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1146 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1150 // Check if the object contains any non-header fields. 1147 // Check if the object contains any non-header fields.
1151 // Small objects are initialized using a consecutive set of writes. 1148 // Small objects are initialized using a consecutive set of writes.
1152 for (intptr_t current_offset = Instance::NextFieldOffset(); 1149 for (intptr_t current_offset = Instance::NextFieldOffset();
1153 current_offset < instance_size; 1150 current_offset < instance_size;
1154 current_offset += kWordSize) { 1151 current_offset += kWordSize) {
1155 __ StoreToOffset(R0, R2, current_offset); 1152 __ StoreToOffset(R0, R2, current_offset, kNoPP);
1156 } 1153 }
1157 } else { 1154 } else {
1158 __ AddImmediate(R4, R2, Instance::NextFieldOffset(), kNoPP); 1155 __ AddImmediate(R4, R2, Instance::NextFieldOffset(), kNoPP);
1159 // Loop until the whole object is initialized. 1156 // Loop until the whole object is initialized.
1160 // R0: raw null. 1157 // R0: raw null.
1161 // R2: new object. 1158 // R2: new object.
1162 // R3: next object start. 1159 // R3: next object start.
1163 // R4: next word to be initialized. 1160 // R4: next word to be initialized.
1164 // R1: new object type arguments (if is_cls_parameterized). 1161 // R1: new object type arguments (if is_cls_parameterized).
1165 Label init_loop; 1162 Label init_loop;
1166 Label done; 1163 Label done;
1167 __ Bind(&init_loop); 1164 __ Bind(&init_loop);
1168 __ CompareRegisters(R4, R3); 1165 __ CompareRegisters(R4, R3);
1169 __ b(&done, CS); 1166 __ b(&done, CS);
1170 __ str(R0, Address(R4)); 1167 __ str(R0, Address(R4));
1171 __ AddImmediate(R4, R4, kWordSize, kNoPP); 1168 __ AddImmediate(R4, R4, kWordSize, kNoPP);
1172 __ b(&init_loop); 1169 __ b(&init_loop);
1173 __ Bind(&done); 1170 __ Bind(&done);
1174 } 1171 }
1175 if (is_cls_parameterized) { 1172 if (is_cls_parameterized) {
1176 // R1: new object type arguments. 1173 // R1: new object type arguments.
1177 // Set the type arguments in the new object. 1174 // Set the type arguments in the new object.
1178 __ StoreToOffset(R1, R2, cls.type_arguments_field_offset()); 1175 __ StoreToOffset(R1, R2, cls.type_arguments_field_offset(), kNoPP);
1179 } 1176 }
1180 // Done allocating and initializing the instance. 1177 // Done allocating and initializing the instance.
1181 // R2: new object still missing its heap tag. 1178 // R2: new object still missing its heap tag.
1182 __ add(R0, R2, Operand(kHeapObjectTag)); 1179 __ add(R0, R2, Operand(kHeapObjectTag));
1183 // R0: new object. 1180 // R0: new object.
1184 __ ret(); 1181 __ ret();
1185 1182
1186 __ Bind(&slow_case); 1183 __ Bind(&slow_case);
1187 } 1184 }
1188 // If is_cls_parameterized: 1185 // If is_cls_parameterized:
(...skipping 26 matching lines...) Expand all
1215 // name or number is detected. 1212 // name or number is detected.
1216 // Input parameters: 1213 // Input parameters:
1217 // LR : return address. 1214 // LR : return address.
1218 // SP : address of last argument. 1215 // SP : address of last argument.
1219 // R5: inline cache data object. 1216 // R5: inline cache data object.
1220 // R4: arguments descriptor array. 1217 // R4: arguments descriptor array.
1221 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { 1218 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
1222 __ EnterStubFrame(true); 1219 __ EnterStubFrame(true);
1223 1220
1224 // Load the receiver. 1221 // Load the receiver.
1225 __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset()); 1222 __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset(), kNoPP);
1226 __ add(TMP, FP, Operand(R2, LSL, 2)); // R2 is Smi. 1223 __ add(TMP, FP, Operand(R2, LSL, 2)); // R2 is Smi.
1227 __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize); 1224 __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize, kNoPP);
1228 1225
1229 // Push space for the return value. 1226 // Push space for the return value.
1230 // Push the receiver. 1227 // Push the receiver.
1231 // Push IC data object. 1228 // Push IC data object.
1232 // Push arguments descriptor array. 1229 // Push arguments descriptor array.
1233 __ PushObject(Object::null_object(), PP); 1230 __ PushObject(Object::null_object(), PP);
1234 __ Push(R6); 1231 __ Push(R6);
1235 __ Push(R5); 1232 __ Push(R5);
1236 __ Push(R4); 1233 __ Push(R4);
1237 1234
(...skipping 21 matching lines...) Expand all
1259 __ Push(R6); // Preserve. 1256 __ Push(R6); // Preserve.
1260 __ Push(R5); // Preserve. 1257 __ Push(R5); // Preserve.
1261 __ Push(ic_reg); // Argument. 1258 __ Push(ic_reg); // Argument.
1262 __ Push(func_reg); // Argument. 1259 __ Push(func_reg); // Argument.
1263 __ CallRuntime(kTraceICCallRuntimeEntry, 2); 1260 __ CallRuntime(kTraceICCallRuntimeEntry, 2);
1264 __ Drop(2); // Discard argument; 1261 __ Drop(2); // Discard argument;
1265 __ Pop(R5); // Restore. 1262 __ Pop(R5); // Restore.
1266 __ Pop(R6); // Restore. 1263 __ Pop(R6); // Restore.
1267 __ LeaveStubFrame(); 1264 __ LeaveStubFrame();
1268 } 1265 }
1269 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset()); 1266 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(), kNoPP);
1270 __ add(R7, R7, Operand(1)); 1267 __ add(R7, R7, Operand(1));
1271 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset()); 1268 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(), kNoPP);
1272 } 1269 }
1273 1270
1274 1271
1275 // Loads function into 'temp_reg'. 1272 // Loads function into 'temp_reg'.
1276 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, 1273 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
1277 Register temp_reg) { 1274 Register temp_reg) {
1278 Register ic_reg = R5; 1275 Register ic_reg = R5;
1279 Register func_reg = temp_reg; 1276 Register func_reg = temp_reg;
1280 ASSERT(temp_reg == R6); 1277 ASSERT(temp_reg == R6);
1281 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset()); 1278 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset(), kNoPP);
1282 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset()); 1279 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(), kNoPP);
1283 __ AddImmediate(R7, R7, 1, kNoPP); 1280 __ AddImmediate(R7, R7, 1, kNoPP);
1284 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset()); 1281 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(), kNoPP);
1285 } 1282 }
1286 1283
1287 1284
1288 // Generate inline cache check for 'num_args'. 1285 // Generate inline cache check for 'num_args'.
1289 // LR: return address. 1286 // LR: return address.
1290 // R5: inline cache data object. 1287 // R5: inline cache data object.
1291 // Control flow: 1288 // Control flow:
1292 // - If receiver is null -> jump to IC miss. 1289 // - If receiver is null -> jump to IC miss.
1293 // - If receiver is Smi -> load Smi class. 1290 // - If receiver is Smi -> load Smi class.
1294 // - If receiver is not-Smi -> load receiver's class. 1291 // - If receiver is not-Smi -> load receiver's class.
1295 // - Check if 'num_args' (including receiver) match any IC data group. 1292 // - Check if 'num_args' (including receiver) match any IC data group.
1296 // - Match found -> jump to target. 1293 // - Match found -> jump to target.
1297 // - Match not found -> jump to IC miss. 1294 // - Match not found -> jump to IC miss.
1298 void StubCode::GenerateNArgsCheckInlineCacheStub( 1295 void StubCode::GenerateNArgsCheckInlineCacheStub(
1299 Assembler* assembler, 1296 Assembler* assembler,
1300 intptr_t num_args, 1297 intptr_t num_args,
1301 const RuntimeEntry& handle_ic_miss) { 1298 const RuntimeEntry& handle_ic_miss) {
1302 ASSERT(num_args > 0); 1299 ASSERT(num_args > 0);
1303 #if defined(DEBUG) 1300 #if defined(DEBUG)
1304 { Label ok; 1301 { Label ok;
1305 // Check that the IC data array has NumArgsTested() == num_args. 1302 // Check that the IC data array has NumArgsTested() == num_args.
1306 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1303 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1307 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, 1304 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
1308 kUnsignedWord); 1305 kNoPP, kUnsignedWord);
1309 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1306 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1310 __ andi(R6, R6, ICData::NumArgsTestedMask()); 1307 __ andi(R6, R6, ICData::NumArgsTestedMask());
1311 __ CompareImmediate(R6, num_args, kNoPP); 1308 __ CompareImmediate(R6, num_args, kNoPP);
1312 __ b(&ok, EQ); 1309 __ b(&ok, EQ);
1313 __ Stop("Incorrect stub for IC data"); 1310 __ Stop("Incorrect stub for IC data");
1314 __ Bind(&ok); 1311 __ Bind(&ok);
1315 } 1312 }
1316 #endif // DEBUG 1313 #endif // DEBUG
1317 1314
1318 // Check single stepping. 1315 // Check single stepping.
1319 Label not_stepping; 1316 Label not_stepping;
1320 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset()); 1317 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset(), kNoPP);
1321 __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte); 1318 __ LoadFromOffset(
1319 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
1322 __ CompareRegisters(R6, ZR); 1320 __ CompareRegisters(R6, ZR);
1323 __ b(&not_stepping, EQ); 1321 __ b(&not_stepping, EQ);
1324 __ EnterStubFrame(); 1322 __ EnterStubFrame();
1325 __ Push(R5); // Preserve IC data. 1323 __ Push(R5); // Preserve IC data.
1326 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1324 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1327 __ Pop(R5); 1325 __ Pop(R5);
1328 __ LeaveStubFrame(); 1326 __ LeaveStubFrame();
1329 __ Bind(&not_stepping); 1327 __ Bind(&not_stepping);
1330 1328
1331 // Load arguments descriptor into R4. 1329 // Load arguments descriptor into R4.
1332 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset()); 1330 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP);
1333 // Loop that checks if there is an IC data match. 1331 // Loop that checks if there is an IC data match.
1334 Label loop, update, test, found, get_class_id_as_smi; 1332 Label loop, update, test, found, get_class_id_as_smi;
1335 // R5: IC data object (preserved). 1333 // R5: IC data object (preserved).
1336 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); 1334 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP);
1337 // R6: ic_data_array with check entries: classes and target functions. 1335 // R6: ic_data_array with check entries: classes and target functions.
1338 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); 1336 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP);
1339 // R6: points directly to the first ic data array element. 1337 // R6: points directly to the first ic data array element.
1340 1338
1341 // Get the receiver's class ID (first read number of arguments from 1339 // Get the receiver's class ID (first read number of arguments from
1342 // arguments descriptor array and then access the receiver from the stack). 1340 // arguments descriptor array and then access the receiver from the stack).
1343 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); 1341 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), kNoPP);
1344 __ SmiUntag(R7); // Untag so we can use the LSL 3 addressing mode. 1342 __ SmiUntag(R7); // Untag so we can use the LSL 3 addressing mode.
1345 __ sub(R7, R7, Operand(1)); 1343 __ sub(R7, R7, Operand(1));
1346 1344
1347 // R0 <- [SP + (R7 << 3)] 1345 // R0 <- [SP + (R7 << 3)]
1348 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled)); 1346 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled));
1349 1347
1350 { 1348 {
1351 // TODO(zra): Put this code in a subroutine call as with other architectures 1349 // TODO(zra): Put this code in a subroutine call as with other architectures
1352 // when we have a bl(Label& l) instruction. 1350 // when we have a bl(Label& l) instruction.
1353 // Instance in R0, return its class-id in R0 as Smi. 1351 // Instance in R0, return its class-id in R0 as Smi.
1354 // Test if Smi -> load Smi class for comparison. 1352 // Test if Smi -> load Smi class for comparison.
1355 Label not_smi, done; 1353 Label not_smi, done;
1356 __ tsti(R0, kSmiTagMask); 1354 __ tsti(R0, kSmiTagMask);
1357 __ b(&not_smi, NE); 1355 __ b(&not_smi, NE);
1358 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoPP); 1356 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoPP);
1359 __ b(&done); 1357 __ b(&done);
1360 1358
1361 __ Bind(&not_smi); 1359 __ Bind(&not_smi);
1362 __ LoadClassId(R0, R0); 1360 __ LoadClassId(R0, R0, kNoPP);
1363 __ SmiTag(R0); 1361 __ SmiTag(R0);
1364 __ Bind(&done); 1362 __ Bind(&done);
1365 } 1363 }
1366 1364
1367 // R7: argument_count - 1 (untagged). 1365 // R7: argument_count - 1 (untagged).
1368 // R0: receiver's class ID (smi). 1366 // R0: receiver's class ID (smi).
1369 __ ldr(R1, Address(R6)); // First class id (smi) to check. 1367 __ ldr(R1, Address(R6)); // First class id (smi) to check.
1370 __ b(&test); 1368 __ b(&test);
1371 1369
1372 __ Bind(&loop); 1370 __ Bind(&loop);
1373 for (int i = 0; i < num_args; i++) { 1371 for (int i = 0; i < num_args; i++) {
1374 if (i > 0) { 1372 if (i > 0) {
1375 // If not the first, load the next argument's class ID. 1373 // If not the first, load the next argument's class ID.
1376 __ AddImmediate(R0, R7, -i, kNoPP); 1374 __ AddImmediate(R0, R7, -i, kNoPP);
1377 // R0 <- [SP + (R0 << 3)] 1375 // R0 <- [SP + (R0 << 3)]
1378 __ ldr(R0, Address(SP, R0, UXTX, Address::Scaled)); 1376 __ ldr(R0, Address(SP, R0, UXTX, Address::Scaled));
1379 { 1377 {
1380 // Instance in R0, return its class-id in R0 as Smi. 1378 // Instance in R0, return its class-id in R0 as Smi.
1381 // Test if Smi -> load Smi class for comparison. 1379 // Test if Smi -> load Smi class for comparison.
1382 Label not_smi, done; 1380 Label not_smi, done;
1383 __ tsti(R0, kSmiTagMask); 1381 __ tsti(R0, kSmiTagMask);
1384 __ b(&not_smi, NE); 1382 __ b(&not_smi, NE);
1385 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoPP); 1383 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoPP);
1386 __ b(&done); 1384 __ b(&done);
1387 1385
1388 __ Bind(&not_smi); 1386 __ Bind(&not_smi);
1389 __ LoadClassId(R0, R0); 1387 __ LoadClassId(R0, R0, kNoPP);
1390 __ SmiTag(R0); 1388 __ SmiTag(R0);
1391 __ Bind(&done); 1389 __ Bind(&done);
1392 } 1390 }
1393 // R0: next argument class ID (smi). 1391 // R0: next argument class ID (smi).
1394 __ LoadFromOffset(R1, R6, i * kWordSize); 1392 __ LoadFromOffset(R1, R6, i * kWordSize, kNoPP);
1395 // R1: next class ID to check (smi). 1393 // R1: next class ID to check (smi).
1396 } 1394 }
1397 __ CompareRegisters(R0, R1); // Class id match? 1395 __ CompareRegisters(R0, R1); // Class id match?
1398 if (i < (num_args - 1)) { 1396 if (i < (num_args - 1)) {
1399 __ b(&update, NE); // Continue. 1397 __ b(&update, NE); // Continue.
1400 } else { 1398 } else {
1401 // Last check, all checks before matched. 1399 // Last check, all checks before matched.
1402 __ b(&found, EQ); // Break. 1400 __ b(&found, EQ); // Break.
1403 } 1401 }
1404 } 1402 }
1405 __ Bind(&update); 1403 __ Bind(&update);
1406 // Reload receiver class ID. It has not been destroyed when num_args == 1. 1404 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1407 if (num_args > 1) { 1405 if (num_args > 1) {
1408 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled)); 1406 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled));
1409 { 1407 {
1410 // Instance in R0, return its class-id in R0 as Smi. 1408 // Instance in R0, return its class-id in R0 as Smi.
1411 // Test if Smi -> load Smi class for comparison. 1409 // Test if Smi -> load Smi class for comparison.
1412 Label not_smi, done; 1410 Label not_smi, done;
1413 __ tsti(R0, kSmiTagMask); 1411 __ tsti(R0, kSmiTagMask);
1414 __ b(&not_smi, NE); 1412 __ b(&not_smi, NE);
1415 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoPP); 1413 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoPP);
1416 __ b(&done); 1414 __ b(&done);
1417 1415
1418 __ Bind(&not_smi); 1416 __ Bind(&not_smi);
1419 __ LoadClassId(R0, R0); 1417 __ LoadClassId(R0, R0, kNoPP);
1420 __ SmiTag(R0); 1418 __ SmiTag(R0);
1421 __ Bind(&done); 1419 __ Bind(&done);
1422 } 1420 }
1423 } 1421 }
1424 1422
1425 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1423 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1426 __ AddImmediate(R6, R6, entry_size, kNoPP); // Next entry. 1424 __ AddImmediate(R6, R6, entry_size, kNoPP); // Next entry.
1427 __ ldr(R1, Address(R6)); // Next class ID. 1425 __ ldr(R1, Address(R6)); // Next class ID.
1428 1426
1429 __ Bind(&test); 1427 __ Bind(&test);
(...skipping 10 matching lines...) Expand all
1440 // calling into the runtime. 1438 // calling into the runtime.
1441 __ EnterStubFrame(); 1439 __ EnterStubFrame();
1442 // Preserve IC data object and arguments descriptor array and 1440 // Preserve IC data object and arguments descriptor array and
1443 // setup space on stack for result (target code object). 1441 // setup space on stack for result (target code object).
1444 __ Push(R4); // Preserve arguments descriptor array. 1442 __ Push(R4); // Preserve arguments descriptor array.
1445 __ Push(R5); // Preserve IC Data. 1443 __ Push(R5); // Preserve IC Data.
1446 // Setup space on stack for the result (target code object). 1444 // Setup space on stack for the result (target code object).
1447 __ PushObject(Object::null_object(), PP); 1445 __ PushObject(Object::null_object(), PP);
1448 // Push call arguments. 1446 // Push call arguments.
1449 for (intptr_t i = 0; i < num_args; i++) { 1447 for (intptr_t i = 0; i < num_args; i++) {
1450 __ LoadFromOffset(TMP, R7, -i * kWordSize); 1448 __ LoadFromOffset(TMP, R7, -i * kWordSize, kNoPP);
1451 __ Push(TMP); 1449 __ Push(TMP);
1452 } 1450 }
1453 // Pass IC data object. 1451 // Pass IC data object.
1454 __ Push(R5); 1452 __ Push(R5);
1455 __ CallRuntime(handle_ic_miss, num_args + 1); 1453 __ CallRuntime(handle_ic_miss, num_args + 1);
1456 // Remove the call arguments pushed earlier, including the IC data object. 1454 // Remove the call arguments pushed earlier, including the IC data object.
1457 __ Drop(num_args + 1); 1455 __ Drop(num_args + 1);
1458 // Pop returned function object into R0. 1456 // Pop returned function object into R0.
1459 // Restore arguments descriptor array and IC data array. 1457 // Restore arguments descriptor array and IC data array.
1460 __ Pop(R0); // Pop returned function object into R0. 1458 __ Pop(R0); // Pop returned function object into R0.
1461 __ Pop(R5); // Restore IC Data. 1459 __ Pop(R5); // Restore IC Data.
1462 __ Pop(R4); // Restore arguments descriptor array. 1460 __ Pop(R4); // Restore arguments descriptor array.
1463 __ LeaveStubFrame(); 1461 __ LeaveStubFrame();
1464 Label call_target_function; 1462 Label call_target_function;
1465 __ b(&call_target_function); 1463 __ b(&call_target_function);
1466 1464
1467 __ Bind(&found); 1465 __ Bind(&found);
1468 // R6: pointer to an IC data check group. 1466 // R6: pointer to an IC data check group.
1469 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1467 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1470 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1468 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1471 __ LoadFromOffset(R0, R6, target_offset); 1469 __ LoadFromOffset(R0, R6, target_offset, kNoPP);
1472 __ LoadFromOffset(R1, R6, count_offset); 1470 __ LoadFromOffset(R1, R6, count_offset, kNoPP);
1473 __ adds(R1, R1, Operand(Smi::RawValue(1))); 1471 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1474 __ StoreToOffset(R1, R6, count_offset); 1472 __ StoreToOffset(R1, R6, count_offset, kNoPP);
1475 __ b(&call_target_function, VC); // No overflow. 1473 __ b(&call_target_function, VC); // No overflow.
1476 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), kNoPP); 1474 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), kNoPP);
1477 __ StoreToOffset(R1, R6, count_offset); 1475 __ StoreToOffset(R1, R6, count_offset, kNoPP);
1478 1476
1479 __ Bind(&call_target_function); 1477 __ Bind(&call_target_function);
1480 // R0: target function. 1478 // R0: target function.
1481 __ LoadFieldFromOffset(R2, R0, Function::code_offset()); 1479 __ LoadFieldFromOffset(R2, R0, Function::code_offset(), kNoPP);
1482 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset()); 1480 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), kNoPP);
1483 __ AddImmediate( 1481 __ AddImmediate(
1484 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); 1482 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
1485 __ br(R2); 1483 __ br(R2);
1486 } 1484 }
1487 1485
1488 1486
1489 // Use inline cache data array to invoke the target or continue in inline 1487 // Use inline cache data array to invoke the target or continue in inline
1490 // cache miss handler. Stub for 1-argument check (receiver class). 1488 // cache miss handler. Stub for 1-argument check (receiver class).
1491 // LR: return address. 1489 // LR: return address.
1492 // R5: inline cache data object. 1490 // R5: inline cache data object.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1546 } 1544 }
1547 1545
1548 1546
1549 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1547 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1550 GenerateUsageCounterIncrement(assembler, R6); 1548 GenerateUsageCounterIncrement(assembler, R6);
1551 #if defined(DEBUG) 1549 #if defined(DEBUG)
1552 { Label ok; 1550 { Label ok;
1553 // Check that the IC data array has NumArgsTested() == 0. 1551 // Check that the IC data array has NumArgsTested() == 0.
1554 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1552 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1555 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, 1553 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
1556 kUnsignedWord); 1554 kNoPP, kUnsignedWord);
1557 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1555 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1558 __ andi(R6, R6, ICData::NumArgsTestedMask()); 1556 __ andi(R6, R6, ICData::NumArgsTestedMask());
1559 __ CompareImmediate(R6, 0, kNoPP); 1557 __ CompareImmediate(R6, 0, kNoPP);
1560 __ b(&ok, EQ); 1558 __ b(&ok, EQ);
1561 __ Stop("Incorrect IC data for unoptimized static call"); 1559 __ Stop("Incorrect IC data for unoptimized static call");
1562 __ Bind(&ok); 1560 __ Bind(&ok);
1563 } 1561 }
1564 #endif // DEBUG 1562 #endif // DEBUG
1565 1563
1566 // Check single stepping. 1564 // Check single stepping.
1567 Label not_stepping; 1565 Label not_stepping;
1568 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset()); 1566 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset(), kNoPP);
1569 __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte); 1567 __ LoadFromOffset(
1568 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
1570 __ CompareImmediate(R6, 0, kNoPP); 1569 __ CompareImmediate(R6, 0, kNoPP);
1571 __ b(&not_stepping, EQ); 1570 __ b(&not_stepping, EQ);
1572 __ EnterStubFrame(); 1571 __ EnterStubFrame();
1573 __ Push(R5); // Preserve IC data. 1572 __ Push(R5); // Preserve IC data.
1574 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1573 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1575 __ Pop(R5); 1574 __ Pop(R5);
1576 __ LeaveStubFrame(); 1575 __ LeaveStubFrame();
1577 __ Bind(&not_stepping); 1576 __ Bind(&not_stepping);
1578 1577
1579 // R5: IC data object (preserved). 1578 // R5: IC data object (preserved).
1580 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); 1579 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP);
1581 // R6: ic_data_array with entries: target functions and count. 1580 // R6: ic_data_array with entries: target functions and count.
1582 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); 1581 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP);
1583 // R6: points directly to the first ic data array element. 1582 // R6: points directly to the first ic data array element.
1584 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; 1583 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
1585 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; 1584 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
1586 1585
1587 // Increment count for this call. 1586 // Increment count for this call.
1588 Label increment_done; 1587 Label increment_done;
1589 __ LoadFromOffset(R1, R6, count_offset); 1588 __ LoadFromOffset(R1, R6, count_offset, kNoPP);
1590 __ adds(R1, R1, Operand(Smi::RawValue(1))); 1589 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1591 __ StoreToOffset(R1, R6, count_offset); 1590 __ StoreToOffset(R1, R6, count_offset, kNoPP);
1592 __ b(&increment_done, VC); // No overflow. 1591 __ b(&increment_done, VC); // No overflow.
1593 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), kNoPP); 1592 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), kNoPP);
1594 __ StoreToOffset(R1, R6, count_offset); 1593 __ StoreToOffset(R1, R6, count_offset, kNoPP);
1595 __ Bind(&increment_done); 1594 __ Bind(&increment_done);
1596 1595
1597 // Load arguments descriptor into R4. 1596 // Load arguments descriptor into R4.
1598 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset()); 1597 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP);
1599 1598
1600 // Get function and call it, if possible. 1599 // Get function and call it, if possible.
1601 __ LoadFromOffset(R0, R6, target_offset); 1600 __ LoadFromOffset(R0, R6, target_offset, kNoPP);
1602 __ LoadFieldFromOffset(R2, R0, Function::code_offset()); 1601 __ LoadFieldFromOffset(R2, R0, Function::code_offset(), kNoPP);
1603 1602
1604 // R0: function. 1603 // R0: function.
1605 // R2: target code. 1604 // R2: target code.
1606 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset()); 1605 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), kNoPP);
1607 __ AddImmediate( 1606 __ AddImmediate(
1608 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); 1607 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
1609 __ br(R2); 1608 __ br(R2);
1610 } 1609 }
1611 1610
1612 1611
1613 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1612 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1614 GenerateUsageCounterIncrement(assembler, R6); 1613 GenerateUsageCounterIncrement(assembler, R6);
1615 GenerateNArgsCheckInlineCacheStub( 1614 GenerateNArgsCheckInlineCacheStub(
1616 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); 1615 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry);
1617 } 1616 }
1618 1617
1619 1618
1620 // Stub for compiling a function and jumping to the compiled code. 1619 // Stub for compiling a function and jumping to the compiled code.
1621 // R5: IC-Data (for methods). 1620 // R5: IC-Data (for methods).
1622 // R4: Arguments descriptor. 1621 // R4: Arguments descriptor.
1623 // R0: Function. 1622 // R0: Function.
1624 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1623 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1625 // Preserve arg desc. and IC data object. 1624 // Preserve arg desc. and IC data object.
1626 __ EnterStubFrame(); 1625 __ EnterStubFrame();
1627 __ Push(R5); // Save IC Data. 1626 __ Push(R5); // Save IC Data.
1628 __ Push(R4); // Save arg. desc. 1627 __ Push(R4); // Save arg. desc.
1629 __ Push(R0); // Pass function. 1628 __ Push(R0); // Pass function.
1630 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); 1629 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
1631 __ Pop(R0); // Restore argument. 1630 __ Pop(R0); // Restore argument.
1632 __ Pop(R4); // Restore arg desc. 1631 __ Pop(R4); // Restore arg desc.
1633 __ Pop(R5); // Restore IC Data. 1632 __ Pop(R5); // Restore IC Data.
1634 __ LeaveStubFrame(); 1633 __ LeaveStubFrame();
1635 1634
1636 __ LoadFieldFromOffset(R2, R0, Function::code_offset()); 1635 __ LoadFieldFromOffset(R2, R0, Function::code_offset(), kNoPP);
1637 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset()); 1636 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset(), kNoPP);
1638 __ AddImmediate( 1637 __ AddImmediate(
1639 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); 1638 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
1640 __ br(R2); 1639 __ br(R2);
1641 } 1640 }
1642 1641
1643 1642
1644 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { 1643 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) {
1645 __ Stop("GenerateBreakpointRuntimeStub"); 1644 __ Stop("GenerateBreakpointRuntimeStub");
1646 } 1645 }
1647 1646
1648 1647
1649 // Called only from unoptimized code. All relevant registers have been saved. 1648 // Called only from unoptimized code. All relevant registers have been saved.
1650 void StubCode::GenerateDebugStepCheckStub( 1649 void StubCode::GenerateDebugStepCheckStub(
1651 Assembler* assembler) { 1650 Assembler* assembler) {
1652 // Check single stepping. 1651 // Check single stepping.
1653 Label not_stepping; 1652 Label not_stepping;
1654 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset()); 1653 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset(), kNoPP);
1655 __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte); 1654 __ LoadFromOffset(
1655 R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
1656 __ CompareImmediate(R1, 0, kNoPP); 1656 __ CompareImmediate(R1, 0, kNoPP);
1657 __ b(&not_stepping, EQ); 1657 __ b(&not_stepping, EQ);
1658 __ EnterStubFrame(); 1658 __ EnterStubFrame();
1659 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1659 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1660 __ LeaveStubFrame(); 1660 __ LeaveStubFrame();
1661 __ Bind(&not_stepping); 1661 __ Bind(&not_stepping);
1662 __ ret(); 1662 __ ret();
1663 } 1663 }
1664 1664
1665 1665
1666 // Used to check class and type arguments. Arguments passed in registers: 1666 // Used to check class and type arguments. Arguments passed in registers:
1667 // LR: return address. 1667 // LR: return address.
1668 // R0: instance (must be preserved). 1668 // R0: instance (must be preserved).
1669 // R1: instantiator type arguments or NULL. 1669 // R1: instantiator type arguments or NULL.
1670 // R2: cache array. 1670 // R2: cache array.
1671 // Result in R1: null -> not found, otherwise result (true or false). 1671 // Result in R1: null -> not found, otherwise result (true or false).
1672 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { 1672 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
1673 ASSERT((1 <= n) && (n <= 3)); 1673 ASSERT((1 <= n) && (n <= 3));
1674 if (n > 1) { 1674 if (n > 1) {
1675 // Get instance type arguments. 1675 // Get instance type arguments.
1676 __ LoadClass(R3, R0); 1676 __ LoadClass(R3, R0, kNoPP);
1677 // Compute instance type arguments into R4. 1677 // Compute instance type arguments into R4.
1678 Label has_no_type_arguments; 1678 Label has_no_type_arguments;
1679 __ LoadObject(R4, Object::null_object(), PP); 1679 __ LoadObject(R4, Object::null_object(), PP);
1680 __ LoadFieldFromOffset( 1680 __ LoadFieldFromOffset(
1681 R5, R3, Class::type_arguments_field_offset_in_words_offset()); 1681 R5, R3, Class::type_arguments_field_offset_in_words_offset(), kNoPP);
1682 __ CompareImmediate(R5, Class::kNoTypeArguments, kNoPP); 1682 __ CompareImmediate(R5, Class::kNoTypeArguments, kNoPP);
1683 __ b(&has_no_type_arguments, EQ); 1683 __ b(&has_no_type_arguments, EQ);
1684 __ add(R5, R0, Operand(R5, LSL, 3)); 1684 __ add(R5, R0, Operand(R5, LSL, 3));
1685 __ LoadFieldFromOffset(R4, R5, 0); 1685 __ LoadFieldFromOffset(R4, R5, 0, kNoPP);
1686 __ Bind(&has_no_type_arguments); 1686 __ Bind(&has_no_type_arguments);
1687 } 1687 }
1688 __ LoadClassId(R3, R0); 1688 __ LoadClassId(R3, R0, kNoPP);
1689 // R0: instance. 1689 // R0: instance.
1690 // R1: instantiator type arguments or NULL. 1690 // R1: instantiator type arguments or NULL.
1691 // R2: SubtypeTestCache. 1691 // R2: SubtypeTestCache.
1692 // R3: instance class id. 1692 // R3: instance class id.
1693 // R4: instance type arguments (null if none), used only if n > 1. 1693 // R4: instance type arguments (null if none), used only if n > 1.
1694 __ LoadFieldFromOffset(R2, R2, SubtypeTestCache::cache_offset()); 1694 __ LoadFieldFromOffset(R2, R2, SubtypeTestCache::cache_offset(), kNoPP);
1695 __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag, kNoPP); 1695 __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag, kNoPP);
1696 1696
1697 Label loop, found, not_found, next_iteration; 1697 Label loop, found, not_found, next_iteration;
1698 // R2: entry start. 1698 // R2: entry start.
1699 // R3: instance class id. 1699 // R3: instance class id.
1700 // R4: instance type arguments. 1700 // R4: instance type arguments.
1701 __ SmiTag(R3); 1701 __ SmiTag(R3);
1702 __ Bind(&loop); 1702 __ Bind(&loop);
1703 __ LoadFromOffset(R5, R2, kWordSize * SubtypeTestCache::kInstanceClassId); 1703 __ LoadFromOffset(
1704 R5, R2, kWordSize * SubtypeTestCache::kInstanceClassId, kNoPP);
1704 __ CompareObject(R5, Object::null_object(), PP); 1705 __ CompareObject(R5, Object::null_object(), PP);
1705 __ b(&not_found, EQ); 1706 __ b(&not_found, EQ);
1706 __ CompareRegisters(R5, R3); 1707 __ CompareRegisters(R5, R3);
1707 if (n == 1) { 1708 if (n == 1) {
1708 __ b(&found, EQ); 1709 __ b(&found, EQ);
1709 } else { 1710 } else {
1710 __ b(&next_iteration, NE); 1711 __ b(&next_iteration, NE);
1711 __ LoadFromOffset( 1712 __ LoadFromOffset(
1712 R5, R2, kWordSize * SubtypeTestCache::kInstanceTypeArguments); 1713 R5, R2, kWordSize * SubtypeTestCache::kInstanceTypeArguments, kNoPP);
1713 __ CompareRegisters(R5, R4); 1714 __ CompareRegisters(R5, R4);
1714 if (n == 2) { 1715 if (n == 2) {
1715 __ b(&found, EQ); 1716 __ b(&found, EQ);
1716 } else { 1717 } else {
1717 __ b(&next_iteration, NE); 1718 __ b(&next_iteration, NE);
1718 __ LoadFromOffset( 1719 __ LoadFromOffset(R5, R2,
1719 R5, R2, kWordSize * SubtypeTestCache::kInstantiatorTypeArguments); 1720 kWordSize * SubtypeTestCache::kInstantiatorTypeArguments, kNoPP);
1720 __ CompareRegisters(R5, R1); 1721 __ CompareRegisters(R5, R1);
1721 __ b(&found, EQ); 1722 __ b(&found, EQ);
1722 } 1723 }
1723 } 1724 }
1724 __ Bind(&next_iteration); 1725 __ Bind(&next_iteration);
1725 __ AddImmediate( 1726 __ AddImmediate(
1726 R2, R2, kWordSize * SubtypeTestCache::kTestEntryLength, kNoPP); 1727 R2, R2, kWordSize * SubtypeTestCache::kTestEntryLength, kNoPP);
1727 __ b(&loop); 1728 __ b(&loop);
1728 // Fall through to not found. 1729 // Fall through to not found.
1729 __ Bind(&not_found); 1730 __ Bind(&not_found);
1730 __ LoadObject(R1, Object::null_object(), PP); 1731 __ LoadObject(R1, Object::null_object(), PP);
1731 __ ret(); 1732 __ ret();
1732 1733
1733 __ Bind(&found); 1734 __ Bind(&found);
1734 __ LoadFromOffset(R1, R2, kWordSize * SubtypeTestCache::kTestResult); 1735 __ LoadFromOffset(R1, R2, kWordSize * SubtypeTestCache::kTestResult, kNoPP);
1735 __ ret(); 1736 __ ret();
1736 } 1737 }
1737 1738
1738 1739
1739 // Used to check class and type arguments. Arguments passed on stack: 1740 // Used to check class and type arguments. Arguments passed on stack:
1740 // TOS + 0: return address. 1741 // TOS + 0: return address.
1741 // TOS + 1: instantiator type arguments or NULL. 1742 // TOS + 1: instantiator type arguments or NULL.
1742 // TOS + 2: instance. 1743 // TOS + 2: instance.
1743 // TOS + 3: cache array. 1744 // TOS + 3: cache array.
1744 // Result in RCX: null -> not found, otherwise result (true or false). 1745 // Result in RCX: null -> not found, otherwise result (true or false).
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 1786 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
1786 __ EnterStubFrame(); 1787 __ EnterStubFrame();
1787 __ Push(R4); 1788 __ Push(R4);
1788 // Setup space on stack for the return value. 1789 // Setup space on stack for the return value.
1789 __ PushObject(Object::null_object(), PP); 1790 __ PushObject(Object::null_object(), PP);
1790 __ Push(R6); 1791 __ Push(R6);
1791 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); 1792 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
1792 __ Pop(R0); // Discard argument. 1793 __ Pop(R0); // Discard argument.
1793 __ Pop(R0); // Get Code object 1794 __ Pop(R0); // Get Code object
1794 __ Pop(R4); // Restore argument descriptor. 1795 __ Pop(R4); // Restore argument descriptor.
1795 __ LoadFieldFromOffset(R0, R0, Code::instructions_offset()); 1796 __ LoadFieldFromOffset(R0, R0, Code::instructions_offset(), kNoPP);
1796 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, PP); 1797 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag, PP);
1797 __ LeaveStubFrame(); 1798 __ LeaveStubFrame();
1798 __ br(R0); 1799 __ br(R0);
1799 __ hlt(0); 1800 __ hlt(0);
1800 } 1801 }
1801 1802
1802 1803
1803 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, 1804 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t,
1804 BigintCompare, 1805 BigintCompare,
1805 RawBigint* left, 1806 RawBigint* left,
(...skipping 12 matching lines...) Expand all
1818 const Register unused1, 1819 const Register unused1,
1819 const Register unused2) { 1820 const Register unused2) {
1820 Label reference_compare, done, check_mint, check_bigint; 1821 Label reference_compare, done, check_mint, check_bigint;
1821 // If any of the arguments is Smi do reference compare. 1822 // If any of the arguments is Smi do reference compare.
1822 __ tsti(left, kSmiTagMask); 1823 __ tsti(left, kSmiTagMask);
1823 __ b(&reference_compare, EQ); 1824 __ b(&reference_compare, EQ);
1824 __ tsti(right, kSmiTagMask); 1825 __ tsti(right, kSmiTagMask);
1825 __ b(&reference_compare, EQ); 1826 __ b(&reference_compare, EQ);
1826 1827
1827 // Value compare for two doubles. 1828 // Value compare for two doubles.
1828 __ CompareClassId(left, kDoubleCid); 1829 __ CompareClassId(left, kDoubleCid, kNoPP);
1829 __ b(&check_mint, NE); 1830 __ b(&check_mint, NE);
1830 __ CompareClassId(right, kDoubleCid); 1831 __ CompareClassId(right, kDoubleCid, kNoPP);
1831 __ b(&done, NE); 1832 __ b(&done, NE);
1832 1833
1833 // Double values bitwise compare. 1834 // Double values bitwise compare.
1834 __ LoadFieldFromOffset(left, left, Double::value_offset()); 1835 __ LoadFieldFromOffset(left, left, Double::value_offset(), kNoPP);
1835 __ LoadFieldFromOffset(right, right, Double::value_offset()); 1836 __ LoadFieldFromOffset(right, right, Double::value_offset(), kNoPP);
1836 __ CompareRegisters(left, right); 1837 __ CompareRegisters(left, right);
1837 __ b(&done); 1838 __ b(&done);
1838 1839
1839 __ Bind(&check_mint); 1840 __ Bind(&check_mint);
1840 __ CompareClassId(left, kMintCid); 1841 __ CompareClassId(left, kMintCid, kNoPP);
1841 __ b(&check_bigint, NE); 1842 __ b(&check_bigint, NE);
1842 __ CompareClassId(right, kMintCid); 1843 __ CompareClassId(right, kMintCid, kNoPP);
1843 __ b(&done, NE); 1844 __ b(&done, NE);
1844 __ LoadFieldFromOffset(left, left, Mint::value_offset()); 1845 __ LoadFieldFromOffset(left, left, Mint::value_offset(), kNoPP);
1845 __ LoadFieldFromOffset(right, right, Mint::value_offset()); 1846 __ LoadFieldFromOffset(right, right, Mint::value_offset(), kNoPP);
1846 __ b(&done); 1847 __ b(&done);
1847 1848
1848 __ Bind(&check_bigint); 1849 __ Bind(&check_bigint);
1849 __ CompareClassId(left, kBigintCid); 1850 __ CompareClassId(left, kBigintCid, kNoPP);
1850 __ b(&reference_compare, NE); 1851 __ b(&reference_compare, NE);
1851 __ CompareClassId(right, kBigintCid); 1852 __ CompareClassId(right, kBigintCid, kNoPP);
1852 __ b(&done, NE); 1853 __ b(&done, NE);
1853 __ EnterFrame(0); 1854 __ EnterFrame(0);
1854 __ ReserveAlignedFrameSpace(2 * kWordSize); 1855 __ ReserveAlignedFrameSpace(2 * kWordSize);
1855 __ StoreToOffset(left, SP, 0 * kWordSize); 1856 __ StoreToOffset(left, SP, 0 * kWordSize, kNoPP);
1856 __ StoreToOffset(right, SP, 1 * kWordSize); 1857 __ StoreToOffset(right, SP, 1 * kWordSize, kNoPP);
1857 __ CallRuntime(kBigintCompareRuntimeEntry, 2); 1858 __ CallRuntime(kBigintCompareRuntimeEntry, 2);
1858 // Result in R0, 0 means equal. 1859 // Result in R0, 0 means equal.
1859 __ LeaveFrame(); 1860 __ LeaveFrame();
1860 __ cmp(R0, Operand(0)); 1861 __ cmp(R0, Operand(0));
1861 __ b(&done); 1862 __ b(&done);
1862 1863
1863 __ Bind(&reference_compare); 1864 __ Bind(&reference_compare);
1864 __ CompareRegisters(left, right); 1865 __ CompareRegisters(left, right);
1865 __ Bind(&done); 1866 __ Bind(&done);
1866 } 1867 }
1867 1868
1868 1869
1869 // Called only from unoptimized code. All relevant registers have been saved. 1870 // Called only from unoptimized code. All relevant registers have been saved.
1870 // LR: return address. 1871 // LR: return address.
1871 // SP + 4: left operand. 1872 // SP + 4: left operand.
1872 // SP + 0: right operand. 1873 // SP + 0: right operand.
1873 // Return Zero condition flag set if equal. 1874 // Return Zero condition flag set if equal.
1874 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( 1875 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
1875 Assembler* assembler) { 1876 Assembler* assembler) {
1876 // Check single stepping. 1877 // Check single stepping.
1877 Label not_stepping; 1878 Label not_stepping;
1878 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset()); 1879 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset(), kNoPP);
1879 __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte); 1880 __ LoadFromOffset(
1881 R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
1880 __ CompareImmediate(R1, 0, kNoPP); 1882 __ CompareImmediate(R1, 0, kNoPP);
1881 __ b(&not_stepping, EQ); 1883 __ b(&not_stepping, EQ);
1882 __ EnterStubFrame(); 1884 __ EnterStubFrame();
1883 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1885 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1884 __ LeaveStubFrame(); 1886 __ LeaveStubFrame();
1885 __ Bind(&not_stepping); 1887 __ Bind(&not_stepping);
1886 1888
1887 const Register left = R1; 1889 const Register left = R1;
1888 const Register right = R0; 1890 const Register right = R0;
1889 __ LoadFromOffset(left, SP, 1 * kWordSize); 1891 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP);
1890 __ LoadFromOffset(right, SP, 0 * kWordSize); 1892 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP);
1891 GenerateIdenticalWithNumberCheckStub(assembler, left, right); 1893 GenerateIdenticalWithNumberCheckStub(assembler, left, right);
1892 __ ret(); 1894 __ ret();
1893 } 1895 }
1894 1896
1895 1897
1896 // Called from optimized code only. 1898 // Called from optimized code only.
1897 // LR: return address. 1899 // LR: return address.
1898 // SP + 4: left operand. 1900 // SP + 4: left operand.
1899 // SP + 0: right operand. 1901 // SP + 0: right operand.
1900 // Return Zero condition flag set if equal. 1902 // Return Zero condition flag set if equal.
1901 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( 1903 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
1902 Assembler* assembler) { 1904 Assembler* assembler) {
1903 const Register temp = R2; 1905 const Register temp = R2;
1904 const Register left = R1; 1906 const Register left = R1;
1905 const Register right = R0; 1907 const Register right = R0;
1906 __ LoadFromOffset(left, SP, 1 * kWordSize); 1908 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP);
1907 __ LoadFromOffset(right, SP, 0 * kWordSize); 1909 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP);
1908 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); 1910 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
1909 __ ret(); 1911 __ ret();
1910 } 1912 }
1911 1913
1912 } // namespace dart 1914 } // namespace dart
1913 1915
1914 #endif // defined TARGET_ARCH_ARM64 1916 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm64.cc ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698