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

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

Issue 14268006: Minor cleanup of ARM stubs. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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 | « no previous file | 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/compiler.h" 10 #include "vm/compiler.h"
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 __ bx(R0); 213 __ bx(R0);
214 } 214 }
215 215
216 216
217 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 217 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
218 __ Unimplemented("FixCallersTarget stub"); 218 __ Unimplemented("FixCallersTarget stub");
219 } 219 }
220 220
221 221
222 // Input parameters: 222 // Input parameters:
223 // R2: Smi-tagged argument count, may be zero. 223 // R2: smi-tagged argument count, may be zero.
224 // FP[kLastParamSlotIndex]: Last argument. 224 // FP[kLastParamSlotIndex]: last argument.
225 static void PushArgumentsArray(Assembler* assembler) { 225 static void PushArgumentsArray(Assembler* assembler) {
226 // Allocate array to store arguments of caller. 226 // Allocate array to store arguments of caller.
227 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); 227 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
228 // R1: Null element type for raw Array. 228 // R1: null element type for raw Array.
229 // R2: Smi-tagged argument count, may be zero. 229 // R2: smi-tagged argument count, may be zero.
230 __ BranchLink(&StubCode::AllocateArrayLabel()); 230 __ BranchLink(&StubCode::AllocateArrayLabel());
231 // R0: newly allocated array. 231 // R0: newly allocated array.
232 // R2: Smi-tagged argument count, may be zero (was preserved by the stub). 232 // R2: smi-tagged argument count, may be zero (was preserved by the stub).
233 __ Push(R0); // Array is in R0 and on top of stack. 233 __ Push(R0); // Array is in R0 and on top of stack.
234 __ add(R1, FP, ShifterOperand(R2, LSL, 1)); 234 __ add(R1, FP, ShifterOperand(R2, LSL, 1));
235 __ AddImmediate(R1, (kLastParamSlotIndex - 1) * kWordSize); 235 __ AddImmediate(R1, (kLastParamSlotIndex - 1) * kWordSize);
236 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag); 236 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag);
237 Label loop, loop_condition; 237 // R1: address of first argument on stack.
238 __ b(&loop_condition); 238 // R3: address of first argument in array.
239 Label loop;
239 __ Bind(&loop); 240 __ Bind(&loop);
240 __ ldr(IP, Address(R1, 0));
241 __ str(IP, Address(R3, 0));
242 __ AddImmediate(R1, -kWordSize);
243 __ AddImmediate(R3, kWordSize);
244 __ Bind(&loop_condition);
245 __ subs(R2, R2, ShifterOperand(Smi::RawValue(1))); // R2 is Smi. 241 __ subs(R2, R2, ShifterOperand(Smi::RawValue(1))); // R2 is Smi.
242 __ ldr(IP, Address(R1, 0), PL);
243 __ str(IP, Address(R3, 0), PL);
244 __ AddImmediate(R1, -kWordSize, PL);
245 __ AddImmediate(R3, kWordSize, PL);
246 __ b(&loop, PL); 246 __ b(&loop, PL);
247 } 247 }
248 248
249 249
250 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { 250 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) {
251 __ Unimplemented("InstanceFunctionLookup stub"); 251 __ Unimplemented("InstanceFunctionLookup stub");
252 } 252 }
253 253
254 254
255 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { 255 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
256 __ Unimplemented("DeoptimizeLazy stub"); 256 __ Unimplemented("DeoptimizeLazy stub");
257 } 257 }
258 258
259 259
260 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 260 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
261 __ Unimplemented("Deoptimize stub"); 261 __ Unimplemented("Deoptimize stub");
262 } 262 }
263 263
264 264
265 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 265 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
266 __ Unimplemented("MegamorphicMiss stub"); 266 __ Unimplemented("MegamorphicMiss stub");
267 } 267 }
268 268
269 269
270 // Called for inline allocation of arrays. 270 // Called for inline allocation of arrays.
271 // Input parameters: 271 // Input parameters:
272 // LR: return address. 272 // LR: return address.
273 // R2: Array length as Smi. 273 // R2: array length as Smi.
274 // R1: array element type (either NULL or an instantiated type). 274 // R1: array element type (either NULL or an instantiated type).
275 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved. 275 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved.
276 // The newly allocated object is returned in R0. 276 // The newly allocated object is returned in R0.
277 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { 277 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
278 Label slow_case; 278 Label slow_case;
279 if (FLAG_inline_alloc) { 279 if (FLAG_inline_alloc) {
280 // Compute the size to be allocated, it is based on the array length 280 // Compute the size to be allocated, it is based on the array length
281 // and is computed as: 281 // and is computed as:
282 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). 282 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
283 // Assert that length is a Smi. 283 // Assert that length is a Smi.
284 __ tst(R2, ShifterOperand(kSmiTagMask)); 284 __ tst(R2, ShifterOperand(kSmiTagMask));
285 if (FLAG_use_slow_path) { 285 if (FLAG_use_slow_path) {
286 __ b(&slow_case); 286 __ b(&slow_case);
287 } else { 287 } else {
288 __ b(&slow_case, NE); 288 __ b(&slow_case, NE);
289 } 289 }
290 __ ldr(R8, FieldAddress(CTX, Context::isolate_offset())); 290 __ ldr(R8, FieldAddress(CTX, Context::isolate_offset()));
291 __ LoadFromOffset(kLoadWord, R8, R8, Isolate::heap_offset()); 291 __ LoadFromOffset(kLoadWord, R8, R8, Isolate::heap_offset());
292 __ LoadFromOffset(kLoadWord, R8, R8, Heap::new_space_offset()); 292 __ LoadFromOffset(kLoadWord, R8, R8, Heap::new_space_offset());
293 293
294 // Calculate and align allocation size. 294 // Calculate and align allocation size.
295 // Load new object start and calculate next object start. 295 // Load new object start and calculate next object start.
296 // R1: array element type. 296 // R1: array element type.
297 // R2: Array length as Smi. 297 // R2: array length as Smi.
298 // R8: Points to new space object. 298 // R8: points to new space object.
299 __ LoadFromOffset(kLoadWord, R0, R8, Scavenger::top_offset()); 299 __ LoadFromOffset(kLoadWord, R0, R8, Scavenger::top_offset());
300 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; 300 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1;
301 __ LoadImmediate(R7, fixed_size); 301 __ LoadImmediate(R3, fixed_size);
302 __ add(R7, R7, ShifterOperand(R2, LSL, 1)); // R2 is Smi. 302 __ add(R3, R3, ShifterOperand(R2, LSL, 1)); // R2 is Smi.
303 ASSERT(kSmiTagShift == 1); 303 ASSERT(kSmiTagShift == 1);
304 __ bic(R7, R7, ShifterOperand(kObjectAlignment - 1)); 304 __ bic(R3, R3, ShifterOperand(kObjectAlignment - 1));
305 __ add(R7, R7, ShifterOperand(R0)); 305 __ add(R7, R3, ShifterOperand(R0));
306 306
307 // Check if the allocation fits into the remaining space. 307 // Check if the allocation fits into the remaining space.
308 // R0: potential new object start. 308 // R0: potential new object start.
309 // R1: array element type. 309 // R1: array element type.
310 // R2: Array length as Smi. 310 // R2: array length as Smi.
311 // R3: array size.
311 // R7: potential next object start. 312 // R7: potential next object start.
312 // R8: Points to new space object. 313 // R8: points to new space object.
313 __ LoadFromOffset(kLoadWord, IP, R8, Scavenger::end_offset()); 314 __ LoadFromOffset(kLoadWord, IP, R8, Scavenger::end_offset());
314 __ cmp(R7, ShifterOperand(IP)); 315 __ cmp(R7, ShifterOperand(IP));
315 __ b(&slow_case, CS); // Branch if unsigned higher or equal. 316 __ b(&slow_case, CS); // Branch if unsigned higher or equal.
316 317
317 // Successfully allocated the object(s), now update top to point to 318 // Successfully allocated the object(s), now update top to point to
318 // next object start and initialize the object. 319 // next object start and initialize the object.
319 // R0: potential new object start. 320 // R0: potential new object start.
320 // R7: potential next object start. 321 // R7: potential next object start.
321 // R8: Points to new space object. 322 // R8: Points to new space object.
322 __ StoreToOffset(kStoreWord, R7, R8, Scavenger::top_offset()); 323 __ StoreToOffset(kStoreWord, R7, R8, Scavenger::top_offset());
323 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); 324 __ add(R0, R0, ShifterOperand(kHeapObjectTag));
324 325
325 // R0: new object start as a tagged pointer. 326 // R0: new object start as a tagged pointer.
326 // R1: array element type. 327 // R1: array element type.
327 // R2: Array length as Smi. 328 // R2: array length as Smi.
329 // R3: array size.
328 // R7: new object end address. 330 // R7: new object end address.
329 331
330 // Store the type argument field. 332 // Store the type argument field.
331 __ StoreIntoObjectNoBarrier( 333 __ StoreIntoObjectNoBarrier(
332 R0, 334 R0,
333 FieldAddress(R0, Array::type_arguments_offset()), 335 FieldAddress(R0, Array::type_arguments_offset()),
334 R1); 336 R1);
335 337
336 // Set the length field. 338 // Set the length field.
337 __ StoreIntoObjectNoBarrier( 339 __ StoreIntoObjectNoBarrier(
338 R0, 340 R0,
339 FieldAddress(R0, Array::length_offset()), 341 FieldAddress(R0, Array::length_offset()),
340 R2); 342 R2);
341 343
342 // Calculate the size tag. 344 // Calculate the size tag.
343 // R0: new object start as a tagged pointer. 345 // R0: new object start as a tagged pointer.
344 // R2: Array length as Smi. 346 // R2: array length as Smi.
347 // R3: array size.
345 // R7: new object end address. 348 // R7: new object end address.
346 __ LoadImmediate(R1, fixed_size);
347 __ add(R1, R1, ShifterOperand(R2, LSL, 1)); // R2 is Smi.
348 ASSERT(kSmiTagShift == 1);
349 __ bic(R1, R1, ShifterOperand(kObjectAlignment - 1));
350 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; 349 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2;
351 __ CompareImmediate(R1, RawObject::SizeTag::kMaxSizeTag); 350 __ CompareImmediate(R3, RawObject::SizeTag::kMaxSizeTag);
352 // If no size tag overflow, shift R1 left, else set R1 to zero. 351 // If no size tag overflow, shift R1 left, else set R1 to zero.
353 __ mov(R1, ShifterOperand(R1, LSL, shift), LS); 352 __ mov(R1, ShifterOperand(R3, LSL, shift), LS);
354 __ mov(R1, ShifterOperand(0), HI); 353 __ mov(R1, ShifterOperand(0), HI);
355 354
356 // Get the class index and insert it into the tags. 355 // Get the class index and insert it into the tags.
357 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(kArrayCid)); 356 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(kArrayCid));
358 __ orr(R1, R1, ShifterOperand(IP)); 357 __ orr(R1, R1, ShifterOperand(IP));
359 __ str(R1, FieldAddress(R0, Array::tags_offset())); 358 __ str(R1, FieldAddress(R0, Array::tags_offset()));
360 359
361 // Initialize all array elements to raw_null. 360 // Initialize all array elements to raw_null.
362 // R0: new object start as a tagged pointer. 361 // R0: new object start as a tagged pointer.
363 // R7: new object end address. 362 // R7: new object end address.
364 // R2: Array length as Smi. 363 // R2: array length as Smi.
365 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag); 364 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag);
366 // R1: iterator which initially points to the start of the variable 365 // R1: iterator which initially points to the start of the variable
367 // data area to be initialized. 366 // data area to be initialized.
368 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); 367 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
369 Label loop, test; 368 Label loop;
370 __ b(&test);
371 __ Bind(&loop); 369 __ Bind(&loop);
372 // TODO(cshapiro): StoreIntoObjectNoBarrier 370 // TODO(cshapiro): StoreIntoObjectNoBarrier
373 __ str(IP, Address(R1, 0));
374 __ AddImmediate(R1, kWordSize);
375 __ Bind(&test);
376 __ cmp(R1, ShifterOperand(R7)); 371 __ cmp(R1, ShifterOperand(R7));
377 __ b(&loop, NE); 372 __ str(IP, Address(R1, 0), CC); // Store if unsigned lower.
373 __ AddImmediate(R1, kWordSize, CC);
374 __ b(&loop, CS);
378 375
379 // Done allocating and initializing the array. 376 // Done allocating and initializing the array.
380 // R0: new object. 377 // R0: new object.
381 // R2: Array length as Smi (preserved for the caller.) 378 // R2: array length as Smi (preserved for the caller.)
382 __ Ret(); 379 __ Ret();
383 } 380 }
384 381
385 // Unable to allocate the array using the fast inline code, just call 382 // Unable to allocate the array using the fast inline code, just call
386 // into the runtime. 383 // into the runtime.
387 __ Bind(&slow_case); 384 __ Bind(&slow_case);
388 // Create a stub frame as we are pushing some objects on the stack before 385 // Create a stub frame as we are pushing some objects on the stack before
389 // calling into the runtime. 386 // calling into the runtime.
390 __ EnterStubFrame(); 387 __ EnterStubFrame();
391 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); 388 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
392 // Setup space on stack for return value. 389 // Setup space on stack for return value.
393 // Push array length as Smi and element type. 390 // Push array length as Smi and element type.
394 __ PushList((1 << R1) | (1 << R2) | (1 << IP)); 391 __ PushList((1 << R1) | (1 << R2) | (1 << IP));
395 __ CallRuntime(kAllocateArrayRuntimeEntry); 392 __ CallRuntime(kAllocateArrayRuntimeEntry);
396 // Pop arguments; result is popped in IP. 393 // Pop arguments; result is popped in IP.
397 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored. 394 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored.
398 __ mov(R0, ShifterOperand(IP)); 395 __ mov(R0, ShifterOperand(IP));
399 __ LeaveStubFrame(); 396 __ LeaveStubFrame();
400 __ Ret(); 397 __ Ret();
401 } 398 }
402 399
403 400
404 // Input parameters: 401 // Input parameters:
405 // LR: return address. 402 // LR: return address.
406 // SP: address of last argument. 403 // SP: address of last argument.
407 // R4: Arguments descriptor array. 404 // R4: arguments descriptor array.
408 // Note: The closure object is the first argument to the function being 405 // Note: The closure object is the first argument to the function being
409 // called, the stub accesses the closure from this location directly 406 // called, the stub accesses the closure from this location directly
410 // when trying to resolve the call. 407 // when trying to resolve the call.
411 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { 408 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) {
412 // Load num_args. 409 // Load num_args.
413 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 410 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
414 __ sub(R0, R0, ShifterOperand(Smi::RawValue(1))); 411 __ sub(R0, R0, ShifterOperand(Smi::RawValue(1)));
415 // Load closure object in R1. 412 // Load closure object in R1.
416 __ ldr(R1, Address(SP, R0, LSL, 1)); // R0 (num_args - 1) is a Smi. 413 __ ldr(R1, Address(SP, R0, LSL, 1)); // R0 (num_args - 1) is a Smi.
417 414
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 __ CallRuntime(kCompileFunctionRuntimeEntry); 449 __ CallRuntime(kCompileFunctionRuntimeEntry);
453 // Restore arguments descriptor array and read-only function object argument. 450 // Restore arguments descriptor array and read-only function object argument.
454 __ PopList((1 << R2) | (1 << R4)); 451 __ PopList((1 << R2) | (1 << R4));
455 // Restore R0. 452 // Restore R0.
456 __ ldr(R0, FieldAddress(R2, Function::code_offset())); 453 __ ldr(R0, FieldAddress(R2, Function::code_offset()));
457 454
458 // Remove the stub frame as we are about to jump to the closure function. 455 // Remove the stub frame as we are about to jump to the closure function.
459 __ LeaveStubFrame(); 456 __ LeaveStubFrame();
460 457
461 __ Bind(&function_compiled); 458 __ Bind(&function_compiled);
462 // R0: Code. 459 // R0: code.
463 // R4: Arguments descriptor array. 460 // R4: arguments descriptor array.
464 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); 461 __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
465 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); 462 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag);
466 __ bx(R0); 463 __ bx(R0);
467 464
468 __ Bind(&not_closure); 465 __ Bind(&not_closure);
469 // Call runtime to attempt to resolve and invoke a call method on a 466 // Call runtime to attempt to resolve and invoke a call method on a
470 // non-closure object, passing the non-closure object and its arguments array, 467 // non-closure object, passing the non-closure object and its arguments array,
471 // returning here. 468 // returning here.
472 // If no call method exists, throw a NoSuchMethodError. 469 // If no call method exists, throw a NoSuchMethodError.
473 // R1: non-closure object. 470 // R1: non-closure object.
474 // R4: arguments descriptor array. 471 // R4: arguments descriptor array.
475 472
476 // Create a stub frame as we are pushing some objects on the stack before 473 // Create a stub frame as we are pushing some objects on the stack before
477 // calling into the runtime. 474 // calling into the runtime.
478 __ EnterStubFrame(); 475 __ EnterStubFrame();
479 476
480 // Setup space on stack for result from error reporting. 477 // Setup space on stack for result from error reporting.
481 __ PushList((1 << R4) | (1 << R8)); // Arguments descriptor and raw null. 478 __ PushList((1 << R4) | (1 << R8)); // Arguments descriptor and raw null.
482 479
483 // Load smi-tagged arguments array length, including the non-closure. 480 // Load smi-tagged arguments array length, including the non-closure.
484 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 481 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
485 PushArgumentsArray(assembler); 482 PushArgumentsArray(assembler);
486 483
487 // Stack: 484 // Stack:
488 // TOS + 0: Argument array. 485 // TOS + 0: argument array.
489 // TOS + 1: Arguments descriptor array. 486 // TOS + 1: arguments descriptor array.
490 // TOS + 2: Place for result from the call. 487 // TOS + 2: place for result from the call.
491 // TOS + 3: Saved FP of previous frame. 488 // TOS + 3: saved FP of previous frame.
492 // TOS + 4: Dart code return address 489 // TOS + 4: dart code return address
493 // TOS + 5: PC marker (0 for stub). 490 // TOS + 5: pc marker (0 for stub).
494 // TOS + 6: Last argument of caller. 491 // TOS + 6: last argument of caller.
495 // .... 492 // ....
496 __ CallRuntime(kInvokeNonClosureRuntimeEntry); 493 __ CallRuntime(kInvokeNonClosureRuntimeEntry);
497 // Remove arguments. 494 // Remove arguments.
498 __ Drop(2); 495 __ Drop(2);
499 __ Pop(R0); // Get result into R0. 496 __ Pop(R0); // Get result into R0.
500 497
501 // Remove the stub frame as we are about to return. 498 // Remove the stub frame as we are about to return.
502 __ LeaveStubFrame(); 499 __ LeaveStubFrame();
503 __ Ret(); 500 __ Ret();
504 } 501 }
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 // Setup up number of context variables field. 671 // Setup up number of context variables field.
675 // R0: new object. 672 // R0: new object.
676 // R1: number of context variables as integer value (not object). 673 // R1: number of context variables as integer value (not object).
677 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); 674 __ str(R1, FieldAddress(R0, Context::num_variables_offset()));
678 675
679 // Setup isolate field. 676 // Setup isolate field.
680 // Load Isolate pointer from Context structure into R2. 677 // Load Isolate pointer from Context structure into R2.
681 // R0: new object. 678 // R0: new object.
682 // R1: number of context variables. 679 // R1: number of context variables.
683 __ ldr(R2, FieldAddress(CTX, Context::isolate_offset())); 680 __ ldr(R2, FieldAddress(CTX, Context::isolate_offset()));
684 // R2: Isolate, not an object. 681 // R2: isolate, not an object.
685 __ str(R2, FieldAddress(R0, Context::isolate_offset())); 682 __ str(R2, FieldAddress(R0, Context::isolate_offset()));
686 683
687 // Setup the parent field. 684 // Setup the parent field.
688 // R0: new object. 685 // R0: new object.
689 // R1: number of context variables. 686 // R1: number of context variables.
690 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); 687 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null()));
691 __ str(R2, FieldAddress(R0, Context::parent_offset())); 688 __ str(R2, FieldAddress(R0, Context::parent_offset()));
692 689
693 // Initialize the context variables. 690 // Initialize the context variables.
694 // R0: new object. 691 // R0: new object.
(...skipping 26 matching lines...) Expand all
721 // Restore the frame pointer. 718 // Restore the frame pointer.
722 __ LeaveStubFrame(); 719 __ LeaveStubFrame();
723 __ Ret(); 720 __ Ret();
724 } 721 }
725 722
726 723
727 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); 724 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate);
728 725
729 // Helper stub to implement Assembler::StoreIntoObject. 726 // Helper stub to implement Assembler::StoreIntoObject.
730 // Input parameters: 727 // Input parameters:
731 // R0: Address (i.e. object) being stored into. 728 // R0: address (i.e. object) being stored into.
732 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { 729 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
733 // Save values being destroyed. 730 // Save values being destroyed.
734 __ PushList((1 << R1) | (1 << R2) | (1 << R3)); 731 __ PushList((1 << R1) | (1 << R2) | (1 << R3));
735 732
736 // Load the isolate out of the context. 733 // Load the isolate out of the context.
737 // Spilled: R1, R2, R3. 734 // Spilled: R1, R2, R3.
738 // R0: Address being stored. 735 // R0: address being stored.
739 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset())); 736 __ ldr(R1, FieldAddress(CTX, Context::isolate_offset()));
740 737
741 // Load top_ out of the StoreBufferBlock and add the address to the pointers_. 738 // Load top_ out of the StoreBufferBlock and add the address to the pointers_.
742 // R1: Isolate. 739 // R1: isolate.
743 intptr_t store_buffer_offset = Isolate::store_buffer_block_offset(); 740 intptr_t store_buffer_offset = Isolate::store_buffer_block_offset();
744 __ LoadFromOffset(kLoadWord, R2, R1, 741 __ LoadFromOffset(kLoadWord, R2, R1,
745 store_buffer_offset + StoreBufferBlock::top_offset()); 742 store_buffer_offset + StoreBufferBlock::top_offset());
746 __ add(R3, R1, ShifterOperand(R2, LSL, 2)); 743 __ add(R3, R1, ShifterOperand(R2, LSL, 2));
747 __ StoreToOffset(kStoreWord, R0, R3, 744 __ StoreToOffset(kStoreWord, R0, R3,
748 store_buffer_offset + StoreBufferBlock::pointers_offset()); 745 store_buffer_offset + StoreBufferBlock::pointers_offset());
749 746
750 // Increment top_ and check for overflow. 747 // Increment top_ and check for overflow.
751 // R2: top_ 748 // R2: top_.
752 // R1: Isolate 749 // R1: isolate.
753 Label L; 750 Label L;
754 __ add(R2, R2, ShifterOperand(1)); 751 __ add(R2, R2, ShifterOperand(1));
755 __ StoreToOffset(kStoreWord, R2, R1, 752 __ StoreToOffset(kStoreWord, R2, R1,
756 store_buffer_offset + StoreBufferBlock::top_offset()); 753 store_buffer_offset + StoreBufferBlock::top_offset());
757 __ CompareImmediate(R2, StoreBufferBlock::kSize); 754 __ CompareImmediate(R2, StoreBufferBlock::kSize);
758 // Restore values. 755 // Restore values.
759 __ PopList((1 << R1) | (1 << R2) | (1 << R3)); 756 __ PopList((1 << R1) | (1 << R2) | (1 << R3));
760 __ b(&L, EQ); 757 __ b(&L, EQ);
761 __ Ret(); 758 __ Ret();
762 759
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
1120 // but only at exit so that we have collected all type feedback before 1117 // but only at exit so that we have collected all type feedback before
1121 // optimizing. 1118 // optimizing.
1122 } 1119 }
1123 __ add(R7, R7, ShifterOperand(1)); 1120 __ add(R7, R7, ShifterOperand(1));
1124 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset())); 1121 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
1125 __ Bind(&is_hot); 1122 __ Bind(&is_hot);
1126 } 1123 }
1127 1124
1128 1125
1129 // Generate inline cache check for 'num_args'. 1126 // Generate inline cache check for 'num_args'.
1130 // LR: return address 1127 // LR: return address.
1131 // R5: Inline cache data object. 1128 // R5: inline cache data object.
1132 // R4: Arguments descriptor array. 1129 // R4: arguments descriptor array.
1133 // Control flow: 1130 // Control flow:
1134 // - If receiver is null -> jump to IC miss. 1131 // - If receiver is null -> jump to IC miss.
1135 // - If receiver is Smi -> load Smi class. 1132 // - If receiver is Smi -> load Smi class.
1136 // - If receiver is not-Smi -> load receiver's class. 1133 // - If receiver is not-Smi -> load receiver's class.
1137 // - Check if 'num_args' (including receiver) match any IC data group. 1134 // - Check if 'num_args' (including receiver) match any IC data group.
1138 // - Match found -> jump to target. 1135 // - Match found -> jump to target.
1139 // - Match not found -> jump to IC miss. 1136 // - Match not found -> jump to IC miss.
1140 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, 1137 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
1141 intptr_t num_args) { 1138 intptr_t num_args) {
1142 ASSERT(num_args > 0); 1139 ASSERT(num_args > 0);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); 1248 __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
1252 __ b(&call_target_function, NE); 1249 __ b(&call_target_function, NE);
1253 // NoSuchMethod or closure. 1250 // NoSuchMethod or closure.
1254 // Mark IC call that it may be a closure call that does not collect 1251 // Mark IC call that it may be a closure call that does not collect
1255 // type feedback. 1252 // type feedback.
1256 __ mov(IP, ShifterOperand(1)); 1253 __ mov(IP, ShifterOperand(1));
1257 __ strb(IP, FieldAddress(R5, ICData::is_closure_call_offset())); 1254 __ strb(IP, FieldAddress(R5, ICData::is_closure_call_offset()));
1258 __ Branch(&StubCode::InstanceFunctionLookupLabel()); 1255 __ Branch(&StubCode::InstanceFunctionLookupLabel());
1259 1256
1260 __ Bind(&found); 1257 __ Bind(&found);
1261 // R6: Pointer to an IC data check group. 1258 // R6: pointer to an IC data check group.
1262 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1259 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1263 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1260 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1264 __ LoadFromOffset(kLoadWord, R0, R6, target_offset); 1261 __ LoadFromOffset(kLoadWord, R0, R6, target_offset);
1265 __ LoadFromOffset(kLoadWord, R1, R6, count_offset); 1262 __ LoadFromOffset(kLoadWord, R1, R6, count_offset);
1266 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); 1263 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1)));
1267 __ StoreToOffset(kStoreWord, R1, R6, count_offset); 1264 __ StoreToOffset(kStoreWord, R1, R6, count_offset);
1268 __ b(&call_target_function, VC); // No overflow. 1265 __ b(&call_target_function, VC); // No overflow.
1269 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); 1266 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue));
1270 __ StoreToOffset(kStoreWord, R1, R6, count_offset); 1267 __ StoreToOffset(kStoreWord, R1, R6, count_offset);
1271 1268
1272 __ Bind(&call_target_function); 1269 __ Bind(&call_target_function);
1273 // R0: Target function. 1270 // R0: target function.
1274 __ ldr(R0, FieldAddress(R0, Function::code_offset())); 1271 __ ldr(R0, FieldAddress(R0, Function::code_offset()));
1275 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); 1272 __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
1276 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); 1273 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag);
1277 __ bx(R0); 1274 __ bx(R0);
1278 1275
1279 // Instance in R0, return its class-id in R0 as Smi. 1276 // Instance in R0, return its class-id in R0 as Smi.
1280 __ Bind(&get_class_id_as_smi); 1277 __ Bind(&get_class_id_as_smi);
1281 1278
1282 // Test if Smi -> load Smi class for comparison. 1279 // Test if Smi -> load Smi class for comparison.
1283 __ tst(R0, ShifterOperand(kSmiTagMask)); 1280 __ tst(R0, ShifterOperand(kSmiTagMask));
1284 __ mov(R0, ShifterOperand(Smi::RawValue(kSmiCid)), EQ); 1281 __ mov(R0, ShifterOperand(Smi::RawValue(kSmiCid)), EQ);
1285 __ bx(LR, EQ); 1282 __ bx(LR, EQ);
1286 __ LoadClassId(R0, R0); 1283 __ LoadClassId(R0, R0);
1287 __ SmiTag(R0); 1284 __ SmiTag(R0);
1288 __ bx(LR); 1285 __ bx(LR);
1289 } 1286 }
1290 1287
1291 1288
1292 // Use inline cache data array to invoke the target or continue in inline 1289 // Use inline cache data array to invoke the target or continue in inline
1293 // cache miss handler. Stub for 1-argument check (receiver class). 1290 // cache miss handler. Stub for 1-argument check (receiver class).
1294 // LR: Return address. 1291 // LR: return address.
1295 // R5: Inline cache data object. 1292 // R5: inline cache data object.
1296 // R4: Arguments descriptor array. 1293 // R4: arguments descriptor array.
1297 // Inline cache data object structure: 1294 // Inline cache data object structure:
1298 // 0: function-name 1295 // 0: function-name
1299 // 1: N, number of arguments checked. 1296 // 1: N, number of arguments checked.
1300 // 2 .. (length - 1): group of checks, each check containing: 1297 // 2 .. (length - 1): group of checks, each check containing:
1301 // - N classes. 1298 // - N classes.
1302 // - 1 target function. 1299 // - 1 target function.
1303 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1300 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1304 GenerateUsageCounterIncrement(assembler, R6); 1301 GenerateUsageCounterIncrement(assembler, R6);
1305 GenerateNArgsCheckInlineCacheStub(assembler, 1); 1302 GenerateNArgsCheckInlineCacheStub(assembler, 1);
1306 } 1303 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1389 __ LoadClassId(R3, R0); 1386 __ LoadClassId(R3, R0);
1390 // R0: instance. 1387 // R0: instance.
1391 // R1: instantiator type arguments or NULL. 1388 // R1: instantiator type arguments or NULL.
1392 // R2: SubtypeTestCache. 1389 // R2: SubtypeTestCache.
1393 // R3: instance class id. 1390 // R3: instance class id.
1394 // R4: instance type arguments (null if none), used only if n > 1. 1391 // R4: instance type arguments (null if none), used only if n > 1.
1395 __ ldr(R2, FieldAddress(R2, SubtypeTestCache::cache_offset())); 1392 __ ldr(R2, FieldAddress(R2, SubtypeTestCache::cache_offset()));
1396 __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag); 1393 __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag);
1397 1394
1398 Label loop, found, not_found, next_iteration; 1395 Label loop, found, not_found, next_iteration;
1399 // R2: Entry start. 1396 // R2: entry start.
1400 // R3: instance class id. 1397 // R3: instance class id.
1401 // R4: instance type arguments. 1398 // R4: instance type arguments.
1402 __ SmiTag(R3); 1399 __ SmiTag(R3);
1403 __ Bind(&loop); 1400 __ Bind(&loop);
1404 __ ldr(R5, Address(R2, kWordSize * SubtypeTestCache::kInstanceClassId)); 1401 __ ldr(R5, Address(R2, kWordSize * SubtypeTestCache::kInstanceClassId));
1405 __ CompareImmediate(R5, reinterpret_cast<intptr_t>(Object::null())); 1402 __ CompareImmediate(R5, reinterpret_cast<intptr_t>(Object::null()));
1406 __ b(&not_found, EQ); 1403 __ b(&not_found, EQ);
1407 __ cmp(R5, ShifterOperand(R3)); 1404 __ cmp(R5, ShifterOperand(R3));
1408 if (n == 1) { 1405 if (n == 1) {
1409 __ b(&found, EQ); 1406 __ b(&found, EQ);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 __ Bind(&reference_compare); 1594 __ Bind(&reference_compare);
1598 __ cmp(left, ShifterOperand(right)); 1595 __ cmp(left, ShifterOperand(right));
1599 __ Bind(&done); 1596 __ Bind(&done);
1600 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); 1597 __ PopList((1 << R0) | (1 << R1) | (1 << R2));
1601 __ Ret(); 1598 __ Ret();
1602 } 1599 }
1603 1600
1604 } // namespace dart 1601 } // namespace dart
1605 1602
1606 #endif // defined TARGET_ARCH_ARM 1603 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698