1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
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 "art_method.h"
18 
19 #include "arch/context.h"
20 #include "art_field-inl.h"
21 #include "art_method-inl.h"
22 #include "base/stringpiece.h"
23 #include "dex_file-inl.h"
24 #include "dex_instruction.h"
25 #include "entrypoints/entrypoint_utils.h"
26 #include "entrypoints/runtime_asm_entrypoints.h"
27 #include "gc/accounting/card_table-inl.h"
28 #include "interpreter/interpreter.h"
29 #include "jit/jit.h"
30 #include "jit/jit_code_cache.h"
31 #include "jni_internal.h"
32 #include "mapping_table.h"
33 #include "mirror/abstract_method.h"
34 #include "mirror/class-inl.h"
35 #include "mirror/object_array-inl.h"
36 #include "mirror/object-inl.h"
37 #include "mirror/string.h"
38 #include "scoped_thread_state_change.h"
39 #include "well_known_classes.h"
40 
41 namespace art {
42 
43 extern "C" void art_quick_invoke_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
44                                       const char*);
45 #if defined(__LP64__) || defined(__arm__) || defined(__i386__)
46 extern "C" void art_quick_invoke_static_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
47                                              const char*);
48 #endif
49 
FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable & soa,jobject jlr_method)50 ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
51                                           jobject jlr_method) {
52   auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(jlr_method);
53   DCHECK(abstract_method != nullptr);
54   return abstract_method->GetArtMethod();
55 }
56 
GetNameAsString(Thread * self)57 mirror::String* ArtMethod::GetNameAsString(Thread* self) {
58   CHECK(!IsProxyMethod());
59   StackHandleScope<1> hs(self);
60   Handle<mirror::DexCache> dex_cache(hs.NewHandle(GetDexCache()));
61   auto* dex_file = dex_cache->GetDexFile();
62   uint32_t dex_method_idx = GetDexMethodIndex();
63   const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
64   return Runtime::Current()->GetClassLinker()->ResolveString(*dex_file, method_id.name_idx_,
65                                                              dex_cache);
66 }
67 
GetInvokeType()68 InvokeType ArtMethod::GetInvokeType() {
69   // TODO: kSuper?
70   if (GetDeclaringClass()->IsInterface()) {
71     return kInterface;
72   } else if (IsStatic()) {
73     return kStatic;
74   } else if (IsDirect()) {
75     return kDirect;
76   } else {
77     return kVirtual;
78   }
79 }
80 
NumArgRegisters(const StringPiece & shorty)81 size_t ArtMethod::NumArgRegisters(const StringPiece& shorty) {
82   CHECK_LE(1U, shorty.length());
83   uint32_t num_registers = 0;
84   for (size_t i = 1; i < shorty.length(); ++i) {
85     char ch = shorty[i];
86     if (ch == 'D' || ch == 'J') {
87       num_registers += 2;
88     } else {
89       num_registers += 1;
90     }
91   }
92   return num_registers;
93 }
94 
HasSameNameAndSignature(ArtMethod * method1,ArtMethod * method2)95 static bool HasSameNameAndSignature(ArtMethod* method1, ArtMethod* method2)
96     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
97   ScopedAssertNoThreadSuspension ants(Thread::Current(), "HasSameNameAndSignature");
98   const DexFile* dex_file = method1->GetDexFile();
99   const DexFile::MethodId& mid = dex_file->GetMethodId(method1->GetDexMethodIndex());
100   if (method1->GetDexCache() == method2->GetDexCache()) {
101     const DexFile::MethodId& mid2 = dex_file->GetMethodId(method2->GetDexMethodIndex());
102     return mid.name_idx_ == mid2.name_idx_ && mid.proto_idx_ == mid2.proto_idx_;
103   }
104   const DexFile* dex_file2 = method2->GetDexFile();
105   const DexFile::MethodId& mid2 = dex_file2->GetMethodId(method2->GetDexMethodIndex());
106   if (!DexFileStringEquals(dex_file, mid.name_idx_, dex_file2, mid2.name_idx_)) {
107     return false;  // Name mismatch.
108   }
109   return dex_file->GetMethodSignature(mid) == dex_file2->GetMethodSignature(mid2);
110 }
111 
FindOverriddenMethod(size_t pointer_size)112 ArtMethod* ArtMethod::FindOverriddenMethod(size_t pointer_size) {
113   if (IsStatic()) {
114     return nullptr;
115   }
116   mirror::Class* declaring_class = GetDeclaringClass();
117   mirror::Class* super_class = declaring_class->GetSuperClass();
118   uint16_t method_index = GetMethodIndex();
119   ArtMethod* result = nullptr;
120   // Did this method override a super class method? If so load the result from the super class'
121   // vtable
122   if (super_class->HasVTable() && method_index < super_class->GetVTableLength()) {
123     result = super_class->GetVTableEntry(method_index, pointer_size);
124   } else {
125     // Method didn't override superclass method so search interfaces
126     if (IsProxyMethod()) {
127       result = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>(
128           GetDexMethodIndex(), pointer_size);
129       CHECK_EQ(result,
130                Runtime::Current()->GetClassLinker()->FindMethodForProxy(GetDeclaringClass(), this));
131     } else {
132       mirror::IfTable* iftable = GetDeclaringClass()->GetIfTable();
133       for (size_t i = 0; i < iftable->Count() && result == nullptr; i++) {
134         mirror::Class* interface = iftable->GetInterface(i);
135         for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
136           ArtMethod* interface_method = interface->GetVirtualMethod(j, pointer_size);
137           if (HasSameNameAndSignature(
138               this, interface_method->GetInterfaceMethodIfProxy(sizeof(void*)))) {
139             result = interface_method;
140             break;
141           }
142         }
143       }
144     }
145   }
146   DCHECK(result == nullptr || HasSameNameAndSignature(
147       GetInterfaceMethodIfProxy(sizeof(void*)), result->GetInterfaceMethodIfProxy(sizeof(void*))));
148   return result;
149 }
150 
FindDexMethodIndexInOtherDexFile(const DexFile & other_dexfile,uint32_t name_and_signature_idx)151 uint32_t ArtMethod::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
152                                                      uint32_t name_and_signature_idx) {
153   const DexFile* dexfile = GetDexFile();
154   const uint32_t dex_method_idx = GetDexMethodIndex();
155   const DexFile::MethodId& mid = dexfile->GetMethodId(dex_method_idx);
156   const DexFile::MethodId& name_and_sig_mid = other_dexfile.GetMethodId(name_and_signature_idx);
157   DCHECK_STREQ(dexfile->GetMethodName(mid), other_dexfile.GetMethodName(name_and_sig_mid));
158   DCHECK_EQ(dexfile->GetMethodSignature(mid), other_dexfile.GetMethodSignature(name_and_sig_mid));
159   if (dexfile == &other_dexfile) {
160     return dex_method_idx;
161   }
162   const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_);
163   const DexFile::StringId* other_descriptor =
164       other_dexfile.FindStringId(mid_declaring_class_descriptor);
165   if (other_descriptor != nullptr) {
166     const DexFile::TypeId* other_type_id =
167         other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor));
168     if (other_type_id != nullptr) {
169       const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(
170           *other_type_id, other_dexfile.GetStringId(name_and_sig_mid.name_idx_),
171           other_dexfile.GetProtoId(name_and_sig_mid.proto_idx_));
172       if (other_mid != nullptr) {
173         return other_dexfile.GetIndexForMethodId(*other_mid);
174       }
175     }
176   }
177   return DexFile::kDexNoIndex;
178 }
179 
ToDexPc(const uintptr_t pc,bool abort_on_failure)180 uint32_t ArtMethod::ToDexPc(const uintptr_t pc, bool abort_on_failure) {
181   const void* entry_point = GetQuickOatEntryPoint(sizeof(void*));
182   uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(entry_point);
183   if (IsOptimized(sizeof(void*))) {
184     CodeInfo code_info = GetOptimizedCodeInfo();
185     StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset);
186     if (stack_map.IsValid()) {
187       return stack_map.GetDexPc(code_info);
188     }
189   } else {
190     MappingTable table(entry_point != nullptr ?
191         GetMappingTable(EntryPointToCodePointer(entry_point), sizeof(void*)) : nullptr);
192     if (table.TotalSize() == 0) {
193       // NOTE: Special methods (see Mir2Lir::GenSpecialCase()) have an empty mapping
194       // but they have no suspend checks and, consequently, we never call ToDexPc() for them.
195       DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this);
196       return DexFile::kDexNoIndex;   // Special no mapping case
197     }
198     // Assume the caller wants a pc-to-dex mapping so check here first.
199     typedef MappingTable::PcToDexIterator It;
200     for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
201       if (cur.NativePcOffset() == sought_offset) {
202         return cur.DexPc();
203       }
204     }
205     // Now check dex-to-pc mappings.
206     typedef MappingTable::DexToPcIterator It2;
207     for (It2 cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
208       if (cur.NativePcOffset() == sought_offset) {
209         return cur.DexPc();
210       }
211     }
212   }
213   if (abort_on_failure) {
214       LOG(FATAL) << "Failed to find Dex offset for PC offset " << reinterpret_cast<void*>(sought_offset)
215              << "(PC " << reinterpret_cast<void*>(pc) << ", entry_point=" << entry_point
216              << " current entry_point=" << GetQuickOatEntryPoint(sizeof(void*))
217              << ") in " << PrettyMethod(this);
218   }
219   return DexFile::kDexNoIndex;
220 }
221 
ToNativeQuickPc(const uint32_t dex_pc,bool abort_on_failure)222 uintptr_t ArtMethod::ToNativeQuickPc(const uint32_t dex_pc, bool abort_on_failure) {
223   const void* entry_point = GetQuickOatEntryPoint(sizeof(void*));
224   MappingTable table(entry_point != nullptr ?
225       GetMappingTable(EntryPointToCodePointer(entry_point), sizeof(void*)) : nullptr);
226   if (table.TotalSize() == 0) {
227     DCHECK_EQ(dex_pc, 0U);
228     return 0;   // Special no mapping/pc == 0 case
229   }
230   // Assume the caller wants a dex-to-pc mapping so check here first.
231   typedef MappingTable::DexToPcIterator It;
232   for (It cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
233     if (cur.DexPc() == dex_pc) {
234       return reinterpret_cast<uintptr_t>(entry_point) + cur.NativePcOffset();
235     }
236   }
237   // Now check pc-to-dex mappings.
238   typedef MappingTable::PcToDexIterator It2;
239   for (It2 cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
240     if (cur.DexPc() == dex_pc) {
241       return reinterpret_cast<uintptr_t>(entry_point) + cur.NativePcOffset();
242     }
243   }
244   if (abort_on_failure) {
245     LOG(FATAL) << "Failed to find native offset for dex pc 0x" << std::hex << dex_pc
246                << " in " << PrettyMethod(this);
247   }
248   return UINTPTR_MAX;
249 }
250 
FindCatchBlock(Handle<mirror::Class> exception_type,uint32_t dex_pc,bool * has_no_move_exception)251 uint32_t ArtMethod::FindCatchBlock(Handle<mirror::Class> exception_type,
252                                    uint32_t dex_pc, bool* has_no_move_exception) {
253   const DexFile::CodeItem* code_item = GetCodeItem();
254   // Set aside the exception while we resolve its type.
255   Thread* self = Thread::Current();
256   StackHandleScope<1> hs(self);
257   Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException()));
258   self->ClearException();
259   // Default to handler not found.
260   uint32_t found_dex_pc = DexFile::kDexNoIndex;
261   // Iterate over the catch handlers associated with dex_pc.
262   for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
263     uint16_t iter_type_idx = it.GetHandlerTypeIndex();
264     // Catch all case
265     if (iter_type_idx == DexFile::kDexNoIndex16) {
266       found_dex_pc = it.GetHandlerAddress();
267       break;
268     }
269     // Does this catch exception type apply?
270     mirror::Class* iter_exception_type = GetClassFromTypeIndex(iter_type_idx, true);
271     if (UNLIKELY(iter_exception_type == nullptr)) {
272       // Now have a NoClassDefFoundError as exception. Ignore in case the exception class was
273       // removed by a pro-guard like tool.
274       // Note: this is not RI behavior. RI would have failed when loading the class.
275       self->ClearException();
276       // Delete any long jump context as this routine is called during a stack walk which will
277       // release its in use context at the end.
278       delete self->GetLongJumpContext();
279       LOG(WARNING) << "Unresolved exception class when finding catch block: "
280         << DescriptorToDot(GetTypeDescriptorFromTypeIdx(iter_type_idx));
281     } else if (iter_exception_type->IsAssignableFrom(exception_type.Get())) {
282       found_dex_pc = it.GetHandlerAddress();
283       break;
284     }
285   }
286   if (found_dex_pc != DexFile::kDexNoIndex) {
287     const Instruction* first_catch_instr =
288         Instruction::At(&code_item->insns_[found_dex_pc]);
289     *has_no_move_exception = (first_catch_instr->Opcode() != Instruction::MOVE_EXCEPTION);
290   }
291   // Put the exception back.
292   if (exception.Get() != nullptr) {
293     self->SetException(exception.Get());
294   }
295   return found_dex_pc;
296 }
297 
AssertPcIsWithinQuickCode(uintptr_t pc)298 void ArtMethod::AssertPcIsWithinQuickCode(uintptr_t pc) {
299   if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) {
300     return;
301   }
302   if (pc == reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc())) {
303     return;
304   }
305   const void* code = GetEntryPointFromQuickCompiledCode();
306   if (code == GetQuickInstrumentationEntryPoint()) {
307     return;
308   }
309   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
310   if (class_linker->IsQuickToInterpreterBridge(code) ||
311       class_linker->IsQuickResolutionStub(code)) {
312     return;
313   }
314   // If we are the JIT then we may have just compiled the method after the
315   // IsQuickToInterpreterBridge check.
316   jit::Jit* const jit = Runtime::Current()->GetJit();
317   if (jit != nullptr &&
318       jit->GetCodeCache()->ContainsCodePtr(reinterpret_cast<const void*>(code))) {
319     return;
320   }
321   /*
322    * During a stack walk, a return PC may point past-the-end of the code
323    * in the case that the last instruction is a call that isn't expected to
324    * return.  Thus, we check <= code + GetCodeSize().
325    *
326    * NOTE: For Thumb both pc and code are offset by 1 indicating the Thumb state.
327    */
328   CHECK(PcIsWithinQuickCode(reinterpret_cast<uintptr_t>(code), pc))
329       << PrettyMethod(this)
330       << " pc=" << std::hex << pc
331       << " code=" << code
332       << " size=" << GetCodeSize(
333           EntryPointToCodePointer(reinterpret_cast<const void*>(code)));
334 }
335 
IsEntrypointInterpreter()336 bool ArtMethod::IsEntrypointInterpreter() {
337   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
338   const void* oat_quick_code = class_linker->GetOatMethodQuickCodeFor(this);
339   return oat_quick_code == nullptr || oat_quick_code != GetEntryPointFromQuickCompiledCode();
340 }
341 
GetQuickOatEntryPoint(size_t pointer_size)342 const void* ArtMethod::GetQuickOatEntryPoint(size_t pointer_size) {
343   if (IsAbstract() || IsRuntimeMethod() || IsProxyMethod()) {
344     return nullptr;
345   }
346   Runtime* runtime = Runtime::Current();
347   ClassLinker* class_linker = runtime->GetClassLinker();
348   const void* code = runtime->GetInstrumentation()->GetQuickCodeFor(this, pointer_size);
349   // On failure, instead of null we get the quick-generic-jni-trampoline for native method
350   // indicating the generic JNI, or the quick-to-interpreter-bridge (but not the trampoline)
351   // for non-native methods.
352   if (class_linker->IsQuickToInterpreterBridge(code) ||
353       class_linker->IsQuickGenericJniStub(code)) {
354     return nullptr;
355   }
356   return code;
357 }
358 
359 #ifndef NDEBUG
NativeQuickPcOffset(const uintptr_t pc,const void * quick_entry_point)360 uintptr_t ArtMethod::NativeQuickPcOffset(const uintptr_t pc, const void* quick_entry_point) {
361   CHECK_NE(quick_entry_point, GetQuickToInterpreterBridge());
362   CHECK_EQ(quick_entry_point,
363            Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this, sizeof(void*)));
364   return pc - reinterpret_cast<uintptr_t>(quick_entry_point);
365 }
366 #endif
367 
Invoke(Thread * self,uint32_t * args,uint32_t args_size,JValue * result,const char * shorty)368 void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
369                        const char* shorty) {
370   if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
371     ThrowStackOverflowError(self);
372     return;
373   }
374 
375   if (kIsDebugBuild) {
376     self->AssertThreadSuspensionIsAllowable();
377     CHECK_EQ(kRunnable, self->GetState());
378     CHECK_STREQ(GetInterfaceMethodIfProxy(sizeof(void*))->GetShorty(), shorty);
379   }
380 
381   // Push a transition back into managed code onto the linked list in thread.
382   ManagedStack fragment;
383   self->PushManagedStackFragment(&fragment);
384 
385   Runtime* runtime = Runtime::Current();
386   // Call the invoke stub, passing everything as arguments.
387   // If the runtime is not yet started or it is required by the debugger, then perform the
388   // Invocation by the interpreter.
389   if (UNLIKELY(!runtime->IsStarted() || Dbg::IsForcedInterpreterNeededForCalling(self, this))) {
390     if (IsStatic()) {
391       art::interpreter::EnterInterpreterFromInvoke(self, this, nullptr, args, result);
392     } else {
393       mirror::Object* receiver =
394           reinterpret_cast<StackReference<mirror::Object>*>(&args[0])->AsMirrorPtr();
395       art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args + 1, result);
396     }
397   } else {
398     DCHECK_EQ(runtime->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
399 
400     constexpr bool kLogInvocationStartAndReturn = false;
401     bool have_quick_code = GetEntryPointFromQuickCompiledCode() != nullptr;
402     if (LIKELY(have_quick_code)) {
403       if (kLogInvocationStartAndReturn) {
404         LOG(INFO) << StringPrintf(
405             "Invoking '%s' quick code=%p static=%d", PrettyMethod(this).c_str(),
406             GetEntryPointFromQuickCompiledCode(), static_cast<int>(IsStatic() ? 1 : 0));
407       }
408 
409       // Ensure that we won't be accidentally calling quick compiled code when -Xint.
410       if (kIsDebugBuild && runtime->GetInstrumentation()->IsForcedInterpretOnly()) {
411         DCHECK(!runtime->UseJit());
412         CHECK(IsEntrypointInterpreter())
413             << "Don't call compiled code when -Xint " << PrettyMethod(this);
414       }
415 
416 #if defined(__LP64__) || defined(__arm__) || defined(__i386__)
417       if (!IsStatic()) {
418         (*art_quick_invoke_stub)(this, args, args_size, self, result, shorty);
419       } else {
420         (*art_quick_invoke_static_stub)(this, args, args_size, self, result, shorty);
421       }
422 #else
423       (*art_quick_invoke_stub)(this, args, args_size, self, result, shorty);
424 #endif
425       if (UNLIKELY(self->GetException() == Thread::GetDeoptimizationException())) {
426         // Unusual case where we were running generated code and an
427         // exception was thrown to force the activations to be removed from the
428         // stack. Continue execution in the interpreter.
429         self->ClearException();
430         ShadowFrame* shadow_frame =
431             self->PopStackedShadowFrame(StackedShadowFrameType::kDeoptimizationShadowFrame);
432         result->SetJ(self->PopDeoptimizationReturnValue().GetJ());
433         self->SetTopOfStack(nullptr);
434         self->SetTopOfShadowStack(shadow_frame);
435         interpreter::EnterInterpreterFromDeoptimize(self, shadow_frame, result);
436       }
437       if (kLogInvocationStartAndReturn) {
438         LOG(INFO) << StringPrintf("Returned '%s' quick code=%p", PrettyMethod(this).c_str(),
439                                   GetEntryPointFromQuickCompiledCode());
440       }
441     } else {
442       LOG(INFO) << "Not invoking '" << PrettyMethod(this) << "' code=null";
443       if (result != nullptr) {
444         result->SetJ(0);
445       }
446     }
447   }
448 
449   // Pop transition.
450   self->PopManagedStackFragment(fragment);
451 }
452 
453 // Counts the number of references in the parameter list of the corresponding method.
454 // Note: Thus does _not_ include "this" for non-static methods.
GetNumberOfReferenceArgsWithoutReceiver(ArtMethod * method)455 static uint32_t GetNumberOfReferenceArgsWithoutReceiver(ArtMethod* method)
456     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
457   uint32_t shorty_len;
458   const char* shorty = method->GetShorty(&shorty_len);
459   uint32_t refs = 0;
460   for (uint32_t i = 1; i < shorty_len ; ++i) {
461     if (shorty[i] == 'L') {
462       refs++;
463     }
464   }
465   return refs;
466 }
467 
GetQuickFrameInfo()468 QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() {
469   Runtime* runtime = Runtime::Current();
470 
471   if (UNLIKELY(IsAbstract())) {
472     return runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
473   }
474 
475   // This goes before IsProxyMethod since runtime methods have a null declaring class.
476   if (UNLIKELY(IsRuntimeMethod())) {
477     return runtime->GetRuntimeMethodFrameInfo(this);
478   }
479 
480   // For Proxy method we add special handling for the direct method case  (there is only one
481   // direct method - constructor). Direct method is cloned from original
482   // java.lang.reflect.Proxy class together with code and as a result it is executed as usual
483   // quick compiled method without any stubs. So the frame info should be returned as it is a
484   // quick method not a stub. However, if instrumentation stubs are installed, the
485   // instrumentation->GetQuickCodeFor() returns the artQuickProxyInvokeHandler instead of an
486   // oat code pointer, thus we have to add a special case here.
487   if (UNLIKELY(IsProxyMethod())) {
488     if (IsDirect()) {
489       CHECK(IsConstructor());
490       return GetQuickFrameInfo(EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode()));
491     } else {
492       return runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
493     }
494   }
495 
496   const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this, sizeof(void*));
497   ClassLinker* class_linker = runtime->GetClassLinker();
498   // On failure, instead of null we get the quick-generic-jni-trampoline for native method
499   // indicating the generic JNI, or the quick-to-interpreter-bridge (but not the trampoline)
500   // for non-native methods. And we really shouldn't see a failure for non-native methods here.
501   DCHECK(!class_linker->IsQuickToInterpreterBridge(entry_point));
502 
503   if (class_linker->IsQuickGenericJniStub(entry_point)) {
504     // Generic JNI frame.
505     DCHECK(IsNative());
506     uint32_t handle_refs = GetNumberOfReferenceArgsWithoutReceiver(this) + 1;
507     size_t scope_size = HandleScope::SizeOf(handle_refs);
508     QuickMethodFrameInfo callee_info = runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
509 
510     // Callee saves + handle scope + method ref + alignment
511     // Note: -sizeof(void*) since callee-save frame stores a whole method pointer.
512     size_t frame_size = RoundUp(callee_info.FrameSizeInBytes() - sizeof(void*) +
513                                 sizeof(ArtMethod*) + scope_size, kStackAlignment);
514     return QuickMethodFrameInfo(frame_size, callee_info.CoreSpillMask(), callee_info.FpSpillMask());
515   }
516 
517   const void* code_pointer = EntryPointToCodePointer(entry_point);
518   return GetQuickFrameInfo(code_pointer);
519 }
520 
RegisterNative(const void * native_method,bool is_fast)521 void ArtMethod::RegisterNative(const void* native_method, bool is_fast) {
522   CHECK(IsNative()) << PrettyMethod(this);
523   CHECK(!IsFastNative()) << PrettyMethod(this);
524   CHECK(native_method != nullptr) << PrettyMethod(this);
525   if (is_fast) {
526     SetAccessFlags(GetAccessFlags() | kAccFastNative);
527   }
528   SetEntryPointFromJni(native_method);
529 }
530 
UnregisterNative()531 void ArtMethod::UnregisterNative() {
532   CHECK(IsNative() && !IsFastNative()) << PrettyMethod(this);
533   // restore stub to lookup native pointer via dlsym
534   RegisterNative(GetJniDlsymLookupStub(), false);
535 }
536 
EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params)537 bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params) {
538   auto* dex_cache = GetDexCache();
539   auto* dex_file = dex_cache->GetDexFile();
540   const auto& method_id = dex_file->GetMethodId(GetDexMethodIndex());
541   const auto& proto_id = dex_file->GetMethodPrototype(method_id);
542   const DexFile::TypeList* proto_params = dex_file->GetProtoParameters(proto_id);
543   auto count = proto_params != nullptr ? proto_params->Size() : 0u;
544   auto param_len = params.Get() != nullptr ? params->GetLength() : 0u;
545   if (param_len != count) {
546     return false;
547   }
548   auto* cl = Runtime::Current()->GetClassLinker();
549   for (size_t i = 0; i < count; ++i) {
550     auto type_idx = proto_params->GetTypeItem(i).type_idx_;
551     auto* type = cl->ResolveType(type_idx, this);
552     if (type == nullptr) {
553       Thread::Current()->AssertPendingException();
554       return false;
555     }
556     if (type != params->GetWithoutChecks(i)) {
557       return false;
558     }
559   }
560   return true;
561 }
562 
563 }  // namespace art
564