blob: 7b4c85ee80d25329d307c3194927a02943e9d3dd [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);
jeffhao4f8f04a2012-10-02 18:10:35 -070044 __ StoreToOffset(kStoreWord, FP, SP, 56);
45 __ StoreToOffset(kStoreWord, S7, SP, 52);
46 __ StoreToOffset(kStoreWord, S6, SP, 48);
47 __ StoreToOffset(kStoreWord, S5, SP, 44);
48 __ StoreToOffset(kStoreWord, S4, SP, 40);
49 __ StoreToOffset(kStoreWord, S3, SP, 36);
50 __ StoreToOffset(kStoreWord, S2, SP, 32);
51 __ StoreToOffset(kStoreWord, A3, SP, 28);
52 __ StoreToOffset(kStoreWord, A2, SP, 24);
53 __ StoreToOffset(kStoreWord, A1, SP, 20);
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
jeffhao4f8f04a2012-10-02 18:10:35 -070063 __ LoadFromOffset(kLoadWord, A1, SP, 20);
64 __ LoadFromOffset(kLoadWord, A2, SP, 24);
65 __ LoadFromOffset(kLoadWord, A3, SP, 28);
66 __ LoadFromOffset(kLoadWord, S2, SP, 32);
67 __ LoadFromOffset(kLoadWord, S3, SP, 36);
68 __ LoadFromOffset(kLoadWord, S4, SP, 40);
69 __ LoadFromOffset(kLoadWord, S5, SP, 44);
70 __ LoadFromOffset(kLoadWord, S6, SP, 48);
71 __ LoadFromOffset(kLoadWord, S7, SP, 52);
72 __ LoadFromOffset(kLoadWord, FP, SP, 56);
jeffhao7fbee072012-08-24 17:56:54 -070073 __ LoadFromOffset(kLoadWord, RA, SP, 60);
74 __ AddConstant(SP, SP, 64);
75
76 __ Move(A0, V0); // Put returned Method* into A0
77 __ Jr(V0); // Leaf call to method's code
78
79 __ Break();
80#else // ART_USE_LLVM_COMPILER
81 // Build frame and save argument registers and RA.
82 __ AddConstant(SP, SP, -32);
83 __ StoreToOffset(kStoreWord, RA, SP, 28);
84 __ StoreToOffset(kStoreWord, A3, SP, 24);
85 __ StoreToOffset(kStoreWord, A2, SP, 20);
86 __ StoreToOffset(kStoreWord, A1, SP, 16);
87 __ StoreToOffset(kStoreWord, A0, SP, 12);
88
89 __ LoadFromOffset(kLoadWord, T9, S1,
90 ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
jeffhao0ac41d52012-08-27 13:07:54 -070091 __ Move(A2, S1); // Pass Thread::Current() in A2
jeffhao7fbee072012-08-24 17:56:54 -070092 __ LoadImmediate(A3, type); // Pass is_static
jeffhao0ac41d52012-08-27 13:07:54 -070093 __ Move(A1, SP); // Pass SP for Method** callee_addr
jeffhao7fbee072012-08-24 17:56:54 -070094 __ Jalr(T9); // Call to unresolved direct method trampoline (callee, callee_addr, Thread*, is_static)
95
96 // Restore frame, argument registers, and RA.
97 __ LoadFromOffset(kLoadWord, A0, SP, 12);
98 __ LoadFromOffset(kLoadWord, A1, SP, 16);
99 __ LoadFromOffset(kLoadWord, A2, SP, 20);
100 __ LoadFromOffset(kLoadWord, A3, SP, 24);
101 __ LoadFromOffset(kLoadWord, RA, SP, 28);
102 __ AddConstant(SP, SP, 32);
103
104 Label resolve_fail;
105 __ EmitBranch(V0, ZERO, &resolve_fail, true);
106 __ Jr(V0); // If V0 != 0 tail call method's code
107 __ Bind(&resolve_fail, false);
108 __ Jr(RA); // Return to caller to handle exception
109#endif // ART_USE_LLVM_COMPILER
110
111 assembler->EmitSlowPaths();
112
113 size_t cs = assembler->CodeSize();
114 SirtRef<ByteArray> resolution_trampoline(ByteArray::Alloc(cs));
115 CHECK(resolution_trampoline.get() != NULL);
116 MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
117 assembler->FinalizeInstructions(code);
118
119 return resolution_trampoline.get();
120}
121
Mathieu Chartier66f19252012-09-18 08:57:04 -0700122typedef void (*ThrowAme)(AbstractMethod*, Thread*);
jeffhao7fbee072012-08-24 17:56:54 -0700123
124ByteArray* CreateAbstractMethodErrorStub() {
125 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
126#if !defined(ART_USE_LLVM_COMPILER)
127 // Save callee saves and ready frame for exception delivery
jeffhao07030602012-09-26 14:33:14 -0700128 __ AddConstant(SP, SP, -48);
129 __ StoreToOffset(kStoreWord, RA, SP, 44);
jeffhao4f8f04a2012-10-02 18:10:35 -0700130 __ StoreToOffset(kStoreWord, FP, SP, 40);
131 __ StoreToOffset(kStoreWord, S7, SP, 36);
132 __ StoreToOffset(kStoreWord, S6, SP, 32);
133 __ StoreToOffset(kStoreWord, S5, SP, 28);
134 __ StoreToOffset(kStoreWord, S4, SP, 24);
135 __ StoreToOffset(kStoreWord, S3, SP, 20);
136 __ StoreToOffset(kStoreWord, S2, SP, 16);
jeffhao7fbee072012-08-24 17:56:54 -0700137
jeffhao07030602012-09-26 14:33:14 -0700138 // A0 is the Method* already
jeffhao7fbee072012-08-24 17:56:54 -0700139 __ Move(A1, S1); // Pass Thread::Current() in A1
140 __ Move(A2, SP); // Pass SP in A2
141 // Call to throw AbstractMethodError
142 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
143 __ Jr(T9); // Leaf call to routine that never returns
144
145 __ Break();
146#else // ART_USE_LLVM_COMPILER
147 // R0 is the Method* already
148 __ Move(A1, S1); // Pass Thread::Current() in A1
149 // Call to throw AbstractMethodError
150 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
151 __ Jr(T9); // Leaf call to routine that never returns
152
153 __ Break();
154#endif // ART_USE_LLVM_COMPILER
155
156 assembler->EmitSlowPaths();
157
158 size_t cs = assembler->CodeSize();
159 SirtRef<ByteArray> abstract_stub(ByteArray::Alloc(cs));
160 CHECK(abstract_stub.get() != NULL);
161 MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
162 assembler->FinalizeInstructions(code);
163
164 return abstract_stub.get();
165}
166
167ByteArray* CreateJniDlsymLookupStub() {
168 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
169
170 // Build frame and save argument registers and RA.
171 __ AddConstant(SP, SP, -32);
172 __ StoreToOffset(kStoreWord, RA, SP, 28);
173 __ StoreToOffset(kStoreWord, A3, SP, 24);
174 __ StoreToOffset(kStoreWord, A2, SP, 20);
175 __ StoreToOffset(kStoreWord, A1, SP, 16);
176 __ StoreToOffset(kStoreWord, A0, SP, 12);
177
178 __ Move(A0, S1); // Pass Thread::Current() in A0
179 __ LoadFromOffset(kLoadWord, T9, S1, ENTRYPOINT_OFFSET(pFindNativeMethod));
180 __ Jalr(T9); // Call FindNativeMethod
181
182 // Restore frame, argument registers, and RA.
183 __ LoadFromOffset(kLoadWord, A0, SP, 12);
184 __ LoadFromOffset(kLoadWord, A1, SP, 16);
185 __ LoadFromOffset(kLoadWord, A2, SP, 20);
186 __ LoadFromOffset(kLoadWord, A3, SP, 24);
187 __ LoadFromOffset(kLoadWord, RA, SP, 28);
188 __ AddConstant(SP, SP, 32);
189
190 Label no_native_code_found;
191 __ EmitBranch(V0, ZERO, &no_native_code_found, true);
192 __ Jr(V0); // If V0 != 0 tail call method's code
193 __ Bind(&no_native_code_found, false);
194 __ Jr(RA); // Return to caller to handle exception
195
196 assembler->EmitSlowPaths();
197
198 size_t cs = assembler->CodeSize();
199 SirtRef<ByteArray> jni_stub(ByteArray::Alloc(cs));
200 CHECK(jni_stub.get() != NULL);
201 MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
202 assembler->FinalizeInstructions(code);
203
204 return jni_stub.get();
205}
206
207} // namespace mips
208} // namespace art