| 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 29 matching lines...) Expand all Loading... |
| 40 const intptr_t argv_offset = NativeArguments::argv_offset(); | 40 const intptr_t argv_offset = NativeArguments::argv_offset(); |
| 41 const intptr_t retval_offset = NativeArguments::retval_offset(); | 41 const intptr_t retval_offset = NativeArguments::retval_offset(); |
| 42 | 42 |
| 43 __ EnterFrame((1 << FP) | (1 << LR), 0); | 43 __ EnterFrame((1 << FP) | (1 << LR), 0); |
| 44 | 44 |
| 45 // Load current Isolate pointer from Context structure into R0. | 45 // Load current Isolate pointer from Context structure into R0. |
| 46 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); | 46 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); |
| 47 | 47 |
| 48 // Save exit frame information to enable stack walking as we are about | 48 // Save exit frame information to enable stack walking as we are about |
| 49 // to transition to Dart VM C++ code. | 49 // to transition to Dart VM C++ code. |
| 50 __ StoreToOffset(kStoreWord, SP, R0, Isolate::top_exit_frame_info_offset()); | 50 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset()); |
| 51 | 51 |
| 52 // Save current Context pointer into Isolate structure. | 52 // Save current Context pointer into Isolate structure. |
| 53 __ StoreToOffset(kStoreWord, CTX, R0, Isolate::top_context_offset()); | 53 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset()); |
| 54 | 54 |
| 55 // Cache Isolate pointer into CTX while executing runtime code. | 55 // Cache Isolate pointer into CTX while executing runtime code. |
| 56 __ mov(CTX, ShifterOperand(R0)); | 56 __ mov(CTX, ShifterOperand(R0)); |
| 57 | 57 |
| 58 // Reserve space for arguments and align frame before entering C++ world. | 58 // Reserve space for arguments and align frame before entering C++ world. |
| 59 // NativeArguments are passed in registers. | 59 // NativeArguments are passed in registers. |
| 60 ASSERT(sizeof(NativeArguments) == 4 * kWordSize); | 60 ASSERT(sizeof(NativeArguments) == 4 * kWordSize); |
| 61 __ ReserveAlignedFrameSpace(0); | 61 __ ReserveAlignedFrameSpace(0); |
| 62 | 62 |
| 63 // Pass NativeArguments structure by value and call runtime. | 63 // Pass NativeArguments structure by value and call runtime. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 76 __ AddImmediate(R2, kWordSize); // Set argv in NativeArguments. | 76 __ AddImmediate(R2, kWordSize); // Set argv in NativeArguments. |
| 77 | 77 |
| 78 ASSERT(retval_offset == 3 * kWordSize); | 78 ASSERT(retval_offset == 3 * kWordSize); |
| 79 __ add(R3, R2, ShifterOperand(kWordSize)); // Retval is next to 1st argument. | 79 __ add(R3, R2, ShifterOperand(kWordSize)); // Retval is next to 1st argument. |
| 80 | 80 |
| 81 // Call runtime or redirection via simulator. | 81 // Call runtime or redirection via simulator. |
| 82 __ blx(R5); | 82 __ blx(R5); |
| 83 | 83 |
| 84 // Reset exit frame information in Isolate structure. | 84 // Reset exit frame information in Isolate structure. |
| 85 __ LoadImmediate(R2, 0); | 85 __ LoadImmediate(R2, 0); |
| 86 __ StoreToOffset(kStoreWord, R2, CTX, Isolate::top_exit_frame_info_offset()); | 86 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset()); |
| 87 | 87 |
| 88 // Load Context pointer from Isolate structure into R2. | 88 // Load Context pointer from Isolate structure into R2. |
| 89 __ LoadFromOffset(kLoadWord, R2, CTX, Isolate::top_context_offset()); | 89 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset()); |
| 90 | 90 |
| 91 // Reset Context pointer in Isolate structure. | 91 // Reset Context pointer in Isolate structure. |
| 92 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); | 92 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); |
| 93 __ StoreToOffset(kStoreWord, R3, CTX, Isolate::top_context_offset()); | 93 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset()); |
| 94 | 94 |
| 95 // Cache Context pointer into CTX while executing Dart code. | 95 // Cache Context pointer into CTX while executing Dart code. |
| 96 __ mov(CTX, ShifterOperand(R2)); | 96 __ mov(CTX, ShifterOperand(R2)); |
| 97 | 97 |
| 98 __ LeaveFrame((1 << FP) | (1 << LR)); | 98 __ LeaveFrame((1 << FP) | (1 << LR)); |
| 99 __ Ret(); | 99 __ Ret(); |
| 100 } | 100 } |
| 101 | 101 |
| 102 | 102 |
| 103 // Print the stop message. | 103 // Print the stop message. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 131 const intptr_t argv_offset = NativeArguments::argv_offset(); | 131 const intptr_t argv_offset = NativeArguments::argv_offset(); |
| 132 const intptr_t retval_offset = NativeArguments::retval_offset(); | 132 const intptr_t retval_offset = NativeArguments::retval_offset(); |
| 133 | 133 |
| 134 __ EnterFrame((1 << FP) | (1 << LR), 0); | 134 __ EnterFrame((1 << FP) | (1 << LR), 0); |
| 135 | 135 |
| 136 // Load current Isolate pointer from Context structure into R0. | 136 // Load current Isolate pointer from Context structure into R0. |
| 137 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); | 137 __ ldr(R0, FieldAddress(CTX, Context::isolate_offset())); |
| 138 | 138 |
| 139 // Save exit frame information to enable stack walking as we are about | 139 // Save exit frame information to enable stack walking as we are about |
| 140 // to transition to native code. | 140 // to transition to native code. |
| 141 __ StoreToOffset(kStoreWord, SP, R0, Isolate::top_exit_frame_info_offset()); | 141 __ StoreToOffset(kWord, SP, R0, Isolate::top_exit_frame_info_offset()); |
| 142 | 142 |
| 143 // Save current Context pointer into Isolate structure. | 143 // Save current Context pointer into Isolate structure. |
| 144 __ StoreToOffset(kStoreWord, CTX, R0, Isolate::top_context_offset()); | 144 __ StoreToOffset(kWord, CTX, R0, Isolate::top_context_offset()); |
| 145 | 145 |
| 146 // Cache Isolate pointer into CTX while executing native code. | 146 // Cache Isolate pointer into CTX while executing native code. |
| 147 __ mov(CTX, ShifterOperand(R0)); | 147 __ mov(CTX, ShifterOperand(R0)); |
| 148 | 148 |
| 149 // Reserve space for the native arguments structure passed on the stack (the | 149 // Reserve space for the native arguments structure passed on the stack (the |
| 150 // outgoing pointer parameter to the native arguments structure is passed in | 150 // outgoing pointer parameter to the native arguments structure is passed in |
| 151 // R0) and align frame before entering the C++ world. | 151 // R0) and align frame before entering the C++ world. |
| 152 __ ReserveAlignedFrameSpace(sizeof(NativeArguments)); | 152 __ ReserveAlignedFrameSpace(sizeof(NativeArguments)); |
| 153 | 153 |
| 154 // Initialize NativeArguments structure and call native function. | 154 // Initialize NativeArguments structure and call native function. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 172 // It would require changing Dart API for native functions. | 172 // It would require changing Dart API for native functions. |
| 173 // For now, space is reserved on the stack and we pass a pointer to it. | 173 // For now, space is reserved on the stack and we pass a pointer to it. |
| 174 __ stm(IA, SP, (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3)); | 174 __ stm(IA, SP, (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3)); |
| 175 __ mov(R0, ShifterOperand(SP)); // Pass the pointer to the NativeArguments. | 175 __ mov(R0, ShifterOperand(SP)); // Pass the pointer to the NativeArguments. |
| 176 | 176 |
| 177 // Call native function or redirection via simulator. | 177 // Call native function or redirection via simulator. |
| 178 __ blx(R5); | 178 __ blx(R5); |
| 179 | 179 |
| 180 // Reset exit frame information in Isolate structure. | 180 // Reset exit frame information in Isolate structure. |
| 181 __ LoadImmediate(R2, 0); | 181 __ LoadImmediate(R2, 0); |
| 182 __ StoreToOffset(kStoreWord, R2, CTX, Isolate::top_exit_frame_info_offset()); | 182 __ StoreToOffset(kWord, R2, CTX, Isolate::top_exit_frame_info_offset()); |
| 183 | 183 |
| 184 // Load Context pointer from Isolate structure into R2. | 184 // Load Context pointer from Isolate structure into R2. |
| 185 __ LoadFromOffset(kLoadWord, R2, CTX, Isolate::top_context_offset()); | 185 __ LoadFromOffset(kWord, R2, CTX, Isolate::top_context_offset()); |
| 186 | 186 |
| 187 // Reset Context pointer in Isolate structure. | 187 // Reset Context pointer in Isolate structure. |
| 188 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); | 188 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); |
| 189 __ StoreToOffset(kStoreWord, R3, CTX, Isolate::top_context_offset()); | 189 __ StoreToOffset(kWord, R3, CTX, Isolate::top_context_offset()); |
| 190 | 190 |
| 191 // Cache Context pointer into CTX while executing Dart code. | 191 // Cache Context pointer into CTX while executing Dart code. |
| 192 __ mov(CTX, ShifterOperand(R2)); | 192 __ mov(CTX, ShifterOperand(R2)); |
| 193 | 193 |
| 194 __ LeaveFrame((1 << FP) | (1 << LR)); | 194 __ LeaveFrame((1 << FP) | (1 << LR)); |
| 195 __ Ret(); | 195 __ Ret(); |
| 196 } | 196 } |
| 197 | 197 |
| 198 | 198 |
| 199 // Input parameters: | 199 // Input parameters: |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 // and is computed as: | 468 // and is computed as: |
| 469 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 469 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 470 // Assert that length is a Smi. | 470 // Assert that length is a Smi. |
| 471 __ tst(R2, ShifterOperand(kSmiTagMask)); | 471 __ tst(R2, ShifterOperand(kSmiTagMask)); |
| 472 if (FLAG_use_slow_path) { | 472 if (FLAG_use_slow_path) { |
| 473 __ b(&slow_case); | 473 __ b(&slow_case); |
| 474 } else { | 474 } else { |
| 475 __ b(&slow_case, NE); | 475 __ b(&slow_case, NE); |
| 476 } | 476 } |
| 477 __ ldr(R8, FieldAddress(CTX, Context::isolate_offset())); | 477 __ ldr(R8, FieldAddress(CTX, Context::isolate_offset())); |
| 478 __ LoadFromOffset(kLoadWord, R8, R8, Isolate::heap_offset()); | 478 __ LoadFromOffset(kWord, R8, R8, Isolate::heap_offset()); |
| 479 __ LoadFromOffset(kLoadWord, R8, R8, Heap::new_space_offset()); | 479 __ LoadFromOffset(kWord, R8, R8, Heap::new_space_offset()); |
| 480 | 480 |
| 481 // Calculate and align allocation size. | 481 // Calculate and align allocation size. |
| 482 // Load new object start and calculate next object start. | 482 // Load new object start and calculate next object start. |
| 483 // R1: array element type. | 483 // R1: array element type. |
| 484 // R2: array length as Smi. | 484 // R2: array length as Smi. |
| 485 // R8: points to new space object. | 485 // R8: points to new space object. |
| 486 __ LoadFromOffset(kLoadWord, R0, R8, Scavenger::top_offset()); | 486 __ LoadFromOffset(kWord, R0, R8, Scavenger::top_offset()); |
| 487 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 487 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 488 __ LoadImmediate(R3, fixed_size); | 488 __ LoadImmediate(R3, fixed_size); |
| 489 __ add(R3, R3, ShifterOperand(R2, LSL, 1)); // R2 is Smi. | 489 __ add(R3, R3, ShifterOperand(R2, LSL, 1)); // R2 is Smi. |
| 490 ASSERT(kSmiTagShift == 1); | 490 ASSERT(kSmiTagShift == 1); |
| 491 __ bic(R3, R3, ShifterOperand(kObjectAlignment - 1)); | 491 __ bic(R3, R3, ShifterOperand(kObjectAlignment - 1)); |
| 492 __ add(R7, R3, ShifterOperand(R0)); | 492 __ add(R7, R3, ShifterOperand(R0)); |
| 493 | 493 |
| 494 // Check if the allocation fits into the remaining space. | 494 // Check if the allocation fits into the remaining space. |
| 495 // R0: potential new object start. | 495 // R0: potential new object start. |
| 496 // R1: array element type. | 496 // R1: array element type. |
| 497 // R2: array length as Smi. | 497 // R2: array length as Smi. |
| 498 // R3: array size. | 498 // R3: array size. |
| 499 // R7: potential next object start. | 499 // R7: potential next object start. |
| 500 // R8: points to new space object. | 500 // R8: points to new space object. |
| 501 __ LoadFromOffset(kLoadWord, IP, R8, Scavenger::end_offset()); | 501 __ LoadFromOffset(kWord, IP, R8, Scavenger::end_offset()); |
| 502 __ cmp(R7, ShifterOperand(IP)); | 502 __ cmp(R7, ShifterOperand(IP)); |
| 503 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | 503 __ b(&slow_case, CS); // Branch if unsigned higher or equal. |
| 504 | 504 |
| 505 // Successfully allocated the object(s), now update top to point to | 505 // Successfully allocated the object(s), now update top to point to |
| 506 // next object start and initialize the object. | 506 // next object start and initialize the object. |
| 507 // R0: potential new object start. | 507 // R0: potential new object start. |
| 508 // R7: potential next object start. | 508 // R7: potential next object start. |
| 509 // R8: Points to new space object. | 509 // R8: Points to new space object. |
| 510 __ StoreToOffset(kStoreWord, R7, R8, Scavenger::top_offset()); | 510 __ StoreToOffset(kWord, R7, R8, Scavenger::top_offset()); |
| 511 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); | 511 __ add(R0, R0, ShifterOperand(kHeapObjectTag)); |
| 512 | 512 |
| 513 // R0: new object start as a tagged pointer. | 513 // R0: new object start as a tagged pointer. |
| 514 // R1: array element type. | 514 // R1: array element type. |
| 515 // R2: array length as Smi. | 515 // R2: array length as Smi. |
| 516 // R3: array size. | 516 // R3: array size. |
| 517 // R7: new object end address. | 517 // R7: new object end address. |
| 518 | 518 |
| 519 // Store the type argument field. | 519 // Store the type argument field. |
| 520 __ StoreIntoObjectNoBarrier( | 520 __ StoreIntoObjectNoBarrier( |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 // compiled or runtime stub code. | 702 // compiled or runtime stub code. |
| 703 | 703 |
| 704 // Cache the new Context pointer into CTX while executing Dart code. | 704 // Cache the new Context pointer into CTX while executing Dart code. |
| 705 __ ldr(CTX, Address(R3, VMHandles::kOffsetOfRawPtrInHandle)); | 705 __ ldr(CTX, Address(R3, VMHandles::kOffsetOfRawPtrInHandle)); |
| 706 | 706 |
| 707 // Load Isolate pointer from Context structure into temporary register R8. | 707 // Load Isolate pointer from Context structure into temporary register R8. |
| 708 __ ldr(R8, FieldAddress(CTX, Context::isolate_offset())); | 708 __ ldr(R8, FieldAddress(CTX, Context::isolate_offset())); |
| 709 | 709 |
| 710 // Save the top exit frame info. Use R5 as a temporary register. | 710 // Save the top exit frame info. Use R5 as a temporary register. |
| 711 // StackFrameIterator reads the top exit frame info saved in this frame. | 711 // StackFrameIterator reads the top exit frame info saved in this frame. |
| 712 __ LoadFromOffset(kLoadWord, R5, R8, Isolate::top_exit_frame_info_offset()); | 712 __ LoadFromOffset(kWord, R5, R8, Isolate::top_exit_frame_info_offset()); |
| 713 __ LoadImmediate(R6, 0); | 713 __ LoadImmediate(R6, 0); |
| 714 __ StoreToOffset(kStoreWord, R6, R8, Isolate::top_exit_frame_info_offset()); | 714 __ StoreToOffset(kWord, R6, R8, Isolate::top_exit_frame_info_offset()); |
| 715 | 715 |
| 716 // Save the old Context pointer. Use R4 as a temporary register. | 716 // Save the old Context pointer. Use R4 as a temporary register. |
| 717 // Note that VisitObjectPointers will find this saved Context pointer during | 717 // Note that VisitObjectPointers will find this saved Context pointer during |
| 718 // GC marking, since it traverses any information between SP and | 718 // GC marking, since it traverses any information between SP and |
| 719 // FP - kExitLinkSlotFromEntryFp. | 719 // FP - kExitLinkSlotFromEntryFp. |
| 720 // EntryFrame::SavedContext reads the context saved in this frame. | 720 // EntryFrame::SavedContext reads the context saved in this frame. |
| 721 __ LoadFromOffset(kLoadWord, R4, R8, Isolate::top_context_offset()); | 721 __ LoadFromOffset(kWord, R4, R8, Isolate::top_context_offset()); |
| 722 | 722 |
| 723 // The constants kSavedContextSlotFromEntryFp and | 723 // The constants kSavedContextSlotFromEntryFp and |
| 724 // kExitLinkSlotFromEntryFp must be kept in sync with the code below. | 724 // kExitLinkSlotFromEntryFp must be kept in sync with the code below. |
| 725 ASSERT(kExitLinkSlotFromEntryFp == -9); | 725 ASSERT(kExitLinkSlotFromEntryFp == -9); |
| 726 ASSERT(kSavedContextSlotFromEntryFp == -10); | 726 ASSERT(kSavedContextSlotFromEntryFp == -10); |
| 727 __ PushList((1 << R4) | (1 << R5)); | 727 __ PushList((1 << R4) | (1 << R5)); |
| 728 | 728 |
| 729 // The stack pointer is restored after the call to this location. | 729 // The stack pointer is restored after the call to this location. |
| 730 const intptr_t kSavedContextSlotFromEntryFp = -10 * kWordSize; | 730 const intptr_t kSavedContextSlotFromEntryFp = -10 * kWordSize; |
| 731 | 731 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 __ AddImmediate(SP, FP, kSavedContextSlotFromEntryFp); | 766 __ AddImmediate(SP, FP, kSavedContextSlotFromEntryFp); |
| 767 | 767 |
| 768 // Load Isolate pointer from Context structure into CTX. Drop Context. | 768 // Load Isolate pointer from Context structure into CTX. Drop Context. |
| 769 __ ldr(CTX, FieldAddress(CTX, Context::isolate_offset())); | 769 __ ldr(CTX, FieldAddress(CTX, Context::isolate_offset())); |
| 770 | 770 |
| 771 // Restore the saved Context pointer into the Isolate structure. | 771 // Restore the saved Context pointer into the Isolate structure. |
| 772 // Uses R4 as a temporary register for this. | 772 // Uses R4 as a temporary register for this. |
| 773 // Restore the saved top exit frame info back into the Isolate structure. | 773 // Restore the saved top exit frame info back into the Isolate structure. |
| 774 // Uses R5 as a temporary register for this. | 774 // Uses R5 as a temporary register for this. |
| 775 __ PopList((1 << R4) | (1 << R5)); | 775 __ PopList((1 << R4) | (1 << R5)); |
| 776 __ StoreToOffset(kStoreWord, R4, CTX, Isolate::top_context_offset()); | 776 __ StoreToOffset(kWord, R4, CTX, Isolate::top_context_offset()); |
| 777 __ StoreToOffset(kStoreWord, R5, CTX, Isolate::top_exit_frame_info_offset()); | 777 __ StoreToOffset(kWord, R5, CTX, Isolate::top_exit_frame_info_offset()); |
| 778 | 778 |
| 779 // Restore C++ ABI callee-saved registers. | 779 // Restore C++ ABI callee-saved registers. |
| 780 __ PopList((1 << R3) | kAbiPreservedCpuRegs); // Ignore restored R3. | 780 __ PopList((1 << R3) | kAbiPreservedCpuRegs); // Ignore restored R3. |
| 781 | 781 |
| 782 // Restore the frame pointer and return. | 782 // Restore the frame pointer and return. |
| 783 __ LeaveStubFrame(); | 783 __ LeaveStubFrame(); |
| 784 __ Ret(); | 784 __ Ret(); |
| 785 } | 785 } |
| 786 | 786 |
| 787 | 787 |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1063 // R2: new object start. | 1063 // R2: new object start. |
| 1064 // R3: next object start. | 1064 // R3: next object start. |
| 1065 // R1: new object type arguments (if is_cls_parameterized). | 1065 // R1: new object type arguments (if is_cls_parameterized). |
| 1066 // First try inlining the initialization without a loop. | 1066 // First try inlining the initialization without a loop. |
| 1067 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1067 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
| 1068 // Check if the object contains any non-header fields. | 1068 // Check if the object contains any non-header fields. |
| 1069 // Small objects are initialized using a consecutive set of writes. | 1069 // Small objects are initialized using a consecutive set of writes. |
| 1070 for (intptr_t current_offset = sizeof(RawObject); | 1070 for (intptr_t current_offset = sizeof(RawObject); |
| 1071 current_offset < instance_size; | 1071 current_offset < instance_size; |
| 1072 current_offset += kWordSize) { | 1072 current_offset += kWordSize) { |
| 1073 __ StoreToOffset(kStoreWord, R0, R2, current_offset); | 1073 __ StoreToOffset(kWord, R0, R2, current_offset); |
| 1074 } | 1074 } |
| 1075 } else { | 1075 } else { |
| 1076 __ add(R4, R2, ShifterOperand(sizeof(RawObject))); | 1076 __ add(R4, R2, ShifterOperand(sizeof(RawObject))); |
| 1077 // Loop until the whole object is initialized. | 1077 // Loop until the whole object is initialized. |
| 1078 // R0: raw null. | 1078 // R0: raw null. |
| 1079 // R2: new object. | 1079 // R2: new object. |
| 1080 // R3: next object start. | 1080 // R3: next object start. |
| 1081 // R4: next word to be initialized. | 1081 // R4: next word to be initialized. |
| 1082 // R1: new object type arguments (if is_cls_parameterized). | 1082 // R1: new object type arguments (if is_cls_parameterized). |
| 1083 Label init_loop; | 1083 Label init_loop; |
| 1084 Label done; | 1084 Label done; |
| 1085 __ Bind(&init_loop); | 1085 __ Bind(&init_loop); |
| 1086 __ cmp(R4, ShifterOperand(R3)); | 1086 __ cmp(R4, ShifterOperand(R3)); |
| 1087 __ b(&done, CS); | 1087 __ b(&done, CS); |
| 1088 __ str(R0, Address(R4, 0)); | 1088 __ str(R0, Address(R4, 0)); |
| 1089 __ AddImmediate(R4, kWordSize); | 1089 __ AddImmediate(R4, kWordSize); |
| 1090 __ b(&init_loop); | 1090 __ b(&init_loop); |
| 1091 __ Bind(&done); | 1091 __ Bind(&done); |
| 1092 } | 1092 } |
| 1093 if (is_cls_parameterized) { | 1093 if (is_cls_parameterized) { |
| 1094 // R1: new object type arguments. | 1094 // R1: new object type arguments. |
| 1095 // Set the type arguments in the new object. | 1095 // Set the type arguments in the new object. |
| 1096 __ StoreToOffset(kStoreWord, R1, R2, cls.type_arguments_field_offset()); | 1096 __ StoreToOffset(kWord, R1, R2, cls.type_arguments_field_offset()); |
| 1097 } | 1097 } |
| 1098 // Done allocating and initializing the instance. | 1098 // Done allocating and initializing the instance. |
| 1099 // R2: new object still missing its heap tag. | 1099 // R2: new object still missing its heap tag. |
| 1100 __ add(R0, R2, ShifterOperand(kHeapObjectTag)); | 1100 __ add(R0, R2, ShifterOperand(kHeapObjectTag)); |
| 1101 // R0: new object. | 1101 // R0: new object. |
| 1102 __ Ret(); | 1102 __ Ret(); |
| 1103 | 1103 |
| 1104 __ Bind(&slow_case); | 1104 __ Bind(&slow_case); |
| 1105 } | 1105 } |
| 1106 if (is_cls_parameterized) { | 1106 if (is_cls_parameterized) { |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1414 __ b(&test); | 1414 __ b(&test); |
| 1415 | 1415 |
| 1416 __ Bind(&loop); | 1416 __ Bind(&loop); |
| 1417 for (int i = 0; i < num_args; i++) { | 1417 for (int i = 0; i < num_args; i++) { |
| 1418 if (i > 0) { | 1418 if (i > 0) { |
| 1419 // If not the first, load the next argument's class ID. | 1419 // If not the first, load the next argument's class ID. |
| 1420 __ AddImmediate(R0, R7, Smi::RawValue(-i)); | 1420 __ AddImmediate(R0, R7, Smi::RawValue(-i)); |
| 1421 __ ldr(R0, Address(SP, R0, LSL, 1)); | 1421 __ ldr(R0, Address(SP, R0, LSL, 1)); |
| 1422 __ bl(&get_class_id_as_smi); | 1422 __ bl(&get_class_id_as_smi); |
| 1423 // R0: next argument class ID (smi). | 1423 // R0: next argument class ID (smi). |
| 1424 __ LoadFromOffset(kLoadWord, R1, R6, i * kWordSize); | 1424 __ LoadFromOffset(kWord, R1, R6, i * kWordSize); |
| 1425 // R1: next class ID to check (smi). | 1425 // R1: next class ID to check (smi). |
| 1426 } | 1426 } |
| 1427 __ cmp(R0, ShifterOperand(R1)); // Class id match? | 1427 __ cmp(R0, ShifterOperand(R1)); // Class id match? |
| 1428 if (i < (num_args - 1)) { | 1428 if (i < (num_args - 1)) { |
| 1429 __ b(&update, NE); // Continue. | 1429 __ b(&update, NE); // Continue. |
| 1430 } else { | 1430 } else { |
| 1431 // Last check, all checks before matched. | 1431 // Last check, all checks before matched. |
| 1432 __ mov(LR, ShifterOperand(R8), EQ); // Restore return address if found. | 1432 __ mov(LR, ShifterOperand(R8), EQ); // Restore return address if found. |
| 1433 __ b(&found, EQ); // Break. | 1433 __ b(&found, EQ); // Break. |
| 1434 } | 1434 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1458 // R7: address of receiver. | 1458 // R7: address of receiver. |
| 1459 // Create a stub frame as we are pushing some objects on the stack before | 1459 // Create a stub frame as we are pushing some objects on the stack before |
| 1460 // calling into the runtime. | 1460 // calling into the runtime. |
| 1461 __ EnterStubFrame(); | 1461 __ EnterStubFrame(); |
| 1462 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1462 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1463 // Preserve IC data object and arguments descriptor array and | 1463 // Preserve IC data object and arguments descriptor array and |
| 1464 // setup space on stack for result (target code object). | 1464 // setup space on stack for result (target code object). |
| 1465 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); | 1465 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); |
| 1466 // Push call arguments. | 1466 // Push call arguments. |
| 1467 for (intptr_t i = 0; i < num_args; i++) { | 1467 for (intptr_t i = 0; i < num_args; i++) { |
| 1468 __ LoadFromOffset(kLoadWord, IP, R7, -i * kWordSize); | 1468 __ LoadFromOffset(kWord, IP, R7, -i * kWordSize); |
| 1469 __ Push(IP); | 1469 __ Push(IP); |
| 1470 } | 1470 } |
| 1471 // Pass IC data object and arguments descriptor array. | 1471 // Pass IC data object and arguments descriptor array. |
| 1472 __ PushList((1 << R4) | (1 << R5)); | 1472 __ PushList((1 << R4) | (1 << R5)); |
| 1473 | 1473 |
| 1474 if (num_args == 1) { | 1474 if (num_args == 1) { |
| 1475 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); | 1475 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1476 } else if (num_args == 2) { | 1476 } else if (num_args == 2) { |
| 1477 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); | 1477 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| 1478 } else if (num_args == 3) { | 1478 } else if (num_args == 3) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1494 // Mark IC call that it may be a closure call that does not collect | 1494 // Mark IC call that it may be a closure call that does not collect |
| 1495 // type feedback. | 1495 // type feedback. |
| 1496 __ mov(IP, ShifterOperand(1)); | 1496 __ mov(IP, ShifterOperand(1)); |
| 1497 __ strb(IP, FieldAddress(R5, ICData::is_closure_call_offset())); | 1497 __ strb(IP, FieldAddress(R5, ICData::is_closure_call_offset())); |
| 1498 __ Branch(&StubCode::InstanceFunctionLookupLabel()); | 1498 __ Branch(&StubCode::InstanceFunctionLookupLabel()); |
| 1499 | 1499 |
| 1500 __ Bind(&found); | 1500 __ Bind(&found); |
| 1501 // R6: pointer to an IC data check group. | 1501 // R6: pointer to an IC data check group. |
| 1502 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1502 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1503 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1503 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1504 __ LoadFromOffset(kLoadWord, R0, R6, target_offset); | 1504 __ LoadFromOffset(kWord, R0, R6, target_offset); |
| 1505 __ LoadFromOffset(kLoadWord, R1, R6, count_offset); | 1505 __ LoadFromOffset(kWord, R1, R6, count_offset); |
| 1506 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); | 1506 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); |
| 1507 __ StoreToOffset(kStoreWord, R1, R6, count_offset); | 1507 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1508 __ b(&call_target_function, VC); // No overflow. | 1508 __ b(&call_target_function, VC); // No overflow. |
| 1509 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); | 1509 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); |
| 1510 __ StoreToOffset(kStoreWord, R1, R6, count_offset); | 1510 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1511 | 1511 |
| 1512 __ Bind(&call_target_function); | 1512 __ Bind(&call_target_function); |
| 1513 // R0: target function. | 1513 // R0: target function. |
| 1514 __ ldr(R0, FieldAddress(R0, Function::code_offset())); | 1514 __ ldr(R0, FieldAddress(R0, Function::code_offset())); |
| 1515 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | 1515 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); |
| 1516 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); | 1516 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); |
| 1517 __ bx(R0); | 1517 __ bx(R0); |
| 1518 | 1518 |
| 1519 // Instance in R0, return its class-id in R0 as Smi. | 1519 // Instance in R0, return its class-id in R0 as Smi. |
| 1520 __ Bind(&get_class_id_as_smi); | 1520 __ Bind(&get_class_id_as_smi); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1621 // R5: IC data object (preserved). | 1621 // R5: IC data object (preserved). |
| 1622 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1622 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
| 1623 // R6: ic_data_array with entries: target functions and count. | 1623 // R6: ic_data_array with entries: target functions and count. |
| 1624 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1624 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
| 1625 // R6: points directly to the first ic data array element. | 1625 // R6: points directly to the first ic data array element. |
| 1626 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1626 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1627 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1627 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1628 | 1628 |
| 1629 // Increment count for this call. | 1629 // Increment count for this call. |
| 1630 Label increment_done; | 1630 Label increment_done; |
| 1631 __ LoadFromOffset(kLoadWord, R1, R6, count_offset); | 1631 __ LoadFromOffset(kWord, R1, R6, count_offset); |
| 1632 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); | 1632 __ adds(R1, R1, ShifterOperand(Smi::RawValue(1))); |
| 1633 __ StoreToOffset(kStoreWord, R1, R6, count_offset); | 1633 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1634 __ b(&increment_done, VC); // No overflow. | 1634 __ b(&increment_done, VC); // No overflow. |
| 1635 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); | 1635 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); |
| 1636 __ StoreToOffset(kStoreWord, R1, R6, count_offset); | 1636 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1637 __ Bind(&increment_done); | 1637 __ Bind(&increment_done); |
| 1638 | 1638 |
| 1639 Label target_is_compiled; | 1639 Label target_is_compiled; |
| 1640 // Get function and call it, if possible. | 1640 // Get function and call it, if possible. |
| 1641 __ LoadFromOffset(kLoadWord, R1, R6, target_offset); | 1641 __ LoadFromOffset(kWord, R1, R6, target_offset); |
| 1642 __ ldr(R0, FieldAddress(R1, Function::code_offset())); | 1642 __ ldr(R0, FieldAddress(R1, Function::code_offset())); |
| 1643 __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1643 __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1644 __ b(&target_is_compiled, NE); | 1644 __ b(&target_is_compiled, NE); |
| 1645 // R1: function. | 1645 // R1: function. |
| 1646 | 1646 |
| 1647 __ EnterStubFrame(); | 1647 __ EnterStubFrame(); |
| 1648 // Preserve target function and IC data object. | 1648 // Preserve target function and IC data object. |
| 1649 __ PushList((1 << R1) | (1 << R5)); | 1649 __ PushList((1 << R1) | (1 << R5)); |
| 1650 __ Push(R1); // Pass function. | 1650 __ Push(R1); // Pass function. |
| 1651 __ CallRuntime(kCompileFunctionRuntimeEntry); | 1651 __ CallRuntime(kCompileFunctionRuntimeEntry); |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2091 __ ldr(left, Address(SP, 4 * kWordSize)); | 2091 __ ldr(left, Address(SP, 4 * kWordSize)); |
| 2092 __ ldr(right, Address(SP, 3 * kWordSize)); | 2092 __ ldr(right, Address(SP, 3 * kWordSize)); |
| 2093 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2093 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2094 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); | 2094 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); |
| 2095 __ Ret(); | 2095 __ Ret(); |
| 2096 } | 2096 } |
| 2097 | 2097 |
| 2098 } // namespace dart | 2098 } // namespace dart |
| 2099 | 2099 |
| 2100 #endif // defined TARGET_ARCH_ARM | 2100 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |