blob: d78bbf3bc855a9c95b16fbc6be3f76d9cea7f93c [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 quick. Called by stub code.
34extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
Ian Rogerse3cd2f02013-05-24 15:32:56 -070035 mirror::Object* receiver,
Jeff Hao58df3272013-04-22 15:28:53 -070036 mirror::AbstractMethod** sp, Thread* thread)
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());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080055 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::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());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080075 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::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
Jeff Hao1f3bc2f2013-04-30 15:17:19 -070093 DCHECK_EQ(64U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
94 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 64);
jeffhaofa147e22012-10-12 17:03:32 -070095 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
Jeff Hao1f3bc2f2013-04-30 15:17:19 -070096 uint32_t pc_offset = 15;
jeffhaofa147e22012-10-12 17:03:32 -070097 uintptr_t caller_pc = regs[pc_offset];
Ian Rogers7caad772012-03-30 01:07:54 -070098#else
99 UNIMPLEMENTED(FATAL);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800100 mirror::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();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800112 mirror::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
Jeff Hao58df3272013-04-22 15:28:53 -0700119 if (called->IsRuntimeMethod()) {
Ian Rogers0c7abda2012-09-19 13:33:42 -0700120 uint32_t dex_pc = caller->ToDexPc(caller_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -0700121 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
122 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
123 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
124 Instruction::Code instr_code = instr->Opcode();
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200125 bool is_range;
Ian Rogers08f753d2012-08-24 14:35:25 -0700126 switch (instr_code) {
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200127 case Instruction::INVOKE_DIRECT:
128 invoke_type = kDirect;
129 is_range = false;
130 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700131 case Instruction::INVOKE_DIRECT_RANGE:
132 invoke_type = kDirect;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200133 is_range = true;
Ian Rogers08f753d2012-08-24 14:35:25 -0700134 break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200135 case Instruction::INVOKE_STATIC:
136 invoke_type = kStatic;
137 is_range = false;
138 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700139 case Instruction::INVOKE_STATIC_RANGE:
140 invoke_type = kStatic;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200141 is_range = true;
Ian Rogers08f753d2012-08-24 14:35:25 -0700142 break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200143 case Instruction::INVOKE_SUPER:
144 invoke_type = kSuper;
145 is_range = false;
146 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700147 case Instruction::INVOKE_SUPER_RANGE:
148 invoke_type = kSuper;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200149 is_range = true;
Ian Rogers08f753d2012-08-24 14:35:25 -0700150 break;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200151 case Instruction::INVOKE_VIRTUAL:
152 invoke_type = kVirtual;
153 is_range = false;
154 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700155 case Instruction::INVOKE_VIRTUAL_RANGE:
156 invoke_type = kVirtual;
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200157 is_range = true;
Ian Rogers08f753d2012-08-24 14:35:25 -0700158 break;
Ian Rogerse3cd2f02013-05-24 15:32:56 -0700159 case Instruction::INVOKE_INTERFACE:
160 invoke_type = kInterface;
161 is_range = false;
162 break;
163 case Instruction::INVOKE_INTERFACE_RANGE:
164 invoke_type = kInterface;
165 is_range = true;
166 break;
Ian Rogers08f753d2012-08-24 14:35:25 -0700167 default:
168 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200169 // Avoid used uninitialized warnings.
170 invoke_type = kDirect;
171 is_range = false;
Ian Rogers08f753d2012-08-24 14:35:25 -0700172 }
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200173 dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700174#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700175 shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700176#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700177 } else {
Jeff Hao58df3272013-04-22 15:28:53 -0700178 invoke_type = kStatic;
Ian Rogers57b86d42012-03-27 16:05:41 -0700179 dex_method_idx = called->GetDexMethodIndex();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700180#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700181 MethodHelper mh(called);
182 shorty = mh.GetShorty();
183 shorty_len = mh.GetShortyLength();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700184#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700185 }
Ian Rogers7caad772012-03-30 01:07:54 -0700186#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700187 // Discover shorty (avoid GCs)
188 size_t args_in_regs = 0;
189 for (size_t i = 1; i < shorty_len; i++) {
190 char c = shorty[i];
191 args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
192 if (args_in_regs > 3) {
193 args_in_regs = 3;
194 break;
195 }
196 }
197 // Place into local references incoming arguments from the caller's register arguments
198 size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1
Ian Rogers08f753d2012-08-24 14:35:25 -0700199 if (invoke_type != kStatic) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800200 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers57b86d42012-03-27 16:05:41 -0700201 cur_arg++;
202 if (args_in_regs < 3) {
203 // If we thought we had fewer than 3 arguments in registers, account for the receiver
204 args_in_regs++;
205 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700206 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700207 }
208 size_t shorty_index = 1; // skip return value
209 // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
210 // R0)
211 while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
212 char c = shorty[shorty_index];
213 shorty_index++;
214 if (c == 'L') {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800215 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700216 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700217 }
218 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
219 }
220 // Place into local references incoming arguments from the caller's stack arguments
jeffhaofa147e22012-10-12 17:03:32 -0700221 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 -0700222 while (shorty_index < shorty_len) {
223 char c = shorty[shorty_index];
224 shorty_index++;
225 if (c == 'L') {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800226 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700227 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700228 }
229 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
230 }
Ian Rogers7caad772012-03-30 01:07:54 -0700231#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700232 // Resolve method filling in dex cache
Jeff Hao58df3272013-04-22 15:28:53 -0700233 if (called->IsRuntimeMethod()) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700234 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
Ian Rogers57b86d42012-03-27 16:05:41 -0700235 }
236 const void* code = NULL;
237 if (LIKELY(!thread->IsExceptionPending())) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700238 // Incompatible class change should have been handled in resolve method.
239 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
Ian Rogerse3cd2f02013-05-24 15:32:56 -0700240 // Refine called method based on receiver.
241 if (invoke_type == kVirtual) {
242 called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
243 } else if (invoke_type == kInterface) {
244 called = receiver->GetClass()->FindVirtualMethodForInterface(called);
245 }
Ian Rogers08f753d2012-08-24 14:35:25 -0700246 // Ensure that the called method's class is initialized.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800247 mirror::Class* called_class = called->GetDeclaringClass();
Ian Rogers08f753d2012-08-24 14:35:25 -0700248 linker->EnsureInitialized(called_class, true, true);
249 if (LIKELY(called_class->IsInitialized())) {
Jeff Haoaa4a7932013-05-13 11:28:27 -0700250 code = called->GetEntryPointFromCompiledCode();
Ian Rogers08f753d2012-08-24 14:35:25 -0700251 } else if (called_class->IsInitializing()) {
252 if (invoke_type == kStatic) {
253 // Class is still initializing, go to oat and grab code (trampoline must be left in place
254 // until class is initialized to stop races between threads).
255 code = linker->GetOatCodeFor(called);
Ian Rogers57b86d42012-03-27 16:05:41 -0700256 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700257 // No trampoline for non-static methods.
Jeff Haoaa4a7932013-05-13 11:28:27 -0700258 code = called->GetEntryPointFromCompiledCode();
Ian Rogers57b86d42012-03-27 16:05:41 -0700259 }
260 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700261 DCHECK(called_class->IsErroneous());
Ian Rogers57b86d42012-03-27 16:05:41 -0700262 }
263 }
264 if (UNLIKELY(code == NULL)) {
265 // Something went wrong in ResolveMethod or EnsureInitialized,
266 // go into deliver exception with the pending exception in r0
Ian Rogersf3e98552013-03-20 15:49:49 -0700267 CHECK(thread->IsExceptionPending());
Logan Chien8dbb7082013-01-25 20:31:17 +0800268 code = reinterpret_cast<void*>(art_quick_deliver_exception_from_code);
Ian Rogers62d6c772013-02-27 08:32:07 -0800269 regs[0] = reinterpret_cast<uintptr_t>(thread->GetException(NULL));
Ian Rogers57b86d42012-03-27 16:05:41 -0700270 thread->ClearException();
271 } else {
272 // Expect class to at least be initializing.
273 DCHECK(called->GetDeclaringClass()->IsInitializing());
274 // Don't want infinite recursion.
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700275 DCHECK(code != GetResolutionTrampoline(linker));
Ian Rogers57b86d42012-03-27 16:05:41 -0700276 // Set up entry into main method
277 regs[0] = reinterpret_cast<uintptr_t>(called);
278 }
279 return code;
280}
TDYa12705fe3b62012-04-21 00:28:54 -0700281
Jeff Hao79fe5392013-04-24 18:41:58 -0700282// Called by the abstract method error stub.
283extern "C" void artThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* self,
284 mirror::AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700285 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers1c42ff92013-04-09 10:03:34 -0700286#if !defined(ART_USE_PORTABLE_COMPILER)
Ian Rogers62d6c772013-02-27 08:32:07 -0800287 FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
Ian Rogers1c42ff92013-04-09 10:03:34 -0700288#else
289 UNUSED(sp);
290#endif
Sebastien Hertz56adf602013-07-09 17:27:07 +0200291 ThrowAbstractMethodError(method);
Ian Rogers62d6c772013-02-27 08:32:07 -0800292 self->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -0700293}
Ian Rogers57b86d42012-03-27 16:05:41 -0700294
Ian Rogers57b86d42012-03-27 16:05:41 -0700295} // namespace art