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

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

Issue 297163012: Rename ShifterOperand to Operand on ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 6 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/object_arm_test.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
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/cpu.h" 10 #include "vm/cpu.h"
(...skipping 25 matching lines...) Expand all
36 // SP + 4*R4 : address of return value. 36 // SP + 4*R4 : address of return value.
37 // R5 : address of the runtime function to call. 37 // R5 : address of the runtime function to call.
38 // R4 : number of arguments to the call. 38 // R4 : number of arguments to the call.
39 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { 39 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
40 const intptr_t isolate_offset = NativeArguments::isolate_offset(); 40 const intptr_t isolate_offset = NativeArguments::isolate_offset();
41 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 41 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
42 const intptr_t argv_offset = NativeArguments::argv_offset(); 42 const intptr_t argv_offset = NativeArguments::argv_offset();
43 const intptr_t retval_offset = NativeArguments::retval_offset(); 43 const intptr_t retval_offset = NativeArguments::retval_offset();
44 const intptr_t exitframe_last_param_slot_from_fp = 2; 44 const intptr_t exitframe_last_param_slot_from_fp = 2;
45 45
46 __ mov(IP, ShifterOperand(0)); 46 __ mov(IP, Operand(0));
47 __ Push(IP); // Push 0 for the PC marker. 47 __ Push(IP); // Push 0 for the PC marker.
48 __ EnterFrame((1 << FP) | (1 << LR), 0); 48 __ EnterFrame((1 << FP) | (1 << LR), 0);
49 49
50 // Load current Isolate pointer from Context structure into R0. 50 // Load current Isolate pointer from Context structure into R0.
51 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); 51 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset()));
52 52
53 // Save exit frame information to enable stack walking as we are about 53 // Save exit frame information to enable stack walking as we are about
54 // to transition to Dart VM C++ code. 54 // to transition to Dart VM C++ code.
55 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset()); 55 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset());
56 56
57 // Save current Context pointer into Isolate structure. 57 // Save current Context pointer into Isolate structure.
58 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset()); 58 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset());
59 59
60 // Cache Isolate pointer into CTX while executing runtime code. 60 // Cache Isolate pointer into CTX while executing runtime code.
61 __ mov(CTX, ShifterOperand(R0)); 61 __ mov(CTX, Operand(R0));
62 62
63 #if defined(DEBUG) 63 #if defined(DEBUG)
64 { Label ok; 64 { Label ok;
65 // Check that we are always entering from Dart code. 65 // Check that we are always entering from Dart code.
66 __ LoadFromOffset(kWord, R6, CTX, Isolate::vm_tag_offset()); 66 __ LoadFromOffset(kWord, R6, CTX, Isolate::vm_tag_offset());
67 __ CompareImmediate(R6, VMTag::kScriptTagId); 67 __ CompareImmediate(R6, VMTag::kScriptTagId);
68 __ b(&ok, EQ); 68 __ b(&ok, EQ);
69 __ Stop("Not coming from Dart code."); 69 __ Stop("Not coming from Dart code.");
70 __ Bind(&ok); 70 __ Bind(&ok);
71 } 71 }
72 #endif 72 #endif
73 73
74 // Mark that the isolate is executing VM code. 74 // Mark that the isolate is executing VM code.
75 __ StoreToOffset(kWord, R5, CTX, Isolate::vm_tag_offset()); 75 __ StoreToOffset(kWord, R5, CTX, Isolate::vm_tag_offset());
76 76
77 // Reserve space for arguments and align frame before entering C++ world. 77 // Reserve space for arguments and align frame before entering C++ world.
78 // NativeArguments are passed in registers. 78 // NativeArguments are passed in registers.
79 ASSERT(sizeof(NativeArguments) == 4 * kWordSize); 79 ASSERT(sizeof(NativeArguments) == 4 * kWordSize);
80 __ ReserveAlignedFrameSpace(0); 80 __ ReserveAlignedFrameSpace(0);
81 81
82 // Pass NativeArguments structure by value and call runtime. 82 // Pass NativeArguments structure by value and call runtime.
83 // Registers R0, R1, R2, and R3 are used. 83 // Registers R0, R1, R2, and R3 are used.
84 84
85 ASSERT(isolate_offset == 0 * kWordSize); 85 ASSERT(isolate_offset == 0 * kWordSize);
86 // Set isolate in NativeArgs: R0 already contains CTX. 86 // Set isolate in NativeArgs: R0 already contains CTX.
87 87
88 // There are no runtime calls to closures, so we do not need to set the tag 88 // There are no runtime calls to closures, so we do not need to set the tag
89 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 89 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
90 ASSERT(argc_tag_offset == 1 * kWordSize); 90 ASSERT(argc_tag_offset == 1 * kWordSize);
91 __ mov(R1, ShifterOperand(R4)); // Set argc in NativeArguments. 91 __ mov(R1, Operand(R4)); // Set argc in NativeArguments.
92 92
93 ASSERT(argv_offset == 2 * kWordSize); 93 ASSERT(argv_offset == 2 * kWordSize);
94 __ add(R2, FP, ShifterOperand(R4, LSL, 2)); // Compute argv. 94 __ add(R2, FP, Operand(R4, LSL, 2)); // Compute argv.
95 // Set argv in NativeArguments. 95 // Set argv in NativeArguments.
96 __ AddImmediate(R2, exitframe_last_param_slot_from_fp * kWordSize); 96 __ AddImmediate(R2, exitframe_last_param_slot_from_fp * kWordSize);
97 97
98 ASSERT(retval_offset == 3 * kWordSize); 98 ASSERT(retval_offset == 3 * kWordSize);
99 __ add(R3, R2, ShifterOperand(kWordSize)); // Retval is next to 1st argument. 99 __ add(R3, R2, Operand(kWordSize)); // Retval is next to 1st argument.
100 100
101 // Call runtime or redirection via simulator. 101 // Call runtime or redirection via simulator.
102 __ blx(R5); 102 __ blx(R5);
103 103
104 // Mark that the isolate is executing Dart code. 104 // Mark that the isolate is executing Dart code.
105 __ LoadImmediate(R2, VMTag::kScriptTagId); 105 __ LoadImmediate(R2, VMTag::kScriptTagId);
106 __ StoreToOffset(kWord, R2, CTX, Isolate::vm_tag_offset()); 106 __ StoreToOffset(kWord, R2, CTX, Isolate::vm_tag_offset());
107 107
108 // Reset exit frame information in Isolate structure. 108 // Reset exit frame information in Isolate structure.
109 __ LoadImmediate(R2, 0); 109 __ LoadImmediate(R2, 0);
110 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset()); 110 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset());
111 111
112 // Load Context pointer from Isolate structure into R2. 112 // Load Context pointer from Isolate structure into R2.
113 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset()); 113 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset());
114 114
115 // Reset Context pointer in Isolate structure. 115 // Reset Context pointer in Isolate structure.
116 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); 116 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null()));
117 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset()); 117 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset());
118 118
119 // Cache Context pointer into CTX while executing Dart code. 119 // Cache Context pointer into CTX while executing Dart code.
120 __ mov(CTX, ShifterOperand(R2)); 120 __ mov(CTX, Operand(R2));
121 121
122 __ LeaveFrame((1 << FP) | (1 << LR)); 122 __ LeaveFrame((1 << FP) | (1 << LR));
123 // Adjust SP for the empty PC marker. 123 // Adjust SP for the empty PC marker.
124 __ AddImmediate(SP, kWordSize); 124 __ AddImmediate(SP, kWordSize);
125 __ Ret(); 125 __ Ret();
126 } 126 }
127 127
128 128
129 // Print the stop message. 129 // Print the stop message.
130 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { 130 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) {
(...skipping 19 matching lines...) Expand all
150 // SP : address of return value. 150 // SP : address of return value.
151 // R5 : address of the native function to call. 151 // R5 : address of the native function to call.
152 // R2 : address of first argument in argument array. 152 // R2 : address of first argument in argument array.
153 // R1 : argc_tag including number of arguments and function kind. 153 // R1 : argc_tag including number of arguments and function kind.
154 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { 154 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) {
155 const intptr_t isolate_offset = NativeArguments::isolate_offset(); 155 const intptr_t isolate_offset = NativeArguments::isolate_offset();
156 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 156 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
157 const intptr_t argv_offset = NativeArguments::argv_offset(); 157 const intptr_t argv_offset = NativeArguments::argv_offset();
158 const intptr_t retval_offset = NativeArguments::retval_offset(); 158 const intptr_t retval_offset = NativeArguments::retval_offset();
159 159
160 __ mov(IP, ShifterOperand(0)); 160 __ mov(IP, Operand(0));
161 __ Push(IP); // Push 0 for the PC marker. 161 __ Push(IP); // Push 0 for the PC marker.
162 __ EnterFrame((1 << FP) | (1 << LR), 0); 162 __ EnterFrame((1 << FP) | (1 << LR), 0);
163 163
164 // Load current Isolate pointer from Context structure into R0. 164 // Load current Isolate pointer from Context structure into R0.
165 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); 165 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset()));
166 166
167 // Save exit frame information to enable stack walking as we are about 167 // Save exit frame information to enable stack walking as we are about
168 // to transition to native code. 168 // to transition to native code.
169 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset()); 169 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset());
170 170
171 // Save current Context pointer into Isolate structure. 171 // Save current Context pointer into Isolate structure.
172 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset()); 172 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset());
173 173
174 // Cache Isolate pointer into CTX while executing native code. 174 // Cache Isolate pointer into CTX while executing native code.
175 __ mov(CTX, ShifterOperand(R0)); 175 __ mov(CTX, Operand(R0));
176 176
177 #if defined(DEBUG) 177 #if defined(DEBUG)
178 { Label ok; 178 { Label ok;
179 // Check that we are always entering from Dart code. 179 // Check that we are always entering from Dart code.
180 __ LoadFromOffset(kWord, R6, CTX, Isolate::vm_tag_offset()); 180 __ LoadFromOffset(kWord, R6, CTX, Isolate::vm_tag_offset());
181 __ CompareImmediate(R6, VMTag::kScriptTagId); 181 __ CompareImmediate(R6, VMTag::kScriptTagId);
182 __ b(&ok, EQ); 182 __ b(&ok, EQ);
183 __ Stop("Not coming from Dart code."); 183 __ Stop("Not coming from Dart code.");
184 __ Bind(&ok); 184 __ Bind(&ok);
185 } 185 }
(...skipping 15 matching lines...) Expand all
201 201
202 // There are no native calls to closures, so we do not need to set the tag 202 // There are no native calls to closures, so we do not need to set the tag
203 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 203 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
204 ASSERT(argc_tag_offset == 1 * kWordSize); 204 ASSERT(argc_tag_offset == 1 * kWordSize);
205 // Set argc in NativeArguments: R1 already contains argc. 205 // Set argc in NativeArguments: R1 already contains argc.
206 206
207 ASSERT(argv_offset == 2 * kWordSize); 207 ASSERT(argv_offset == 2 * kWordSize);
208 // Set argv in NativeArguments: R2 already contains argv. 208 // Set argv in NativeArguments: R2 already contains argv.
209 209
210 ASSERT(retval_offset == 3 * kWordSize); 210 ASSERT(retval_offset == 3 * kWordSize);
211 __ add(R3, FP, ShifterOperand(3 * kWordSize)); // Set retval in NativeArgs. 211 __ add(R3, FP, Operand(3 * kWordSize)); // Set retval in NativeArgs.
212 212
213 // TODO(regis): Should we pass the structure by value as in runtime calls? 213 // TODO(regis): Should we pass the structure by value as in runtime calls?
214 // It would require changing Dart API for native functions. 214 // It would require changing Dart API for native functions.
215 // For now, space is reserved on the stack and we pass a pointer to it. 215 // For now, space is reserved on the stack and we pass a pointer to it.
216 __ stm(IA, SP, (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3)); 216 __ stm(IA, SP, (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3));
217 __ mov(R0, ShifterOperand(SP)); // Pass the pointer to the NativeArguments. 217 __ mov(R0, Operand(SP)); // Pass the pointer to the NativeArguments.
218 218
219 // Call native function (setsup scope if not leaf function). 219 // Call native function (setsup scope if not leaf function).
220 Label leaf_call; 220 Label leaf_call;
221 Label done; 221 Label done;
222 __ TestImmediate(R1, NativeArguments::AutoSetupScopeMask()); 222 __ TestImmediate(R1, NativeArguments::AutoSetupScopeMask());
223 __ b(&leaf_call, EQ); 223 __ b(&leaf_call, EQ);
224 224
225 __ mov(R1, ShifterOperand(R5)); // Pass the function entrypoint to call. 225 __ mov(R1, Operand(R5)); // Pass the function entrypoint to call.
226 // Call native function invocation wrapper or redirection via simulator. 226 // Call native function invocation wrapper or redirection via simulator.
227 #if defined(USING_SIMULATOR) 227 #if defined(USING_SIMULATOR)
228 uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper); 228 uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper);
229 entry = Simulator::RedirectExternalReference( 229 entry = Simulator::RedirectExternalReference(
230 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); 230 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
231 __ LoadImmediate(R2, entry); 231 __ LoadImmediate(R2, entry);
232 __ blx(R2); 232 __ blx(R2);
233 #else 233 #else
234 __ BranchLink(&NativeEntry::NativeCallWrapperLabel()); 234 __ BranchLink(&NativeEntry::NativeCallWrapperLabel());
235 #endif 235 #endif
(...skipping 14 matching lines...) Expand all
250 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset()); 250 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset());
251 251
252 // Load Context pointer from Isolate structure into R2. 252 // Load Context pointer from Isolate structure into R2.
253 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset()); 253 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset());
254 254
255 // Reset Context pointer in Isolate structure. 255 // Reset Context pointer in Isolate structure.
256 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); 256 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null()));
257 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset()); 257 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset());
258 258
259 // Cache Context pointer into CTX while executing Dart code. 259 // Cache Context pointer into CTX while executing Dart code.
260 __ mov(CTX, ShifterOperand(R2)); 260 __ mov(CTX, Operand(R2));
261 261
262 __ LeaveFrame((1 << FP) | (1 << LR)); 262 __ LeaveFrame((1 << FP) | (1 << LR));
263 // Adjust SP for the empty PC marker. 263 // Adjust SP for the empty PC marker.
264 __ AddImmediate(SP, kWordSize); 264 __ AddImmediate(SP, kWordSize);
265 __ Ret(); 265 __ Ret();
266 } 266 }
267 267
268 268
269 // Input parameters: 269 // Input parameters:
270 // LR : return address. 270 // LR : return address.
271 // SP : address of return value. 271 // SP : address of return value.
272 // R5 : address of the native function to call. 272 // R5 : address of the native function to call.
273 // R2 : address of first argument in argument array. 273 // R2 : address of first argument in argument array.
274 // R1 : argc_tag including number of arguments and function kind. 274 // R1 : argc_tag including number of arguments and function kind.
275 void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) { 275 void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) {
276 const intptr_t isolate_offset = NativeArguments::isolate_offset(); 276 const intptr_t isolate_offset = NativeArguments::isolate_offset();
277 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 277 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
278 const intptr_t argv_offset = NativeArguments::argv_offset(); 278 const intptr_t argv_offset = NativeArguments::argv_offset();
279 const intptr_t retval_offset = NativeArguments::retval_offset(); 279 const intptr_t retval_offset = NativeArguments::retval_offset();
280 280
281 __ mov(IP, ShifterOperand(0)); 281 __ mov(IP, Operand(0));
282 __ Push(IP); // Push 0 for the PC marker. 282 __ Push(IP); // Push 0 for the PC marker.
283 __ EnterFrame((1 << FP) | (1 << LR), 0); 283 __ EnterFrame((1 << FP) | (1 << LR), 0);
284 284
285 // Load current Isolate pointer from Context structure into R0. 285 // Load current Isolate pointer from Context structure into R0.
286 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); 286 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset()));
287 287
288 // Save exit frame information to enable stack walking as we are about 288 // Save exit frame information to enable stack walking as we are about
289 // to transition to native code. 289 // to transition to native code.
290 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset()); 290 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset());
291 291
292 // Save current Context pointer into Isolate structure. 292 // Save current Context pointer into Isolate structure.
293 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset()); 293 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset());
294 294
295 // Cache Isolate pointer into CTX while executing native code. 295 // Cache Isolate pointer into CTX while executing native code.
296 __ mov(CTX, ShifterOperand(R0)); 296 __ mov(CTX, Operand(R0));
297 297
298 #if defined(DEBUG) 298 #if defined(DEBUG)
299 { Label ok; 299 { Label ok;
300 // Check that we are always entering from Dart code. 300 // Check that we are always entering from Dart code.
301 __ LoadFromOffset(kWord, R6, CTX, Isolate::vm_tag_offset()); 301 __ LoadFromOffset(kWord, R6, CTX, Isolate::vm_tag_offset());
302 __ CompareImmediate(R6, VMTag::kScriptTagId); 302 __ CompareImmediate(R6, VMTag::kScriptTagId);
303 __ b(&ok, EQ); 303 __ b(&ok, EQ);
304 __ Stop("Not coming from Dart code."); 304 __ Stop("Not coming from Dart code.");
305 __ Bind(&ok); 305 __ Bind(&ok);
306 } 306 }
(...skipping 15 matching lines...) Expand all
322 322
323 // There are no native calls to closures, so we do not need to set the tag 323 // There are no native calls to closures, so we do not need to set the tag
324 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 324 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
325 ASSERT(argc_tag_offset == 1 * kWordSize); 325 ASSERT(argc_tag_offset == 1 * kWordSize);
326 // Set argc in NativeArguments: R1 already contains argc. 326 // Set argc in NativeArguments: R1 already contains argc.
327 327
328 ASSERT(argv_offset == 2 * kWordSize); 328 ASSERT(argv_offset == 2 * kWordSize);
329 // Set argv in NativeArguments: R2 already contains argv. 329 // Set argv in NativeArguments: R2 already contains argv.
330 330
331 ASSERT(retval_offset == 3 * kWordSize); 331 ASSERT(retval_offset == 3 * kWordSize);
332 __ add(R3, FP, ShifterOperand(3 * kWordSize)); // Set retval in NativeArgs. 332 __ add(R3, FP, Operand(3 * kWordSize)); // Set retval in NativeArgs.
333 333
334 // TODO(regis): Should we pass the structure by value as in runtime calls? 334 // TODO(regis): Should we pass the structure by value as in runtime calls?
335 // It would require changing Dart API for native functions. 335 // It would require changing Dart API for native functions.
336 // For now, space is reserved on the stack and we pass a pointer to it. 336 // For now, space is reserved on the stack and we pass a pointer to it.
337 __ stm(IA, SP, (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3)); 337 __ stm(IA, SP, (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3));
338 __ mov(R0, ShifterOperand(SP)); // Pass the pointer to the NativeArguments. 338 __ mov(R0, Operand(SP)); // Pass the pointer to the NativeArguments.
339 339
340 // Call native function or redirection via simulator. 340 // Call native function or redirection via simulator.
341 __ blx(R5); 341 __ blx(R5);
342 342
343 // Mark that the isolate is executing Dart code. 343 // Mark that the isolate is executing Dart code.
344 __ LoadImmediate(R2, VMTag::kScriptTagId); 344 __ LoadImmediate(R2, VMTag::kScriptTagId);
345 __ StoreToOffset(kWord, R2, CTX, Isolate::vm_tag_offset()); 345 __ StoreToOffset(kWord, R2, CTX, Isolate::vm_tag_offset());
346 346
347 // Reset exit frame information in Isolate structure. 347 // Reset exit frame information in Isolate structure.
348 __ LoadImmediate(R2, 0); 348 __ LoadImmediate(R2, 0);
349 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset()); 349 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset());
350 350
351 // Load Context pointer from Isolate structure into R2. 351 // Load Context pointer from Isolate structure into R2.
352 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset()); 352 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset());
353 353
354 // Reset Context pointer in Isolate structure. 354 // Reset Context pointer in Isolate structure.
355 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); 355 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null()));
356 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset()); 356 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset());
357 357
358 // Cache Context pointer into CTX while executing Dart code. 358 // Cache Context pointer into CTX while executing Dart code.
359 __ mov(CTX, ShifterOperand(R2)); 359 __ mov(CTX, Operand(R2));
360 360
361 __ LeaveFrame((1 << FP) | (1 << LR)); 361 __ LeaveFrame((1 << FP) | (1 << LR));
362 // Adjust SP for the empty PC marker. 362 // Adjust SP for the empty PC marker.
363 __ AddImmediate(SP, kWordSize); 363 __ AddImmediate(SP, kWordSize);
364 __ Ret(); 364 __ Ret();
365 } 365 }
366 366
367 367
368 // Input parameters: 368 // Input parameters:
369 // R4: arguments descriptor array. 369 // R4: arguments descriptor array.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 // FP[kParamEndSlotFromFp + 1]: last argument. 413 // FP[kParamEndSlotFromFp + 1]: last argument.
414 static void PushArgumentsArray(Assembler* assembler) { 414 static void PushArgumentsArray(Assembler* assembler) {
415 // Allocate array to store arguments of caller. 415 // Allocate array to store arguments of caller.
416 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); 416 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
417 // R1: null element type for raw Array. 417 // R1: null element type for raw Array.
418 // R2: smi-tagged argument count, may be zero. 418 // R2: smi-tagged argument count, may be zero.
419 __ BranchLink(&StubCode::AllocateArrayLabel()); 419 __ BranchLink(&StubCode::AllocateArrayLabel());
420 // R0: newly allocated array. 420 // R0: newly allocated array.
421 // R2: smi-tagged argument count, may be zero (was preserved by the stub). 421 // R2: smi-tagged argument count, may be zero (was preserved by the stub).
422 __ Push(R0); // Array is in R0 and on top of stack. 422 __ Push(R0); // Array is in R0 and on top of stack.
423 __ add(R1, FP, ShifterOperand(R2, LSL, 1)); 423 __ add(R1, FP, Operand(R2, LSL, 1));
424 __ AddImmediate(R1, kParamEndSlotFromFp * kWordSize); 424 __ AddImmediate(R1, kParamEndSlotFromFp * kWordSize);
425 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag); 425 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag);
426 // R1: address of first argument on stack. 426 // R1: address of first argument on stack.
427 // R3: address of first argument in array. 427 // R3: address of first argument in array.
428 Label loop; 428 Label loop;
429 __ Bind(&loop); 429 __ Bind(&loop);
430 __ subs(R2, R2, ShifterOperand(Smi::RawValue(1))); // R2 is Smi. 430 __ subs(R2, R2, Operand(Smi::RawValue(1))); // R2 is Smi.
431 __ ldr(IP, Address(R1, 0), PL); 431 __ ldr(IP, Address(R1, 0), PL);
432 __ str(IP, Address(R3, 0), PL); 432 __ str(IP, Address(R3, 0), PL);
433 __ AddImmediate(R1, -kWordSize, PL); 433 __ AddImmediate(R1, -kWordSize, PL);
434 __ AddImmediate(R3, kWordSize, PL); 434 __ AddImmediate(R3, kWordSize, PL);
435 __ b(&loop, PL); 435 __ b(&loop, PL);
436 } 436 }
437 437
438 438
439 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, 439 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
440 intptr_t deopt_reason, 440 intptr_t deopt_reason,
(...skipping 23 matching lines...) Expand all
464 // +------------------+ 464 // +------------------+
465 // | PC marker | 465 // | PC marker |
466 // +------------------+ 466 // +------------------+
467 // | ... | <- SP of optimized frame 467 // | ... | <- SP of optimized frame
468 // 468 //
469 // Parts of the code cannot GC, part of the code can GC. 469 // Parts of the code cannot GC, part of the code can GC.
470 static void GenerateDeoptimizationSequence(Assembler* assembler, 470 static void GenerateDeoptimizationSequence(Assembler* assembler,
471 bool preserve_result) { 471 bool preserve_result) {
472 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 472 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
473 // is no need to set the correct PC marker or load PP, since they get patched. 473 // is no need to set the correct PC marker or load PP, since they get patched.
474 __ mov(IP, ShifterOperand(LR)); 474 __ mov(IP, Operand(LR));
475 __ mov(LR, ShifterOperand(0)); 475 __ mov(LR, Operand(0));
476 __ EnterFrame((1 << PP) | (1 << FP) | (1 << IP) | (1 << LR), 0); 476 __ EnterFrame((1 << PP) | (1 << FP) | (1 << IP) | (1 << LR), 0);
477 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry 477 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
478 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. 478 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
479 const intptr_t saved_result_slot_from_fp = 479 const intptr_t saved_result_slot_from_fp =
480 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0); 480 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0);
481 // Result in R0 is preserved as part of pushing all registers below. 481 // Result in R0 is preserved as part of pushing all registers below.
482 482
483 // TODO(regis): Should we align the stack before pushing the fpu registers? 483 // TODO(regis): Should we align the stack before pushing the fpu registers?
484 // If we do, saved_r0_offset_from_fp is not constant anymore. 484 // If we do, saved_r0_offset_from_fp is not constant anymore.
485 485
486 // Push registers in their enumeration order: lowest register number at 486 // Push registers in their enumeration order: lowest register number at
487 // lowest address. 487 // lowest address.
488 __ PushList(kAllCpuRegistersList); 488 __ PushList(kAllCpuRegistersList);
489 489
490 if (TargetCPUFeatures::vfp_supported()) { 490 if (TargetCPUFeatures::vfp_supported()) {
491 ASSERT(kFpuRegisterSize == 4 * kWordSize); 491 ASSERT(kFpuRegisterSize == 4 * kWordSize);
492 if (kNumberOfDRegisters > 16) { 492 if (kNumberOfDRegisters > 16) {
493 __ vstmd(DB_W, SP, D16, kNumberOfDRegisters - 16); 493 __ vstmd(DB_W, SP, D16, kNumberOfDRegisters - 16);
494 __ vstmd(DB_W, SP, D0, 16); 494 __ vstmd(DB_W, SP, D0, 16);
495 } else { 495 } else {
496 __ vstmd(DB_W, SP, D0, kNumberOfDRegisters); 496 __ vstmd(DB_W, SP, D0, kNumberOfDRegisters);
497 } 497 }
498 } else { 498 } else {
499 __ AddImmediate(SP, SP, -kNumberOfFpuRegisters * kFpuRegisterSize); 499 __ AddImmediate(SP, SP, -kNumberOfFpuRegisters * kFpuRegisterSize);
500 } 500 }
501 501
502 __ mov(R0, ShifterOperand(SP)); // Pass address of saved registers block. 502 __ mov(R0, Operand(SP)); // Pass address of saved registers block.
503 __ ReserveAlignedFrameSpace(0); 503 __ ReserveAlignedFrameSpace(0);
504 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1); 504 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1);
505 // Result (R0) is stack-size (FP - SP) in bytes. 505 // Result (R0) is stack-size (FP - SP) in bytes.
506 506
507 if (preserve_result) { 507 if (preserve_result) {
508 // Restore result into R1 temporarily. 508 // Restore result into R1 temporarily.
509 __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize)); 509 __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize));
510 } 510 }
511 511
512 __ LeaveDartFrame(); 512 __ LeaveDartFrame();
513 __ sub(SP, FP, ShifterOperand(R0)); 513 __ sub(SP, FP, Operand(R0));
514 514
515 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 515 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
516 // is no need to set the correct PC marker or load PP, since they get patched. 516 // is no need to set the correct PC marker or load PP, since they get patched.
517 __ mov(IP, ShifterOperand(LR)); 517 __ mov(IP, Operand(LR));
518 __ mov(LR, ShifterOperand(0)); 518 __ mov(LR, Operand(0));
519 __ EnterFrame((1 << PP) | (1 << FP) | (1 << IP) | (1 << LR), 0); 519 __ EnterFrame((1 << PP) | (1 << FP) | (1 << IP) | (1 << LR), 0);
520 __ mov(R0, ShifterOperand(FP)); // Get last FP address. 520 __ mov(R0, Operand(FP)); // Get last FP address.
521 if (preserve_result) { 521 if (preserve_result) {
522 __ Push(R1); // Preserve result as first local. 522 __ Push(R1); // Preserve result as first local.
523 } 523 }
524 __ ReserveAlignedFrameSpace(0); 524 __ ReserveAlignedFrameSpace(0);
525 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); // Pass last FP in R0. 525 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); // Pass last FP in R0.
526 if (preserve_result) { 526 if (preserve_result) {
527 // Restore result into R1. 527 // Restore result into R1.
528 __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize)); 528 __ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize));
529 } 529 }
530 // Code above cannot cause GC. 530 // Code above cannot cause GC.
531 __ LeaveDartFrame(); 531 __ LeaveDartFrame();
532 532
533 // Frame is fully rewritten at this point and it is safe to perform a GC. 533 // Frame is fully rewritten at this point and it is safe to perform a GC.
534 // Materialize any objects that were deferred by FillFrame because they 534 // Materialize any objects that were deferred by FillFrame because they
535 // require allocation. 535 // require allocation.
536 __ EnterStubFrame(); 536 __ EnterStubFrame();
537 if (preserve_result) { 537 if (preserve_result) {
538 __ Push(R1); // Preserve result, it will be GC-d here. 538 __ Push(R1); // Preserve result, it will be GC-d here.
539 } 539 }
540 __ PushObject(Smi::ZoneHandle()); // Space for the result. 540 __ PushObject(Smi::ZoneHandle()); // Space for the result.
541 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0); 541 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
542 // Result tells stub how many bytes to remove from the expression stack 542 // Result tells stub how many bytes to remove from the expression stack
543 // of the bottom-most frame. They were used as materialization arguments. 543 // of the bottom-most frame. They were used as materialization arguments.
544 __ Pop(R1); 544 __ Pop(R1);
545 if (preserve_result) { 545 if (preserve_result) {
546 __ Pop(R0); // Restore result. 546 __ Pop(R0); // Restore result.
547 } 547 }
548 __ LeaveStubFrame(); 548 __ LeaveStubFrame();
549 // Remove materialization arguments. 549 // Remove materialization arguments.
550 __ add(SP, SP, ShifterOperand(R1, ASR, kSmiTagSize)); 550 __ add(SP, SP, Operand(R1, ASR, kSmiTagSize));
551 __ Ret(); 551 __ Ret();
552 } 552 }
553 553
554 554
555 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { 555 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
556 // Correct return address to point just after the call that is being 556 // Correct return address to point just after the call that is being
557 // deoptimized. 557 // deoptimized.
558 __ AddImmediate(LR, -CallPattern::LengthInBytes()); 558 __ AddImmediate(LR, -CallPattern::LengthInBytes());
559 GenerateDeoptimizationSequence(assembler, true); // Preserve R0. 559 GenerateDeoptimizationSequence(assembler, true); // Preserve R0.
560 } 560 }
561 561
562 562
563 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 563 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
564 GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0. 564 GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0.
565 } 565 }
566 566
567 567
568 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 568 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
569 __ EnterStubFrame(); 569 __ EnterStubFrame();
570 570
571 // Load the receiver. 571 // Load the receiver.
572 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 572 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
573 __ add(IP, FP, ShifterOperand(R2, LSL, 1)); // R2 is Smi. 573 __ add(IP, FP, Operand(R2, LSL, 1)); // R2 is Smi.
574 __ ldr(R6, Address(IP, kParamEndSlotFromFp * kWordSize)); 574 __ ldr(R6, Address(IP, kParamEndSlotFromFp * kWordSize));
575 575
576 // Preserve IC data and arguments descriptor. 576 // Preserve IC data and arguments descriptor.
577 __ PushList((1 << R4) | (1 << R5)); 577 __ PushList((1 << R4) | (1 << R5));
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 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); 583 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
(...skipping 24 matching lines...) Expand all
608 // The newly allocated object is returned in R0. 608 // The newly allocated object is returned in R0.
609 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { 609 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
610 Label slow_case; 610 Label slow_case;
611 611
612 // Compute the size to be allocated, it is based on the array length 612 // Compute the size to be allocated, it is based on the array length
613 // and is computed as: 613 // and is computed as:
614 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). 614 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
615 __ MoveRegister(R3, R2); // Array length. 615 __ MoveRegister(R3, R2); // Array length.
616 616
617 // Check that length is a positive Smi. 617 // Check that length is a positive Smi.
618 __ tst(R3, ShifterOperand(kSmiTagMask)); 618 __ tst(R3, Operand(kSmiTagMask));
619 __ b(&slow_case, NE); 619 __ b(&slow_case, NE);
620 __ cmp(R3, ShifterOperand(0)); 620 __ cmp(R3, Operand(0));
621 __ b(&slow_case, LT); 621 __ b(&slow_case, LT);
622 622
623 // Check for maximum allowed length. 623 // Check for maximum allowed length.
624 const intptr_t max_len = 624 const intptr_t max_len =
625 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); 625 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements));
626 __ CompareImmediate(R3, max_len); 626 __ CompareImmediate(R3, max_len);
627 __ b(&slow_case, GT); 627 __ b(&slow_case, GT);
628 628
629 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; 629 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
630 __ LoadImmediate(R8, fixed_size); 630 __ LoadImmediate(R8, fixed_size);
631 __ add(R8, R8, ShifterOperand(R3, LSL, 1)); // R3 is a Smi. 631 __ add(R8, R8, Operand(R3, LSL, 1)); // R3 is a Smi.
632 ASSERT(kSmiTagShift == 1); 632 ASSERT(kSmiTagShift == 1);
633 __ bic(R8, R8, ShifterOperand(kObjectAlignment - 1)); 633 __ bic(R8, R8, Operand(kObjectAlignment - 1));
634 634
635 // R8: Allocation size. 635 // R8: Allocation size.
636 636
637 Isolate* isolate = Isolate::Current(); 637 Isolate* isolate = Isolate::Current();
638 Heap* heap = isolate->heap(); 638 Heap* heap = isolate->heap();
639 639
640 __ LoadImmediate(R6, heap->TopAddress()); 640 __ LoadImmediate(R6, heap->TopAddress());
641 __ ldr(R0, Address(R6, 0)); // Potential new object start. 641 __ ldr(R0, Address(R6, 0)); // Potential new object start.
642 __ adds(R7, R0, ShifterOperand(R8)); // Potential next object start. 642 __ adds(R7, R0, Operand(R8)); // Potential next object start.
643 __ b(&slow_case, VS); 643 __ b(&slow_case, VS);
644 644
645 // Check if the allocation fits into the remaining space. 645 // Check if the allocation fits into the remaining space.
646 // R0: potential new object start. 646 // R0: potential new object start.
647 // R7: potential next object start. 647 // R7: potential next object start.
648 // R8: allocation size. 648 // R8: allocation size.
649 __ LoadImmediate(R3, heap->EndAddress()); 649 __ LoadImmediate(R3, heap->EndAddress());
650 __ ldr(R3, Address(R3, 0)); 650 __ ldr(R3, Address(R3, 0));
651 __ cmp(R7, ShifterOperand(R3)); 651 __ cmp(R7, Operand(R3));
652 __ b(&slow_case, CS); 652 __ b(&slow_case, CS);
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 __ str(R7, Address(R6, 0)); 656 __ str(R7, Address(R6, 0));
657 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); 657 __ add(R0, R0, Operand(kHeapObjectTag));
658 __ UpdateAllocationStatsWithSize(kArrayCid, R8, R4); 658 __ UpdateAllocationStatsWithSize(kArrayCid, R8, R4);
659 659
660 // Initialize the tags. 660 // Initialize the tags.
661 // R0: new object start as a tagged pointer. 661 // R0: new object start as a tagged pointer.
662 // R7: new object end address. 662 // R7: new object end address.
663 // R8: allocation size. 663 // R8: allocation size.
664 { 664 {
665 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; 665 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
666 const Class& cls = Class::Handle(isolate->object_store()->array_class()); 666 const Class& cls = Class::Handle(isolate->object_store()->array_class());
667 667
668 __ CompareImmediate(R8, RawObject::SizeTag::kMaxSizeTag); 668 __ CompareImmediate(R8, RawObject::SizeTag::kMaxSizeTag);
669 __ mov(R8, ShifterOperand(R8, LSL, shift), LS); 669 __ mov(R8, Operand(R8, LSL, shift), LS);
670 __ mov(R8, ShifterOperand(0), HI); 670 __ mov(R8, Operand(0), HI);
671 671
672 // Get the class index and insert it into the tags. 672 // Get the class index and insert it into the tags.
673 // R8: size and bit tags. 673 // R8: size and bit tags.
674 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id())); 674 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id()));
675 __ orr(R8, R8, ShifterOperand(TMP)); 675 __ orr(R8, R8, Operand(TMP));
676 __ str(R8, FieldAddress(R0, Array::tags_offset())); // Store tags. 676 __ str(R8, FieldAddress(R0, Array::tags_offset())); // Store tags.
677 } 677 }
678 678
679 // R0: new object start as a tagged pointer. 679 // R0: new object start as a tagged pointer.
680 // R7: new object end address. 680 // R7: new object end address.
681 // Store the type argument field. 681 // Store the type argument field.
682 __ StoreIntoObjectNoBarrier(R0, 682 __ StoreIntoObjectNoBarrier(R0,
683 FieldAddress(R0, Array::type_arguments_offset()), 683 FieldAddress(R0, Array::type_arguments_offset()),
684 R1); 684 R1);
685 685
686 // Set the length field. 686 // Set the length field.
687 __ StoreIntoObjectNoBarrier(R0, 687 __ StoreIntoObjectNoBarrier(R0,
688 FieldAddress(R0, Array::length_offset()), 688 FieldAddress(R0, Array::length_offset()),
689 R2); 689 R2);
690 690
691 // Initialize all array elements to raw_null. 691 // Initialize all array elements to raw_null.
692 // R0: new object start as a tagged pointer. 692 // R0: new object start as a tagged pointer.
693 // R7: new object end address. 693 // R7: new object end address.
694 // R8: iterator which initially points to the start of the variable 694 // R8: iterator which initially points to the start of the variable
695 // data area to be initialized. 695 // data area to be initialized.
696 // R3: null 696 // R3: null
697 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); 697 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null()));
698 __ AddImmediate(R8, R0, sizeof(RawArray) - kHeapObjectTag); 698 __ AddImmediate(R8, R0, sizeof(RawArray) - kHeapObjectTag);
699 699
700 Label init_loop; 700 Label init_loop;
701 __ Bind(&init_loop); 701 __ Bind(&init_loop);
702 __ cmp(R8, ShifterOperand(R7)); 702 __ cmp(R8, Operand(R7));
703 __ str(R3, Address(R8, 0), CC); 703 __ str(R3, Address(R8, 0), CC);
704 __ AddImmediate(R8, kWordSize, CC); 704 __ AddImmediate(R8, kWordSize, CC);
705 __ b(&init_loop, CC); 705 __ b(&init_loop, CC);
706 706
707 __ Ret(); // Returns the newly allocated object in R0. 707 __ Ret(); // Returns the newly allocated object in R0.
708 // Unable to allocate the array using the fast inline code, just call 708 // Unable to allocate the array using the fast inline code, just call
709 // into the runtime. 709 // into the runtime.
710 __ Bind(&slow_case); 710 __ Bind(&slow_case);
711 711
712 // Create a stub frame as we are pushing some objects on the stack before 712 // Create a stub frame as we are pushing some objects on the stack before
713 // calling into the runtime. 713 // calling into the runtime.
714 __ EnterStubFrame(); 714 __ EnterStubFrame();
715 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); 715 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
716 // Setup space on stack for return value. 716 // Setup space on stack for return value.
717 // Push array length as Smi and element type. 717 // Push array length as Smi and element type.
718 __ PushList((1 << R1) | (1 << R2) | (1 << IP)); 718 __ PushList((1 << R1) | (1 << R2) | (1 << IP));
719 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); 719 __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
720 // Pop arguments; result is popped in IP. 720 // Pop arguments; result is popped in IP.
721 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored. 721 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored.
722 __ mov(R0, ShifterOperand(IP)); 722 __ mov(R0, Operand(IP));
723 __ LeaveStubFrame(); 723 __ LeaveStubFrame();
724 __ Ret(); 724 __ Ret();
725 } 725 }
726 726
727 727
728 // Called when invoking Dart code from C++ (VM code). 728 // Called when invoking Dart code from C++ (VM code).
729 // Input parameters: 729 // Input parameters:
730 // LR : points to return address. 730 // LR : points to return address.
731 // R0 : entrypoint of the Dart function to call. 731 // R0 : entrypoint of the Dart function to call.
732 // R1 : arguments descriptor array. 732 // R1 : arguments descriptor array.
733 // R2 : arguments array. 733 // R2 : arguments array.
734 // R3 : new context containing the current isolate pointer. 734 // R3 : new context containing the current isolate pointer.
735 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { 735 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
736 // Save frame pointer coming in. 736 // Save frame pointer coming in.
737 __ EnterFrame((1 << FP) | (1 << LR), 0); 737 __ EnterFrame((1 << FP) | (1 << LR), 0);
738 738
739 // Save new context and C++ ABI callee-saved registers. 739 // Save new context and C++ ABI callee-saved registers.
740 const intptr_t kNewContextOffsetFromFp = 740 const intptr_t kNewContextOffsetFromFp =
741 -(1 + kAbiPreservedCpuRegCount) * kWordSize; 741 -(1 + kAbiPreservedCpuRegCount) * kWordSize;
742 __ PushList((1 << R3) | kAbiPreservedCpuRegs); 742 __ PushList((1 << R3) | kAbiPreservedCpuRegs);
743 743
744 const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg); 744 const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
745 if (TargetCPUFeatures::vfp_supported()) { 745 if (TargetCPUFeatures::vfp_supported()) {
746 ASSERT(2 * kAbiPreservedFpuRegCount < 16); 746 ASSERT(2 * kAbiPreservedFpuRegCount < 16);
747 // Save FPU registers. 2 D registers per Q register. 747 // Save FPU registers. 2 D registers per Q register.
748 __ vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount); 748 __ vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
749 } else { 749 } else {
750 __ sub(SP, SP, 750 __ sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
751 ShifterOperand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
752 } 751 }
753 752
754 // We now load the pool pointer(PP) as we are about to invoke dart code and we 753 // We now load the pool pointer(PP) as we are about to invoke dart code and we
755 // could potentially invoke some intrinsic functions which need the PP to be 754 // could potentially invoke some intrinsic functions which need the PP to be
756 // set up. 755 // set up.
757 __ LoadPoolPointer(); 756 __ LoadPoolPointer();
758 757
759 // The new Context structure contains a pointer to the current Isolate 758 // The new Context structure contains a pointer to the current Isolate
760 // structure. Cache the Context pointer in the CTX register so that it is 759 // structure. Cache the Context pointer in the CTX register so that it is
761 // available in generated code and calls to Isolate::Current() need not be 760 // available in generated code and calls to Isolate::Current() need not be
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 Label push_arguments; 810 Label push_arguments;
812 Label done_push_arguments; 811 Label done_push_arguments;
813 __ CompareImmediate(R5, 0); // check if there are arguments. 812 __ CompareImmediate(R5, 0); // check if there are arguments.
814 __ b(&done_push_arguments, EQ); 813 __ b(&done_push_arguments, EQ);
815 __ LoadImmediate(R1, 0); 814 __ LoadImmediate(R1, 0);
816 __ Bind(&push_arguments); 815 __ Bind(&push_arguments);
817 __ ldr(R3, Address(R2)); 816 __ ldr(R3, Address(R2));
818 __ Push(R3); 817 __ Push(R3);
819 __ AddImmediate(R2, kWordSize); 818 __ AddImmediate(R2, kWordSize);
820 __ AddImmediate(R1, 1); 819 __ AddImmediate(R1, 1);
821 __ cmp(R1, ShifterOperand(R5)); 820 __ cmp(R1, Operand(R5));
822 __ b(&push_arguments, LT); 821 __ b(&push_arguments, LT);
823 __ Bind(&done_push_arguments); 822 __ Bind(&done_push_arguments);
824 823
825 // Call the Dart code entrypoint. 824 // Call the Dart code entrypoint.
826 __ blx(R0); // R4 is the arguments descriptor array. 825 __ blx(R0); // R4 is the arguments descriptor array.
827 826
828 // Read the saved new Context pointer. 827 // Read the saved new Context pointer.
829 __ ldr(CTX, Address(FP, kNewContextOffsetFromFp)); 828 __ ldr(CTX, Address(FP, kNewContextOffsetFromFp));
830 __ ldr(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); 829 __ ldr(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle));
831 830
(...skipping 13 matching lines...) Expand all
845 844
846 // Restore the current VMTag from the stack. 845 // Restore the current VMTag from the stack.
847 __ Pop(R4); 846 __ Pop(R4);
848 __ StoreToOffset(kWord, R4, CTX, Isolate::vm_tag_offset()); 847 __ StoreToOffset(kWord, R4, CTX, Isolate::vm_tag_offset());
849 848
850 // Restore C++ ABI callee-saved registers. 849 // Restore C++ ABI callee-saved registers.
851 if (TargetCPUFeatures::vfp_supported()) { 850 if (TargetCPUFeatures::vfp_supported()) {
852 // Restore FPU registers. 2 D registers per Q register. 851 // Restore FPU registers. 2 D registers per Q register.
853 __ vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount); 852 __ vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
854 } else { 853 } else {
855 __ add(SP, SP, 854 __ AddImmediate(SP, kAbiPreservedFpuRegCount * kFpuRegisterSize);
856 ShifterOperand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
857 } 855 }
858 // Restore CPU registers. 856 // Restore CPU registers.
859 __ PopList((1 << R3) | kAbiPreservedCpuRegs); // Ignore restored R3. 857 __ PopList((1 << R3) | kAbiPreservedCpuRegs); // Ignore restored R3.
860 858
861 // Restore the frame pointer and return. 859 // Restore the frame pointer and return.
862 __ LeaveFrame((1 << FP) | (1 << LR)); 860 __ LeaveFrame((1 << FP) | (1 << LR));
863 __ Ret(); 861 __ Ret();
864 } 862 }
865 863
866 864
867 // Called for inline allocation of contexts. 865 // Called for inline allocation of contexts.
868 // Input: 866 // Input:
869 // R1: number of context variables. 867 // R1: number of context variables.
870 // Output: 868 // Output:
871 // R0: new allocated RawContext object. 869 // R0: new allocated RawContext object.
872 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { 870 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
873 if (FLAG_inline_alloc) { 871 if (FLAG_inline_alloc) {
874 const Class& context_class = Class::ZoneHandle(Object::context_class()); 872 const Class& context_class = Class::ZoneHandle(Object::context_class());
875 Label slow_case; 873 Label slow_case;
876 Heap* heap = Isolate::Current()->heap(); 874 Heap* heap = Isolate::Current()->heap();
877 // First compute the rounded instance size. 875 // First compute the rounded instance size.
878 // R1: number of context variables. 876 // R1: number of context variables.
879 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; 877 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1;
880 __ LoadImmediate(R2, fixed_size); 878 __ LoadImmediate(R2, fixed_size);
881 __ add(R2, R2, ShifterOperand(R1, LSL, 2)); 879 __ add(R2, R2, Operand(R1, LSL, 2));
882 ASSERT(kSmiTagShift == 1); 880 ASSERT(kSmiTagShift == 1);
883 __ bic(R2, R2, ShifterOperand(kObjectAlignment - 1)); 881 __ bic(R2, R2, Operand(kObjectAlignment - 1));
884 882
885 // Now allocate the object. 883 // Now allocate the object.
886 // R1: number of context variables. 884 // R1: number of context variables.
887 // R2: object size. 885 // R2: object size.
888 __ LoadImmediate(R5, heap->TopAddress()); 886 __ LoadImmediate(R5, heap->TopAddress());
889 __ ldr(R0, Address(R5, 0)); 887 __ ldr(R0, Address(R5, 0));
890 __ add(R3, R2, ShifterOperand(R0)); 888 __ add(R3, R2, Operand(R0));
891 // Check if the allocation fits into the remaining space. 889 // Check if the allocation fits into the remaining space.
892 // R0: potential new object. 890 // R0: potential new object.
893 // R1: number of context variables. 891 // R1: number of context variables.
894 // R2: object size. 892 // R2: object size.
895 // R3: potential next object start. 893 // R3: potential next object start.
896 __ LoadImmediate(IP, heap->EndAddress()); 894 __ LoadImmediate(IP, heap->EndAddress());
897 __ ldr(IP, Address(IP, 0)); 895 __ ldr(IP, Address(IP, 0));
898 __ cmp(R3, ShifterOperand(IP)); 896 __ cmp(R3, Operand(IP));
899 if (FLAG_use_slow_path) { 897 if (FLAG_use_slow_path) {
900 __ b(&slow_case); 898 __ b(&slow_case);
901 } else { 899 } else {
902 __ b(&slow_case, CS); // Branch if unsigned higher or equal. 900 __ b(&slow_case, CS); // Branch if unsigned higher or equal.
903 } 901 }
904 902
905 // Successfully allocated the object, now update top to point to 903 // Successfully allocated the object, now update top to point to
906 // next object start and initialize the object. 904 // next object start and initialize the object.
907 // R0: new object. 905 // R0: new object.
908 // R1: number of context variables. 906 // R1: number of context variables.
909 // R2: object size. 907 // R2: object size.
910 // R3: next object start. 908 // R3: next object start.
911 __ str(R3, Address(R5, 0)); 909 __ str(R3, Address(R5, 0));
912 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); 910 __ add(R0, R0, Operand(kHeapObjectTag));
913 __ UpdateAllocationStatsWithSize(context_class.id(), R2, R5); 911 __ UpdateAllocationStatsWithSize(context_class.id(), R2, R5);
914 912
915 // Calculate the size tag. 913 // Calculate the size tag.
916 // R0: new object. 914 // R0: new object.
917 // R1: number of context variables. 915 // R1: number of context variables.
918 // R2: object size. 916 // R2: object size.
919 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; 917 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
920 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); 918 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
921 // If no size tag overflow, shift R2 left, else set R2 to zero. 919 // If no size tag overflow, shift R2 left, else set R2 to zero.
922 __ mov(R2, ShifterOperand(R2, LSL, shift), LS); 920 __ mov(R2, Operand(R2, LSL, shift), LS);
923 __ mov(R2, ShifterOperand(0), HI); 921 __ mov(R2, Operand(0), HI);
924 922
925 // Get the class index and insert it into the tags. 923 // Get the class index and insert it into the tags.
926 // R2: size and bit tags. 924 // R2: size and bit tags.
927 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(context_class.id())); 925 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(context_class.id()));
928 __ orr(R2, R2, ShifterOperand(IP)); 926 __ orr(R2, R2, Operand(IP));
929 __ str(R2, FieldAddress(R0, Context::tags_offset())); 927 __ str(R2, FieldAddress(R0, Context::tags_offset()));
930 928
931 // Setup up number of context variables field. 929 // Setup up number of context variables field.
932 // R0: new object. 930 // R0: new object.
933 // R1: number of context variables as integer value (not object). 931 // R1: number of context variables as integer value (not object).
934 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); 932 __ str(R1, FieldAddress(R0, Context::num_variables_offset()));
935 933
936 // Setup isolate field. 934 // Setup isolate field.
937 // Load Isolate pointer from Context structure into R2. 935 // Load Isolate pointer from Context structure into R2.
938 // R0: new object. 936 // R0: new object.
939 // R1: number of context variables. 937 // R1: number of context variables.
940 __ ldr(R2, FieldAddress(CTX, Context::isolate_offset())); 938 __ ldr(R2, FieldAddress(CTX, Context::isolate_offset()));
941 // R2: isolate, not an object. 939 // R2: isolate, not an object.
942 __ str(R2, FieldAddress(R0, Context::isolate_offset())); 940 __ str(R2, FieldAddress(R0, Context::isolate_offset()));
943 941
944 // Setup the parent field. 942 // Setup the parent field.
945 // R0: new object. 943 // R0: new object.
946 // R1: number of context variables. 944 // R1: number of context variables.
947 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); 945 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null()));
948 __ str(R2, FieldAddress(R0, Context::parent_offset())); 946 __ str(R2, FieldAddress(R0, Context::parent_offset()));
949 947
950 // Initialize the context variables. 948 // Initialize the context variables.
951 // R0: new object. 949 // R0: new object.
952 // R1: number of context variables. 950 // R1: number of context variables.
953 // R2: raw null. 951 // R2: raw null.
954 Label loop; 952 Label loop;
955 __ AddImmediate(R3, R0, Context::variable_offset(0) - kHeapObjectTag); 953 __ AddImmediate(R3, R0, Context::variable_offset(0) - kHeapObjectTag);
956 __ Bind(&loop); 954 __ Bind(&loop);
957 __ subs(R1, R1, ShifterOperand(1)); 955 __ subs(R1, R1, Operand(1));
958 __ str(R2, Address(R3, R1, LSL, 2), PL); // Store if R1 positive or zero. 956 __ str(R2, Address(R3, R1, LSL, 2), PL); // Store if R1 positive or zero.
959 __ b(&loop, NE); // Loop if R1 not zero. 957 __ b(&loop, NE); // Loop if R1 not zero.
960 958
961 // Done allocating and initializing the context. 959 // Done allocating and initializing the context.
962 // R0: new object. 960 // R0: new object.
963 __ Ret(); 961 __ Ret();
964 962
965 __ Bind(&slow_case); 963 __ Bind(&slow_case);
966 } 964 }
967 // Create a stub frame as we are pushing some objects on the stack before 965 // Create a stub frame as we are pushing some objects on the stack before
(...skipping 21 matching lines...) Expand all
989 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { 987 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
990 // Save values being destroyed. 988 // Save values being destroyed.
991 __ PushList((1 << R1) | (1 << R2) | (1 << R3)); 989 __ PushList((1 << R1) | (1 << R2) | (1 << R3));
992 990
993 Label add_to_buffer; 991 Label add_to_buffer;
994 // Check whether this object has already been remembered. Skip adding to the 992 // Check whether this object has already been remembered. Skip adding to the
995 // store buffer if the object is in the store buffer already. 993 // store buffer if the object is in the store buffer already.
996 // Spilled: R1, R2, R3 994 // Spilled: R1, R2, R3
997 // R0: Address being stored 995 // R0: Address being stored
998 __ ldr(R2, FieldAddress(R0, Object::tags_offset())); 996 __ ldr(R2, FieldAddress(R0, Object::tags_offset()));
999 __ tst(R2, ShifterOperand(1 << RawObject::kRememberedBit)); 997 __ tst(R2, Operand(1 << RawObject::kRememberedBit));
1000 __ b(&add_to_buffer, EQ); 998 __ b(&add_to_buffer, EQ);
1001 __ PopList((1 << R1) | (1 << R2) | (1 << R3)); 999 __ PopList((1 << R1) | (1 << R2) | (1 << R3));
1002 __ Ret(); 1000 __ Ret();
1003 1001
1004 __ Bind(&add_to_buffer); 1002 __ Bind(&add_to_buffer);
1005 __ orr(R2, R2, ShifterOperand(1 << RawObject::kRememberedBit)); 1003 __ orr(R2, R2, Operand(1 << RawObject::kRememberedBit));
1006 __ str(R2, FieldAddress(R0, Object::tags_offset())); 1004 __ str(R2, FieldAddress(R0, Object::tags_offset()));
1007 1005
1008 // Load the isolate out of the context. 1006 // Load the isolate out of the context.
1009 // Spilled: R1, R2, R3. 1007 // Spilled: R1, R2, R3.
1010 // R0: address being stored. 1008 // R0: address being stored.
1011 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); 1009 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset()));
1012 1010
1013 // Load the StoreBuffer block out of the isolate. Then load top_ out of the 1011 // Load the StoreBuffer block out of the isolate. Then load top_ out of the
1014 // StoreBufferBlock and add the address to the pointers_. 1012 // StoreBufferBlock and add the address to the pointers_.
1015 // R1: isolate. 1013 // R1: isolate.
1016 __ ldr(R1, Address(R1, Isolate::store_buffer_offset())); 1014 __ ldr(R1, Address(R1, Isolate::store_buffer_offset()));
1017 __ ldr(R2, Address(R1, StoreBufferBlock::top_offset())); 1015 __ ldr(R2, Address(R1, StoreBufferBlock::top_offset()));
1018 __ add(R3, R1, ShifterOperand(R2, LSL, 2)); 1016 __ add(R3, R1, Operand(R2, LSL, 2));
1019 __ str(R0, Address(R3, StoreBufferBlock::pointers_offset())); 1017 __ str(R0, Address(R3, StoreBufferBlock::pointers_offset()));
1020 1018
1021 // Increment top_ and check for overflow. 1019 // Increment top_ and check for overflow.
1022 // R2: top_. 1020 // R2: top_.
1023 // R1: StoreBufferBlock. 1021 // R1: StoreBufferBlock.
1024 Label L; 1022 Label L;
1025 __ add(R2, R2, ShifterOperand(1)); 1023 __ add(R2, R2, Operand(1));
1026 __ str(R2, Address(R1, StoreBufferBlock::top_offset())); 1024 __ str(R2, Address(R1, StoreBufferBlock::top_offset()));
1027 __ CompareImmediate(R2, StoreBufferBlock::kSize); 1025 __ CompareImmediate(R2, StoreBufferBlock::kSize);
1028 // Restore values. 1026 // Restore values.
1029 __ PopList((1 << R1) | (1 << R2) | (1 << R3)); 1027 __ PopList((1 << R1) | (1 << R2) | (1 << R3));
1030 __ b(&L, EQ); 1028 __ b(&L, EQ);
1031 __ Ret(); 1029 __ Ret();
1032 1030
1033 // Handle overflow: Call the runtime leaf function. 1031 // Handle overflow: Call the runtime leaf function.
1034 __ Bind(&L); 1032 __ Bind(&L);
1035 // Setup frame, push callee-saved registers. 1033 // Setup frame, push callee-saved registers.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 // R1: instantiated type arguments (if is_cls_parameterized). 1068 // R1: instantiated type arguments (if is_cls_parameterized).
1071 Heap* heap = Isolate::Current()->heap(); 1069 Heap* heap = Isolate::Current()->heap();
1072 __ LoadImmediate(R5, heap->TopAddress()); 1070 __ LoadImmediate(R5, heap->TopAddress());
1073 __ ldr(R2, Address(R5, 0)); 1071 __ ldr(R2, Address(R5, 0));
1074 __ AddImmediate(R3, R2, instance_size); 1072 __ AddImmediate(R3, R2, instance_size);
1075 // Check if the allocation fits into the remaining space. 1073 // Check if the allocation fits into the remaining space.
1076 // R2: potential new object start. 1074 // R2: potential new object start.
1077 // R3: potential next object start. 1075 // R3: potential next object start.
1078 __ LoadImmediate(IP, heap->EndAddress()); 1076 __ LoadImmediate(IP, heap->EndAddress());
1079 __ ldr(IP, Address(IP, 0)); 1077 __ ldr(IP, Address(IP, 0));
1080 __ cmp(R3, ShifterOperand(IP)); 1078 __ cmp(R3, Operand(IP));
1081 if (FLAG_use_slow_path) { 1079 if (FLAG_use_slow_path) {
1082 __ b(&slow_case); 1080 __ b(&slow_case);
1083 } else { 1081 } else {
1084 __ b(&slow_case, CS); // Unsigned higher or equal. 1082 __ b(&slow_case, CS); // Unsigned higher or equal.
1085 } 1083 }
1086 __ str(R3, Address(R5, 0)); 1084 __ str(R3, Address(R5, 0));
1087 __ UpdateAllocationStats(cls.id(), R5); 1085 __ UpdateAllocationStats(cls.id(), R5);
1088 1086
1089 // R2: new object start. 1087 // R2: new object start.
1090 // R3: next object start. 1088 // R3: next object start.
(...skipping 16 matching lines...) Expand all
1107 // First try inlining the initialization without a loop. 1105 // First try inlining the initialization without a loop.
1108 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1106 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1109 // Check if the object contains any non-header fields. 1107 // Check if the object contains any non-header fields.
1110 // Small objects are initialized using a consecutive set of writes. 1108 // Small objects are initialized using a consecutive set of writes.
1111 for (intptr_t current_offset = Instance::NextFieldOffset(); 1109 for (intptr_t current_offset = Instance::NextFieldOffset();
1112 current_offset < instance_size; 1110 current_offset < instance_size;
1113 current_offset += kWordSize) { 1111 current_offset += kWordSize) {
1114 __ StoreToOffset(kWord, R0, R2, current_offset); 1112 __ StoreToOffset(kWord, R0, R2, current_offset);
1115 } 1113 }
1116 } else { 1114 } else {
1117 __ add(R4, R2, ShifterOperand(Instance::NextFieldOffset())); 1115 __ add(R4, R2, Operand(Instance::NextFieldOffset()));
1118 // Loop until the whole object is initialized. 1116 // Loop until the whole object is initialized.
1119 // R0: raw null. 1117 // R0: raw null.
1120 // R2: new object. 1118 // R2: new object.
1121 // R3: next object start. 1119 // R3: next object start.
1122 // R4: next word to be initialized. 1120 // R4: next word to be initialized.
1123 // R1: new object type arguments (if is_cls_parameterized). 1121 // R1: new object type arguments (if is_cls_parameterized).
1124 Label init_loop; 1122 Label init_loop;
1125 Label done; 1123 Label done;
1126 __ Bind(&init_loop); 1124 __ Bind(&init_loop);
1127 __ cmp(R4, ShifterOperand(R3)); 1125 __ cmp(R4, Operand(R3));
1128 __ b(&done, CS); 1126 __ b(&done, CS);
1129 __ str(R0, Address(R4, 0)); 1127 __ str(R0, Address(R4, 0));
1130 __ AddImmediate(R4, kWordSize); 1128 __ AddImmediate(R4, kWordSize);
1131 __ b(&init_loop); 1129 __ b(&init_loop);
1132 __ Bind(&done); 1130 __ Bind(&done);
1133 } 1131 }
1134 if (is_cls_parameterized) { 1132 if (is_cls_parameterized) {
1135 // R1: new object type arguments. 1133 // R1: new object type arguments.
1136 // Set the type arguments in the new object. 1134 // Set the type arguments in the new object.
1137 __ StoreToOffset(kWord, R1, R2, cls.type_arguments_field_offset()); 1135 __ StoreToOffset(kWord, R1, R2, cls.type_arguments_field_offset());
1138 } 1136 }
1139 // Done allocating and initializing the instance. 1137 // Done allocating and initializing the instance.
1140 // R2: new object still missing its heap tag. 1138 // R2: new object still missing its heap tag.
1141 __ add(R0, R2, ShifterOperand(kHeapObjectTag)); 1139 __ add(R0, R2, Operand(kHeapObjectTag));
1142 // R0: new object. 1140 // R0: new object.
1143 __ Ret(); 1141 __ Ret();
1144 1142
1145 __ Bind(&slow_case); 1143 __ Bind(&slow_case);
1146 } 1144 }
1147 // If is_cls_parameterized: 1145 // If is_cls_parameterized:
1148 // R1: new object type arguments. 1146 // R1: new object type arguments.
1149 // Create a stub frame as we are pushing some objects on the stack before 1147 // Create a stub frame as we are pushing some objects on the stack before
1150 // calling into the runtime. 1148 // calling into the runtime.
1151 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. 1149 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime.
(...skipping 23 matching lines...) Expand all
1175 // Input parameters: 1173 // Input parameters:
1176 // LR : return address. 1174 // LR : return address.
1177 // SP : address of last argument. 1175 // SP : address of last argument.
1178 // R5: inline cache data object. 1176 // R5: inline cache data object.
1179 // R4: arguments descriptor array. 1177 // R4: arguments descriptor array.
1180 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { 1178 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
1181 __ EnterStubFrame(); 1179 __ EnterStubFrame();
1182 1180
1183 // Load the receiver. 1181 // Load the receiver.
1184 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 1182 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
1185 __ add(IP, FP, ShifterOperand(R2, LSL, 1)); // R2 is Smi. 1183 __ add(IP, FP, Operand(R2, LSL, 1)); // R2 is Smi.
1186 __ ldr(R6, Address(IP, kParamEndSlotFromFp * kWordSize)); 1184 __ ldr(R6, Address(IP, kParamEndSlotFromFp * kWordSize));
1187 1185
1188 // Push space for the return value. 1186 // Push space for the return value.
1189 // Push the receiver. 1187 // Push the receiver.
1190 // Push IC data object. 1188 // Push IC data object.
1191 // Push arguments descriptor array. 1189 // Push arguments descriptor array.
1192 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); 1190 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
1193 __ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP)); 1191 __ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP));
1194 1192
1195 // R2: Smi-tagged arguments array length. 1193 // R2: Smi-tagged arguments array length.
(...skipping 19 matching lines...) Expand all
1215 __ EnterStubFrame(); 1213 __ EnterStubFrame();
1216 __ PushList((1 << R5) | (1 << R6)); // Preserve. 1214 __ PushList((1 << R5) | (1 << R6)); // Preserve.
1217 __ Push(ic_reg); // Argument. 1215 __ Push(ic_reg); // Argument.
1218 __ Push(func_reg); // Argument. 1216 __ Push(func_reg); // Argument.
1219 __ CallRuntime(kTraceICCallRuntimeEntry, 2); 1217 __ CallRuntime(kTraceICCallRuntimeEntry, 2);
1220 __ Drop(2); // Discard argument; 1218 __ Drop(2); // Discard argument;
1221 __ PopList((1 << R5) | (1 << R6)); // Restore. 1219 __ PopList((1 << R5) | (1 << R6)); // Restore.
1222 __ LeaveStubFrame(); 1220 __ LeaveStubFrame();
1223 } 1221 }
1224 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset())); 1222 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
1225 __ add(R7, R7, ShifterOperand(1)); 1223 __ add(R7, R7, Operand(1));
1226 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset())); 1224 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
1227 } 1225 }
1228 1226
1229 1227
1230 // Loads function into 'temp_reg'. 1228 // Loads function into 'temp_reg'.
1231 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, 1229 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
1232 Register temp_reg) { 1230 Register temp_reg) {
1233 Register ic_reg = R5; 1231 Register ic_reg = R5;
1234 Register func_reg = temp_reg; 1232 Register func_reg = temp_reg;
1235 ASSERT(temp_reg == R6); 1233 ASSERT(temp_reg == R6);
1236 __ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); 1234 __ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
1237 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset())); 1235 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
1238 __ add(R7, R7, ShifterOperand(1)); 1236 __ add(R7, R7, Operand(1));
1239 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset())); 1237 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
1240 } 1238 }
1241 1239
1242 1240
1243 // Generate inline cache check for 'num_args'. 1241 // Generate inline cache check for 'num_args'.
1244 // LR: return address. 1242 // LR: return address.
1245 // R5: inline cache data object. 1243 // R5: inline cache data object.
1246 // Control flow: 1244 // Control flow:
1247 // - If receiver is null -> jump to IC miss. 1245 // - If receiver is null -> jump to IC miss.
1248 // - If receiver is Smi -> load Smi class. 1246 // - If receiver is Smi -> load Smi class.
1249 // - If receiver is not-Smi -> load receiver's class. 1247 // - If receiver is not-Smi -> load receiver's class.
1250 // - Check if 'num_args' (including receiver) match any IC data group. 1248 // - Check if 'num_args' (including receiver) match any IC data group.
1251 // - Match found -> jump to target. 1249 // - Match found -> jump to target.
1252 // - Match not found -> jump to IC miss. 1250 // - Match not found -> jump to IC miss.
1253 void StubCode::GenerateNArgsCheckInlineCacheStub( 1251 void StubCode::GenerateNArgsCheckInlineCacheStub(
1254 Assembler* assembler, 1252 Assembler* assembler,
1255 intptr_t num_args, 1253 intptr_t num_args,
1256 const RuntimeEntry& handle_ic_miss) { 1254 const RuntimeEntry& handle_ic_miss) {
1257 ASSERT(num_args > 0); 1255 ASSERT(num_args > 0);
1258 #if defined(DEBUG) 1256 #if defined(DEBUG)
1259 { Label ok; 1257 { Label ok;
1260 // Check that the IC data array has NumArgsTested() == num_args. 1258 // Check that the IC data array has NumArgsTested() == num_args.
1261 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1259 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1262 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); 1260 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset()));
1263 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1261 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1264 __ and_(R6, R6, ShifterOperand(ICData::NumArgsTestedMask())); 1262 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask()));
1265 __ CompareImmediate(R6, num_args); 1263 __ CompareImmediate(R6, num_args);
1266 __ b(&ok, EQ); 1264 __ b(&ok, EQ);
1267 __ Stop("Incorrect stub for IC data"); 1265 __ Stop("Incorrect stub for IC data");
1268 __ Bind(&ok); 1266 __ Bind(&ok);
1269 } 1267 }
1270 #endif // DEBUG 1268 #endif // DEBUG
1271 1269
1272 if (FLAG_enable_debugger) { 1270 if (FLAG_enable_debugger) {
1273 // Check single stepping. 1271 // Check single stepping.
1274 Label not_stepping; 1272 Label not_stepping;
1275 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); 1273 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset()));
1276 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); 1274 __ ldrb(R6, Address(R6, Isolate::single_step_offset()));
1277 __ CompareImmediate(R6, 0); 1275 __ CompareImmediate(R6, 0);
1278 __ b(&not_stepping, EQ); 1276 __ b(&not_stepping, EQ);
1279 __ EnterStubFrame(); 1277 __ EnterStubFrame();
1280 __ Push(R5); // Preserve IC data. 1278 __ Push(R5); // Preserve IC data.
1281 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1279 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1282 __ Pop(R5); 1280 __ Pop(R5);
1283 __ LeaveStubFrame(); 1281 __ LeaveStubFrame();
1284 __ Bind(&not_stepping); 1282 __ Bind(&not_stepping);
1285 } 1283 }
1286 1284
1287 // Load arguments descriptor into R4. 1285 // Load arguments descriptor into R4.
1288 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); 1286 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
1289 // Preserve return address, since LR is needed for subroutine call. 1287 // Preserve return address, since LR is needed for subroutine call.
1290 __ mov(R8, ShifterOperand(LR)); 1288 __ mov(R8, Operand(LR));
1291 // Loop that checks if there is an IC data match. 1289 // Loop that checks if there is an IC data match.
1292 Label loop, update, test, found, get_class_id_as_smi; 1290 Label loop, update, test, found, get_class_id_as_smi;
1293 // R5: IC data object (preserved). 1291 // R5: IC data object (preserved).
1294 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); 1292 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset()));
1295 // R6: ic_data_array with check entries: classes and target functions. 1293 // R6: ic_data_array with check entries: classes and target functions.
1296 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); 1294 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag);
1297 // R6: points directly to the first ic data array element. 1295 // R6: points directly to the first ic data array element.
1298 1296
1299 // Get the receiver's class ID (first read number of arguments from 1297 // Get the receiver's class ID (first read number of arguments from
1300 // arguments descriptor array and then access the receiver from the stack). 1298 // arguments descriptor array and then access the receiver from the stack).
1301 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 1299 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
1302 __ sub(R7, R7, ShifterOperand(Smi::RawValue(1))); 1300 __ sub(R7, R7, Operand(Smi::RawValue(1)));
1303 __ ldr(R0, Address(SP, R7, LSL, 1)); // R7 (argument_count - 1) is smi. 1301 __ ldr(R0, Address(SP, R7, LSL, 1)); // R7 (argument_count - 1) is smi.
1304 __ bl(&get_class_id_as_smi); 1302 __ bl(&get_class_id_as_smi);
1305 // R7: argument_count - 1 (smi). 1303 // R7: argument_count - 1 (smi).
1306 // R0: receiver's class ID (smi). 1304 // R0: receiver's class ID (smi).
1307 __ ldr(R1, Address(R6, 0)); // First class id (smi) to check. 1305 __ ldr(R1, Address(R6, 0)); // First class id (smi) to check.
1308 __ b(&test); 1306 __ b(&test);
1309 1307
1310 __ Bind(&loop); 1308 __ Bind(&loop);
1311 for (int i = 0; i < num_args; i++) { 1309 for (int i = 0; i < num_args; i++) {
1312 if (i > 0) { 1310 if (i > 0) {
1313 // If not the first, load the next argument's class ID. 1311 // If not the first, load the next argument's class ID.
1314 __ AddImmediate(R0, R7, Smi::RawValue(-i)); 1312 __ AddImmediate(R0, R7, Smi::RawValue(-i));
1315 __ ldr(R0, Address(SP, R0, LSL, 1)); 1313 __ ldr(R0, Address(SP, R0, LSL, 1));
1316 __ bl(&get_class_id_as_smi); 1314 __ bl(&get_class_id_as_smi);
1317 // R0: next argument class ID (smi). 1315 // R0: next argument class ID (smi).
1318 __ LoadFromOffset(kWord, R1, R6, i * kWordSize); 1316 __ LoadFromOffset(kWord, R1, R6, i * kWordSize);
1319 // R1: next class ID to check (smi). 1317 // R1: next class ID to check (smi).
1320 } 1318 }
1321 __ cmp(R0, ShifterOperand(R1)); // Class id match? 1319 __ cmp(R0, Operand(R1)); // Class id match?
1322 if (i < (num_args - 1)) { 1320 if (i < (num_args - 1)) {
1323 __ b(&update, NE); // Continue. 1321 __ b(&update, NE); // Continue.
1324 } else { 1322 } else {
1325 // Last check, all checks before matched. 1323 // Last check, all checks before matched.
1326 __ mov(LR, ShifterOperand(R8), EQ); // Restore return address if found. 1324 __ mov(LR, Operand(R8), EQ); // Restore return address if found.
1327 __ b(&found, EQ); // Break. 1325 __ b(&found, EQ); // Break.
1328 } 1326 }
1329 } 1327 }
1330 __ Bind(&update); 1328 __ Bind(&update);
1331 // Reload receiver class ID. It has not been destroyed when num_args == 1. 1329 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1332 if (num_args > 1) { 1330 if (num_args > 1) {
1333 __ ldr(R0, Address(SP, R7, LSL, 1)); 1331 __ ldr(R0, Address(SP, R7, LSL, 1));
1334 __ bl(&get_class_id_as_smi); 1332 __ bl(&get_class_id_as_smi);
1335 } 1333 }
1336 1334
1337 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1335 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1338 __ AddImmediate(R6, entry_size); // Next entry. 1336 __ AddImmediate(R6, entry_size); // Next entry.
1339 __ ldr(R1, Address(R6, 0)); // Next class ID. 1337 __ ldr(R1, Address(R6, 0)); // Next class ID.
1340 1338
1341 __ Bind(&test); 1339 __ Bind(&test);
1342 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? 1340 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done?
1343 __ b(&loop, NE); 1341 __ b(&loop, NE);
1344 1342
1345 // IC miss. 1343 // IC miss.
1346 // Restore return address. 1344 // Restore return address.
1347 __ mov(LR, ShifterOperand(R8)); 1345 __ mov(LR, Operand(R8));
1348 1346
1349 // Compute address of arguments. 1347 // Compute address of arguments.
1350 // R7: argument_count - 1 (smi). 1348 // R7: argument_count - 1 (smi).
1351 __ add(R7, SP, ShifterOperand(R7, LSL, 1)); // R7 is Smi. 1349 __ add(R7, SP, Operand(R7, LSL, 1)); // R7 is Smi.
1352 // R7: address of receiver. 1350 // R7: address of receiver.
1353 // Create a stub frame as we are pushing some objects on the stack before 1351 // Create a stub frame as we are pushing some objects on the stack before
1354 // calling into the runtime. 1352 // calling into the runtime.
1355 __ EnterStubFrame(); 1353 __ EnterStubFrame();
1356 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); 1354 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
1357 // Preserve IC data object and arguments descriptor array and 1355 // Preserve IC data object and arguments descriptor array and
1358 // setup space on stack for result (target code object). 1356 // setup space on stack for result (target code object).
1359 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); 1357 __ PushList((1 << R0) | (1 << R4) | (1 << R5));
1360 // Push call arguments. 1358 // Push call arguments.
1361 for (intptr_t i = 0; i < num_args; i++) { 1359 for (intptr_t i = 0; i < num_args; i++) {
(...skipping 11 matching lines...) Expand all
1373 __ LeaveStubFrame(); 1371 __ LeaveStubFrame();
1374 Label call_target_function; 1372 Label call_target_function;
1375 __ b(&call_target_function); 1373 __ b(&call_target_function);
1376 1374
1377 __ Bind(&found); 1375 __ Bind(&found);
1378 // R6: pointer to an IC data check group. 1376 // R6: pointer to an IC data check group.
1379 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1377 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1380 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1378 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1381 __ LoadFromOffset(kWord, R0, R6, target_offset); 1379 __ LoadFromOffset(kWord, R0, R6, target_offset);
1382 __ LoadFromOffset(kWord, R1, R6, count_offset); 1380 __ LoadFromOffset(kWord, R1, R6, count_offset);
1383 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); 1381 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1384 __ StoreToOffset(kWord, R1, R6, count_offset); 1382 __ StoreToOffset(kWord, R1, R6, count_offset);
1385 __ b(&call_target_function, VC); // No overflow. 1383 __ b(&call_target_function, VC); // No overflow.
1386 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); 1384 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue));
1387 __ StoreToOffset(kWord, R1, R6, count_offset); 1385 __ StoreToOffset(kWord, R1, R6, count_offset);
1388 1386
1389 __ Bind(&call_target_function); 1387 __ Bind(&call_target_function);
1390 // R0: target function. 1388 // R0: target function.
1391 __ ldr(R2, FieldAddress(R0, Function::code_offset())); 1389 __ ldr(R2, FieldAddress(R0, Function::code_offset()));
1392 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); 1390 __ ldr(R2, FieldAddress(R2, Code::instructions_offset()));
1393 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); 1391 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag);
1394 __ bx(R2); 1392 __ bx(R2);
1395 1393
1396 // Instance in R0, return its class-id in R0 as Smi. 1394 // Instance in R0, return its class-id in R0 as Smi.
1397 __ Bind(&get_class_id_as_smi); 1395 __ Bind(&get_class_id_as_smi);
1398 1396
1399 // Test if Smi -> load Smi class for comparison. 1397 // Test if Smi -> load Smi class for comparison.
1400 __ tst(R0, ShifterOperand(kSmiTagMask)); 1398 __ tst(R0, Operand(kSmiTagMask));
1401 __ mov(R0, ShifterOperand(Smi::RawValue(kSmiCid)), EQ); 1399 __ mov(R0, Operand(Smi::RawValue(kSmiCid)), EQ);
1402 __ bx(LR, EQ); 1400 __ bx(LR, EQ);
1403 __ LoadClassId(R0, R0); 1401 __ LoadClassId(R0, R0);
1404 __ SmiTag(R0); 1402 __ SmiTag(R0);
1405 __ bx(LR); 1403 __ bx(LR);
1406 } 1404 }
1407 1405
1408 1406
1409 // Use inline cache data array to invoke the target or continue in inline 1407 // Use inline cache data array to invoke the target or continue in inline
1410 // cache miss handler. Stub for 1-argument check (receiver class). 1408 // cache miss handler. Stub for 1-argument check (receiver class).
1411 // LR: return address. 1409 // LR: return address.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1471 // the target function and the call count. 1469 // the target function and the call count.
1472 // R5: ICData 1470 // R5: ICData
1473 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1471 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1474 GenerateUsageCounterIncrement(assembler, R6); 1472 GenerateUsageCounterIncrement(assembler, R6);
1475 #if defined(DEBUG) 1473 #if defined(DEBUG)
1476 { Label ok; 1474 { Label ok;
1477 // Check that the IC data array has NumArgsTested() == 0. 1475 // Check that the IC data array has NumArgsTested() == 0.
1478 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1476 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1479 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); 1477 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset()));
1480 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1478 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1481 __ and_(R6, R6, ShifterOperand(ICData::NumArgsTestedMask())); 1479 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask()));
1482 __ CompareImmediate(R6, 0); 1480 __ CompareImmediate(R6, 0);
1483 __ b(&ok, EQ); 1481 __ b(&ok, EQ);
1484 __ Stop("Incorrect IC data for unoptimized static call"); 1482 __ Stop("Incorrect IC data for unoptimized static call");
1485 __ Bind(&ok); 1483 __ Bind(&ok);
1486 } 1484 }
1487 #endif // DEBUG 1485 #endif // DEBUG
1488 1486
1489 if (FLAG_enable_debugger) { 1487 if (FLAG_enable_debugger) {
1490 // Check single stepping. 1488 // Check single stepping.
1491 Label not_stepping; 1489 Label not_stepping;
(...skipping 13 matching lines...) Expand all
1505 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); 1503 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset()));
1506 // R6: ic_data_array with entries: target functions and count. 1504 // R6: ic_data_array with entries: target functions and count.
1507 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); 1505 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag);
1508 // R6: points directly to the first ic data array element. 1506 // R6: points directly to the first ic data array element.
1509 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; 1507 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
1510 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; 1508 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
1511 1509
1512 // Increment count for this call. 1510 // Increment count for this call.
1513 Label increment_done; 1511 Label increment_done;
1514 __ LoadFromOffset(kWord, R1, R6, count_offset); 1512 __ LoadFromOffset(kWord, R1, R6, count_offset);
1515 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); 1513 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1516 __ StoreToOffset(kWord, R1, R6, count_offset); 1514 __ StoreToOffset(kWord, R1, R6, count_offset);
1517 __ b(&increment_done, VC); // No overflow. 1515 __ b(&increment_done, VC); // No overflow.
1518 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); 1516 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue));
1519 __ StoreToOffset(kWord, R1, R6, count_offset); 1517 __ StoreToOffset(kWord, R1, R6, count_offset);
1520 __ Bind(&increment_done); 1518 __ Bind(&increment_done);
1521 1519
1522 // Load arguments descriptor into R4. 1520 // Load arguments descriptor into R4.
1523 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); 1521 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
1524 1522
1525 // Get function and call it, if possible. 1523 // Get function and call it, if possible.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1604 if (n > 1) { 1602 if (n > 1) {
1605 // Get instance type arguments. 1603 // Get instance type arguments.
1606 __ LoadClass(R3, R0, R4); 1604 __ LoadClass(R3, R0, R4);
1607 // Compute instance type arguments into R4. 1605 // Compute instance type arguments into R4.
1608 Label has_no_type_arguments; 1606 Label has_no_type_arguments;
1609 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null())); 1607 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null()));
1610 __ ldr(R5, FieldAddress(R3, 1608 __ ldr(R5, FieldAddress(R3,
1611 Class::type_arguments_field_offset_in_words_offset())); 1609 Class::type_arguments_field_offset_in_words_offset()));
1612 __ CompareImmediate(R5, Class::kNoTypeArguments); 1610 __ CompareImmediate(R5, Class::kNoTypeArguments);
1613 __ b(&has_no_type_arguments, EQ); 1611 __ b(&has_no_type_arguments, EQ);
1614 __ add(R5, R0, ShifterOperand(R5, LSL, 2)); 1612 __ add(R5, R0, Operand(R5, LSL, 2));
1615 __ ldr(R4, FieldAddress(R5, 0)); 1613 __ ldr(R4, FieldAddress(R5, 0));
1616 __ Bind(&has_no_type_arguments); 1614 __ Bind(&has_no_type_arguments);
1617 } 1615 }
1618 __ LoadClassId(R3, R0); 1616 __ LoadClassId(R3, R0);
1619 // R0: instance. 1617 // R0: instance.
1620 // R1: instantiator type arguments or NULL. 1618 // R1: instantiator type arguments or NULL.
1621 // R2: SubtypeTestCache. 1619 // R2: SubtypeTestCache.
1622 // R3: instance class id. 1620 // R3: instance class id.
1623 // R4: instance type arguments (null if none), used only if n > 1. 1621 // R4: instance type arguments (null if none), used only if n > 1.
1624 __ ldr(R2, FieldAddress(R2, SubtypeTestCache::cache_offset())); 1622 __ ldr(R2, FieldAddress(R2, SubtypeTestCache::cache_offset()));
1625 __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag); 1623 __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag);
1626 1624
1627 Label loop, found, not_found, next_iteration; 1625 Label loop, found, not_found, next_iteration;
1628 // R2: entry start. 1626 // R2: entry start.
1629 // R3: instance class id. 1627 // R3: instance class id.
1630 // R4: instance type arguments. 1628 // R4: instance type arguments.
1631 __ SmiTag(R3); 1629 __ SmiTag(R3);
1632 __ Bind(&loop); 1630 __ Bind(&loop);
1633 __ ldr(R5, Address(R2, kWordSize * SubtypeTestCache::kInstanceClassId)); 1631 __ ldr(R5, Address(R2, kWordSize * SubtypeTestCache::kInstanceClassId));
1634 __ CompareImmediate(R5, reinterpret_cast<intptr_t>(Object::null())); 1632 __ CompareImmediate(R5, reinterpret_cast<intptr_t>(Object::null()));
1635 __ b(&not_found, EQ); 1633 __ b(&not_found, EQ);
1636 __ cmp(R5, ShifterOperand(R3)); 1634 __ cmp(R5, Operand(R3));
1637 if (n == 1) { 1635 if (n == 1) {
1638 __ b(&found, EQ); 1636 __ b(&found, EQ);
1639 } else { 1637 } else {
1640 __ b(&next_iteration, NE); 1638 __ b(&next_iteration, NE);
1641 __ ldr(R5, 1639 __ ldr(R5,
1642 Address(R2, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); 1640 Address(R2, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
1643 __ cmp(R5, ShifterOperand(R4)); 1641 __ cmp(R5, Operand(R4));
1644 if (n == 2) { 1642 if (n == 2) {
1645 __ b(&found, EQ); 1643 __ b(&found, EQ);
1646 } else { 1644 } else {
1647 __ b(&next_iteration, NE); 1645 __ b(&next_iteration, NE);
1648 __ ldr(R5, Address(R2, kWordSize * 1646 __ ldr(R5, Address(R2, kWordSize *
1649 SubtypeTestCache::kInstantiatorTypeArguments)); 1647 SubtypeTestCache::kInstantiatorTypeArguments));
1650 __ cmp(R5, ShifterOperand(R1)); 1648 __ cmp(R5, Operand(R1));
1651 __ b(&found, EQ); 1649 __ b(&found, EQ);
1652 } 1650 }
1653 } 1651 }
1654 __ Bind(&next_iteration); 1652 __ Bind(&next_iteration);
1655 __ AddImmediate(R2, kWordSize * SubtypeTestCache::kTestEntryLength); 1653 __ AddImmediate(R2, kWordSize * SubtypeTestCache::kTestEntryLength);
1656 __ b(&loop); 1654 __ b(&loop);
1657 // Fall through to not found. 1655 // Fall through to not found.
1658 __ Bind(&not_found); 1656 __ Bind(&not_found);
1659 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); 1657 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
1660 __ Ret(); 1658 __ Ret();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1693 // R1: instantiator type arguments or NULL. 1691 // R1: instantiator type arguments or NULL.
1694 // R2: cache array. 1692 // R2: cache array.
1695 // Result in R1: null -> not found, otherwise result (true or false). 1693 // Result in R1: null -> not found, otherwise result (true or false).
1696 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { 1694 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) {
1697 GenerateSubtypeNTestCacheStub(assembler, 3); 1695 GenerateSubtypeNTestCacheStub(assembler, 3);
1698 } 1696 }
1699 1697
1700 1698
1701 // Return the current stack pointer address, used to do stack alignment checks. 1699 // Return the current stack pointer address, used to do stack alignment checks.
1702 void StubCode::GenerateGetStackPointerStub(Assembler* assembler) { 1700 void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
1703 __ mov(R0, ShifterOperand(SP)); 1701 __ mov(R0, Operand(SP));
1704 __ Ret(); 1702 __ Ret();
1705 } 1703 }
1706 1704
1707 1705
1708 // Jump to the exception or error handler. 1706 // Jump to the exception or error handler.
1709 // LR: return address. 1707 // LR: return address.
1710 // R0: program_counter. 1708 // R0: program_counter.
1711 // R1: stack_pointer. 1709 // R1: stack_pointer.
1712 // R2: frame_pointer. 1710 // R2: frame_pointer.
1713 // R3: error object. 1711 // R3: error object.
1714 // SP: address of stacktrace object. 1712 // SP: address of stacktrace object.
1715 // Does not return. 1713 // Does not return.
1716 void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) { 1714 void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
1717 ASSERT(kExceptionObjectReg == R0); 1715 ASSERT(kExceptionObjectReg == R0);
1718 ASSERT(kStackTraceObjectReg == R1); 1716 ASSERT(kStackTraceObjectReg == R1);
1719 __ mov(IP, ShifterOperand(R1)); // Stack pointer. 1717 __ mov(IP, Operand(R1)); // Stack pointer.
1720 __ mov(LR, ShifterOperand(R0)); // Program counter. 1718 __ mov(LR, Operand(R0)); // Program counter.
1721 __ mov(R0, ShifterOperand(R3)); // Exception object. 1719 __ mov(R0, Operand(R3)); // Exception object.
1722 __ ldr(R1, Address(SP, 0)); // StackTrace object. 1720 __ ldr(R1, Address(SP, 0)); // StackTrace object.
1723 __ mov(FP, ShifterOperand(R2)); // Frame_pointer. 1721 __ mov(FP, Operand(R2)); // Frame_pointer.
1724 __ mov(SP, ShifterOperand(IP)); // Stack pointer. 1722 __ mov(SP, Operand(IP)); // Stack pointer.
1725 __ bx(LR); // Jump to the exception handler code. 1723 __ bx(LR); // Jump to the exception handler code.
1726 } 1724 }
1727 1725
1728 1726
1729 // Calls to the runtime to optimize the given function. 1727 // Calls to the runtime to optimize the given function.
1730 // R6: function to be reoptimized. 1728 // R6: function to be reoptimized.
1731 // R4: argument descriptor (preserved). 1729 // R4: argument descriptor (preserved).
1732 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 1730 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
1733 __ EnterStubFrame(); 1731 __ EnterStubFrame();
1734 __ Push(R4); 1732 __ Push(R4);
(...skipping 24 matching lines...) Expand all
1759 // Return Zero condition flag set if equal. 1757 // Return Zero condition flag set if equal.
1760 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint 1758 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
1761 // cannot contain a value that fits in Mint or Smi. 1759 // cannot contain a value that fits in Mint or Smi.
1762 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler, 1760 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
1763 const Register left, 1761 const Register left,
1764 const Register right, 1762 const Register right,
1765 const Register temp, 1763 const Register temp,
1766 const Register unused) { 1764 const Register unused) {
1767 Label reference_compare, done, check_mint, check_bigint; 1765 Label reference_compare, done, check_mint, check_bigint;
1768 // If any of the arguments is Smi do reference compare. 1766 // If any of the arguments is Smi do reference compare.
1769 __ tst(left, ShifterOperand(kSmiTagMask)); 1767 __ tst(left, Operand(kSmiTagMask));
1770 __ b(&reference_compare, EQ); 1768 __ b(&reference_compare, EQ);
1771 __ tst(right, ShifterOperand(kSmiTagMask)); 1769 __ tst(right, Operand(kSmiTagMask));
1772 __ b(&reference_compare, EQ); 1770 __ b(&reference_compare, EQ);
1773 1771
1774 // Value compare for two doubles. 1772 // Value compare for two doubles.
1775 __ CompareClassId(left, kDoubleCid, temp); 1773 __ CompareClassId(left, kDoubleCid, temp);
1776 __ b(&check_mint, NE); 1774 __ b(&check_mint, NE);
1777 __ CompareClassId(right, kDoubleCid, temp); 1775 __ CompareClassId(right, kDoubleCid, temp);
1778 __ b(&done, NE); 1776 __ b(&done, NE);
1779 1777
1780 // Double values bitwise compare. 1778 // Double values bitwise compare.
1781 __ ldr(temp, FieldAddress(left, Double::value_offset() + 0 * kWordSize)); 1779 __ ldr(temp, FieldAddress(left, Double::value_offset() + 0 * kWordSize));
1782 __ ldr(IP, FieldAddress(right, Double::value_offset() + 0 * kWordSize)); 1780 __ ldr(IP, FieldAddress(right, Double::value_offset() + 0 * kWordSize));
1783 __ cmp(temp, ShifterOperand(IP)); 1781 __ cmp(temp, Operand(IP));
1784 __ b(&done, NE); 1782 __ b(&done, NE);
1785 __ ldr(temp, FieldAddress(left, Double::value_offset() + 1 * kWordSize)); 1783 __ ldr(temp, FieldAddress(left, Double::value_offset() + 1 * kWordSize));
1786 __ ldr(IP, FieldAddress(right, Double::value_offset() + 1 * kWordSize)); 1784 __ ldr(IP, FieldAddress(right, Double::value_offset() + 1 * kWordSize));
1787 __ cmp(temp, ShifterOperand(IP)); 1785 __ cmp(temp, Operand(IP));
1788 __ b(&done); 1786 __ b(&done);
1789 1787
1790 __ Bind(&check_mint); 1788 __ Bind(&check_mint);
1791 __ CompareClassId(left, kMintCid, temp); 1789 __ CompareClassId(left, kMintCid, temp);
1792 __ b(&check_bigint, NE); 1790 __ b(&check_bigint, NE);
1793 __ CompareClassId(right, kMintCid, temp); 1791 __ CompareClassId(right, kMintCid, temp);
1794 __ b(&done, NE); 1792 __ b(&done, NE);
1795 __ ldr(temp, FieldAddress(left, Mint::value_offset() + 0 * kWordSize)); 1793 __ ldr(temp, FieldAddress(left, Mint::value_offset() + 0 * kWordSize));
1796 __ ldr(IP, FieldAddress(right, Mint::value_offset() + 0 * kWordSize)); 1794 __ ldr(IP, FieldAddress(right, Mint::value_offset() + 0 * kWordSize));
1797 __ cmp(temp, ShifterOperand(IP)); 1795 __ cmp(temp, Operand(IP));
1798 __ b(&done, NE); 1796 __ b(&done, NE);
1799 __ ldr(temp, FieldAddress(left, Mint::value_offset() + 1 * kWordSize)); 1797 __ ldr(temp, FieldAddress(left, Mint::value_offset() + 1 * kWordSize));
1800 __ ldr(IP, FieldAddress(right, Mint::value_offset() + 1 * kWordSize)); 1798 __ ldr(IP, FieldAddress(right, Mint::value_offset() + 1 * kWordSize));
1801 __ cmp(temp, ShifterOperand(IP)); 1799 __ cmp(temp, Operand(IP));
1802 __ b(&done); 1800 __ b(&done);
1803 1801
1804 __ Bind(&check_bigint); 1802 __ Bind(&check_bigint);
1805 __ CompareClassId(left, kBigintCid, temp); 1803 __ CompareClassId(left, kBigintCid, temp);
1806 __ b(&reference_compare, NE); 1804 __ b(&reference_compare, NE);
1807 __ CompareClassId(right, kBigintCid, temp); 1805 __ CompareClassId(right, kBigintCid, temp);
1808 __ b(&done, NE); 1806 __ b(&done, NE);
1809 __ EnterStubFrame(); 1807 __ EnterStubFrame();
1810 __ ReserveAlignedFrameSpace(2 * kWordSize); 1808 __ ReserveAlignedFrameSpace(2 * kWordSize);
1811 __ stm(IA, SP, (1 << R0) | (1 << R1)); 1809 __ stm(IA, SP, (1 << R0) | (1 << R1));
1812 __ CallRuntime(kBigintCompareRuntimeEntry, 2); 1810 __ CallRuntime(kBigintCompareRuntimeEntry, 2);
1813 // Result in R0, 0 means equal. 1811 // Result in R0, 0 means equal.
1814 __ LeaveStubFrame(); 1812 __ LeaveStubFrame();
1815 __ cmp(R0, ShifterOperand(0)); 1813 __ cmp(R0, Operand(0));
1816 __ b(&done); 1814 __ b(&done);
1817 1815
1818 __ Bind(&reference_compare); 1816 __ Bind(&reference_compare);
1819 __ cmp(left, ShifterOperand(right)); 1817 __ cmp(left, Operand(right));
1820 __ Bind(&done); 1818 __ Bind(&done);
1821 } 1819 }
1822 1820
1823 1821
1824 // Called only from unoptimized code. All relevant registers have been saved. 1822 // Called only from unoptimized code. All relevant registers have been saved.
1825 // LR: return address. 1823 // LR: return address.
1826 // SP + 4: left operand. 1824 // SP + 4: left operand.
1827 // SP + 0: right operand. 1825 // SP + 0: right operand.
1828 // Return Zero condition flag set if equal. 1826 // Return Zero condition flag set if equal.
1829 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( 1827 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1863 const Register right = R0; 1861 const Register right = R0;
1864 __ ldr(left, Address(SP, 1 * kWordSize)); 1862 __ ldr(left, Address(SP, 1 * kWordSize));
1865 __ ldr(right, Address(SP, 0 * kWordSize)); 1863 __ ldr(right, Address(SP, 0 * kWordSize));
1866 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); 1864 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
1867 __ Ret(); 1865 __ Ret();
1868 } 1866 }
1869 1867
1870 } // namespace dart 1868 } // namespace dart
1871 1869
1872 #endif // defined TARGET_ARCH_ARM 1870 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/object_arm_test.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698