Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 372 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 372 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 373 __ Stop("GenerateDeoptimizeStub"); | 373 __ Stop("GenerateDeoptimizeStub"); |
| 374 } | 374 } |
| 375 | 375 |
| 376 | 376 |
| 377 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 377 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
| 378 __ Stop("GenerateMegamorphicMissStub"); | 378 __ Stop("GenerateMegamorphicMissStub"); |
| 379 } | 379 } |
| 380 | 380 |
| 381 | 381 |
| 382 // Called for inline allocation of arrays. | |
| 383 // Input parameters: | |
| 384 // LR: return address. | |
| 385 // R2: array length as Smi. | |
| 386 // R1: array element type (either NULL or an instantiated type). | |
| 387 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved. | |
| 388 // The newly allocated object is returned in R0. | |
| 382 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 389 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 383 __ Stop("GenerateAllocateArrayStub"); | 390 Label slow_case; |
| 391 if (FLAG_inline_alloc) { | |
| 392 // Compute the size to be allocated, it is based on the array length | |
| 393 // and is computed as: | |
| 394 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | |
| 395 // Assert that length is a Smi. | |
| 396 __ tsti(R2, kSmiTagMask); | |
| 397 if (FLAG_use_slow_path) { | |
| 398 __ b(&slow_case); | |
| 399 } else { | |
| 400 __ b(&slow_case, NE); | |
| 401 } | |
| 402 __ LoadFieldFromOffset(R8, CTX, Context::isolate_offset()); | |
| 403 __ LoadFromOffset(R8, R8, Isolate::heap_offset()); | |
| 404 __ LoadFromOffset(R8, R8, Heap::new_space_offset()); | |
| 405 | |
| 406 // Calculate and align allocation size. | |
| 407 // Load new object start and calculate next object start. | |
| 408 // R1: array element type. | |
| 409 // R2: array length as Smi. | |
| 410 // R8: points to new space object. | |
| 411 __ LoadFromOffset(R0, R8, Scavenger::top_offset()); | |
| 412 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | |
| 413 __ LoadImmediate(R3, fixed_size, kNoPP); | |
| 414 __ add(R3, R3, Operand(R2, LSL, 2)); // R2 is Smi. | |
| 415 ASSERT(kSmiTagShift == 1); | |
| 416 __ andi(R3, R3, ~(kObjectAlignment - 1)); | |
| 417 __ add(R7, R3, Operand(R0)); | |
| 418 | |
| 419 // Check if the allocation fits into the remaining space. | |
| 420 // R0: potential new object start. | |
| 421 // R1: array element type. | |
| 422 // R2: array length as Smi. | |
| 423 // R3: array size. | |
| 424 // R7: potential next object start. | |
| 425 // R8: points to new space object. | |
| 426 __ LoadFromOffset(TMP, R8, Scavenger::end_offset()); | |
| 427 __ CompareRegisters(R7, TMP); | |
| 428 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | |
| 429 | |
| 430 // Successfully allocated the object(s), now update top to point to | |
| 431 // next object start and initialize the object. | |
| 432 // R0: potential new object start. | |
| 433 // R3: array size. | |
| 434 // R7: potential next object start. | |
| 435 // R8: Points to new space object. | |
| 436 __ StoreToOffset(R7, R8, Scavenger::top_offset()); | |
| 437 __ add(R0, R0, Operand(kHeapObjectTag)); | |
| 438 __ UpdateAllocationStatsWithSize(kArrayCid, R3, R8, kNoPP); | |
| 439 | |
| 440 // R0: new object start as a tagged pointer. | |
| 441 // R1: array element type. | |
| 442 // R2: array length as Smi. | |
| 443 // R3: array size. | |
| 444 // R7: new object end address. | |
| 445 | |
| 446 // Store the type argument field. | |
| 447 __ StoreIntoObjectNoBarrier( | |
| 448 R0, | |
| 449 FieldAddress(R0, Array::type_arguments_offset()), | |
| 450 R1); | |
| 451 | |
| 452 // Set the length field. | |
| 453 __ StoreIntoObjectNoBarrier( | |
| 454 R0, | |
| 455 FieldAddress(R0, Array::length_offset()), | |
| 456 R2); | |
| 457 | |
| 458 // Calculate the size tag. | |
| 459 // R0: new object start as a tagged pointer. | |
| 460 // R2: array length as Smi. | |
| 461 // R3: array size. | |
| 462 // R7: new object end address. | |
| 463 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | |
| 464 __ CompareImmediate(R3, RawObject::SizeTag::kMaxSizeTag, kNoPP); | |
| 465 // If no size tag overflow, shift R1 left, else set R1 to zero. | |
| 466 __ Lsl(TMP, R3, shift); | |
| 467 __ LoadImmediate(TMP2, 0, kNoPP); | |
| 468 __ csel(R1, TMP, R1, LS); | |
| 469 __ csel(R1, TMP2, R1, HI); | |
|
regis
2014/04/29 23:09:21
Can't you use ZR register here?
zra
2014/04/29 23:18:19
Done.
| |
| 470 | |
| 471 // Get the class index and insert it into the tags. | |
| 472 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(kArrayCid), kNoPP); | |
| 473 __ orr(R1, R1, Operand(TMP)); | |
| 474 __ StoreFieldToOffset(R1, R0, Array::tags_offset()); | |
| 475 | |
| 476 // Initialize all array elements to raw_null. | |
| 477 // R0: new object start as a tagged pointer. | |
| 478 // R7: new object end address. | |
| 479 // R2: array length as Smi. | |
| 480 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag, kNoPP); | |
| 481 // R1: iterator which initially points to the start of the variable | |
| 482 // data area to be initialized. | |
| 483 __ LoadObject(TMP, Object::null_object(), PP); | |
| 484 Label loop, done; | |
| 485 __ Bind(&loop); | |
| 486 // TODO(cshapiro): StoreIntoObjectNoBarrier | |
|
regis
2014/04/29 23:09:21
Mmm, any volunteer?
zra
2014/04/29 23:18:19
Maybe we can chat about this tomorrow.
| |
| 487 __ CompareRegisters(R1, R7); | |
| 488 __ b(&done, CS); | |
| 489 __ str(TMP, Address(R1)); // Store if unsigned lower. | |
| 490 __ AddImmediate(R1, R1, kWordSize, kNoPP); | |
| 491 __ b(&loop); // Loop until R1 == R7. | |
| 492 __ Bind(&done); | |
| 493 | |
| 494 // Done allocating and initializing the array. | |
| 495 // R0: new object. | |
| 496 // R2: array length as Smi (preserved for the caller.) | |
| 497 __ ret(); | |
| 498 } | |
| 499 | |
| 500 // Unable to allocate the array using the fast inline code, just call | |
| 501 // into the runtime. | |
| 502 __ Bind(&slow_case); | |
| 503 // Create a stub frame as we are pushing some objects on the stack before | |
| 504 // calling into the runtime. | |
| 505 __ EnterStubFrame(); | |
| 506 __ LoadObject(TMP, Object::null_object(), PP); | |
| 507 // Setup space on stack for return value. | |
| 508 // Push array length as Smi and element type. | |
| 509 __ Push(TMP); | |
| 510 __ Push(R2); | |
| 511 __ Push(R1); | |
| 512 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); | |
| 513 // Pop arguments; result is popped in IP. | |
| 514 __ Pop(R1); | |
| 515 __ Pop(R2); | |
| 516 __ Pop(TMP); | |
| 517 __ mov(R0, TMP); | |
| 518 __ LeaveStubFrame(); | |
| 519 __ ret(); | |
| 384 } | 520 } |
| 385 | 521 |
| 386 | 522 |
| 387 // Called when invoking Dart code from C++ (VM code). | 523 // Called when invoking Dart code from C++ (VM code). |
| 388 // Input parameters: | 524 // Input parameters: |
| 389 // LR : points to return address. | 525 // LR : points to return address. |
| 390 // R0 : entrypoint of the Dart function to call. | 526 // R0 : entrypoint of the Dart function to call. |
| 391 // R1 : arguments descriptor array. | 527 // R1 : arguments descriptor array. |
| 392 // R2 : arguments array. | 528 // R2 : arguments array. |
| 393 // R3 : new context containing the current isolate pointer. | 529 // R3 : new context containing the current isolate pointer. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 528 } | 664 } |
| 529 | 665 |
| 530 // TODO(zra): Restore callee-saved fpu registers. | 666 // TODO(zra): Restore callee-saved fpu registers. |
| 531 | 667 |
| 532 // Restore the frame pointer and return. | 668 // Restore the frame pointer and return. |
| 533 __ LeaveFrame(); | 669 __ LeaveFrame(); |
| 534 __ ret(); | 670 __ ret(); |
| 535 } | 671 } |
| 536 | 672 |
| 537 | 673 |
| 674 // Called for inline allocation of contexts. | |
| 675 // Input: | |
| 676 // R1: number of context variables. | |
| 677 // Output: | |
| 678 // R0: new allocated RawContext object. | |
| 538 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 679 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 539 __ Stop("GenerateAllocateContextStub"); | 680 if (FLAG_inline_alloc) { |
| 681 const Class& context_class = Class::ZoneHandle(Object::context_class()); | |
| 682 Label slow_case; | |
| 683 Heap* heap = Isolate::Current()->heap(); | |
| 684 // First compute the rounded instance size. | |
| 685 // R1: number of context variables. | |
| 686 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; | |
| 687 __ LoadImmediate(R2, fixed_size, kNoPP); | |
| 688 __ add(R2, R2, Operand(R1, LSL, 3)); | |
| 689 ASSERT(kSmiTagShift == 1); | |
| 690 __ andi(R2, R2, ~(kObjectAlignment - 1)); | |
| 691 | |
| 692 // Now allocate the object. | |
| 693 // R1: number of context variables. | |
| 694 // R2: object size. | |
| 695 __ LoadImmediate(R5, heap->TopAddress(), kNoPP); | |
| 696 __ ldr(R0, Address(R5)); | |
| 697 __ add(R3, R2, Operand(R0)); | |
| 698 // Check if the allocation fits into the remaining space. | |
| 699 // R0: potential new object. | |
| 700 // R1: number of context variables. | |
| 701 // R2: object size. | |
| 702 // R3: potential next object start. | |
| 703 __ LoadImmediate(TMP, heap->EndAddress(), kNoPP); | |
| 704 __ ldr(TMP, Address(TMP)); | |
| 705 __ CompareRegisters(R3, TMP); | |
| 706 if (FLAG_use_slow_path) { | |
| 707 __ b(&slow_case); | |
| 708 } else { | |
| 709 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | |
| 710 } | |
| 711 | |
| 712 // Successfully allocated the object, now update top to point to | |
| 713 // next object start and initialize the object. | |
| 714 // R0: new object. | |
| 715 // R1: number of context variables. | |
| 716 // R2: object size. | |
| 717 // R3: next object start. | |
| 718 __ str(R3, Address(R5)); | |
| 719 __ add(R0, R0, Operand(kHeapObjectTag)); | |
| 720 __ UpdateAllocationStatsWithSize(context_class.id(), R2, R5, kNoPP); | |
| 721 | |
| 722 // Calculate the size tag. | |
| 723 // R0: new object. | |
| 724 // R1: number of context variables. | |
| 725 // R2: object size. | |
| 726 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | |
| 727 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP); | |
| 728 // If no size tag overflow, shift R2 left, else set R2 to zero. | |
| 729 __ Lsl(TMP, R2, shift); | |
| 730 __ LoadImmediate(TMP2, 0, kNoPP); | |
| 731 __ csel(R2, TMP, R2, LS); | |
| 732 __ csel(R2, TMP2, R2, HI); | |
|
regis
2014/04/29 23:09:21
ditto
zra
2014/04/29 23:18:19
Done. Thanks for spotting this.
| |
| 733 | |
| 734 // Get the class index and insert it into the tags. | |
| 735 // R2: size and bit tags. | |
| 736 __ LoadImmediate( | |
| 737 TMP, RawObject::ClassIdTag::encode(context_class.id()), kNoPP); | |
| 738 __ orr(R2, R2, Operand(TMP)); | |
| 739 __ StoreFieldToOffset(R2, R0, Context::tags_offset()); | |
| 740 | |
| 741 // Setup up number of context variables field. | |
| 742 // R0: new object. | |
| 743 // R1: number of context variables as integer value (not object). | |
| 744 __ StoreFieldToOffset(R1, R0, Context::num_variables_offset()); | |
| 745 | |
| 746 // Setup isolate field. | |
| 747 // Load Isolate pointer from Context structure into R2. | |
| 748 // R0: new object. | |
| 749 // R1: number of context variables. | |
| 750 __ LoadFieldFromOffset(R2, CTX, Context::isolate_offset()); | |
| 751 // R2: isolate, not an object. | |
| 752 __ StoreFieldToOffset(R2, R0, Context::isolate_offset()); | |
| 753 | |
| 754 // Setup the parent field. | |
| 755 // R0: new object. | |
| 756 // R1: number of context variables. | |
| 757 __ LoadObject(R2, Object::null_object(), PP); | |
| 758 __ StoreFieldToOffset(R2, R0, Context::parent_offset()); | |
| 759 | |
| 760 // Initialize the context variables. | |
| 761 // R0: new object. | |
| 762 // R1: number of context variables. | |
| 763 // R2: raw null. | |
| 764 Label loop, done; | |
| 765 __ AddImmediate( | |
| 766 R3, R0, Context::variable_offset(0) - kHeapObjectTag, kNoPP); | |
| 767 __ Bind(&loop); | |
| 768 __ subs(R1, R1, Operand(1)); | |
| 769 __ b(&done, MI); | |
| 770 __ str(R2, Address(R3, R1, UXTX, Address::Scaled)); | |
| 771 __ b(&loop, NE); // Loop if R1 not zero. | |
| 772 __ Bind(&done); | |
| 773 | |
| 774 // Done allocating and initializing the context. | |
| 775 // R0: new object. | |
| 776 __ ret(); | |
| 777 | |
| 778 __ Bind(&slow_case); | |
| 779 } | |
| 780 // Create a stub frame as we are pushing some objects on the stack before | |
| 781 // calling into the runtime. | |
| 782 __ EnterStubFrame(); | |
| 783 // Setup space on stack for return value. | |
| 784 __ LoadObject(R2, Object::null_object(), PP); | |
| 785 __ SmiTag(R1); | |
| 786 __ Push(R2); | |
| 787 __ Push(R1); | |
| 788 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. | |
| 789 __ Drop(1); // Pop number of context variables argument. | |
| 790 __ Pop(R0); // Pop the new context object. | |
| 791 // R0: new object | |
| 792 // Restore the frame pointer. | |
| 793 __ LeaveStubFrame(); | |
| 794 __ ret(); | |
| 540 } | 795 } |
| 541 | 796 |
| 542 | 797 |
| 543 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); | 798 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); |
| 544 | 799 |
| 545 // Helper stub to implement Assembler::StoreIntoObject. | 800 // Helper stub to implement Assembler::StoreIntoObject. |
| 546 // Input parameters: | 801 // Input parameters: |
| 547 // R0: Address being stored | 802 // R0: Address being stored |
| 548 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { | 803 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { |
| 549 Label add_to_buffer; | 804 Label add_to_buffer; |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 971 | 1226 |
| 972 | 1227 |
| 973 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1228 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
| 974 GenerateUsageCounterIncrement(assembler, R6); | 1229 GenerateUsageCounterIncrement(assembler, R6); |
| 975 GenerateNArgsCheckInlineCacheStub( | 1230 GenerateNArgsCheckInlineCacheStub( |
| 976 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); | 1231 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| 977 } | 1232 } |
| 978 | 1233 |
| 979 | 1234 |
| 980 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { | 1235 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { |
| 981 __ Stop("GenerateThreeArgsCheckInlineCacheStub"); | 1236 GenerateUsageCounterIncrement(assembler, R6); |
| 1237 GenerateNArgsCheckInlineCacheStub( | |
| 1238 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); | |
| 982 } | 1239 } |
| 983 | 1240 |
| 984 | 1241 |
| 985 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1242 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
| 986 Assembler* assembler) { | 1243 Assembler* assembler) { |
| 987 __ Stop("GenerateOneArgOptimizedCheckInlineCacheStub"); | 1244 __ Stop("GenerateOneArgOptimizedCheckInlineCacheStub"); |
| 988 } | 1245 } |
| 989 | 1246 |
| 990 | 1247 |
| 991 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( | 1248 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1249 | 1506 |
| 1250 | 1507 |
| 1251 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 1508 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
| 1252 Assembler* assembler) { | 1509 Assembler* assembler) { |
| 1253 __ Stop("GenerateOptimizedIdenticalWithNumberCheckStub"); | 1510 __ Stop("GenerateOptimizedIdenticalWithNumberCheckStub"); |
| 1254 } | 1511 } |
| 1255 | 1512 |
| 1256 } // namespace dart | 1513 } // namespace dart |
| 1257 | 1514 |
| 1258 #endif // defined TARGET_ARCH_ARM64 | 1515 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |