| OLD | NEW |
| 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 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 __ ldr(R2, FieldAddress(R0, Function::code_offset())); | 589 __ ldr(R2, FieldAddress(R0, Function::code_offset())); |
| 590 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); | 590 __ ldr(R2, FieldAddress(R2, Code::instructions_offset())); |
| 591 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | 591 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 592 __ bx(R2); | 592 __ bx(R2); |
| 593 } | 593 } |
| 594 | 594 |
| 595 | 595 |
| 596 // Called for inline allocation of arrays. | 596 // Called for inline allocation of arrays. |
| 597 // Input parameters: | 597 // Input parameters: |
| 598 // LR: return address. | 598 // LR: return address. |
| 599 // R2: array length as Smi. | |
| 600 // R1: array element type (either NULL or an instantiated type). | 599 // R1: array element type (either NULL or an instantiated type). |
| 601 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved. | 600 // R2: array length as Smi (must be preserved). |
| 602 // The newly allocated object is returned in R0. | 601 // The newly allocated object is returned in R0. |
| 603 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 602 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 604 Label slow_case; | 603 Label slow_case; |
| 605 if (FLAG_inline_alloc) { | |
| 606 // Compute the size to be allocated, it is based on the array length | |
| 607 // and is computed as: | |
| 608 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | |
| 609 // Assert that length is a Smi. | |
| 610 __ tst(R2, ShifterOperand(kSmiTagMask)); | |
| 611 if (FLAG_use_slow_path) { | |
| 612 __ b(&slow_case); | |
| 613 } else { | |
| 614 __ b(&slow_case, NE); | |
| 615 } | |
| 616 __ cmp(R2, ShifterOperand(0)); | |
| 617 __ b(&slow_case, LT); | |
| 618 | 604 |
| 619 // Check for maximum allowed length. | 605 // Compute the size to be allocated, it is based on the array length |
| 620 const intptr_t max_len = | 606 // and is computed as: |
| 621 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); | 607 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 622 __ CompareImmediate(R2, max_len); | 608 __ MoveRegister(R3, R2); // Array length. |
| 623 __ b(&slow_case, GT); | |
| 624 | 609 |
| 625 __ ldr(R8, FieldAddress(CTX, Context::isolate_offset())); | 610 // Check that length is a positive Smi. |
| 626 __ LoadFromOffset(kWord, R8, R8, Isolate::heap_offset()); | 611 __ tst(R3, ShifterOperand(kSmiTagMask)); |
| 627 __ LoadFromOffset(kWord, R8, R8, Heap::new_space_offset()); | 612 __ b(&slow_case, NE); |
| 613 __ cmp(R3, ShifterOperand(0)); |
| 614 __ b(&slow_case, LT); |
| 628 | 615 |
| 629 // Calculate and align allocation size. | 616 // Check for maximum allowed length. |
| 630 // Load new object start and calculate next object start. | 617 const intptr_t max_len = |
| 631 // R1: array element type. | 618 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); |
| 632 // R2: array length as Smi. | 619 __ CompareImmediate(R3, max_len); |
| 633 // R8: points to new space object. | 620 __ b(&slow_case, GT); |
| 634 __ LoadFromOffset(kWord, R0, R8, Scavenger::top_offset()); | |
| 635 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | |
| 636 __ LoadImmediate(R3, fixed_size); | |
| 637 __ add(R3, R3, ShifterOperand(R2, LSL, 1)); // R2 is Smi. | |
| 638 ASSERT(kSmiTagShift == 1); | |
| 639 __ bic(R3, R3, ShifterOperand(kObjectAlignment - 1)); | |
| 640 __ adds(R7, R3, ShifterOperand(R0)); | |
| 641 __ b(&slow_case, VS); | |
| 642 | 621 |
| 643 // Check if the allocation fits into the remaining space. | 622 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 644 // R0: potential new object start. | 623 __ LoadImmediate(R8, fixed_size); |
| 645 // R1: array element type. | 624 __ add(R8, R8, ShifterOperand(R3, LSL, 1)); // R3 is a Smi. |
| 646 // R2: array length as Smi. | 625 ASSERT(kSmiTagShift == 1); |
| 647 // R3: array size. | 626 __ bic(R8, R8, ShifterOperand(kObjectAlignment - 1)); |
| 648 // R7: potential next object start. | |
| 649 // R8: points to new space object. | |
| 650 __ LoadFromOffset(kWord, IP, R8, Scavenger::end_offset()); | |
| 651 __ cmp(R7, ShifterOperand(IP)); | |
| 652 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | |
| 653 | 627 |
| 654 // Successfully allocated the object(s), now update top to point to | 628 // R8: Allocation size. |
| 655 // next object start and initialize the object. | |
| 656 // R0: potential new object start. | |
| 657 // R3: array size. | |
| 658 // R7: potential next object start. | |
| 659 // R8: Points to new space object. | |
| 660 __ StoreToOffset(kWord, R7, R8, Scavenger::top_offset()); | |
| 661 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); | |
| 662 __ UpdateAllocationStatsWithSize(kArrayCid, R3, R8); | |
| 663 | 629 |
| 664 // R0: new object start as a tagged pointer. | 630 Isolate* isolate = Isolate::Current(); |
| 665 // R1: array element type. | 631 Heap* heap = isolate->heap(); |
| 666 // R2: array length as Smi. | |
| 667 // R3: array size. | |
| 668 // R7: new object end address. | |
| 669 | 632 |
| 670 // Store the type argument field. | 633 __ LoadImmediate(R6, heap->TopAddress()); |
| 671 __ StoreIntoObjectNoBarrier( | 634 __ ldr(R0, Address(R6, 0)); // Potential new object start. |
| 672 R0, | 635 __ adds(R7, R0, ShifterOperand(R8)); // Potential next object start. |
| 673 FieldAddress(R0, Array::type_arguments_offset()), | 636 __ b(&slow_case, VS); |
| 674 R1); | |
| 675 | 637 |
| 676 // Set the length field. | 638 // Check if the allocation fits into the remaining space. |
| 677 __ StoreIntoObjectNoBarrier( | 639 // R0: potential new object start. |
| 678 R0, | 640 // R7: potential next object start. |
| 679 FieldAddress(R0, Array::length_offset()), | 641 // R8: allocation size. |
| 680 R2); | 642 __ LoadImmediate(R3, heap->EndAddress()); |
| 643 __ ldr(R3, Address(R3, 0)); |
| 644 __ cmp(R7, ShifterOperand(R3)); |
| 645 __ b(&slow_case, CS); |
| 681 | 646 |
| 682 // Calculate the size tag. | 647 // Successfully allocated the object(s), now update top to point to |
| 683 // R0: new object start as a tagged pointer. | 648 // next object start and initialize the object. |
| 684 // R2: array length as Smi. | 649 __ str(R7, Address(R6, 0)); |
| 685 // R3: array size. | 650 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); |
| 686 // R7: new object end address. | 651 __ UpdateAllocationStatsWithSize(kArrayCid, R8, R4); |
| 652 |
| 653 // Initialize the tags. |
| 654 // R0: new object start as a tagged pointer. |
| 655 // R7: new object end address. |
| 656 // R8: allocation size. |
| 657 { |
| 687 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 658 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 688 __ CompareImmediate(R3, RawObject::SizeTag::kMaxSizeTag); | 659 const Class& cls = Class::Handle(isolate->object_store()->array_class()); |
| 689 // If no size tag overflow, shift R1 left, else set R1 to zero. | 660 |
| 690 __ mov(R1, ShifterOperand(R3, LSL, shift), LS); | 661 __ CompareImmediate(R8, RawObject::SizeTag::kMaxSizeTag); |
| 691 __ mov(R1, ShifterOperand(0), HI); | 662 __ mov(R8, ShifterOperand(R8, LSL, shift), LS); |
| 663 __ mov(R8, ShifterOperand(0), HI); |
| 692 | 664 |
| 693 // Get the class index and insert it into the tags. | 665 // Get the class index and insert it into the tags. |
| 694 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(kArrayCid)); | 666 // R8: size and bit tags. |
| 695 __ orr(R1, R1, ShifterOperand(IP)); | 667 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id())); |
| 696 __ str(R1, FieldAddress(R0, Array::tags_offset())); | 668 __ orr(R8, R8, ShifterOperand(TMP)); |
| 697 | 669 __ str(R8, FieldAddress(R0, Array::tags_offset())); // Store tags. |
| 698 // Initialize all array elements to raw_null. | |
| 699 // R0: new object start as a tagged pointer. | |
| 700 // R7: new object end address. | |
| 701 // R2: array length as Smi. | |
| 702 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag); | |
| 703 // R1: iterator which initially points to the start of the variable | |
| 704 // data area to be initialized. | |
| 705 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | |
| 706 Label loop; | |
| 707 __ Bind(&loop); | |
| 708 // TODO(cshapiro): StoreIntoObjectNoBarrier | |
| 709 __ cmp(R1, ShifterOperand(R7)); | |
| 710 __ str(IP, Address(R1, 0), CC); // Store if unsigned lower. | |
| 711 __ AddImmediate(R1, kWordSize, CC); | |
| 712 __ b(&loop, CC); // Loop until R1 == R7. | |
| 713 | |
| 714 // Done allocating and initializing the array. | |
| 715 // R0: new object. | |
| 716 // R2: array length as Smi (preserved for the caller.) | |
| 717 __ Ret(); | |
| 718 } | 670 } |
| 719 | 671 |
| 672 // R0: new object start as a tagged pointer. |
| 673 // R7: new object end address. |
| 674 // Store the type argument field. |
| 675 __ StoreIntoObjectNoBarrier(R0, |
| 676 FieldAddress(R0, Array::type_arguments_offset()), |
| 677 R1); |
| 678 |
| 679 // Set the length field. |
| 680 __ StoreIntoObjectNoBarrier(R0, |
| 681 FieldAddress(R0, Array::length_offset()), |
| 682 R2); |
| 683 |
| 684 // Initialize all array elements to raw_null. |
| 685 // R0: new object start as a tagged pointer. |
| 686 // R7: new object end address. |
| 687 // R8: iterator which initially points to the start of the variable |
| 688 // data area to be initialized. |
| 689 // R3: null |
| 690 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); |
| 691 __ AddImmediate(R8, R0, sizeof(RawArray) - kHeapObjectTag); |
| 692 |
| 693 Label init_loop; |
| 694 __ Bind(&init_loop); |
| 695 __ cmp(R8, ShifterOperand(R7)); |
| 696 __ str(R3, Address(R8, 0), CC); |
| 697 __ AddImmediate(R8, kWordSize, CC); |
| 698 __ b(&init_loop, CC); |
| 699 |
| 700 __ Ret(); // Returns the newly allocated object in R0. |
| 720 // Unable to allocate the array using the fast inline code, just call | 701 // Unable to allocate the array using the fast inline code, just call |
| 721 // into the runtime. | 702 // into the runtime. |
| 722 __ Bind(&slow_case); | 703 __ Bind(&slow_case); |
| 704 |
| 723 // Create a stub frame as we are pushing some objects on the stack before | 705 // Create a stub frame as we are pushing some objects on the stack before |
| 724 // calling into the runtime. | 706 // calling into the runtime. |
| 725 __ EnterStubFrame(); | 707 __ EnterStubFrame(); |
| 726 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | 708 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 727 // Setup space on stack for return value. | 709 // Setup space on stack for return value. |
| 728 // Push array length as Smi and element type. | 710 // Push array length as Smi and element type. |
| 729 __ PushList((1 << R1) | (1 << R2) | (1 << IP)); | 711 __ PushList((1 << R1) | (1 << R2) | (1 << IP)); |
| 730 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); | 712 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); |
| 731 // Pop arguments; result is popped in IP. | 713 // Pop arguments; result is popped in IP. |
| 732 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored. | 714 __ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored. |
| (...skipping 1123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1856 const Register right = R0; | 1838 const Register right = R0; |
| 1857 __ ldr(left, Address(SP, 1 * kWordSize)); | 1839 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 1858 __ ldr(right, Address(SP, 0 * kWordSize)); | 1840 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 1859 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1841 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 1860 __ Ret(); | 1842 __ Ret(); |
| 1861 } | 1843 } |
| 1862 | 1844 |
| 1863 } // namespace dart | 1845 } // namespace dart |
| 1864 | 1846 |
| 1865 #endif // defined TARGET_ARCH_ARM | 1847 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |