blob: 1b5e6cc5ee719e1eb9a41552442e508b13390b8f [file] [log] [blame]
jeffhao7fbee072012-08-24 17:56:54 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080018#include "mirror/array.h"
jeffhao7fbee072012-08-24 17:56:54 -070019#include "oat/runtime/oat_support_entrypoints.h"
20#include "oat/runtime/stub.h"
21#include "oat/utils/mips/assembler_mips.h"
jeffhao7fbee072012-08-24 17:56:54 -070022#include "stack_indirect_reference_table.h"
Ian Rogers1f539342012-10-03 21:09:42 -070023#include "sirt_ref.h"
jeffhao7fbee072012-08-24 17:56:54 -070024
25#define __ assembler->
26
27namespace art {
28namespace mips {
29
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080030mirror::ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) {
jeffhao7fbee072012-08-24 17:56:54 -070031 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
Ian Rogersc928de92013-02-27 14:30:44 -080032#if !defined(ART_USE_PORTABLE_COMPILER)
jeffhaofa147e22012-10-12 17:03:32 -070033 // | Out args |
34 // | Method* | <- SP on entry
35 // | RA | return address into caller
36 // | ... | callee saves
37 // | A3 | possible argument
38 // | A2 | possible argument
39 // | A1 | possible argument
40 // | A0/Method* | Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
jeffhao7fbee072012-08-24 17:56:54 -070041 // Save callee saves and ready frame for exception delivery
jeffhaofa147e22012-10-12 17:03:32 -070042 __ AddConstant(SP, SP, -48);
43 __ StoreToOffset(kStoreWord, RA, SP, 44);
44 __ StoreToOffset(kStoreWord, FP, SP, 40);
45 __ StoreToOffset(kStoreWord, S7, SP, 36);
46 __ StoreToOffset(kStoreWord, S6, SP, 32);
47 __ StoreToOffset(kStoreWord, S5, SP, 28);
48 __ StoreToOffset(kStoreWord, S4, SP, 24);
49 __ StoreToOffset(kStoreWord, S3, SP, 20);
50 __ StoreToOffset(kStoreWord, S2, SP, 16);
51 __ StoreToOffset(kStoreWord, A3, SP, 12);
52 __ StoreToOffset(kStoreWord, A2, SP, 8);
53 __ StoreToOffset(kStoreWord, A1, SP, 4);
jeffhao7fbee072012-08-24 17:56:54 -070054
55 __ LoadFromOffset(kLoadWord, T9, S1,
56 ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
57 __ Move(A2, S1); // Pass Thread::Current() in A2
58 __ LoadImmediate(A3, type); // Pass is_static
59 __ Move(A1, SP); // Pass SP for Method** callee_addr
60 __ Jalr(T9); // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
61
62 // Restore registers which may have been modified by GC
jeffhaofa147e22012-10-12 17:03:32 -070063 __ LoadFromOffset(kLoadWord, A0, SP, 0);
64 __ LoadFromOffset(kLoadWord, A1, SP, 4);
65 __ LoadFromOffset(kLoadWord, A2, SP, 8);
66 __ LoadFromOffset(kLoadWord, A3, SP, 12);
67 __ LoadFromOffset(kLoadWord, S2, SP, 16);
68 __ LoadFromOffset(kLoadWord, S3, SP, 20);
69 __ LoadFromOffset(kLoadWord, S4, SP, 24);
70 __ LoadFromOffset(kLoadWord, S5, SP, 28);
71 __ LoadFromOffset(kLoadWord, S6, SP, 32);
72 __ LoadFromOffset(kLoadWord, S7, SP, 36);
73 __ LoadFromOffset(kLoadWord, FP, SP, 40);
74 __ LoadFromOffset(kLoadWord, RA, SP, 44);
75 __ AddConstant(SP, SP, 48);
jeffhao7fbee072012-08-24 17:56:54 -070076
jeffhao61f916c2012-10-25 17:48:51 -070077 __ Move(T9, V0); // Put method's code in T9
78 __ Jr(T9); // Leaf call to method's code
jeffhao7fbee072012-08-24 17:56:54 -070079
80 __ Break();
Ian Rogersc928de92013-02-27 14:30:44 -080081#else // ART_USE_PORTABLE_COMPILER
jeffhao7fbee072012-08-24 17:56:54 -070082 // Build frame and save argument registers and RA.
83 __ AddConstant(SP, SP, -32);
84 __ StoreToOffset(kStoreWord, RA, SP, 28);
85 __ StoreToOffset(kStoreWord, A3, SP, 24);
86 __ StoreToOffset(kStoreWord, A2, SP, 20);
87 __ StoreToOffset(kStoreWord, A1, SP, 16);
88 __ StoreToOffset(kStoreWord, A0, SP, 12);
89
90 __ LoadFromOffset(kLoadWord, T9, S1,
91 ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
jeffhao0ac41d52012-08-27 13:07:54 -070092 __ Move(A2, S1); // Pass Thread::Current() in A2
jeffhao7fbee072012-08-24 17:56:54 -070093 __ LoadImmediate(A3, type); // Pass is_static
jeffhao0ac41d52012-08-27 13:07:54 -070094 __ Move(A1, SP); // Pass SP for Method** callee_addr
jeffhao7fbee072012-08-24 17:56:54 -070095 __ Jalr(T9); // Call to unresolved direct method trampoline (callee, callee_addr, Thread*, is_static)
96
97 // Restore frame, argument registers, and RA.
98 __ LoadFromOffset(kLoadWord, A0, SP, 12);
99 __ LoadFromOffset(kLoadWord, A1, SP, 16);
100 __ LoadFromOffset(kLoadWord, A2, SP, 20);
101 __ LoadFromOffset(kLoadWord, A3, SP, 24);
102 __ LoadFromOffset(kLoadWord, RA, SP, 28);
103 __ AddConstant(SP, SP, 32);
104
105 Label resolve_fail;
106 __ EmitBranch(V0, ZERO, &resolve_fail, true);
107 __ Jr(V0); // If V0 != 0 tail call method's code
108 __ Bind(&resolve_fail, false);
109 __ Jr(RA); // Return to caller to handle exception
Ian Rogersc928de92013-02-27 14:30:44 -0800110#endif // ART_USE_PORTABLE_COMPILER
jeffhao7fbee072012-08-24 17:56:54 -0700111
112 assembler->EmitSlowPaths();
113
114 size_t cs = assembler->CodeSize();
Ian Rogers50b35e22012-10-04 10:09:15 -0700115 Thread* self = Thread::Current();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800116 SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs));
jeffhao7fbee072012-08-24 17:56:54 -0700117 CHECK(resolution_trampoline.get() != NULL);
118 MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
119 assembler->FinalizeInstructions(code);
120
121 return resolution_trampoline.get();
122}
123
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800124typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*);
jeffhao7fbee072012-08-24 17:56:54 -0700125
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800126mirror::ByteArray* CreateAbstractMethodErrorStub() {
jeffhao7fbee072012-08-24 17:56:54 -0700127 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
Ian Rogersc928de92013-02-27 14:30:44 -0800128#if !defined(ART_USE_PORTABLE_COMPILER)
jeffhao7fbee072012-08-24 17:56:54 -0700129 // Save callee saves and ready frame for exception delivery
jeffhao4eb68ed2012-10-17 16:41:07 -0700130 __ AddConstant(SP, SP, -64);
131 __ StoreToOffset(kStoreWord, RA, SP, 60);
132 __ StoreToOffset(kStoreWord, FP, SP, 56);
133 __ StoreToOffset(kStoreWord, S7, SP, 52);
134 __ StoreToOffset(kStoreWord, S6, SP, 48);
135 __ StoreToOffset(kStoreWord, S5, SP, 44);
136 __ StoreToOffset(kStoreWord, S4, SP, 40);
137 __ StoreToOffset(kStoreWord, S3, SP, 36);
138 __ StoreToOffset(kStoreWord, S2, SP, 32);
139 __ StoreToOffset(kStoreWord, S1, SP, 28);
140 __ StoreToOffset(kStoreWord, S0, SP, 24);
jeffhao7fbee072012-08-24 17:56:54 -0700141
jeffhao07030602012-09-26 14:33:14 -0700142 // A0 is the Method* already
jeffhao7fbee072012-08-24 17:56:54 -0700143 __ Move(A1, S1); // Pass Thread::Current() in A1
144 __ Move(A2, SP); // Pass SP in A2
145 // Call to throw AbstractMethodError
146 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
147 __ Jr(T9); // Leaf call to routine that never returns
148
149 __ Break();
Ian Rogersc928de92013-02-27 14:30:44 -0800150#else // ART_USE_PORTABLE_COMPILER
jeffhao7fbee072012-08-24 17:56:54 -0700151 // R0 is the Method* already
152 __ Move(A1, S1); // Pass Thread::Current() in A1
153 // Call to throw AbstractMethodError
154 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
155 __ Jr(T9); // Leaf call to routine that never returns
156
157 __ Break();
Ian Rogersc928de92013-02-27 14:30:44 -0800158#endif // ART_USE_PORTABLE_COMPILER
jeffhao7fbee072012-08-24 17:56:54 -0700159
160 assembler->EmitSlowPaths();
161
162 size_t cs = assembler->CodeSize();
Ian Rogers50b35e22012-10-04 10:09:15 -0700163 Thread* self = Thread::Current();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800164 SirtRef<mirror::ByteArray> abstract_stub(self, mirror::ByteArray::Alloc(self, cs));
jeffhao7fbee072012-08-24 17:56:54 -0700165 CHECK(abstract_stub.get() != NULL);
166 MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
167 assembler->FinalizeInstructions(code);
168
169 return abstract_stub.get();
170}
171
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800172mirror::ByteArray* CreateJniDlsymLookupStub() {
jeffhao7fbee072012-08-24 17:56:54 -0700173 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
174
175 // Build frame and save argument registers and RA.
176 __ AddConstant(SP, SP, -32);
177 __ StoreToOffset(kStoreWord, RA, SP, 28);
178 __ StoreToOffset(kStoreWord, A3, SP, 24);
179 __ StoreToOffset(kStoreWord, A2, SP, 20);
180 __ StoreToOffset(kStoreWord, A1, SP, 16);
181 __ StoreToOffset(kStoreWord, A0, SP, 12);
182
183 __ Move(A0, S1); // Pass Thread::Current() in A0
184 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pFindNativeMethod));
185 __ Jalr(T9); // Call FindNativeMethod
186
187 // Restore frame, argument registers, and RA.
188 __ LoadFromOffset(kLoadWord, A0, SP, 12);
189 __ LoadFromOffset(kLoadWord, A1, SP, 16);
190 __ LoadFromOffset(kLoadWord, A2, SP, 20);
191 __ LoadFromOffset(kLoadWord, A3, SP, 24);
192 __ LoadFromOffset(kLoadWord, RA, SP, 28);
193 __ AddConstant(SP, SP, 32);
194
195 Label no_native_code_found;
196 __ EmitBranch(V0, ZERO, &no_native_code_found, true);
jeffhao41ada622012-10-19 17:14:35 -0700197 __ Move(T9, V0); // Move result into T9
198 __ Jr(T9); // If result != 0, tail call method's code
jeffhao7fbee072012-08-24 17:56:54 -0700199 __ Bind(&no_native_code_found, false);
200 __ Jr(RA); // Return to caller to handle exception
201
202 assembler->EmitSlowPaths();
203
204 size_t cs = assembler->CodeSize();
Ian Rogers50b35e22012-10-04 10:09:15 -0700205 Thread* self = Thread::Current();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800206 SirtRef<mirror::ByteArray> jni_stub(self, mirror::ByteArray::Alloc(self, cs));
jeffhao7fbee072012-08-24 17:56:54 -0700207 CHECK(jni_stub.get() != NULL);
208 MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
209 assembler->FinalizeInstructions(code);
210
211 return jni_stub.get();
212}
213
214} // namespace mips
215} // namespace art