blob: 161a7b2b58a14bf916fa0b8af5411eaca21c9482 [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
17#include "callee_save_frame.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080018#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070019#include "dex_file-inl.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070020#include "dex_instruction.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080021#include "mirror/class-inl.h"
22#include "mirror/abstract_method-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080023#include "mirror/object_array-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070024#include "mirror/object-inl.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070025#include "object_utils.h"
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.
Logan Chien8dbb7082013-01-25 20:31:17 +080029extern "C" void art_quick_deliver_exception_from_code(void*);
Ian Rogers57b86d42012-03-27 16:05:41 -070030
31namespace art {
32
Jeff Hao58df3272013-04-22 15:28:53 -070033// Lazily resolve a method for portable. Called by stub code.
34extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
35 mirror::AbstractMethod** called_addr,
36 Thread* thread)
37 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
38 uint32_t dex_pc;
39 mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
40
41 ClassLinker* linker = Runtime::Current()->GetClassLinker();
42 InvokeType invoke_type;
43 uint32_t dex_method_idx;
Jeff Hao09b55e12013-04-24 14:28:19 -070044 if (called->IsRuntimeMethod()) {
45 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
46 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
47 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
48 Instruction::Code instr_code = instr->Opcode();
49 switch (instr_code) {
50 case Instruction::INVOKE_DIRECT: // Fall-through.
51 case Instruction::INVOKE_DIRECT_RANGE:
52 invoke_type = kDirect;
53 break;
54 case Instruction::INVOKE_STATIC: // Fall-through.
55 case Instruction::INVOKE_STATIC_RANGE:
56 invoke_type = kStatic;
57 break;
58 case Instruction::INVOKE_SUPER: // Fall-through.
59 case Instruction::INVOKE_SUPER_RANGE:
60 invoke_type = kSuper;
61 break;
62 case Instruction::INVOKE_VIRTUAL: // Fall-through.
63 case Instruction::INVOKE_VIRTUAL_RANGE:
64 invoke_type = kVirtual;
65 break;
66 default:
67 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
68 invoke_type = kDirect; // Avoid used uninitialized warnings.
69 }
70 DecodedInstruction dec_insn(instr);
71 dex_method_idx = dec_insn.vB;
72 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
73 } else {
74 CHECK(called->IsStatic()) << PrettyMethod(called);
75 invoke_type = kStatic;
Jeff Hao58df3272013-04-22 15:28:53 -070076 }
Jeff Hao58df3272013-04-22 15:28:53 -070077 const void* code = NULL;
78 if (LIKELY(!thread->IsExceptionPending())) {
79 // Incompatible class change should have been handled in resolve method.
80 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
81 // Ensure that the called method's class is initialized.
82 mirror::Class* called_class = called->GetDeclaringClass();
83 linker->EnsureInitialized(called_class, true, true);
84 if (LIKELY(called_class->IsInitialized())) {
Jeff Haoaa4a7932013-05-13 11:28:27 -070085 code = called->GetEntryPointFromCompiledCode();
Jeff Hao58df3272013-04-22 15:28:53 -070086 // TODO: remove this after we solve the link issue.
87 { // for lazy link.
88 if (code == NULL) {
89 code = linker->GetOatCodeFor(called);
90 }
91 }
92 } else if (called_class->IsInitializing()) {
93 if (invoke_type == kStatic) {
94 // Class is still initializing, go to oat and grab code (trampoline must be left in place
95 // until class is initialized to stop races between threads).
96 code = linker->GetOatCodeFor(called);
97 } else {
98 // No trampoline for non-static methods.
Jeff Haoaa4a7932013-05-13 11:28:27 -070099 code = called->GetEntryPointFromCompiledCode();
Jeff Hao58df3272013-04-22 15:28:53 -0700100 // TODO: remove this after we solve the link issue.
101 { // for lazy link.
102 if (code == NULL) {
103 code = linker->GetOatCodeFor(called);
104 }
105 }
106 }
107 } else {
108 DCHECK(called_class->IsErroneous());
109 }
110 }
111 if (LIKELY(code != NULL)) {
112 // Expect class to at least be initializing.
113 DCHECK(called->GetDeclaringClass()->IsInitializing());
114 // Don't want infinite recursion.
115 DCHECK(code != GetResolutionTrampoline());
116 // Set up entry into main method
117 *called_addr = called;
118 }
119 return code;
120}
121
122// Lazily resolve a method for quick. Called by stub code.
123extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
124 mirror::AbstractMethod** sp, Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700125 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers7caad772012-03-30 01:07:54 -0700126#if defined(__arm__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700127 // On entry the stack pointed by sp is:
128 // | argN | |
129 // | ... | |
130 // | arg4 | |
131 // | arg3 spill | | Caller's frame
132 // | arg2 spill | |
133 // | arg1 spill | |
134 // | Method* | ---
135 // | LR |
136 // | ... | callee saves
137 // | R3 | arg3
138 // | R2 | arg2
139 // | R1 | arg1
140 // | R0 |
141 // | Method* | <- sp
Ian Rogers57b86d42012-03-27 16:05:41 -0700142 DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800143 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
Ian Rogers7caad772012-03-30 01:07:54 -0700144 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
jeffhaofa147e22012-10-12 17:03:32 -0700145 uint32_t pc_offset = 10;
146 uintptr_t caller_pc = regs[pc_offset];
Ian Rogers7caad772012-03-30 01:07:54 -0700147#elif defined(__i386__)
148 // On entry the stack pointed by sp is:
149 // | argN | |
150 // | ... | |
151 // | arg4 | |
152 // | arg3 spill | | Caller's frame
153 // | arg2 spill | |
154 // | arg1 spill | |
155 // | Method* | ---
156 // | Return |
157 // | EBP,ESI,EDI | callee saves
158 // | EBX | arg3
159 // | EDX | arg2
160 // | ECX | arg1
161 // | EAX/Method* | <- sp
162 DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800163 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 32);
Ian Rogers7caad772012-03-30 01:07:54 -0700164 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
165 uintptr_t caller_pc = regs[7];
jeffhaofa147e22012-10-12 17:03:32 -0700166#elif defined(__mips__)
167 // On entry the stack pointed by sp is:
168 // | argN | |
169 // | ... | |
170 // | arg4 | |
171 // | arg3 spill | | Caller's frame
172 // | arg2 spill | |
173 // | arg1 spill | |
174 // | Method* | ---
175 // | RA |
176 // | ... | callee saves
177 // | A3 | arg3
178 // | A2 | arg2
179 // | A1 | arg1
180 // | A0/Method* | <- sp
Jeff Hao1f3bc2f2013-04-30 15:17:19 -0700181 DCHECK_EQ(64U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
182 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 64);
jeffhaofa147e22012-10-12 17:03:32 -0700183 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
Jeff Hao1f3bc2f2013-04-30 15:17:19 -0700184 uint32_t pc_offset = 15;
jeffhaofa147e22012-10-12 17:03:32 -0700185 uintptr_t caller_pc = regs[pc_offset];
Ian Rogers7caad772012-03-30 01:07:54 -0700186#else
187 UNIMPLEMENTED(FATAL);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800188 mirror::AbstractMethod** caller_sp = NULL;
Ian Rogers7caad772012-03-30 01:07:54 -0700189 uintptr_t* regs = NULL;
190 uintptr_t caller_pc = 0;
191#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700192 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
193 // Start new JNI local reference state
194 JNIEnvExt* env = thread->GetJniEnv();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700195 ScopedObjectAccessUnchecked soa(env);
Ian Rogers57b86d42012-03-27 16:05:41 -0700196 ScopedJniEnvLocalRefState env_state(env);
197
198 // Compute details about the called method (avoid GCs)
199 ClassLinker* linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800200 mirror::AbstractMethod* caller = *caller_sp;
Ian Rogers08f753d2012-08-24 14:35:25 -0700201 InvokeType invoke_type;
Ian Rogers57b86d42012-03-27 16:05:41 -0700202 uint32_t dex_method_idx;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700203#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700204 const char* shorty;
205 uint32_t shorty_len;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700206#endif
Jeff Hao58df3272013-04-22 15:28:53 -0700207 if (called->IsRuntimeMethod()) {
Ian Rogers0c7abda2012-09-19 13:33:42 -0700208 uint32_t dex_pc = caller->ToDexPc(caller_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -0700209 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
210 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
211 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
212 Instruction::Code instr_code = instr->Opcode();
Ian Rogers08f753d2012-08-24 14:35:25 -0700213 switch (instr_code) {
214 case Instruction::INVOKE_DIRECT: // Fall-through.
215 case Instruction::INVOKE_DIRECT_RANGE:
216 invoke_type = kDirect;
217 break;
218 case Instruction::INVOKE_STATIC: // Fall-through.
219 case Instruction::INVOKE_STATIC_RANGE:
220 invoke_type = kStatic;
221 break;
222 case Instruction::INVOKE_SUPER: // Fall-through.
223 case Instruction::INVOKE_SUPER_RANGE:
224 invoke_type = kSuper;
225 break;
226 case Instruction::INVOKE_VIRTUAL: // Fall-through.
227 case Instruction::INVOKE_VIRTUAL_RANGE:
228 invoke_type = kVirtual;
229 break;
230 default:
231 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
232 invoke_type = kDirect; // Avoid used uninitialized warnings.
233 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700234 DecodedInstruction dec_insn(instr);
235 dex_method_idx = dec_insn.vB;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700236#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700237 shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700238#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700239 } else {
Jeff Hao58df3272013-04-22 15:28:53 -0700240 invoke_type = kStatic;
Ian Rogers57b86d42012-03-27 16:05:41 -0700241 dex_method_idx = called->GetDexMethodIndex();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700242#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700243 MethodHelper mh(called);
244 shorty = mh.GetShorty();
245 shorty_len = mh.GetShortyLength();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700246#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700247 }
Ian Rogers7caad772012-03-30 01:07:54 -0700248#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700249 // Discover shorty (avoid GCs)
250 size_t args_in_regs = 0;
251 for (size_t i = 1; i < shorty_len; i++) {
252 char c = shorty[i];
253 args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
254 if (args_in_regs > 3) {
255 args_in_regs = 3;
256 break;
257 }
258 }
259 // Place into local references incoming arguments from the caller's register arguments
260 size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1
Ian Rogers08f753d2012-08-24 14:35:25 -0700261 if (invoke_type != kStatic) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800262 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers57b86d42012-03-27 16:05:41 -0700263 cur_arg++;
264 if (args_in_regs < 3) {
265 // If we thought we had fewer than 3 arguments in registers, account for the receiver
266 args_in_regs++;
267 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700268 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700269 }
270 size_t shorty_index = 1; // skip return value
271 // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
272 // R0)
273 while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
274 char c = shorty[shorty_index];
275 shorty_index++;
276 if (c == 'L') {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800277 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700278 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700279 }
280 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
281 }
282 // Place into local references incoming arguments from the caller's stack arguments
jeffhaofa147e22012-10-12 17:03:32 -0700283 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 -0700284 while (shorty_index < shorty_len) {
285 char c = shorty[shorty_index];
286 shorty_index++;
287 if (c == 'L') {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800288 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700289 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700290 }
291 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
292 }
Ian Rogers7caad772012-03-30 01:07:54 -0700293#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700294 // Resolve method filling in dex cache
Jeff Hao58df3272013-04-22 15:28:53 -0700295 if (called->IsRuntimeMethod()) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700296 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
Ian Rogers57b86d42012-03-27 16:05:41 -0700297 }
298 const void* code = NULL;
299 if (LIKELY(!thread->IsExceptionPending())) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700300 // Incompatible class change should have been handled in resolve method.
301 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
302 // Ensure that the called method's class is initialized.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800303 mirror::Class* called_class = called->GetDeclaringClass();
Ian Rogers08f753d2012-08-24 14:35:25 -0700304 linker->EnsureInitialized(called_class, true, true);
305 if (LIKELY(called_class->IsInitialized())) {
Jeff Haoaa4a7932013-05-13 11:28:27 -0700306 code = called->GetEntryPointFromCompiledCode();
Ian Rogers08f753d2012-08-24 14:35:25 -0700307 } else if (called_class->IsInitializing()) {
308 if (invoke_type == kStatic) {
309 // Class is still initializing, go to oat and grab code (trampoline must be left in place
310 // until class is initialized to stop races between threads).
311 code = linker->GetOatCodeFor(called);
Ian Rogers57b86d42012-03-27 16:05:41 -0700312 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700313 // No trampoline for non-static methods.
Jeff Haoaa4a7932013-05-13 11:28:27 -0700314 code = called->GetEntryPointFromCompiledCode();
Ian Rogers57b86d42012-03-27 16:05:41 -0700315 }
316 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700317 DCHECK(called_class->IsErroneous());
Ian Rogers57b86d42012-03-27 16:05:41 -0700318 }
319 }
320 if (UNLIKELY(code == NULL)) {
321 // Something went wrong in ResolveMethod or EnsureInitialized,
322 // go into deliver exception with the pending exception in r0
Ian Rogersf3e98552013-03-20 15:49:49 -0700323 CHECK(thread->IsExceptionPending());
Logan Chien8dbb7082013-01-25 20:31:17 +0800324 code = reinterpret_cast<void*>(art_quick_deliver_exception_from_code);
Ian Rogers62d6c772013-02-27 08:32:07 -0800325 regs[0] = reinterpret_cast<uintptr_t>(thread->GetException(NULL));
Ian Rogers57b86d42012-03-27 16:05:41 -0700326 thread->ClearException();
327 } else {
328 // Expect class to at least be initializing.
329 DCHECK(called->GetDeclaringClass()->IsInitializing());
330 // Don't want infinite recursion.
Jeff Hao58df3272013-04-22 15:28:53 -0700331 DCHECK(code != GetResolutionTrampoline());
Ian Rogers57b86d42012-03-27 16:05:41 -0700332 // Set up entry into main method
333 regs[0] = reinterpret_cast<uintptr_t>(called);
334 }
335 return code;
336}
TDYa12705fe3b62012-04-21 00:28:54 -0700337
Jeff Hao79fe5392013-04-24 18:41:58 -0700338// Called by the abstract method error stub.
339extern "C" void artThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* self,
340 mirror::AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700341 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers1c42ff92013-04-09 10:03:34 -0700342#if !defined(ART_USE_PORTABLE_COMPILER)
Ian Rogers62d6c772013-02-27 08:32:07 -0800343 FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
Ian Rogers1c42ff92013-04-09 10:03:34 -0700344#else
345 UNUSED(sp);
346#endif
Ian Rogers62d6c772013-02-27 08:32:07 -0800347 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
348 self->ThrowNewExceptionF(throw_location, "Ljava/lang/AbstractMethodError;",
349 "abstract method \"%s\"", PrettyMethod(method).c_str());
350 self->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -0700351}
Ian Rogers57b86d42012-03-27 16:05:41 -0700352
Jeff Hao79fe5392013-04-24 18:41:58 -0700353// Used by the JNI dlsym stub to find the native method to invoke if none is registered.
354extern "C" void* artFindNativeMethod(Thread* self) {
355 Locks::mutator_lock_->AssertNotHeld(self); // We come here as Native.
356 DCHECK(Thread::Current() == self);
357 ScopedObjectAccess soa(self);
358
359 mirror::AbstractMethod* method = self->GetCurrentMethod(NULL);
360 DCHECK(method != NULL);
361
362 // Lookup symbol address for method, on failure we'll return NULL with an
363 // exception set, otherwise we return the address of the method we found.
364 void* native_code = soa.Vm()->FindCodeForNativeMethod(method);
365 if (native_code == NULL) {
366 DCHECK(self->IsExceptionPending());
367 return NULL;
368 } else {
369 // Register so that future calls don't come here
370 method->RegisterNative(self, native_code);
371 return native_code;
372 }
373}
374
Ian Rogers57b86d42012-03-27 16:05:41 -0700375} // namespace art