blob: 71b67d06bbb31f144307152d0cd19b7970b58625 [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"
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020020#include "dex_instruction-inl.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,
Ian Rogerse3cd2f02013-05-24 15:32:56 -070035 mirror::Object* receiver,
Jeff Hao58df3272013-04-22 15:28:53 -070036 mirror::AbstractMethod** called_addr,
37 Thread* thread)
38 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
39 uint32_t dex_pc;
40 mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
41
42 ClassLinker* linker = Runtime::Current()->GetClassLinker();
43 InvokeType invoke_type;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020044 bool is_range;
Jeff Hao09b55e12013-04-24 14:28:19 -070045 if (called->IsRuntimeMethod()) {
46 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
47 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
48 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
49 Instruction::Code instr_code = instr->Opcode();
50 switch (instr_code) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020051 case Instruction::INVOKE_DIRECT:
52 invoke_type = kDirect;
53 is_range = false;
54 break;
Jeff Hao09b55e12013-04-24 14:28:19 -070055 case Instruction::INVOKE_DIRECT_RANGE:
56 invoke_type = kDirect;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020057 is_range = true;
Jeff Hao09b55e12013-04-24 14:28:19 -070058 break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020059 case Instruction::INVOKE_STATIC:
60 invoke_type = kStatic;
61 is_range = false;
62 break;
Jeff Hao09b55e12013-04-24 14:28:19 -070063 case Instruction::INVOKE_STATIC_RANGE:
64 invoke_type = kStatic;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020065 is_range = true;
Jeff Hao09b55e12013-04-24 14:28:19 -070066 break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020067 case Instruction::INVOKE_SUPER:
68 invoke_type = kSuper;
69 is_range = false;
70 break;
Jeff Hao09b55e12013-04-24 14:28:19 -070071 case Instruction::INVOKE_SUPER_RANGE:
72 invoke_type = kSuper;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020073 is_range = true;
Jeff Hao09b55e12013-04-24 14:28:19 -070074 break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020075 case Instruction::INVOKE_VIRTUAL:
76 invoke_type = kVirtual;
77 is_range = false;
78 break;
Jeff Hao09b55e12013-04-24 14:28:19 -070079 case Instruction::INVOKE_VIRTUAL_RANGE:
80 invoke_type = kVirtual;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020081 is_range = true;
Jeff Hao09b55e12013-04-24 14:28:19 -070082 break;
Ian Rogerse3cd2f02013-05-24 15:32:56 -070083 case Instruction::INVOKE_INTERFACE:
84 invoke_type = kInterface;
85 is_range = false;
86 break;
87 case Instruction::INVOKE_INTERFACE_RANGE:
88 invoke_type = kInterface;
89 is_range = true;
90 break;
Jeff Hao09b55e12013-04-24 14:28:19 -070091 default:
92 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020093 // Avoid used uninitialized warnings.
94 invoke_type = kDirect;
95 is_range = true;
Jeff Hao09b55e12013-04-24 14:28:19 -070096 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020097 uint32_t dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
Jeff Hao09b55e12013-04-24 14:28:19 -070098 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
Ian Rogerse3cd2f02013-05-24 15:32:56 -070099 // Refine called method based on receiver.
100 if (invoke_type == kVirtual) {
101 called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
102 } else if (invoke_type == kInterface) {
103 called = receiver->GetClass()->FindVirtualMethodForInterface(called);
104 }
Jeff Hao09b55e12013-04-24 14:28:19 -0700105 } else {
106 CHECK(called->IsStatic()) << PrettyMethod(called);
107 invoke_type = kStatic;
Jeff Hao58df3272013-04-22 15:28:53 -0700108 }
Jeff Hao58df3272013-04-22 15:28:53 -0700109 const void* code = NULL;
110 if (LIKELY(!thread->IsExceptionPending())) {
111 // Incompatible class change should have been handled in resolve method.
112 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
113 // Ensure that the called method's class is initialized.
114 mirror::Class* called_class = called->GetDeclaringClass();
115 linker->EnsureInitialized(called_class, true, true);
116 if (LIKELY(called_class->IsInitialized())) {
Jeff Haoaa4a7932013-05-13 11:28:27 -0700117 code = called->GetEntryPointFromCompiledCode();
Jeff Hao58df3272013-04-22 15:28:53 -0700118 // TODO: remove this after we solve the link issue.
119 { // for lazy link.
120 if (code == NULL) {
121 code = linker->GetOatCodeFor(called);
122 }
123 }
124 } else if (called_class->IsInitializing()) {
125 if (invoke_type == kStatic) {
126 // Class is still initializing, go to oat and grab code (trampoline must be left in place
127 // until class is initialized to stop races between threads).
128 code = linker->GetOatCodeFor(called);
129 } else {
130 // No trampoline for non-static methods.
Jeff Haoaa4a7932013-05-13 11:28:27 -0700131 code = called->GetEntryPointFromCompiledCode();
Jeff Hao58df3272013-04-22 15:28:53 -0700132 // TODO: remove this after we solve the link issue.
133 { // for lazy link.
134 if (code == NULL) {
135 code = linker->GetOatCodeFor(called);
136 }
137 }
138 }
139 } else {
140 DCHECK(called_class->IsErroneous());
141 }
142 }
143 if (LIKELY(code != NULL)) {
144 // Expect class to at least be initializing.
145 DCHECK(called->GetDeclaringClass()->IsInitializing());
146 // Don't want infinite recursion.
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700147 DCHECK(code != GetResolutionTrampoline(linker));
Jeff Hao58df3272013-04-22 15:28:53 -0700148 // Set up entry into main method
149 *called_addr = called;
150 }
151 return code;
152}
153
154// Lazily resolve a method for quick. Called by stub code.
155extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
Ian Rogerse3cd2f02013-05-24 15:32:56 -0700156 mirror::Object* receiver,
Jeff Hao58df3272013-04-22 15:28:53 -0700157 mirror::AbstractMethod** sp, Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700158 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers7caad772012-03-30 01:07:54 -0700159#if defined(__arm__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700160 // On entry the stack pointed by sp is:
161 // | argN | |
162 // | ... | |
163 // | arg4 | |
164 // | arg3 spill | | Caller's frame
165 // | arg2 spill | |
166 // | arg1 spill | |
167 // | Method* | ---
168 // | LR |
169 // | ... | callee saves
170 // | R3 | arg3
171 // | R2 | arg2
172 // | R1 | arg1
173 // | R0 |
174 // | Method* | <- sp
Ian Rogers57b86d42012-03-27 16:05:41 -0700175 DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800176 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
Ian Rogers7caad772012-03-30 01:07:54 -0700177 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
jeffhaofa147e22012-10-12 17:03:32 -0700178 uint32_t pc_offset = 10;
179 uintptr_t caller_pc = regs[pc_offset];
Ian Rogers7caad772012-03-30 01:07:54 -0700180#elif defined(__i386__)
181 // On entry the stack pointed by sp is:
182 // | argN | |
183 // | ... | |
184 // | arg4 | |
185 // | arg3 spill | | Caller's frame
186 // | arg2 spill | |
187 // | arg1 spill | |
188 // | Method* | ---
189 // | Return |
190 // | EBP,ESI,EDI | callee saves
191 // | EBX | arg3
192 // | EDX | arg2
193 // | ECX | arg1
194 // | EAX/Method* | <- sp
195 DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800196 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 32);
Ian Rogers7caad772012-03-30 01:07:54 -0700197 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
198 uintptr_t caller_pc = regs[7];
jeffhaofa147e22012-10-12 17:03:32 -0700199#elif defined(__mips__)
200 // On entry the stack pointed by sp is:
201 // | argN | |
202 // | ... | |
203 // | arg4 | |
204 // | arg3 spill | | Caller's frame
205 // | arg2 spill | |
206 // | arg1 spill | |
207 // | Method* | ---
208 // | RA |
209 // | ... | callee saves
210 // | A3 | arg3
211 // | A2 | arg2
212 // | A1 | arg1
213 // | A0/Method* | <- sp
Jeff Hao1f3bc2f2013-04-30 15:17:19 -0700214 DCHECK_EQ(64U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
215 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 64);
jeffhaofa147e22012-10-12 17:03:32 -0700216 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
Jeff Hao1f3bc2f2013-04-30 15:17:19 -0700217 uint32_t pc_offset = 15;
jeffhaofa147e22012-10-12 17:03:32 -0700218 uintptr_t caller_pc = regs[pc_offset];
Ian Rogers7caad772012-03-30 01:07:54 -0700219#else
220 UNIMPLEMENTED(FATAL);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800221 mirror::AbstractMethod** caller_sp = NULL;
Ian Rogers7caad772012-03-30 01:07:54 -0700222 uintptr_t* regs = NULL;
223 uintptr_t caller_pc = 0;
224#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700225 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
226 // Start new JNI local reference state
227 JNIEnvExt* env = thread->GetJniEnv();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700228 ScopedObjectAccessUnchecked soa(env);
Ian Rogers57b86d42012-03-27 16:05:41 -0700229 ScopedJniEnvLocalRefState env_state(env);
230
231 // Compute details about the called method (avoid GCs)
232 ClassLinker* linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800233 mirror::AbstractMethod* caller = *caller_sp;
Ian Rogers08f753d2012-08-24 14:35:25 -0700234 InvokeType invoke_type;
Ian Rogers57b86d42012-03-27 16:05:41 -0700235 uint32_t dex_method_idx;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700236#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700237 const char* shorty;
238 uint32_t shorty_len;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700239#endif
Jeff Hao58df3272013-04-22 15:28:53 -0700240 if (called->IsRuntimeMethod()) {
Ian Rogers0c7abda2012-09-19 13:33:42 -0700241 uint32_t dex_pc = caller->ToDexPc(caller_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -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();
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200246 bool is_range;
Ian Rogers08f753d2012-08-24 14:35:25 -0700247 switch (instr_code) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200248 case Instruction::INVOKE_DIRECT:
249 invoke_type = kDirect;
250 is_range = false;
251 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700252 case Instruction::INVOKE_DIRECT_RANGE:
253 invoke_type = kDirect;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200254 is_range = true;
Ian Rogers08f753d2012-08-24 14:35:25 -0700255 break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200256 case Instruction::INVOKE_STATIC:
257 invoke_type = kStatic;
258 is_range = false;
259 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700260 case Instruction::INVOKE_STATIC_RANGE:
261 invoke_type = kStatic;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200262 is_range = true;
Ian Rogers08f753d2012-08-24 14:35:25 -0700263 break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200264 case Instruction::INVOKE_SUPER:
265 invoke_type = kSuper;
266 is_range = false;
267 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700268 case Instruction::INVOKE_SUPER_RANGE:
269 invoke_type = kSuper;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200270 is_range = true;
Ian Rogers08f753d2012-08-24 14:35:25 -0700271 break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200272 case Instruction::INVOKE_VIRTUAL:
273 invoke_type = kVirtual;
274 is_range = false;
275 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700276 case Instruction::INVOKE_VIRTUAL_RANGE:
277 invoke_type = kVirtual;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200278 is_range = true;
Ian Rogers08f753d2012-08-24 14:35:25 -0700279 break;
Ian Rogerse3cd2f02013-05-24 15:32:56 -0700280 case Instruction::INVOKE_INTERFACE:
281 invoke_type = kInterface;
282 is_range = false;
283 break;
284 case Instruction::INVOKE_INTERFACE_RANGE:
285 invoke_type = kInterface;
286 is_range = true;
287 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700288 default:
289 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200290 // Avoid used uninitialized warnings.
291 invoke_type = kDirect;
292 is_range = false;
Ian Rogers08f753d2012-08-24 14:35:25 -0700293 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200294 dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700295#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700296 shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700297#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700298 } else {
Jeff Hao58df3272013-04-22 15:28:53 -0700299 invoke_type = kStatic;
Ian Rogers57b86d42012-03-27 16:05:41 -0700300 dex_method_idx = called->GetDexMethodIndex();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700301#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700302 MethodHelper mh(called);
303 shorty = mh.GetShorty();
304 shorty_len = mh.GetShortyLength();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700305#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700306 }
Ian Rogers7caad772012-03-30 01:07:54 -0700307#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700308 // Discover shorty (avoid GCs)
309 size_t args_in_regs = 0;
310 for (size_t i = 1; i < shorty_len; i++) {
311 char c = shorty[i];
312 args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
313 if (args_in_regs > 3) {
314 args_in_regs = 3;
315 break;
316 }
317 }
318 // Place into local references incoming arguments from the caller's register arguments
319 size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1
Ian Rogers08f753d2012-08-24 14:35:25 -0700320 if (invoke_type != kStatic) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800321 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers57b86d42012-03-27 16:05:41 -0700322 cur_arg++;
323 if (args_in_regs < 3) {
324 // If we thought we had fewer than 3 arguments in registers, account for the receiver
325 args_in_regs++;
326 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700327 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700328 }
329 size_t shorty_index = 1; // skip return value
330 // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
331 // R0)
332 while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
333 char c = shorty[shorty_index];
334 shorty_index++;
335 if (c == 'L') {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800336 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700337 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700338 }
339 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
340 }
341 // Place into local references incoming arguments from the caller's stack arguments
jeffhaofa147e22012-10-12 17:03:32 -0700342 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 -0700343 while (shorty_index < shorty_len) {
344 char c = shorty[shorty_index];
345 shorty_index++;
346 if (c == 'L') {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800347 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700348 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700349 }
350 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
351 }
Ian Rogers7caad772012-03-30 01:07:54 -0700352#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700353 // Resolve method filling in dex cache
Jeff Hao58df3272013-04-22 15:28:53 -0700354 if (called->IsRuntimeMethod()) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700355 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
Ian Rogers57b86d42012-03-27 16:05:41 -0700356 }
357 const void* code = NULL;
358 if (LIKELY(!thread->IsExceptionPending())) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700359 // Incompatible class change should have been handled in resolve method.
360 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
Ian Rogerse3cd2f02013-05-24 15:32:56 -0700361 // Refine called method based on receiver.
362 if (invoke_type == kVirtual) {
363 called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
364 } else if (invoke_type == kInterface) {
365 called = receiver->GetClass()->FindVirtualMethodForInterface(called);
366 }
Ian Rogers08f753d2012-08-24 14:35:25 -0700367 // Ensure that the called method's class is initialized.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800368 mirror::Class* called_class = called->GetDeclaringClass();
Ian Rogers08f753d2012-08-24 14:35:25 -0700369 linker->EnsureInitialized(called_class, true, true);
370 if (LIKELY(called_class->IsInitialized())) {
Jeff Haoaa4a7932013-05-13 11:28:27 -0700371 code = called->GetEntryPointFromCompiledCode();
Ian Rogers08f753d2012-08-24 14:35:25 -0700372 } else if (called_class->IsInitializing()) {
373 if (invoke_type == kStatic) {
374 // Class is still initializing, go to oat and grab code (trampoline must be left in place
375 // until class is initialized to stop races between threads).
376 code = linker->GetOatCodeFor(called);
Ian Rogers57b86d42012-03-27 16:05:41 -0700377 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700378 // No trampoline for non-static methods.
Jeff Haoaa4a7932013-05-13 11:28:27 -0700379 code = called->GetEntryPointFromCompiledCode();
Ian Rogers57b86d42012-03-27 16:05:41 -0700380 }
381 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700382 DCHECK(called_class->IsErroneous());
Ian Rogers57b86d42012-03-27 16:05:41 -0700383 }
384 }
385 if (UNLIKELY(code == NULL)) {
386 // Something went wrong in ResolveMethod or EnsureInitialized,
387 // go into deliver exception with the pending exception in r0
Ian Rogersf3e98552013-03-20 15:49:49 -0700388 CHECK(thread->IsExceptionPending());
Logan Chien8dbb7082013-01-25 20:31:17 +0800389 code = reinterpret_cast<void*>(art_quick_deliver_exception_from_code);
Ian Rogers62d6c772013-02-27 08:32:07 -0800390 regs[0] = reinterpret_cast<uintptr_t>(thread->GetException(NULL));
Ian Rogers57b86d42012-03-27 16:05:41 -0700391 thread->ClearException();
392 } else {
393 // Expect class to at least be initializing.
394 DCHECK(called->GetDeclaringClass()->IsInitializing());
395 // Don't want infinite recursion.
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700396 DCHECK(code != GetResolutionTrampoline(linker));
Ian Rogers57b86d42012-03-27 16:05:41 -0700397 // Set up entry into main method
398 regs[0] = reinterpret_cast<uintptr_t>(called);
399 }
400 return code;
401}
TDYa12705fe3b62012-04-21 00:28:54 -0700402
Jeff Hao79fe5392013-04-24 18:41:58 -0700403// Called by the abstract method error stub.
404extern "C" void artThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* self,
405 mirror::AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700406 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers1c42ff92013-04-09 10:03:34 -0700407#if !defined(ART_USE_PORTABLE_COMPILER)
Ian Rogers62d6c772013-02-27 08:32:07 -0800408 FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
Ian Rogers1c42ff92013-04-09 10:03:34 -0700409#else
410 UNUSED(sp);
411#endif
Ian Rogers62d6c772013-02-27 08:32:07 -0800412 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
413 self->ThrowNewExceptionF(throw_location, "Ljava/lang/AbstractMethodError;",
414 "abstract method \"%s\"", PrettyMethod(method).c_str());
415 self->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -0700416}
Ian Rogers57b86d42012-03-27 16:05:41 -0700417
Jeff Hao79fe5392013-04-24 18:41:58 -0700418// Used by the JNI dlsym stub to find the native method to invoke if none is registered.
419extern "C" void* artFindNativeMethod(Thread* self) {
420 Locks::mutator_lock_->AssertNotHeld(self); // We come here as Native.
421 DCHECK(Thread::Current() == self);
422 ScopedObjectAccess soa(self);
423
424 mirror::AbstractMethod* method = self->GetCurrentMethod(NULL);
425 DCHECK(method != NULL);
426
427 // Lookup symbol address for method, on failure we'll return NULL with an
428 // exception set, otherwise we return the address of the method we found.
429 void* native_code = soa.Vm()->FindCodeForNativeMethod(method);
430 if (native_code == NULL) {
431 DCHECK(self->IsExceptionPending());
432 return NULL;
433 } else {
434 // Register so that future calls don't come here
435 method->RegisterNative(self, native_code);
436 return native_code;
437 }
438}
439
Ian Rogers57b86d42012-03-27 16:05:41 -0700440} // namespace art