blob: 3f6bc8f2aebe125f5c234571ffc705f27b72e75b [file] [log] [blame]
Ian Rogers57b86d42012-03-27 16:05:41 -07001/*
Elliott Hughes0f3c5532012-03-30 14:51:51 -07002 * Copyright (C) 2012 The Android Open Source Project
Ian Rogers57b86d42012-03-27 16:05:41 -07003 *
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
TDYa12705fe3b62012-04-21 00:28:54 -070017#if !defined(ART_USE_LLVM_COMPILER)
Ian Rogers57b86d42012-03-27 16:05:41 -070018#include "callee_save_frame.h"
TDYa12705fe3b62012-04-21 00:28:54 -070019#endif
Ian Rogers57b86d42012-03-27 16:05:41 -070020#include "dex_instruction.h"
21#include "object.h"
22#include "object_utils.h"
TDYa12705fe3b62012-04-21 00:28:54 -070023#if defined(ART_USE_LLVM_COMPILER)
24#include "nth_caller_visitor.h"
25#endif
Ian Rogers365c1022012-06-22 15:05:28 -070026#include "scoped_jni_thread_state.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070027
28// Architecture specific assembler helper to deliver exception.
29extern "C" void art_deliver_exception_from_code(void*);
30
31namespace art {
32
TDYa12705fe3b62012-04-21 00:28:54 -070033#if !defined(ART_USE_LLVM_COMPILER)
Ian Rogers57b86d42012-03-27 16:05:41 -070034// Lazily resolve a method. Called by stub code.
35const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** sp, Thread* thread,
36 Runtime::TrampolineType type) {
Ian Rogers7caad772012-03-30 01:07:54 -070037#if defined(__arm__)
Ian Rogers57b86d42012-03-27 16:05:41 -070038 // On entry the stack pointed by sp is:
39 // | argN | |
40 // | ... | |
41 // | arg4 | |
42 // | arg3 spill | | Caller's frame
43 // | arg2 spill | |
44 // | arg1 spill | |
45 // | Method* | ---
46 // | LR |
47 // | ... | callee saves
48 // | R3 | arg3
49 // | R2 | arg2
50 // | R1 | arg1
51 // | R0 |
52 // | Method* | <- sp
Ian Rogers57b86d42012-03-27 16:05:41 -070053 DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
54 Method** caller_sp = reinterpret_cast<Method**>(reinterpret_cast<byte*>(sp) + 48);
Ian Rogers7caad772012-03-30 01:07:54 -070055 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
Ian Rogers57b86d42012-03-27 16:05:41 -070056 uintptr_t caller_pc = regs[10];
Ian Rogers7caad772012-03-30 01:07:54 -070057#elif defined(__i386__)
58 // On entry the stack pointed by sp is:
59 // | argN | |
60 // | ... | |
61 // | arg4 | |
62 // | arg3 spill | | Caller's frame
63 // | arg2 spill | |
64 // | arg1 spill | |
65 // | Method* | ---
66 // | Return |
67 // | EBP,ESI,EDI | callee saves
68 // | EBX | arg3
69 // | EDX | arg2
70 // | ECX | arg1
71 // | EAX/Method* | <- sp
72 DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
73 Method** caller_sp = reinterpret_cast<Method**>(reinterpret_cast<byte*>(sp) + 32);
74 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
75 uintptr_t caller_pc = regs[7];
76#else
77 UNIMPLEMENTED(FATAL);
78 Method** caller_sp = NULL;
79 uintptr_t* regs = NULL;
80 uintptr_t caller_pc = 0;
81#endif
Ian Rogers57b86d42012-03-27 16:05:41 -070082 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
83 // Start new JNI local reference state
84 JNIEnvExt* env = thread->GetJniEnv();
Ian Rogers365c1022012-06-22 15:05:28 -070085 ScopedJniThreadState ts(env);
Ian Rogers57b86d42012-03-27 16:05:41 -070086 ScopedJniEnvLocalRefState env_state(env);
87
88 // Compute details about the called method (avoid GCs)
89 ClassLinker* linker = Runtime::Current()->GetClassLinker();
90 Method* caller = *caller_sp;
91 bool is_static;
92 bool is_virtual;
93 uint32_t dex_method_idx;
Brian Carlstromfd2ec542012-05-02 15:08:57 -070094#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -070095 const char* shorty;
96 uint32_t shorty_len;
Brian Carlstromfd2ec542012-05-02 15:08:57 -070097#endif
Ian Rogers57b86d42012-03-27 16:05:41 -070098 if (type == Runtime::kUnknownMethod) {
99 DCHECK(called->IsRuntimeMethod());
100 // less two as return address may span into next dex instruction
101 uint32_t dex_pc = caller->ToDexPC(caller_pc - 2);
102 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
103 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
104 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
105 Instruction::Code instr_code = instr->Opcode();
106 is_static = (instr_code == Instruction::INVOKE_STATIC) ||
107 (instr_code == Instruction::INVOKE_STATIC_RANGE);
108 is_virtual = (instr_code == Instruction::INVOKE_VIRTUAL) ||
109 (instr_code == Instruction::INVOKE_VIRTUAL_RANGE) ||
110 (instr_code == Instruction::INVOKE_SUPER) ||
111 (instr_code == Instruction::INVOKE_SUPER_RANGE);
112 DCHECK(is_static || is_virtual || (instr_code == Instruction::INVOKE_DIRECT) ||
113 (instr_code == Instruction::INVOKE_DIRECT_RANGE));
114 DecodedInstruction dec_insn(instr);
115 dex_method_idx = dec_insn.vB;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700116#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700117 shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700118#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700119 } else {
120 DCHECK(!called->IsRuntimeMethod());
121 is_static = type == Runtime::kStaticMethod;
122 is_virtual = false;
123 dex_method_idx = called->GetDexMethodIndex();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700124#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700125 MethodHelper mh(called);
126 shorty = mh.GetShorty();
127 shorty_len = mh.GetShortyLength();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700128#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700129 }
Ian Rogers7caad772012-03-30 01:07:54 -0700130#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700131 // Discover shorty (avoid GCs)
132 size_t args_in_regs = 0;
133 for (size_t i = 1; i < shorty_len; i++) {
134 char c = shorty[i];
135 args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
136 if (args_in_regs > 3) {
137 args_in_regs = 3;
138 break;
139 }
140 }
141 // Place into local references incoming arguments from the caller's register arguments
142 size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1
143 if (!is_static) {
144 Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
145 cur_arg++;
146 if (args_in_regs < 3) {
147 // If we thought we had fewer than 3 arguments in registers, account for the receiver
148 args_in_regs++;
149 }
Ian Rogers365c1022012-06-22 15:05:28 -0700150 ts.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700151 }
152 size_t shorty_index = 1; // skip return value
153 // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
154 // R0)
155 while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
156 char c = shorty[shorty_index];
157 shorty_index++;
158 if (c == 'L') {
159 Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
Ian Rogers365c1022012-06-22 15:05:28 -0700160 ts.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700161 }
162 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
163 }
164 // Place into local references incoming arguments from the caller's stack arguments
165 cur_arg += 11; // skip LR, Method* and spills for R1 to R3 and callee saves
166 while (shorty_index < shorty_len) {
167 char c = shorty[shorty_index];
168 shorty_index++;
169 if (c == 'L') {
170 Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
Ian Rogers365c1022012-06-22 15:05:28 -0700171 ts.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700172 }
173 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
174 }
Ian Rogers7caad772012-03-30 01:07:54 -0700175#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700176 // Resolve method filling in dex cache
177 if (type == Runtime::kUnknownMethod) {
178 called = linker->ResolveMethod(dex_method_idx, caller, !is_virtual);
179 }
180 const void* code = NULL;
181 if (LIKELY(!thread->IsExceptionPending())) {
182 if (LIKELY(called->IsDirect() == !is_virtual)) {
183 // Ensure that the called method's class is initialized.
184 Class* called_class = called->GetDeclaringClass();
Ian Rogers0045a292012-03-31 21:08:41 -0700185 linker->EnsureInitialized(called_class, true, true);
Ian Rogers57b86d42012-03-27 16:05:41 -0700186 if (LIKELY(called_class->IsInitialized())) {
187 code = called->GetCode();
188 } else if (called_class->IsInitializing()) {
189 if (is_static) {
190 // Class is still initializing, go to oat and grab code (trampoline must be left in place
191 // until class is initialized to stop races between threads).
192 code = linker->GetOatCodeFor(called);
193 } else {
194 // No trampoline for non-static methods.
195 code = called->GetCode();
196 }
197 } else {
198 DCHECK(called_class->IsErroneous());
199 }
200 } else {
201 // Direct method has been made virtual
202 thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
203 "Expected direct method but found virtual: %s",
204 PrettyMethod(called, true).c_str());
205 }
206 }
207 if (UNLIKELY(code == NULL)) {
208 // Something went wrong in ResolveMethod or EnsureInitialized,
209 // go into deliver exception with the pending exception in r0
210 code = reinterpret_cast<void*>(art_deliver_exception_from_code);
211 regs[0] = reinterpret_cast<uintptr_t>(thread->GetException());
212 thread->ClearException();
213 } else {
214 // Expect class to at least be initializing.
215 DCHECK(called->GetDeclaringClass()->IsInitializing());
216 // Don't want infinite recursion.
217 DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
218 // Set up entry into main method
219 regs[0] = reinterpret_cast<uintptr_t>(called);
220 }
221 return code;
222}
TDYa12705fe3b62012-04-21 00:28:54 -0700223#else // ART_USE_LLVM_COMPILER
224const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** called_addr,
225 Thread* thread, Runtime::TrampolineType type) {
Ian Rogers0399dde2012-06-06 17:09:28 -0700226 uint32_t dex_pc;
227 Method* caller = thread->GetCurrentMethod(&dex_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -0700228
TDYa12705fe3b62012-04-21 00:28:54 -0700229 ClassLinker* linker = Runtime::Current()->GetClassLinker();
230 bool is_static;
231 bool is_virtual;
232 uint32_t dex_method_idx;
233 if (type == Runtime::kUnknownMethod) {
234 DCHECK(called->IsRuntimeMethod());
TDYa12705fe3b62012-04-21 00:28:54 -0700235 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
236 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
237 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
238 Instruction::Code instr_code = instr->Opcode();
239 is_static = (instr_code == Instruction::INVOKE_STATIC) ||
240 (instr_code == Instruction::INVOKE_STATIC_RANGE);
241 is_virtual = (instr_code == Instruction::INVOKE_VIRTUAL) ||
242 (instr_code == Instruction::INVOKE_VIRTUAL_RANGE) ||
243 (instr_code == Instruction::INVOKE_SUPER) ||
244 (instr_code == Instruction::INVOKE_SUPER_RANGE);
245 DCHECK(is_static || is_virtual || (instr_code == Instruction::INVOKE_DIRECT) ||
246 (instr_code == Instruction::INVOKE_DIRECT_RANGE));
247 DecodedInstruction dec_insn(instr);
248 dex_method_idx = dec_insn.vB;
249 } else {
250 DCHECK(!called->IsRuntimeMethod());
251 is_static = type == Runtime::kStaticMethod;
252 is_virtual = false;
253 dex_method_idx = called->GetDexMethodIndex();
254 }
255 if (type == Runtime::kUnknownMethod) {
256 called = linker->ResolveMethod(dex_method_idx, caller, !is_virtual);
257 }
258 const void* code = NULL;
259 if (LIKELY(!thread->IsExceptionPending())) {
260 if (LIKELY(called->IsDirect() == !is_virtual)) {
261 // Ensure that the called method's class is initialized.
262 Class* called_class = called->GetDeclaringClass();
263 linker->EnsureInitialized(called_class, true, true);
264 if (LIKELY(called_class->IsInitialized())) {
265 code = called->GetCode();
266 // TODO: remove this after we solve the link issue.
267 { // for lazy link.
268 if (code == NULL) {
269 code = linker->GetOatCodeFor(called);
270 }
271 }
272 } else if (called_class->IsInitializing()) {
273 if (is_static) {
274 // Class is still initializing, go to oat and grab code (trampoline must be left in place
275 // until class is initialized to stop races between threads).
276 code = linker->GetOatCodeFor(called);
277 } else {
278 // No trampoline for non-static methods.
279 code = called->GetCode();
280 // TODO: remove this after we solve the link issue.
281 { // for lazy link.
282 if (code == NULL) {
283 code = linker->GetOatCodeFor(called);
284 }
285 }
286 }
287 } else {
288 DCHECK(called_class->IsErroneous());
289 }
290 } else {
291 // Direct method has been made virtual
292 thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
293 "Expected direct method but found virtual: %s",
294 PrettyMethod(called, true).c_str());
295 }
296 }
297 if (LIKELY(code != NULL)) {
298 // Expect class to at least be initializing.
299 DCHECK(called->GetDeclaringClass()->IsInitializing());
300 // Don't want infinite recursion.
301 DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
302 // Set up entry into main method
303 *called_addr = called;
304 }
305 return code;
306}
307#endif // ART_USE_LLVM_COMPILER
308
309#if !defined(ART_USE_LLVM_COMPILER)
Ian Rogers57b86d42012-03-27 16:05:41 -0700310// Called by the AbstractMethodError. Called by stub code.
311extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp) {
312 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
313 thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
314 "abstract method \"%s\"", PrettyMethod(method).c_str());
315 thread->DeliverException();
316}
TDYa12705fe3b62012-04-21 00:28:54 -0700317#else // ART_USE_LLVM_COMPILER
318extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method**) {
319 thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
320 "abstract method \"%s\"", PrettyMethod(method).c_str());
321}
322#endif // ART_USE_LLVM_COMPILER
Ian Rogers57b86d42012-03-27 16:05:41 -0700323
324} // namespace art