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_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
| 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" |
| 10 #include "vm/dart_entry.h" |
| 11 #include "vm/instructions.h" |
| 12 #include "vm/stack_frame.h" |
8 #include "vm/stub_code.h" | 13 #include "vm/stub_code.h" |
9 | 14 |
10 #define __ assembler-> | 15 #define __ assembler-> |
11 | 16 |
12 namespace dart { | 17 namespace dart { |
13 | 18 |
14 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 19 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
15 __ Unimplemented("CallToRuntime stub"); | 20 __ Unimplemented("CallToRuntime stub"); |
16 } | 21 } |
17 | 22 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 64 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
60 __ Unimplemented("AllocateArray stub"); | 65 __ Unimplemented("AllocateArray stub"); |
61 } | 66 } |
62 | 67 |
63 | 68 |
64 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 69 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
65 __ Unimplemented("CallClosureFunction stub"); | 70 __ Unimplemented("CallClosureFunction stub"); |
66 } | 71 } |
67 | 72 |
68 | 73 |
| 74 // Called when invoking Dart code from C++ (VM code). |
| 75 // Input parameters: |
| 76 // RA : points to return address. |
| 77 // A0 : entrypoint of the Dart function to call. |
| 78 // A1 : arguments descriptor array. |
| 79 // A2 : arguments array. |
| 80 // A3 : new context containing the current isolate pointer. |
69 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | 81 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
70 __ Unimplemented("InvokeDartCode stub"); | 82 // Save frame pointer coming in. |
| 83 __ EnterStubFrame(); |
| 84 |
| 85 // Save new context and C++ ABI callee-saved registers. |
| 86 const intptr_t kNewContextOffset = |
| 87 -(2 + kAbiPreservedCpuRegCount) * kWordSize; |
| 88 __ PushList((1 << A3) | kAbiPreservedCpuRegs); |
| 89 |
| 90 // The new Context structure contains a pointer to the current Isolate |
| 91 // structure. Cache the Context pointer in the CTX register so that it is |
| 92 // available in generated code and calls to Isolate::Current() need not be |
| 93 // done. The assumption is that this register will never be clobbered by |
| 94 // compiled or runtime stub code. |
| 95 |
| 96 // Cache the new Context pointer into CTX while executing Dart code. |
| 97 __ lw(CTX, Address(A3, VMHandles::kOffsetOfRawPtrInHandle)); |
| 98 |
| 99 // Load Isolate pointer from Context structure into temporary register R8. |
| 100 __ lw(T2, FieldAddress(CTX, Context::isolate_offset())); |
| 101 |
| 102 // Save the top exit frame info. Use R5 as a temporary register. |
| 103 // StackFrameIterator reads the top exit frame info saved in this frame. |
| 104 __ lw(S5, Address(T2, Isolate::top_exit_frame_info_offset())); |
| 105 __ LoadImmediate(T0, 0); |
| 106 __ sw(T0, Address(T2, Isolate::top_exit_frame_info_offset())); |
| 107 |
| 108 // Save the old Context pointer. Use S4 as a temporary register. |
| 109 // Note that VisitObjectPointers will find this saved Context pointer during |
| 110 // GC marking, since it traverses any information between SP and |
| 111 // FP - kExitLinkOffsetInEntryFrame. |
| 112 // EntryFrame::SavedContext reads the context saved in this frame. |
| 113 __ lw(S4, Address(T2, Isolate::top_context_offset())); |
| 114 |
| 115 // The constants kSavedContextOffsetInEntryFrame and |
| 116 // kExitLinkOffsetInEntryFrame must be kept in sync with the code below. |
| 117 __ PushList((1 << S4) | (1 << S5)); |
| 118 |
| 119 // after the call, The stack pointer is restored to this location. |
| 120 const intptr_t kSavedContextOffsetInEntryFrame = -12 * kWordSize; |
| 121 |
| 122 // Load arguments descriptor array into S4, which is passed to Dart code. |
| 123 __ lw(S4, Address(A1, VMHandles::kOffsetOfRawPtrInHandle)); |
| 124 |
| 125 // Load number of arguments into S5. |
| 126 __ lw(S5, FieldAddress(S4, ArgumentsDescriptor::count_offset())); |
| 127 __ SmiUntag(S5); |
| 128 |
| 129 // Compute address of 'arguments array' data area into A2. |
| 130 __ lw(A2, Address(A2, VMHandles::kOffsetOfRawPtrInHandle)); |
| 131 __ addiu(A2, A2, Immediate(Array::data_offset() - kHeapObjectTag)); |
| 132 |
| 133 // Set up arguments for the Dart call. |
| 134 Label push_arguments; |
| 135 Label done_push_arguments; |
| 136 |
| 137 __ beq(S5, ZR, &done_push_arguments); // check if there are arguments. |
| 138 __ LoadImmediate(A1, 0); |
| 139 __ Bind(&push_arguments); |
| 140 __ lw(A3, Address(A2)); |
| 141 __ Push(A3); |
| 142 __ addiu(A2, A2, Immediate(kWordSize)); |
| 143 __ addiu(A1, A1, Immediate(1)); |
| 144 __ subu(T0, A1, S5); |
| 145 __ bltz(T0, &push_arguments); |
| 146 |
| 147 __ Bind(&done_push_arguments); |
| 148 |
| 149 |
| 150 // Call the Dart code entrypoint. |
| 151 __ jalr(A0); // S4 is the arguments descriptor array. |
| 152 |
| 153 // Read the saved new Context pointer. |
| 154 __ lw(CTX, Address(FP, kNewContextOffset)); |
| 155 __ lw(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 156 |
| 157 // Get rid of arguments pushed on the stack. |
| 158 __ addiu(SP, FP, Immediate(kSavedContextOffsetInEntryFrame)); |
| 159 |
| 160 // Load Isolate pointer from Context structure into CTX. Drop Context. |
| 161 __ lw(CTX, FieldAddress(CTX, Context::isolate_offset())); |
| 162 |
| 163 // Restore the saved Context pointer into the Isolate structure. |
| 164 // Uses S4 as a temporary register for this. |
| 165 // Restore the saved top exit frame info back into the Isolate structure. |
| 166 // Uses S5 as a temporary register for this. |
| 167 __ PopList((1 << S4) | (1 << S5)); |
| 168 __ sw(S4, Address(CTX, Isolate::top_context_offset())); |
| 169 __ sw(S5, Address(CTX, Isolate::top_exit_frame_info_offset())); |
| 170 |
| 171 // Restore C++ ABI callee-saved registers. |
| 172 __ PopList((1 << A3) | kAbiPreservedCpuRegs); // Ignore restored A3. |
| 173 |
| 174 // Restore the frame pointer and return. |
| 175 __ LeaveStubFrame(); |
| 176 __ Ret(); |
71 } | 177 } |
72 | 178 |
73 | 179 |
74 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 180 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
75 __ Unimplemented("AllocateContext stub"); | 181 __ Unimplemented("AllocateContext stub"); |
76 } | 182 } |
77 | 183 |
78 | 184 |
79 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { | 185 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { |
80 __ Unimplemented("UpdateStoreBuffer stub"); | 186 __ Unimplemented("UpdateStoreBuffer stub"); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 } | 328 } |
223 | 329 |
224 | 330 |
225 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) { | 331 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) { |
226 __ Unimplemented("IdenticalWithNumberCheck stub"); | 332 __ Unimplemented("IdenticalWithNumberCheck stub"); |
227 } | 333 } |
228 | 334 |
229 } // namespace dart | 335 } // namespace dart |
230 | 336 |
231 #endif // defined TARGET_ARCH_MIPS | 337 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |