blob: 6565dfe7e57a46218b1c4f71df2fbb22cf71c010 [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 Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "class_linker-inl.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070021#include "dex_instruction.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080022#include "mirror/class-inl.h"
23#include "mirror/abstract_method-inl.h"
24#include "mirror/object.h"
25#include "mirror/object_array-inl.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070026#include "object_utils.h"
TDYa12705fe3b62012-04-21 00:28:54 -070027#if defined(ART_USE_LLVM_COMPILER)
28#include "nth_caller_visitor.h"
29#endif
Ian Rogers00f7d0e2012-07-19 15:28:27 -070030#include "scoped_thread_state_change.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070031
32// Architecture specific assembler helper to deliver exception.
Logan Chien8dbb7082013-01-25 20:31:17 +080033extern "C" void art_quick_deliver_exception_from_code(void*);
Ian Rogers57b86d42012-03-27 16:05:41 -070034
35namespace art {
36
TDYa12705fe3b62012-04-21 00:28:54 -070037#if !defined(ART_USE_LLVM_COMPILER)
Ian Rogers57b86d42012-03-27 16:05:41 -070038// Lazily resolve a method. Called by stub code.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080039const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod* called,
40 mirror::AbstractMethod** sp, Thread* thread,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070041 Runtime::TrampolineType type)
Ian Rogersb726dcb2012-09-05 08:57:23 -070042 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers7caad772012-03-30 01:07:54 -070043#if defined(__arm__)
Ian Rogers57b86d42012-03-27 16:05:41 -070044 // On entry the stack pointed by sp is:
45 // | argN | |
46 // | ... | |
47 // | arg4 | |
48 // | arg3 spill | | Caller's frame
49 // | arg2 spill | |
50 // | arg1 spill | |
51 // | Method* | ---
52 // | LR |
53 // | ... | callee saves
54 // | R3 | arg3
55 // | R2 | arg2
56 // | R1 | arg1
57 // | R0 |
58 // | Method* | <- sp
Ian Rogers57b86d42012-03-27 16:05:41 -070059 DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080060 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
Ian Rogers7caad772012-03-30 01:07:54 -070061 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
jeffhaofa147e22012-10-12 17:03:32 -070062 uint32_t pc_offset = 10;
63 uintptr_t caller_pc = regs[pc_offset];
Ian Rogers7caad772012-03-30 01:07:54 -070064#elif defined(__i386__)
65 // On entry the stack pointed by sp is:
66 // | argN | |
67 // | ... | |
68 // | arg4 | |
69 // | arg3 spill | | Caller's frame
70 // | arg2 spill | |
71 // | arg1 spill | |
72 // | Method* | ---
73 // | Return |
74 // | EBP,ESI,EDI | callee saves
75 // | EBX | arg3
76 // | EDX | arg2
77 // | ECX | arg1
78 // | EAX/Method* | <- sp
79 DCHECK_EQ(32U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080080 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 32);
Ian Rogers7caad772012-03-30 01:07:54 -070081 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
82 uintptr_t caller_pc = regs[7];
jeffhaofa147e22012-10-12 17:03:32 -070083#elif defined(__mips__)
84 // On entry the stack pointed by sp is:
85 // | argN | |
86 // | ... | |
87 // | arg4 | |
88 // | arg3 spill | | Caller's frame
89 // | arg2 spill | |
90 // | arg1 spill | |
91 // | Method* | ---
92 // | RA |
93 // | ... | callee saves
94 // | A3 | arg3
95 // | A2 | arg2
96 // | A1 | arg1
97 // | A0/Method* | <- sp
98 DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080099 mirror::AbstractMethod** caller_sp = reinterpret_cast<mirror::AbstractMethod**>(reinterpret_cast<byte*>(sp) + 48);
jeffhaofa147e22012-10-12 17:03:32 -0700100 uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp));
101 uint32_t pc_offset = 11;
102 uintptr_t caller_pc = regs[pc_offset];
Ian Rogers7caad772012-03-30 01:07:54 -0700103#else
104 UNIMPLEMENTED(FATAL);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800105 mirror::AbstractMethod** caller_sp = NULL;
Ian Rogers7caad772012-03-30 01:07:54 -0700106 uintptr_t* regs = NULL;
107 uintptr_t caller_pc = 0;
108#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700109 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
110 // Start new JNI local reference state
111 JNIEnvExt* env = thread->GetJniEnv();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700112 ScopedObjectAccessUnchecked soa(env);
Ian Rogers57b86d42012-03-27 16:05:41 -0700113 ScopedJniEnvLocalRefState env_state(env);
114
115 // Compute details about the called method (avoid GCs)
116 ClassLinker* linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800117 mirror::AbstractMethod* caller = *caller_sp;
Ian Rogers08f753d2012-08-24 14:35:25 -0700118 InvokeType invoke_type;
Ian Rogers57b86d42012-03-27 16:05:41 -0700119 uint32_t dex_method_idx;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700120#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700121 const char* shorty;
122 uint32_t shorty_len;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700123#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700124 if (type == Runtime::kUnknownMethod) {
125 DCHECK(called->IsRuntimeMethod());
Ian Rogers0c7abda2012-09-19 13:33:42 -0700126 uint32_t dex_pc = caller->ToDexPc(caller_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -0700127 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
128 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
129 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
130 Instruction::Code instr_code = instr->Opcode();
Ian Rogers08f753d2012-08-24 14:35:25 -0700131 switch (instr_code) {
132 case Instruction::INVOKE_DIRECT: // Fall-through.
133 case Instruction::INVOKE_DIRECT_RANGE:
134 invoke_type = kDirect;
135 break;
136 case Instruction::INVOKE_STATIC: // Fall-through.
137 case Instruction::INVOKE_STATIC_RANGE:
138 invoke_type = kStatic;
139 break;
140 case Instruction::INVOKE_SUPER: // Fall-through.
141 case Instruction::INVOKE_SUPER_RANGE:
142 invoke_type = kSuper;
143 break;
144 case Instruction::INVOKE_VIRTUAL: // Fall-through.
145 case Instruction::INVOKE_VIRTUAL_RANGE:
146 invoke_type = kVirtual;
147 break;
148 default:
149 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
150 invoke_type = kDirect; // Avoid used uninitialized warnings.
151 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700152 DecodedInstruction dec_insn(instr);
153 dex_method_idx = dec_insn.vB;
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700154#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700155 shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700156#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700157 } else {
158 DCHECK(!called->IsRuntimeMethod());
Ian Rogers08f753d2012-08-24 14:35:25 -0700159 invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
Ian Rogers57b86d42012-03-27 16:05:41 -0700160 dex_method_idx = called->GetDexMethodIndex();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700161#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700162 MethodHelper mh(called);
163 shorty = mh.GetShorty();
164 shorty_len = mh.GetShortyLength();
Brian Carlstromfd2ec542012-05-02 15:08:57 -0700165#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700166 }
Ian Rogers7caad772012-03-30 01:07:54 -0700167#if !defined(__i386__)
Ian Rogers57b86d42012-03-27 16:05:41 -0700168 // Discover shorty (avoid GCs)
169 size_t args_in_regs = 0;
170 for (size_t i = 1; i < shorty_len; i++) {
171 char c = shorty[i];
172 args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
173 if (args_in_regs > 3) {
174 args_in_regs = 3;
175 break;
176 }
177 }
178 // Place into local references incoming arguments from the caller's register arguments
179 size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1
Ian Rogers08f753d2012-08-24 14:35:25 -0700180 if (invoke_type != kStatic) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800181 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers57b86d42012-03-27 16:05:41 -0700182 cur_arg++;
183 if (args_in_regs < 3) {
184 // If we thought we had fewer than 3 arguments in registers, account for the receiver
185 args_in_regs++;
186 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700187 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700188 }
189 size_t shorty_index = 1; // skip return value
190 // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
191 // R0)
192 while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
193 char c = shorty[shorty_index];
194 shorty_index++;
195 if (c == 'L') {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800196 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700197 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700198 }
199 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
200 }
201 // Place into local references incoming arguments from the caller's stack arguments
jeffhaofa147e22012-10-12 17:03:32 -0700202 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 -0700203 while (shorty_index < shorty_len) {
204 char c = shorty[shorty_index];
205 shorty_index++;
206 if (c == 'L') {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800207 mirror::Object* obj = reinterpret_cast<mirror::Object*>(regs[cur_arg]);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700208 soa.AddLocalReference<jobject>(obj);
Ian Rogers57b86d42012-03-27 16:05:41 -0700209 }
210 cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
211 }
Ian Rogers7caad772012-03-30 01:07:54 -0700212#endif
Ian Rogers57b86d42012-03-27 16:05:41 -0700213 // Resolve method filling in dex cache
214 if (type == Runtime::kUnknownMethod) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700215 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
Ian Rogers57b86d42012-03-27 16:05:41 -0700216 }
217 const void* code = NULL;
218 if (LIKELY(!thread->IsExceptionPending())) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700219 // Incompatible class change should have been handled in resolve method.
220 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
221 // Ensure that the called method's class is initialized.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800222 mirror::Class* called_class = called->GetDeclaringClass();
Ian Rogers08f753d2012-08-24 14:35:25 -0700223 linker->EnsureInitialized(called_class, true, true);
224 if (LIKELY(called_class->IsInitialized())) {
225 code = called->GetCode();
226 } else if (called_class->IsInitializing()) {
227 if (invoke_type == kStatic) {
228 // Class is still initializing, go to oat and grab code (trampoline must be left in place
229 // until class is initialized to stop races between threads).
230 code = linker->GetOatCodeFor(called);
Ian Rogers57b86d42012-03-27 16:05:41 -0700231 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700232 // No trampoline for non-static methods.
233 code = called->GetCode();
Ian Rogers57b86d42012-03-27 16:05:41 -0700234 }
235 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700236 DCHECK(called_class->IsErroneous());
Ian Rogers57b86d42012-03-27 16:05:41 -0700237 }
238 }
239 if (UNLIKELY(code == NULL)) {
240 // Something went wrong in ResolveMethod or EnsureInitialized,
241 // go into deliver exception with the pending exception in r0
Logan Chien8dbb7082013-01-25 20:31:17 +0800242 code = reinterpret_cast<void*>(art_quick_deliver_exception_from_code);
Ian Rogers57b86d42012-03-27 16:05:41 -0700243 regs[0] = reinterpret_cast<uintptr_t>(thread->GetException());
244 thread->ClearException();
245 } else {
246 // Expect class to at least be initializing.
247 DCHECK(called->GetDeclaringClass()->IsInitializing());
248 // Don't want infinite recursion.
249 DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
250 // Set up entry into main method
251 regs[0] = reinterpret_cast<uintptr_t>(called);
252 }
253 return code;
254}
TDYa12705fe3b62012-04-21 00:28:54 -0700255#else // ART_USE_LLVM_COMPILER
Ian Rogers98573f92013-01-30 17:26:32 -0800256const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod* called,
257 mirror::AbstractMethod** called_addr,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700258 Thread* thread, Runtime::TrampolineType type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700259 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers0399dde2012-06-06 17:09:28 -0700260 uint32_t dex_pc;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800261 mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
Ian Rogers57b86d42012-03-27 16:05:41 -0700262
TDYa12705fe3b62012-04-21 00:28:54 -0700263 ClassLinker* linker = Runtime::Current()->GetClassLinker();
Ian Rogers08f753d2012-08-24 14:35:25 -0700264 InvokeType invoke_type;
TDYa12705fe3b62012-04-21 00:28:54 -0700265 uint32_t dex_method_idx;
266 if (type == Runtime::kUnknownMethod) {
267 DCHECK(called->IsRuntimeMethod());
TDYa12705fe3b62012-04-21 00:28:54 -0700268 const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
269 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
270 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
271 Instruction::Code instr_code = instr->Opcode();
Ian Rogers08f753d2012-08-24 14:35:25 -0700272 switch (instr_code) {
273 case Instruction::INVOKE_DIRECT: // Fall-through.
274 case Instruction::INVOKE_DIRECT_RANGE:
275 invoke_type = kDirect;
276 break;
277 case Instruction::INVOKE_STATIC: // Fall-through.
278 case Instruction::INVOKE_STATIC_RANGE:
279 invoke_type = kStatic;
280 break;
281 case Instruction::INVOKE_SUPER: // Fall-through.
282 case Instruction::INVOKE_SUPER_RANGE:
283 invoke_type = kSuper;
284 break;
285 case Instruction::INVOKE_VIRTUAL: // Fall-through.
286 case Instruction::INVOKE_VIRTUAL_RANGE:
287 invoke_type = kVirtual;
288 break;
289 default:
290 LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
291 invoke_type = kDirect; // Avoid used uninitialized warnings.
292 }
TDYa12705fe3b62012-04-21 00:28:54 -0700293 DecodedInstruction dec_insn(instr);
294 dex_method_idx = dec_insn.vB;
295 } else {
296 DCHECK(!called->IsRuntimeMethod());
Ian Rogers08f753d2012-08-24 14:35:25 -0700297 invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
TDYa12705fe3b62012-04-21 00:28:54 -0700298 dex_method_idx = called->GetDexMethodIndex();
299 }
300 if (type == Runtime::kUnknownMethod) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700301 called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
TDYa12705fe3b62012-04-21 00:28:54 -0700302 }
303 const void* code = NULL;
304 if (LIKELY(!thread->IsExceptionPending())) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700305 // Incompatible class change should have been handled in resolve method.
306 CHECK(!called->CheckIncompatibleClassChange(invoke_type));
307 // Ensure that the called method's class is initialized.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800308 mirror::Class* called_class = called->GetDeclaringClass();
Ian Rogers08f753d2012-08-24 14:35:25 -0700309 linker->EnsureInitialized(called_class, true, true);
310 if (LIKELY(called_class->IsInitialized())) {
311 code = called->GetCode();
312 // TODO: remove this after we solve the link issue.
313 { // for lazy link.
314 if (code == NULL) {
315 code = linker->GetOatCodeFor(called);
316 }
317 }
318 } else if (called_class->IsInitializing()) {
319 if (invoke_type == kStatic) {
320 // Class is still initializing, go to oat and grab code (trampoline must be left in place
321 // until class is initialized to stop races between threads).
322 code = linker->GetOatCodeFor(called);
323 } else {
324 // No trampoline for non-static methods.
TDYa12705fe3b62012-04-21 00:28:54 -0700325 code = called->GetCode();
326 // TODO: remove this after we solve the link issue.
327 { // for lazy link.
328 if (code == NULL) {
329 code = linker->GetOatCodeFor(called);
330 }
331 }
TDYa12705fe3b62012-04-21 00:28:54 -0700332 }
333 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700334 DCHECK(called_class->IsErroneous());
TDYa12705fe3b62012-04-21 00:28:54 -0700335 }
336 }
337 if (LIKELY(code != NULL)) {
338 // Expect class to at least be initializing.
339 DCHECK(called->GetDeclaringClass()->IsInitializing());
340 // Don't want infinite recursion.
341 DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
342 // Set up entry into main method
343 *called_addr = called;
344 }
345 return code;
346}
347#endif // ART_USE_LLVM_COMPILER
348
349#if !defined(ART_USE_LLVM_COMPILER)
Ian Rogers57b86d42012-03-27 16:05:41 -0700350// Called by the AbstractMethodError. Called by stub code.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800351extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* thread,
352 mirror::AbstractMethod** sp)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700353 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700354 FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
355 thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
356 "abstract method \"%s\"", PrettyMethod(method).c_str());
jeffhao94d6df42012-11-26 16:02:12 -0800357 thread->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -0700358}
TDYa12705fe3b62012-04-21 00:28:54 -0700359#else // ART_USE_LLVM_COMPILER
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800360extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* thread,
361 mirror::AbstractMethod**)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700362 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa12705fe3b62012-04-21 00:28:54 -0700363 thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
364 "abstract method \"%s\"", PrettyMethod(method).c_str());
365}
366#endif // ART_USE_LLVM_COMPILER
Ian Rogers57b86d42012-03-27 16:05:41 -0700367
368} // namespace art