blob: 9e33c43026166598e948ddcc32ba5b7a1af0c082 [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 Rogers00f7d0e2012-07-19 15:28:27 -070026#include "scoped_thread_state_change.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.
Mathieu Chartier66f19252012-09-18 08:57:04 -070035const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, AbstractMethod** sp, Thread* thread,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070036 Runtime::TrampolineType type)
Ian Rogersb726dcb2012-09-05 08:57:23 -070037 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers7caad772012-03-30 01:07:54 -070038#if defined(__arm__)
Ian Rogers57b86d42012-03-27 16:05:41 -070039 // On entry the stack pointed by sp is:
40 // | argN | |
41 // | ... | |
42 // | arg4 | |
43 // | arg3 spill | | Caller's frame
44 // | arg2 spill | |
45 // | arg1 spill | |
46 // | Method* | ---
47 // | LR |
48 // | ... | callee saves
49 // | R3 | arg3
50 // | R2 | arg2
51 // | R1 | arg1
52 // | R0 |
53 // | Method* | <- sp
Ian Rogers57b86d42012-03-27 16:05:41 -070054 DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Mathieu Chartier66f19252012-09-18 08:57:04 -070055 AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
Ian Rogers7caad772012-03-30 01:07:54 -070056 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
jeffhaofa147e22012-10-12 17:03:32 -070057 uint32_t pc_offset = 10;
58 uintptr_t caller_pc = regs[pc_offset];
Ian Rogers7caad772012-03-30 01:07:54 -070059#elif defined(__i386__)
60 // On entry the stack pointed by sp is:
61 // | argN | |
62 // | ... | |
63 // | arg4 | |
64 // | arg3 spill | | Caller's frame
65 // | arg2 spill | |
66 // | arg1 spill | |
67 // | Method* | ---
68 // | Return |
69 // | EBP,ESI,EDI | callee saves
70 // | EBX | arg3
71 // | EDX | arg2
72 // | ECX | arg1
73 // | EAX/Method* | <- sp
74 DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Mathieu Chartier66f19252012-09-18 08:57:04 -070075 AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 32);
Ian Rogers7caad772012-03-30 01:07:54 -070076 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
77 uintptr_t caller_pc = regs[7];
jeffhaofa147e22012-10-12 17:03:32 -070078#elif defined(__mips__)
79 // On entry the stack pointed by sp is:
80 // | argN | |
81 // | ... | |
82 // | arg4 | |
83 // | arg3 spill | | Caller's frame
84 // | arg2 spill | |
85 // | arg1 spill | |
86 // | Method* | ---
87 // | RA |
88 // | ... | callee saves
89 // | A3 | arg3
90 // | A2 | arg2
91 // | A1 | arg1
92 // | A0/Method* | <- sp
93 DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
94 AbstractMethod** caller_sp = reinterpret_cast<AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
95 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
96 uint32_t pc_offset = 11;
97 uintptr_t caller_pc = regs[pc_offset];
Ian Rogers7caad772012-03-30 01:07:54 -070098#else
99 UNIMPLEMENTED(FATAL);
Mathieu Chartier66f19252012-09-18 08:57:04 -0700100 AbstractMethod** caller_sp = NULL;
Ian Rogers7caad772012-03-30 01:07:54 -0700101 uintptr_t* regs = NULL;
102 uintptr_t caller_pc = 0;
103#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700104 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
105 // Start new JNI local reference state
106 JNIEnvExt* env = thread->GetJniEnv();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700107 ScopedObjectAccessUnchecked soa(env);
Ian Rogers57b86d42012-03-27 16:05:41 -0700108 ScopedJniEnvLocalRefState env_state(env);
109
110 // Compute details about the called method (avoid GCs)
111 ClassLinker* linker = Runtime::Current()->GetClassLinker();
Mathieu Chartier66f19252012-09-18 08:57:04 -0700112 AbstractMethod* caller = *caller_sp;
Ian Rogers08f753d2012-08-24 14:35:25 -0700113 InvokeType invoke_type;
Ian Rogers57b86d42012-03-27 16:05:41 -0700114 uint32_t dex_method_idx;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700115#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700116 const char* shorty;
117 uint32_t shorty_len;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700118#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700119 if (type == Runtime::kUnknownMethod) {
120 DCHECK(called->IsRuntimeMethod());
Ian Rogers0c7abda2012-09-19 13:33:42 -0700121 uint32_t dex_pc = caller->ToDexPc(caller_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -0700122 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
123 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
124 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
125 Instruction::Code instr_code = instr->Opcode();
Ian Rogers08f753d2012-08-24 14:35:25 -0700126 switch (instr_code) {
127 case Instruction::INVOKE_DIRECT: // Fall-through.
128 case Instruction::INVOKE_DIRECT_RANGE:
129 invoke_type = kDirect;
130 break;
131 case Instruction::INVOKE_STATIC: // Fall-through.
132 case Instruction::INVOKE_STATIC_RANGE:
133 invoke_type = kStatic;
134 break;
135 case Instruction::INVOKE_SUPER: // Fall-through.
136 case Instruction::INVOKE_SUPER_RANGE:
137 invoke_type = kSuper;
138 break;
139 case Instruction::INVOKE_VIRTUAL: // Fall-through.
140 case Instruction::INVOKE_VIRTUAL_RANGE:
141 invoke_type = kVirtual;
142 break;
143 default:
144 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
145 invoke_type = kDirect; // Avoid used uninitialized warnings.
146 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700147 DecodedInstruction dec_insn(instr);
148 dex_method_idx = dec_insn.vB;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700149#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700150 shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700151#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700152 } else {
153 DCHECK(!called->IsRuntimeMethod());
Ian Rogers08f753d2012-08-24 14:35:25 -0700154 invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
Ian Rogers57b86d42012-03-27 16:05:41 -0700155 dex_method_idx = called->GetDexMethodIndex();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700156#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700157 MethodHelper mh(called);
158 shorty = mh.GetShorty();
159 shorty_len = mh.GetShortyLength();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700160#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700161 }
Ian Rogers7caad772012-03-30 01:07:54 -0700162#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700163 // Discover shorty (avoid GCs)
164 size_t args_in_regs = 0;
165 for (size_t i = 1; i < shorty_len; i++) {
166 char c = shorty[i];
167 args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
168 if (args_in_regs > 3) {
169 args_in_regs = 3;
170 break;
171 }
172 }
173 // Place into local references incoming arguments from the caller's register arguments
174 size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1
Ian Rogers08f753d2012-08-24 14:35:25 -0700175 if (invoke_type != kStatic) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700176 Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
177 cur_arg++;
178 if (args_in_regs < 3) {
179 // If we thought we had fewer than 3 arguments in registers, account for the receiver
180 args_in_regs++;
181 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700182 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700183 }
184 size_t shorty_index = 1; // skip return value
185 // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
186 // R0)
187 while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
188 char c = shorty[shorty_index];
189 shorty_index++;
190 if (c == 'L') {
191 Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700192 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700193 }
194 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
195 }
196 // Place into local references incoming arguments from the caller's stack arguments
jeffhaofa147e22012-10-12 17:03:32 -0700197 cur_arg += pc_offset + 1; // skip LR/RA, Method* and spills for R1-R3/A1-A3 and callee saves
Ian Rogers57b86d42012-03-27 16:05:41 -0700198 while (shorty_index < shorty_len) {
199 char c = shorty[shorty_index];
200 shorty_index++;
201 if (c == 'L') {
202 Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700203 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700204 }
205 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
206 }
Ian Rogers7caad772012-03-30 01:07:54 -0700207#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700208 // Resolve method filling in dex cache
209 if (type == Runtime::kUnknownMethod) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700210 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
Ian Rogers57b86d42012-03-27 16:05:41 -0700211 }
212 const void* code = NULL;
213 if (LIKELY(!thread->IsExceptionPending())) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700214 // Incompatible class change should have been handled in resolve method.
215 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
216 // Ensure that the called method's class is initialized.
217 Class* called_class = called->GetDeclaringClass();
218 linker->EnsureInitialized(called_class, true, true);
219 if (LIKELY(called_class->IsInitialized())) {
220 code = called->GetCode();
221 } else if (called_class->IsInitializing()) {
222 if (invoke_type == kStatic) {
223 // Class is still initializing, go to oat and grab code (trampoline must be left in place
224 // until class is initialized to stop races between threads).
225 code = linker->GetOatCodeFor(called);
Ian Rogers57b86d42012-03-27 16:05:41 -0700226 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700227 // No trampoline for non-static methods.
228 code = called->GetCode();
Ian Rogers57b86d42012-03-27 16:05:41 -0700229 }
230 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700231 DCHECK(called_class->IsErroneous());
Ian Rogers57b86d42012-03-27 16:05:41 -0700232 }
233 }
234 if (UNLIKELY(code == NULL)) {
235 // Something went wrong in ResolveMethod or EnsureInitialized,
236 // go into deliver exception with the pending exception in r0
237 code = reinterpret_cast<void*>(art_deliver_exception_from_code);
238 regs[0] = reinterpret_cast<uintptr_t>(thread->GetException());
239 thread->ClearException();
240 } else {
241 // Expect class to at least be initializing.
242 DCHECK(called->GetDeclaringClass()->IsInitializing());
243 // Don't want infinite recursion.
244 DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
245 // Set up entry into main method
246 regs[0] = reinterpret_cast<uintptr_t>(called);
247 }
248 return code;
249}
TDYa12705fe3b62012-04-21 00:28:54 -0700250#else // ART_USE_LLVM_COMPILER
Mathieu Chartier66f19252012-09-18 08:57:04 -0700251const void* UnresolvedDirectMethodTrampolineFromCode(AbstractMethod* called, AbstractMethod** called_addr,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700252 Thread* thread, Runtime::TrampolineType type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700253 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers0399dde2012-06-06 17:09:28 -0700254 uint32_t dex_pc;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700255 AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -0700256
TDYa12705fe3b62012-04-21 00:28:54 -0700257 ClassLinker* linker = Runtime::Current()->GetClassLinker();
Ian Rogers08f753d2012-08-24 14:35:25 -0700258 InvokeType invoke_type;
TDYa12705fe3b62012-04-21 00:28:54 -0700259 uint32_t dex_method_idx;
260 if (type == Runtime::kUnknownMethod) {
261 DCHECK(called->IsRuntimeMethod());
TDYa12705fe3b62012-04-21 00:28:54 -0700262 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
263 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
264 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
265 Instruction::Code instr_code = instr->Opcode();
Ian Rogers08f753d2012-08-24 14:35:25 -0700266 switch (instr_code) {
267 case Instruction::INVOKE_DIRECT: // Fall-through.
268 case Instruction::INVOKE_DIRECT_RANGE:
269 invoke_type = kDirect;
270 break;
271 case Instruction::INVOKE_STATIC: // Fall-through.
272 case Instruction::INVOKE_STATIC_RANGE:
273 invoke_type = kStatic;
274 break;
275 case Instruction::INVOKE_SUPER: // Fall-through.
276 case Instruction::INVOKE_SUPER_RANGE:
277 invoke_type = kSuper;
278 break;
279 case Instruction::INVOKE_VIRTUAL: // Fall-through.
280 case Instruction::INVOKE_VIRTUAL_RANGE:
281 invoke_type = kVirtual;
282 break;
283 default:
284 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
285 invoke_type = kDirect; // Avoid used uninitialized warnings.
286 }
TDYa12705fe3b62012-04-21 00:28:54 -0700287 DecodedInstruction dec_insn(instr);
288 dex_method_idx = dec_insn.vB;
289 } else {
290 DCHECK(!called->IsRuntimeMethod());
Ian Rogers08f753d2012-08-24 14:35:25 -0700291 invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
TDYa12705fe3b62012-04-21 00:28:54 -0700292 dex_method_idx = called->GetDexMethodIndex();
293 }
294 if (type == Runtime::kUnknownMethod) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700295 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
TDYa12705fe3b62012-04-21 00:28:54 -0700296 }
297 const void* code = NULL;
298 if (LIKELY(!thread->IsExceptionPending())) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700299 // Incompatible class change should have been handled in resolve method.
300 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
301 // Ensure that the called method's class is initialized.
302 Class* called_class = called->GetDeclaringClass();
303 linker->EnsureInitialized(called_class, true, true);
304 if (LIKELY(called_class->IsInitialized())) {
305 code = called->GetCode();
306 // TODO: remove this after we solve the link issue.
307 { // for lazy link.
308 if (code == NULL) {
309 code = linker->GetOatCodeFor(called);
310 }
311 }
312 } else if (called_class->IsInitializing()) {
313 if (invoke_type == kStatic) {
314 // Class is still initializing, go to oat and grab code (trampoline must be left in place
315 // until class is initialized to stop races between threads).
316 code = linker->GetOatCodeFor(called);
317 } else {
318 // No trampoline for non-static methods.
TDYa12705fe3b62012-04-21 00:28:54 -0700319 code = called->GetCode();
320 // TODO: remove this after we solve the link issue.
321 { // for lazy link.
322 if (code == NULL) {
323 code = linker->GetOatCodeFor(called);
324 }
325 }
TDYa12705fe3b62012-04-21 00:28:54 -0700326 }
327 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700328 DCHECK(called_class->IsErroneous());
TDYa12705fe3b62012-04-21 00:28:54 -0700329 }
330 }
331 if (LIKELY(code != NULL)) {
332 // Expect class to at least be initializing.
333 DCHECK(called->GetDeclaringClass()->IsInitializing());
334 // Don't want infinite recursion.
335 DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
336 // Set up entry into main method
337 *called_addr = called;
338 }
339 return code;
340}
341#endif // ART_USE_LLVM_COMPILER
342
343#if !defined(ART_USE_LLVM_COMPILER)
Ian Rogers57b86d42012-03-27 16:05:41 -0700344// Called by the AbstractMethodError. Called by stub code.
Mathieu Chartier66f19252012-09-18 08:57:04 -0700345extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700346 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700347 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
348 thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
349 "abstract method \"%s\"", PrettyMethod(method).c_str());
350 thread->DeliverException();
351}
TDYa12705fe3b62012-04-21 00:28:54 -0700352#else // ART_USE_LLVM_COMPILER
Mathieu Chartier66f19252012-09-18 08:57:04 -0700353extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod**)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700354 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa12705fe3b62012-04-21 00:28:54 -0700355 thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
356 "abstract method \"%s\"", PrettyMethod(method).c_str());
357}
358#endif // ART_USE_LLVM_COMPILER
Ian Rogers57b86d42012-03-27 16:05:41 -0700359
360} // namespace art