blob: 41de9f7e0ba85cf63f3f2a90ea37c761616d28fd [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.
35const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** 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());
55 Method** caller_sp = reinterpret_cast<Method**>(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);
Ian Rogers57b86d42012-03-27 16:05:41 -070057 uintptr_t caller_pc = regs[10];
Ian Rogers7caad772012-03-30 01:07:54 -070058#elif defined(__i386__)
59 // On entry the stack pointed by sp is:
60 // | argN | |
61 // | ... | |
62 // | arg4 | |
63 // | arg3 spill | | Caller's frame
64 // | arg2 spill | |
65 // | arg1 spill | |
66 // | Method* | ---
67 // | Return |
68 // | EBP,ESI,EDI | callee saves
69 // | EBX | arg3
70 // | EDX | arg2
71 // | ECX | arg1
72 // | EAX/Method* | <- sp
73 DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
74 Method** caller_sp = reinterpret_cast<Method**>(reinterpret_cast<byte*>(sp) + 32);
75 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
76 uintptr_t caller_pc = regs[7];
77#else
78 UNIMPLEMENTED(FATAL);
79 Method** caller_sp = NULL;
80 uintptr_t* regs = NULL;
81 uintptr_t caller_pc = 0;
82#endif
Ian Rogers57b86d42012-03-27 16:05:41 -070083 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
84 // Start new JNI local reference state
85 JNIEnvExt* env = thread->GetJniEnv();
Ian Rogers00f7d0e2012-07-19 15:28:27 -070086 ScopedObjectAccessUnchecked soa(env);
Ian Rogers57b86d42012-03-27 16:05:41 -070087 ScopedJniEnvLocalRefState env_state(env);
88
89 // Compute details about the called method (avoid GCs)
90 ClassLinker* linker = Runtime::Current()->GetClassLinker();
91 Method* caller = *caller_sp;
Ian Rogers08f753d2012-08-24 14:35:25 -070092 InvokeType invoke_type;
Ian Rogers57b86d42012-03-27 16:05:41 -070093 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();
Ian Rogers08f753d2012-08-24 14:35:25 -0700106 switch (instr_code) {
107 case Instruction::INVOKE_DIRECT: // Fall-through.
108 case Instruction::INVOKE_DIRECT_RANGE:
109 invoke_type = kDirect;
110 break;
111 case Instruction::INVOKE_STATIC: // Fall-through.
112 case Instruction::INVOKE_STATIC_RANGE:
113 invoke_type = kStatic;
114 break;
115 case Instruction::INVOKE_SUPER: // Fall-through.
116 case Instruction::INVOKE_SUPER_RANGE:
117 invoke_type = kSuper;
118 break;
119 case Instruction::INVOKE_VIRTUAL: // Fall-through.
120 case Instruction::INVOKE_VIRTUAL_RANGE:
121 invoke_type = kVirtual;
122 break;
123 default:
124 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
125 invoke_type = kDirect; // Avoid used uninitialized warnings.
126 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700127 DecodedInstruction dec_insn(instr);
128 dex_method_idx = dec_insn.vB;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700129#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700130 shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700131#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700132 } else {
133 DCHECK(!called->IsRuntimeMethod());
Ian Rogers08f753d2012-08-24 14:35:25 -0700134 invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
Ian Rogers57b86d42012-03-27 16:05:41 -0700135 dex_method_idx = called->GetDexMethodIndex();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700136#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700137 MethodHelper mh(called);
138 shorty = mh.GetShorty();
139 shorty_len = mh.GetShortyLength();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700140#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700141 }
Ian Rogers7caad772012-03-30 01:07:54 -0700142#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700143 // Discover shorty (avoid GCs)
144 size_t args_in_regs = 0;
145 for (size_t i = 1; i < shorty_len; i++) {
146 char c = shorty[i];
147 args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
148 if (args_in_regs > 3) {
149 args_in_regs = 3;
150 break;
151 }
152 }
153 // Place into local references incoming arguments from the caller's register arguments
154 size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1
Ian Rogers08f753d2012-08-24 14:35:25 -0700155 if (invoke_type != kStatic) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700156 Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
157 cur_arg++;
158 if (args_in_regs < 3) {
159 // If we thought we had fewer than 3 arguments in registers, account for the receiver
160 args_in_regs++;
161 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700162 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700163 }
164 size_t shorty_index = 1; // skip return value
165 // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
166 // R0)
167 while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
168 char c = shorty[shorty_index];
169 shorty_index++;
170 if (c == 'L') {
171 Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700172 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700173 }
174 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
175 }
176 // Place into local references incoming arguments from the caller's stack arguments
177 cur_arg += 11; // skip LR, Method* and spills for R1 to R3 and callee saves
178 while (shorty_index < shorty_len) {
179 char c = shorty[shorty_index];
180 shorty_index++;
181 if (c == 'L') {
182 Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700183 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700184 }
185 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
186 }
Ian Rogers7caad772012-03-30 01:07:54 -0700187#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700188 // Resolve method filling in dex cache
189 if (type == Runtime::kUnknownMethod) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700190 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
Ian Rogers57b86d42012-03-27 16:05:41 -0700191 }
192 const void* code = NULL;
193 if (LIKELY(!thread->IsExceptionPending())) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700194 // Incompatible class change should have been handled in resolve method.
195 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
196 // Ensure that the called method's class is initialized.
197 Class* called_class = called->GetDeclaringClass();
198 linker->EnsureInitialized(called_class, true, true);
199 if (LIKELY(called_class->IsInitialized())) {
200 code = called->GetCode();
201 } else if (called_class->IsInitializing()) {
202 if (invoke_type == kStatic) {
203 // Class is still initializing, go to oat and grab code (trampoline must be left in place
204 // until class is initialized to stop races between threads).
205 code = linker->GetOatCodeFor(called);
Ian Rogers57b86d42012-03-27 16:05:41 -0700206 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700207 // No trampoline for non-static methods.
208 code = called->GetCode();
Ian Rogers57b86d42012-03-27 16:05:41 -0700209 }
210 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700211 DCHECK(called_class->IsErroneous());
Ian Rogers57b86d42012-03-27 16:05:41 -0700212 }
213 }
214 if (UNLIKELY(code == NULL)) {
215 // Something went wrong in ResolveMethod or EnsureInitialized,
216 // go into deliver exception with the pending exception in r0
217 code = reinterpret_cast<void*>(art_deliver_exception_from_code);
218 regs[0] = reinterpret_cast<uintptr_t>(thread->GetException());
219 thread->ClearException();
220 } else {
221 // Expect class to at least be initializing.
222 DCHECK(called->GetDeclaringClass()->IsInitializing());
223 // Don't want infinite recursion.
224 DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
225 // Set up entry into main method
226 regs[0] = reinterpret_cast<uintptr_t>(called);
227 }
228 return code;
229}
TDYa12705fe3b62012-04-21 00:28:54 -0700230#else // ART_USE_LLVM_COMPILER
231const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** called_addr,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700232 Thread* thread, Runtime::TrampolineType type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700233 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers0399dde2012-06-06 17:09:28 -0700234 uint32_t dex_pc;
235 Method* caller = thread->GetCurrentMethod(&dex_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -0700236
TDYa12705fe3b62012-04-21 00:28:54 -0700237 ClassLinker* linker = Runtime::Current()->GetClassLinker();
Ian Rogers08f753d2012-08-24 14:35:25 -0700238 InvokeType invoke_type;
TDYa12705fe3b62012-04-21 00:28:54 -0700239 uint32_t dex_method_idx;
240 if (type == Runtime::kUnknownMethod) {
241 DCHECK(called->IsRuntimeMethod());
TDYa12705fe3b62012-04-21 00:28:54 -0700242 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
243 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
244 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
245 Instruction::Code instr_code = instr->Opcode();
Ian Rogers08f753d2012-08-24 14:35:25 -0700246 switch (instr_code) {
247 case Instruction::INVOKE_DIRECT: // Fall-through.
248 case Instruction::INVOKE_DIRECT_RANGE:
249 invoke_type = kDirect;
250 break;
251 case Instruction::INVOKE_STATIC: // Fall-through.
252 case Instruction::INVOKE_STATIC_RANGE:
253 invoke_type = kStatic;
254 break;
255 case Instruction::INVOKE_SUPER: // Fall-through.
256 case Instruction::INVOKE_SUPER_RANGE:
257 invoke_type = kSuper;
258 break;
259 case Instruction::INVOKE_VIRTUAL: // Fall-through.
260 case Instruction::INVOKE_VIRTUAL_RANGE:
261 invoke_type = kVirtual;
262 break;
263 default:
264 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
265 invoke_type = kDirect; // Avoid used uninitialized warnings.
266 }
TDYa12705fe3b62012-04-21 00:28:54 -0700267 DecodedInstruction dec_insn(instr);
268 dex_method_idx = dec_insn.vB;
269 } else {
270 DCHECK(!called->IsRuntimeMethod());
Ian Rogers08f753d2012-08-24 14:35:25 -0700271 invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
TDYa12705fe3b62012-04-21 00:28:54 -0700272 dex_method_idx = called->GetDexMethodIndex();
273 }
274 if (type == Runtime::kUnknownMethod) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700275 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
TDYa12705fe3b62012-04-21 00:28:54 -0700276 }
277 const void* code = NULL;
278 if (LIKELY(!thread->IsExceptionPending())) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700279 // Incompatible class change should have been handled in resolve method.
280 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
281 // Ensure that the called method's class is initialized.
282 Class* called_class = called->GetDeclaringClass();
283 linker->EnsureInitialized(called_class, true, true);
284 if (LIKELY(called_class->IsInitialized())) {
285 code = called->GetCode();
286 // TODO: remove this after we solve the link issue.
287 { // for lazy link.
288 if (code == NULL) {
289 code = linker->GetOatCodeFor(called);
290 }
291 }
292 } else if (called_class->IsInitializing()) {
293 if (invoke_type == kStatic) {
294 // Class is still initializing, go to oat and grab code (trampoline must be left in place
295 // until class is initialized to stop races between threads).
296 code = linker->GetOatCodeFor(called);
297 } else {
298 // No trampoline for non-static methods.
TDYa12705fe3b62012-04-21 00:28:54 -0700299 code = called->GetCode();
300 // TODO: remove this after we solve the link issue.
301 { // for lazy link.
302 if (code == NULL) {
303 code = linker->GetOatCodeFor(called);
304 }
305 }
TDYa12705fe3b62012-04-21 00:28:54 -0700306 }
307 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700308 DCHECK(called_class->IsErroneous());
TDYa12705fe3b62012-04-21 00:28:54 -0700309 }
310 }
311 if (LIKELY(code != NULL)) {
312 // Expect class to at least be initializing.
313 DCHECK(called->GetDeclaringClass()->IsInitializing());
314 // Don't want infinite recursion.
315 DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
316 // Set up entry into main method
317 *called_addr = called;
318 }
319 return code;
320}
321#endif // ART_USE_LLVM_COMPILER
322
323#if !defined(ART_USE_LLVM_COMPILER)
Ian Rogers57b86d42012-03-27 16:05:41 -0700324// Called by the AbstractMethodError. Called by stub code.
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700325extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700326 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700327 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
328 thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
329 "abstract method \"%s\"", PrettyMethod(method).c_str());
330 thread->DeliverException();
331}
TDYa12705fe3b62012-04-21 00:28:54 -0700332#else // ART_USE_LLVM_COMPILER
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700333extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method**)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700334 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa12705fe3b62012-04-21 00:28:54 -0700335 thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
336 "abstract method \"%s\"", PrettyMethod(method).c_str());
337}
338#endif // ART_USE_LLVM_COMPILER
Ian Rogers57b86d42012-03-27 16:05:41 -0700339
340} // namespace art