| 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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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(kSmiTagSize)); | 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. |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 | 601 |
| 602 // Restore C++ ABI callee-saved registers. | 602 // Restore C++ ABI callee-saved registers. |
| 603 __ PopList((1 << R3) | kAbiPreservedCpuRegs); // Ignore restored R3. | 603 __ PopList((1 << R3) | kAbiPreservedCpuRegs); // Ignore restored R3. |
| 604 | 604 |
| 605 // Restore the frame pointer and return. | 605 // Restore the frame pointer and return. |
| 606 __ LeaveStubFrame(); | 606 __ LeaveStubFrame(); |
| 607 __ Ret(); | 607 __ Ret(); |
| 608 } | 608 } |
| 609 | 609 |
| 610 | 610 |
| 611 // Called for inline allocation of contexts. |
| 612 // Input: |
| 613 // R1: number of context variables. |
| 614 // Output: |
| 615 // R0: new allocated RawContext object. |
| 611 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 616 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 612 __ Unimplemented("AllocateContext stub"); | 617 if (FLAG_inline_alloc) { |
| 618 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 619 Label slow_case; |
| 620 Heap* heap = Isolate::Current()->heap(); |
| 621 // First compute the rounded instance size. |
| 622 // R1: number of context variables. |
| 623 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; |
| 624 __ LoadImmediate(R2, fixed_size); |
| 625 __ add(R2, R2, ShifterOperand(R1, LSL, 2)); |
| 626 ASSERT(kSmiTagShift == 1); |
| 627 __ bic(R2, R2, ShifterOperand(kObjectAlignment - 1)); |
| 628 |
| 629 // Now allocate the object. |
| 630 // R1: number of context variables. |
| 631 // R2: object size. |
| 632 __ LoadImmediate(R5, heap->TopAddress()); |
| 633 __ ldr(R0, Address(R5, 0)); |
| 634 __ add(R3, R2, ShifterOperand(R0)); |
| 635 // Check if the allocation fits into the remaining space. |
| 636 // R0: potential new object. |
| 637 // R1: number of context variables. |
| 638 // R2: object size. |
| 639 // R3: potential next object start. |
| 640 __ LoadImmediate(IP, heap->EndAddress()); |
| 641 __ ldr(IP, Address(IP, 0)); |
| 642 __ cmp(R3, ShifterOperand(IP)); |
| 643 if (FLAG_use_slow_path) { |
| 644 __ b(&slow_case); |
| 645 } else { |
| 646 __ b(&slow_case, CS); // Branch if unsigned higher or equal. |
| 647 } |
| 648 |
| 649 // Successfully allocated the object, now update top to point to |
| 650 // next object start and initialize the object. |
| 651 // R0: new object. |
| 652 // R1: number of context variables. |
| 653 // R2: object size. |
| 654 // R3: next object start. |
| 655 __ str(R3, Address(R5, 0)); |
| 656 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); |
| 657 |
| 658 // Calculate the size tag. |
| 659 // R0: new object. |
| 660 // R1: number of context variables. |
| 661 // R2: object size. |
| 662 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; |
| 663 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); |
| 664 // If no size tag overflow, shift R2 left, else set R2 to zero. |
| 665 __ mov(R2, ShifterOperand(R2, LSL, shift), LS); |
| 666 __ mov(R2, ShifterOperand(0), HI); |
| 667 |
| 668 // Get the class index and insert it into the tags. |
| 669 // R2: size and bit tags. |
| 670 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(context_class.id())); |
| 671 __ orr(R2, R2, ShifterOperand(IP)); |
| 672 __ str(R2, FieldAddress(R0, Context::tags_offset())); |
| 673 |
| 674 // Setup up number of context variables field. |
| 675 // R0: new object. |
| 676 // R1: number of context variables as integer value (not object). |
| 677 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); |
| 678 |
| 679 // Setup isolate field. |
| 680 // Load Isolate pointer from Context structure into R2. |
| 681 // R0: new object. |
| 682 // R1: number of context variables. |
| 683 __ ldr(R2, FieldAddress(CTX, Context::isolate_offset())); |
| 684 // R2: Isolate, not an object. |
| 685 __ str(R2, FieldAddress(R0, Context::isolate_offset())); |
| 686 |
| 687 // Setup the parent field. |
| 688 // R0: new object. |
| 689 // R1: number of context variables. |
| 690 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); |
| 691 __ str(R2, FieldAddress(R0, Context::parent_offset())); |
| 692 |
| 693 // Initialize the context variables. |
| 694 // R0: new object. |
| 695 // R1: number of context variables. |
| 696 // R2: raw null. |
| 697 Label loop; |
| 698 __ AddImmediate(R3, R0, Context::variable_offset(0) - kHeapObjectTag); |
| 699 __ Bind(&loop); |
| 700 __ subs(R1, R1, ShifterOperand(1)); |
| 701 __ str(R2, Address(R3, R1, LSL, 2), PL); // Store if R1 positive or zero. |
| 702 __ b(&loop, NE); // Loop if R1 not zero. |
| 703 |
| 704 // Done allocating and initializing the context. |
| 705 // R0: new object. |
| 706 __ Ret(); |
| 707 |
| 708 __ Bind(&slow_case); |
| 709 } |
| 710 // Create a stub frame as we are pushing some objects on the stack before |
| 711 // calling into the runtime. |
| 712 __ EnterStubFrame(); |
| 713 // Setup space on stack for return value. |
| 714 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); |
| 715 __ SmiTag(R1); |
| 716 __ PushList((1 << R1) | (1 << R2)); |
| 717 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context. |
| 718 __ Drop(1); // Pop number of context variables argument. |
| 719 __ Pop(R0); // Pop the new context object. |
| 720 // R0: new object |
| 721 // Restore the frame pointer. |
| 722 __ LeaveStubFrame(); |
| 723 __ Ret(); |
| 613 } | 724 } |
| 614 | 725 |
| 615 | 726 |
| 616 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); | 727 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); |
| 617 | 728 |
| 618 // Helper stub to implement Assembler::StoreIntoObject. | 729 // Helper stub to implement Assembler::StoreIntoObject. |
| 619 // Input parameters: | 730 // Input parameters: |
| 620 // R0: Address (i.e. object) being stored into. | 731 // R0: Address (i.e. object) being stored into. |
| 621 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { | 732 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { |
| 622 // Save values being destroyed. | 733 // Save values being destroyed. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 // the instantiator is provided (not kNoInstantiator, but may be null). | 804 // the instantiator is provided (not kNoInstantiator, but may be null). |
| 694 __ CompareImmediate(R0, Smi::RawValue(StubCode::kNoInstantiator)); | 805 __ CompareImmediate(R0, Smi::RawValue(StubCode::kNoInstantiator)); |
| 695 __ AddImmediate(R3, type_args_size, NE); | 806 __ AddImmediate(R3, type_args_size, NE); |
| 696 // R4: potential new object end and, if R4 != R3, potential new | 807 // R4: potential new object end and, if R4 != R3, potential new |
| 697 // InstantiatedTypeArguments object start. | 808 // InstantiatedTypeArguments object start. |
| 698 } | 809 } |
| 699 // Check if the allocation fits into the remaining space. | 810 // Check if the allocation fits into the remaining space. |
| 700 // R2: potential new object start. | 811 // R2: potential new object start. |
| 701 // R3: potential next object start. | 812 // R3: potential next object start. |
| 702 __ LoadImmediate(IP, heap->EndAddress()); | 813 __ LoadImmediate(IP, heap->EndAddress()); |
| 814 __ ldr(IP, Address(IP, 0)); |
| 703 __ cmp(R3, ShifterOperand(IP)); | 815 __ cmp(R3, ShifterOperand(IP)); |
| 704 if (FLAG_use_slow_path) { | 816 if (FLAG_use_slow_path) { |
| 705 __ b(&slow_case); | 817 __ b(&slow_case); |
| 706 } else { | 818 } else { |
| 707 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | 819 __ b(&slow_case, CS); // Branch if unsigned higher or equal. |
| 708 } | 820 } |
| 709 | 821 |
| 710 // Successfully allocated the object(s), now update top to point to | 822 // Successfully allocated the object(s), now update top to point to |
| 711 // next object start and initialize the object. | 823 // next object start and initialize the object. |
| 712 __ str(R3, Address(R5, 0)); | 824 __ str(R3, Address(R5, 0)); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 __ AddImmediate(R3, R2, closure_size); | 969 __ AddImmediate(R3, R2, closure_size); |
| 858 if (is_implicit_instance_closure) { | 970 if (is_implicit_instance_closure) { |
| 859 __ mov(R4, ShifterOperand(R3)); // R4: new context address. | 971 __ mov(R4, ShifterOperand(R3)); // R4: new context address. |
| 860 __ AddImmediate(R3, context_size); | 972 __ AddImmediate(R3, context_size); |
| 861 } | 973 } |
| 862 // Check if the allocation fits into the remaining space. | 974 // Check if the allocation fits into the remaining space. |
| 863 // R2: potential new closure object. | 975 // R2: potential new closure object. |
| 864 // R3: potential next object start. | 976 // R3: potential next object start. |
| 865 // R4: potential new context object (only if is_implicit_closure). | 977 // R4: potential new context object (only if is_implicit_closure). |
| 866 __ LoadImmediate(IP, heap->EndAddress()); | 978 __ LoadImmediate(IP, heap->EndAddress()); |
| 979 __ ldr(IP, Address(IP, 0)); |
| 867 __ cmp(R3, ShifterOperand(IP)); | 980 __ cmp(R3, ShifterOperand(IP)); |
| 868 if (FLAG_use_slow_path) { | 981 if (FLAG_use_slow_path) { |
| 869 __ b(&slow_case); | 982 __ b(&slow_case); |
| 870 } else { | 983 } else { |
| 871 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | 984 __ b(&slow_case, CS); // Branch if unsigned higher or equal. |
| 872 } | 985 } |
| 873 | 986 |
| 874 // Successfully allocated the object, now update top to point to | 987 // Successfully allocated the object, now update top to point to |
| 875 // next object start and initialize the object. | 988 // next object start and initialize the object. |
| 876 __ str(R3, Address(R5, 0)); | 989 __ str(R3, Address(R5, 0)); |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1484 __ Bind(&reference_compare); | 1597 __ Bind(&reference_compare); |
| 1485 __ cmp(left, ShifterOperand(right)); | 1598 __ cmp(left, ShifterOperand(right)); |
| 1486 __ Bind(&done); | 1599 __ Bind(&done); |
| 1487 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); | 1600 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); |
| 1488 __ Ret(); | 1601 __ Ret(); |
| 1489 } | 1602 } |
| 1490 | 1603 |
| 1491 } // namespace dart | 1604 } // namespace dart |
| 1492 | 1605 |
| 1493 #endif // defined TARGET_ARCH_ARM | 1606 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |