blob: 4865c5912e9143b37af8c683e4e384461ed9798d [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"
18#include "oat/runtime/oat_support_entrypoints.h"
19#include "oat/runtime/stub.h"
20#include "oat/utils/mips/assembler_mips.h"
21#include "object.h"
22#include "stack_indirect_reference_table.h"
23
24#define __ assembler->
25
26namespace art {
27namespace mips {
28
29ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) {
30 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
31#if !defined(ART_USE_LLVM_COMPILER)
32 // | Out args |
33 // | Method* | <- SP on entry
34 // | RA | return address into caller
35 // | ... | callee saves
36 // | A3 | possible argument
37 // | A2 | possible argument
38 // | A1 | possible argument
39 // | A0 | junk on call to UnresolvedDirectMethodTrampolineFromCode, holds result Method*
40 // | Method* | Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
41 // Save callee saves and ready frame for exception delivery
42 __ AddConstant(SP, SP, -64);
43 __ StoreToOffset(kStoreWord, RA, SP, 60);
44 __ StoreToOffset(kStoreWord, T9, SP, 56);
45 __ StoreToOffset(kStoreWord, T8, SP, 52);
46 __ StoreToOffset(kStoreWord, T7, SP, 48);
47 __ StoreToOffset(kStoreWord, T6, SP, 44);
48 __ StoreToOffset(kStoreWord, T5, SP, 40);
49 __ StoreToOffset(kStoreWord, T4, SP, 36);
50 __ StoreToOffset(kStoreWord, T3, SP, 32);
51 __ StoreToOffset(kStoreWord, T2, SP, 28);
52 __ StoreToOffset(kStoreWord, T1, SP, 24);
53 __ StoreToOffset(kStoreWord, T0, SP, 20);
54 __ StoreToOffset(kStoreWord, A3, SP, 16);
55 __ StoreToOffset(kStoreWord, A2, SP, 12);
56 __ StoreToOffset(kStoreWord, A1, SP, 8);
57
58 __ LoadFromOffset(kLoadWord, T9, S1,
59 ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
60 __ Move(A2, S1); // Pass Thread::Current() in A2
61 __ LoadImmediate(A3, type); // Pass is_static
62 __ Move(A1, SP); // Pass SP for Method** callee_addr
63 __ Jalr(T9); // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
64
65 // Restore registers which may have been modified by GC
66 __ LoadFromOffset(kLoadWord, A1, SP, 8);
67 __ LoadFromOffset(kLoadWord, A2, SP, 12);
68 __ LoadFromOffset(kLoadWord, A3, SP, 16);
69 __ LoadFromOffset(kLoadWord, T0, SP, 20);
70 __ LoadFromOffset(kLoadWord, T1, SP, 24);
71 __ LoadFromOffset(kLoadWord, T2, SP, 28);
72 __ LoadFromOffset(kLoadWord, T3, SP, 32);
73 __ LoadFromOffset(kLoadWord, T4, SP, 36);
74 __ LoadFromOffset(kLoadWord, T5, SP, 40);
75 __ LoadFromOffset(kLoadWord, T6, SP, 44);
76 __ LoadFromOffset(kLoadWord, T7, SP, 48);
77 __ LoadFromOffset(kLoadWord, T8, SP, 52);
78 __ LoadFromOffset(kLoadWord, T9, SP, 56);
79 __ LoadFromOffset(kLoadWord, RA, SP, 60);
80 __ AddConstant(SP, SP, 64);
81
82 __ Move(A0, V0); // Put returned Method* into A0
83 __ Jr(V0); // Leaf call to method's code
84
85 __ Break();
86#else // ART_USE_LLVM_COMPILER
87 // Build frame and save argument registers and RA.
88 __ AddConstant(SP, SP, -32);
89 __ StoreToOffset(kStoreWord, RA, SP, 28);
90 __ StoreToOffset(kStoreWord, A3, SP, 24);
91 __ StoreToOffset(kStoreWord, A2, SP, 20);
92 __ StoreToOffset(kStoreWord, A1, SP, 16);
93 __ StoreToOffset(kStoreWord, A0, SP, 12);
94
95 __ LoadFromOffset(kLoadWord, T9, S1,
96 ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
jeffhao0ac41d52012-08-27 13:07:54 -070097 __ Move(A2, S1); // Pass Thread::Current() in A2
jeffhao7fbee072012-08-24 17:56:54 -070098 __ LoadImmediate(A3, type); // Pass is_static
jeffhao0ac41d52012-08-27 13:07:54 -070099 __ Move(A1, SP); // Pass SP for Method** callee_addr
jeffhao7fbee072012-08-24 17:56:54 -0700100 __ Jalr(T9); // Call to unresolved direct method trampoline (callee, callee_addr, Thread*, is_static)
101
102 // Restore frame, argument registers, and RA.
103 __ LoadFromOffset(kLoadWord, A0, SP, 12);
104 __ LoadFromOffset(kLoadWord, A1, SP, 16);
105 __ LoadFromOffset(kLoadWord, A2, SP, 20);
106 __ LoadFromOffset(kLoadWord, A3, SP, 24);
107 __ LoadFromOffset(kLoadWord, RA, SP, 28);
108 __ AddConstant(SP, SP, 32);
109
110 Label resolve_fail;
111 __ EmitBranch(V0, ZERO, &resolve_fail, true);
112 __ Jr(V0); // If V0 != 0 tail call method's code
113 __ Bind(&resolve_fail, false);
114 __ Jr(RA); // Return to caller to handle exception
115#endif // ART_USE_LLVM_COMPILER
116
117 assembler->EmitSlowPaths();
118
119 size_t cs = assembler->CodeSize();
120 SirtRef<ByteArray> resolution_trampoline(ByteArray::Alloc(cs));
121 CHECK(resolution_trampoline.get() != NULL);
122 MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
123 assembler->FinalizeInstructions(code);
124
125 return resolution_trampoline.get();
126}
127
Mathieu Chartier66f19252012-09-18 08:57:04 -0700128typedef void (*ThrowAme)(AbstractMethod*, Thread*);
jeffhao7fbee072012-08-24 17:56:54 -0700129
130ByteArray* CreateAbstractMethodErrorStub() {
131 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
132#if !defined(ART_USE_LLVM_COMPILER)
133 // Save callee saves and ready frame for exception delivery
jeffhao07030602012-09-26 14:33:14 -0700134 __ AddConstant(SP, SP, -48);
135 __ StoreToOffset(kStoreWord, RA, SP, 44);
136 __ StoreToOffset(kStoreWord, T9, SP, 40);
137 __ StoreToOffset(kStoreWord, T8, SP, 36);
138 __ StoreToOffset(kStoreWord, T7, SP, 32);
139 __ StoreToOffset(kStoreWord, T6, SP, 28);
140 __ StoreToOffset(kStoreWord, T5, SP, 24);
141 __ StoreToOffset(kStoreWord, T4, SP, 20);
142 __ StoreToOffset(kStoreWord, T3, SP, 16);
143 __ StoreToOffset(kStoreWord, T2, SP, 12);
144 __ StoreToOffset(kStoreWord, T1, SP, 8);
145 __ StoreToOffset(kStoreWord, T0, SP, 4);
jeffhao7fbee072012-08-24 17:56:54 -0700146
jeffhao07030602012-09-26 14:33:14 -0700147 // A0 is the Method* already
jeffhao7fbee072012-08-24 17:56:54 -0700148 __ Move(A1, S1); // Pass Thread::Current() in A1
149 __ Move(A2, SP); // Pass SP in A2
150 // Call to throw AbstractMethodError
151 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
152 __ Jr(T9); // Leaf call to routine that never returns
153
154 __ Break();
155#else // ART_USE_LLVM_COMPILER
156 // R0 is the Method* already
157 __ Move(A1, S1); // Pass Thread::Current() in A1
158 // Call to throw AbstractMethodError
159 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
160 __ Jr(T9); // Leaf call to routine that never returns
161
162 __ Break();
163#endif // ART_USE_LLVM_COMPILER
164
165 assembler->EmitSlowPaths();
166
167 size_t cs = assembler->CodeSize();
168 SirtRef<ByteArray> abstract_stub(ByteArray::Alloc(cs));
169 CHECK(abstract_stub.get() != NULL);
170 MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
171 assembler->FinalizeInstructions(code);
172
173 return abstract_stub.get();
174}
175
176ByteArray* CreateJniDlsymLookupStub() {
177 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
178
179 // Build frame and save argument registers and RA.
180 __ AddConstant(SP, SP, -32);
181 __ StoreToOffset(kStoreWord, RA, SP, 28);
182 __ StoreToOffset(kStoreWord, A3, SP, 24);
183 __ StoreToOffset(kStoreWord, A2, SP, 20);
184 __ StoreToOffset(kStoreWord, A1, SP, 16);
185 __ StoreToOffset(kStoreWord, A0, SP, 12);
186
187 __ Move(A0, S1); // Pass Thread::Current() in A0
188 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pFindNativeMethod));
189 __ Jalr(T9); // Call FindNativeMethod
190
191 // Restore frame, argument registers, and RA.
192 __ LoadFromOffset(kLoadWord, A0, SP, 12);
193 __ LoadFromOffset(kLoadWord, A1, SP, 16);
194 __ LoadFromOffset(kLoadWord, A2, SP, 20);
195 __ LoadFromOffset(kLoadWord, A3, SP, 24);
196 __ LoadFromOffset(kLoadWord, RA, SP, 28);
197 __ AddConstant(SP, SP, 32);
198
199 Label no_native_code_found;
200 __ EmitBranch(V0, ZERO, &no_native_code_found, true);
201 __ Jr(V0); // If V0 != 0 tail call method's code
202 __ Bind(&no_native_code_found, false);
203 __ Jr(RA); // Return to caller to handle exception
204
205 assembler->EmitSlowPaths();
206
207 size_t cs = assembler->CodeSize();
208 SirtRef<ByteArray> jni_stub(ByteArray::Alloc(cs));
209 CHECK(jni_stub.get() != NULL);
210 MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
211 assembler->FinalizeInstructions(code);
212
213 return jni_stub.get();
214}
215
216} // namespace mips
217} // namespace art