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 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 __ LeaveStubFrame(); | 234 __ LeaveStubFrame(); |
235 // Jump to the dart function. | 235 // Jump to the dart function. |
236 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | 236 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); |
237 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag); | 237 __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag); |
238 __ bx(R0); | 238 __ bx(R0); |
239 } | 239 } |
240 | 240 |
241 | 241 |
242 // Input parameters: | 242 // Input parameters: |
243 // R2: smi-tagged argument count, may be zero. | 243 // R2: smi-tagged argument count, may be zero. |
244 // FP[kLastParamSlotIndex]: last argument. | 244 // FP[kParamEndSlotFromFp + 1]: last argument. |
245 static void PushArgumentsArray(Assembler* assembler) { | 245 static void PushArgumentsArray(Assembler* assembler) { |
246 // Allocate array to store arguments of caller. | 246 // Allocate array to store arguments of caller. |
247 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); | 247 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); |
248 // R1: null element type for raw Array. | 248 // R1: null element type for raw Array. |
249 // R2: smi-tagged argument count, may be zero. | 249 // R2: smi-tagged argument count, may be zero. |
250 __ BranchLink(&StubCode::AllocateArrayLabel()); | 250 __ BranchLink(&StubCode::AllocateArrayLabel()); |
251 // R0: newly allocated array. | 251 // R0: newly allocated array. |
252 // R2: smi-tagged argument count, may be zero (was preserved by the stub). | 252 // R2: smi-tagged argument count, may be zero (was preserved by the stub). |
253 __ Push(R0); // Array is in R0 and on top of stack. | 253 __ Push(R0); // Array is in R0 and on top of stack. |
254 __ add(R1, FP, ShifterOperand(R2, LSL, 1)); | 254 __ add(R1, FP, ShifterOperand(R2, LSL, 1)); |
255 __ AddImmediate(R1, (kLastParamSlotIndex - 1) * kWordSize); | 255 __ AddImmediate(R1, kParamEndSlotFromFp * kWordSize); |
256 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag); | 256 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag); |
257 // R1: address of first argument on stack. | 257 // R1: address of first argument on stack. |
258 // R3: address of first argument in array. | 258 // R3: address of first argument in array. |
259 Label loop; | 259 Label loop; |
260 __ Bind(&loop); | 260 __ Bind(&loop); |
261 __ subs(R2, R2, ShifterOperand(Smi::RawValue(1))); // R2 is Smi. | 261 __ subs(R2, R2, ShifterOperand(Smi::RawValue(1))); // R2 is Smi. |
262 __ ldr(IP, Address(R1, 0), PL); | 262 __ ldr(IP, Address(R1, 0), PL); |
263 __ str(IP, Address(R3, 0), PL); | 263 __ str(IP, Address(R3, 0), PL); |
264 __ AddImmediate(R1, -kWordSize, PL); | 264 __ AddImmediate(R1, -kWordSize, PL); |
265 __ AddImmediate(R3, kWordSize, PL); | 265 __ AddImmediate(R3, kWordSize, PL); |
266 __ b(&loop, PL); | 266 __ b(&loop, PL); |
267 } | 267 } |
268 | 268 |
269 | 269 |
270 // Input parameters: | 270 // Input parameters: |
271 // R5: ic-data. | 271 // R5: ic-data. |
272 // R4: arguments descriptor array. | 272 // R4: arguments descriptor array. |
273 // Note: The receiver object is the first argument to the function being | 273 // Note: The receiver object is the first argument to the function being |
274 // called, the stub accesses the receiver from this location directly | 274 // called, the stub accesses the receiver from this location directly |
275 // when trying to resolve the call. | 275 // when trying to resolve the call. |
276 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { | 276 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
277 __ EnterStubFrame(); | 277 __ EnterStubFrame(); |
278 | 278 |
279 // Load the receiver. | 279 // Load the receiver. |
280 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 280 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
281 __ add(IP, FP, ShifterOperand(R2, LSL, 1)); // R2 is Smi. | 281 __ add(IP, FP, ShifterOperand(R2, LSL, 1)); // R2 is Smi. |
282 __ ldr(R6, Address(IP, (kLastParamSlotIndex - 1) * kWordSize)); | 282 __ ldr(R6, Address(IP, kParamEndSlotFromFp * kWordSize)); |
283 | 283 |
284 // Push space for the return value. | 284 // Push space for the return value. |
285 // Push the receiver. | 285 // Push the receiver. |
286 // Push IC data object. | 286 // Push IC data object. |
287 // Push arguments descriptor array. | 287 // Push arguments descriptor array. |
288 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | 288 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
289 __ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP)); | 289 __ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP)); |
290 | 290 |
291 // R2: Smi-tagged arguments array length. | 291 // R2: Smi-tagged arguments array length. |
292 PushArgumentsArray(assembler); | 292 PushArgumentsArray(assembler); |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 | 685 |
686 // Save the top exit frame info. Use R5 as a temporary register. | 686 // Save the top exit frame info. Use R5 as a temporary register. |
687 // StackFrameIterator reads the top exit frame info saved in this frame. | 687 // StackFrameIterator reads the top exit frame info saved in this frame. |
688 __ LoadFromOffset(kLoadWord, R5, R8, Isolate::top_exit_frame_info_offset()); | 688 __ LoadFromOffset(kLoadWord, R5, R8, Isolate::top_exit_frame_info_offset()); |
689 __ LoadImmediate(R6, 0); | 689 __ LoadImmediate(R6, 0); |
690 __ StoreToOffset(kStoreWord, R6, R8, Isolate::top_exit_frame_info_offset()); | 690 __ StoreToOffset(kStoreWord, R6, R8, Isolate::top_exit_frame_info_offset()); |
691 | 691 |
692 // Save the old Context pointer. Use R4 as a temporary register. | 692 // Save the old Context pointer. Use R4 as a temporary register. |
693 // Note that VisitObjectPointers will find this saved Context pointer during | 693 // Note that VisitObjectPointers will find this saved Context pointer during |
694 // GC marking, since it traverses any information between SP and | 694 // GC marking, since it traverses any information between SP and |
695 // FP - kExitLinkOffsetInEntryFrame. | 695 // FP - kExitLinkSlotFromEntryFp. |
696 // EntryFrame::SavedContext reads the context saved in this frame. | 696 // EntryFrame::SavedContext reads the context saved in this frame. |
697 __ LoadFromOffset(kLoadWord, R4, R8, Isolate::top_context_offset()); | 697 __ LoadFromOffset(kLoadWord, R4, R8, Isolate::top_context_offset()); |
698 | 698 |
699 // The constants kSavedContextOffsetInEntryFrame and | 699 // The constants kSavedContextSlotFromEntryFp and |
700 // kExitLinkOffsetInEntryFrame must be kept in sync with the code below. | 700 // kExitLinkSlotFromEntryFp must be kept in sync with the code below. |
| 701 ASSERT(kExitLinkSlotFromEntryFp == -9); |
| 702 ASSERT(kSavedContextSlotFromEntryFp == -10); |
701 __ PushList((1 << R4) | (1 << R5)); | 703 __ PushList((1 << R4) | (1 << R5)); |
702 | 704 |
703 // The stack pointer is restored after the call to this location. | 705 // The stack pointer is restored after the call to this location. |
704 const intptr_t kSavedContextOffsetInEntryFrame = -10 * kWordSize; | 706 const intptr_t kSavedContextSlotFromEntryFp = -10 * kWordSize; |
705 | 707 |
706 // Load arguments descriptor array into R4, which is passed to Dart code. | 708 // Load arguments descriptor array into R4, which is passed to Dart code. |
707 __ ldr(R4, Address(R1, VMHandles::kOffsetOfRawPtrInHandle)); | 709 __ ldr(R4, Address(R1, VMHandles::kOffsetOfRawPtrInHandle)); |
708 | 710 |
709 // Load number of arguments into R5. | 711 // Load number of arguments into R5. |
710 __ ldr(R5, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 712 __ ldr(R5, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
711 __ SmiUntag(R5); | 713 __ SmiUntag(R5); |
712 | 714 |
713 // Compute address of 'arguments array' data area into R2. | 715 // Compute address of 'arguments array' data area into R2. |
714 __ ldr(R2, Address(R2, VMHandles::kOffsetOfRawPtrInHandle)); | 716 __ ldr(R2, Address(R2, VMHandles::kOffsetOfRawPtrInHandle)); |
(...skipping 15 matching lines...) Expand all Loading... |
730 __ Bind(&done_push_arguments); | 732 __ Bind(&done_push_arguments); |
731 | 733 |
732 // Call the Dart code entrypoint. | 734 // Call the Dart code entrypoint. |
733 __ blx(R0); // R4 is the arguments descriptor array. | 735 __ blx(R0); // R4 is the arguments descriptor array. |
734 | 736 |
735 // Read the saved new Context pointer. | 737 // Read the saved new Context pointer. |
736 __ ldr(CTX, Address(FP, kNewContextOffset)); | 738 __ ldr(CTX, Address(FP, kNewContextOffset)); |
737 __ ldr(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); | 739 __ ldr(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); |
738 | 740 |
739 // Get rid of arguments pushed on the stack. | 741 // Get rid of arguments pushed on the stack. |
740 __ AddImmediate(SP, FP, kSavedContextOffsetInEntryFrame); | 742 __ AddImmediate(SP, FP, kSavedContextSlotFromEntryFp); |
741 | 743 |
742 // Load Isolate pointer from Context structure into CTX. Drop Context. | 744 // Load Isolate pointer from Context structure into CTX. Drop Context. |
743 __ ldr(CTX, FieldAddress(CTX, Context::isolate_offset())); | 745 __ ldr(CTX, FieldAddress(CTX, Context::isolate_offset())); |
744 | 746 |
745 // Restore the saved Context pointer into the Isolate structure. | 747 // Restore the saved Context pointer into the Isolate structure. |
746 // Uses R4 as a temporary register for this. | 748 // Uses R4 as a temporary register for this. |
747 // Restore the saved top exit frame info back into the Isolate structure. | 749 // Restore the saved top exit frame info back into the Isolate structure. |
748 // Uses R5 as a temporary register for this. | 750 // Uses R5 as a temporary register for this. |
749 __ PopList((1 << R4) | (1 << R5)); | 751 __ PopList((1 << R4) | (1 << R5)); |
750 __ StoreToOffset(kStoreWord, R4, CTX, Isolate::top_context_offset()); | 752 __ StoreToOffset(kStoreWord, R4, CTX, Isolate::top_context_offset()); |
(...skipping 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1923 __ Bind(&reference_compare); | 1925 __ Bind(&reference_compare); |
1924 __ cmp(left, ShifterOperand(right)); | 1926 __ cmp(left, ShifterOperand(right)); |
1925 __ Bind(&done); | 1927 __ Bind(&done); |
1926 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); | 1928 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); |
1927 __ Ret(); | 1929 __ Ret(); |
1928 } | 1930 } |
1929 | 1931 |
1930 } // namespace dart | 1932 } // namespace dart |
1931 | 1933 |
1932 #endif // defined TARGET_ARCH_ARM | 1934 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |