• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "class_linker-inl.h"
24 #include "debugger.h"
25 #include "dex_file-inl.h"
26 #include "dex_instruction.h"
27 #include "entrypoints/runtime_asm_entrypoints.h"
28 #include "gc/accounting/card_table-inl.h"
29 #include "interpreter/interpreter.h"
30 #include "jit/jit.h"
31 #include "jit/jit_code_cache.h"
32 #include "jit/profiling_info.h"
33 #include "jni_internal.h"
34 #include "mirror/abstract_method.h"
35 #include "mirror/class-inl.h"
36 #include "mirror/object_array-inl.h"
37 #include "mirror/object-inl.h"
38 #include "mirror/string.h"
39 #include "oat_file-inl.h"
40 #include "scoped_thread_state_change.h"
41 #include "well_known_classes.h"
42 
43 namespace art {
44 
45 extern "C" void art_quick_invoke_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
46                                       const char*);
47 extern "C" void art_quick_invoke_static_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
48                                              const char*);
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 
ThrowInvocationTimeError()68 void ArtMethod::ThrowInvocationTimeError() {
69   DCHECK(!IsInvokable());
70   // NOTE: IsDefaultConflicting must be first since the actual method might or might not be abstract
71   //       due to the way we select it.
72   if (IsDefaultConflicting()) {
73     ThrowIncompatibleClassChangeErrorForMethodConflict(this);
74   } else {
75     DCHECK(IsAbstract());
76     ThrowAbstractMethodError(this);
77   }
78 }
79 
GetInvokeType()80 InvokeType ArtMethod::GetInvokeType() {
81   // TODO: kSuper?
82   if (IsStatic()) {
83     return kStatic;
84   } else if (GetDeclaringClass()->IsInterface()) {
85     return kInterface;
86   } else if (IsDirect()) {
87     return kDirect;
88   } else {
89     return kVirtual;
90   }
91 }
92 
NumArgRegisters(const StringPiece & shorty)93 size_t ArtMethod::NumArgRegisters(const StringPiece& shorty) {
94   CHECK_LE(1U, shorty.length());
95   uint32_t num_registers = 0;
96   for (size_t i = 1; i < shorty.length(); ++i) {
97     char ch = shorty[i];
98     if (ch == 'D' || ch == 'J') {
99       num_registers += 2;
100     } else {
101       num_registers += 1;
102     }
103   }
104   return num_registers;
105 }
106 
HasSameNameAndSignature(ArtMethod * other)107 bool ArtMethod::HasSameNameAndSignature(ArtMethod* other) {
108   ScopedAssertNoThreadSuspension ants(Thread::Current(), "HasSameNameAndSignature");
109   const DexFile* dex_file = GetDexFile();
110   const DexFile::MethodId& mid = dex_file->GetMethodId(GetDexMethodIndex());
111   if (GetDexCache() == other->GetDexCache()) {
112     const DexFile::MethodId& mid2 = dex_file->GetMethodId(other->GetDexMethodIndex());
113     return mid.name_idx_ == mid2.name_idx_ && mid.proto_idx_ == mid2.proto_idx_;
114   }
115   const DexFile* dex_file2 = other->GetDexFile();
116   const DexFile::MethodId& mid2 = dex_file2->GetMethodId(other->GetDexMethodIndex());
117   if (!DexFileStringEquals(dex_file, mid.name_idx_, dex_file2, mid2.name_idx_)) {
118     return false;  // Name mismatch.
119   }
120   return dex_file->GetMethodSignature(mid) == dex_file2->GetMethodSignature(mid2);
121 }
122 
FindOverriddenMethod(size_t pointer_size)123 ArtMethod* ArtMethod::FindOverriddenMethod(size_t pointer_size) {
124   if (IsStatic()) {
125     return nullptr;
126   }
127   mirror::Class* declaring_class = GetDeclaringClass();
128   mirror::Class* super_class = declaring_class->GetSuperClass();
129   uint16_t method_index = GetMethodIndex();
130   ArtMethod* result = nullptr;
131   // Did this method override a super class method? If so load the result from the super class'
132   // vtable
133   if (super_class->HasVTable() && method_index < super_class->GetVTableLength()) {
134     result = super_class->GetVTableEntry(method_index, pointer_size);
135   } else {
136     // Method didn't override superclass method so search interfaces
137     if (IsProxyMethod()) {
138       result = mirror::DexCache::GetElementPtrSize(GetDexCacheResolvedMethods(pointer_size),
139                                                    GetDexMethodIndex(),
140                                                    pointer_size);
141       CHECK_EQ(result,
142                Runtime::Current()->GetClassLinker()->FindMethodForProxy(GetDeclaringClass(), this));
143     } else {
144       mirror::IfTable* iftable = GetDeclaringClass()->GetIfTable();
145       for (size_t i = 0; i < iftable->Count() && result == nullptr; i++) {
146         mirror::Class* interface = iftable->GetInterface(i);
147         for (ArtMethod& interface_method : interface->GetVirtualMethods(pointer_size)) {
148           if (HasSameNameAndSignature(interface_method.GetInterfaceMethodIfProxy(pointer_size))) {
149             result = &interface_method;
150             break;
151           }
152         }
153       }
154     }
155   }
156   DCHECK(result == nullptr ||
157          GetInterfaceMethodIfProxy(pointer_size)->HasSameNameAndSignature(
158              result->GetInterfaceMethodIfProxy(pointer_size)));
159   return result;
160 }
161 
FindDexMethodIndexInOtherDexFile(const DexFile & other_dexfile,uint32_t name_and_signature_idx)162 uint32_t ArtMethod::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile,
163                                                      uint32_t name_and_signature_idx) {
164   const DexFile* dexfile = GetDexFile();
165   const uint32_t dex_method_idx = GetDexMethodIndex();
166   const DexFile::MethodId& mid = dexfile->GetMethodId(dex_method_idx);
167   const DexFile::MethodId& name_and_sig_mid = other_dexfile.GetMethodId(name_and_signature_idx);
168   DCHECK_STREQ(dexfile->GetMethodName(mid), other_dexfile.GetMethodName(name_and_sig_mid));
169   DCHECK_EQ(dexfile->GetMethodSignature(mid), other_dexfile.GetMethodSignature(name_and_sig_mid));
170   if (dexfile == &other_dexfile) {
171     return dex_method_idx;
172   }
173   const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_);
174   const DexFile::TypeId* other_type_id = other_dexfile.FindTypeId(mid_declaring_class_descriptor);
175   if (other_type_id != nullptr) {
176     const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(
177         *other_type_id, other_dexfile.GetStringId(name_and_sig_mid.name_idx_),
178         other_dexfile.GetProtoId(name_and_sig_mid.proto_idx_));
179     if (other_mid != nullptr) {
180       return other_dexfile.GetIndexForMethodId(*other_mid);
181     }
182   }
183   return DexFile::kDexNoIndex;
184 }
185 
FindCatchBlock(Handle<mirror::Class> exception_type,uint32_t dex_pc,bool * has_no_move_exception)186 uint32_t ArtMethod::FindCatchBlock(Handle<mirror::Class> exception_type,
187                                    uint32_t dex_pc, bool* has_no_move_exception) {
188   const DexFile::CodeItem* code_item = GetCodeItem();
189   // Set aside the exception while we resolve its type.
190   Thread* self = Thread::Current();
191   StackHandleScope<1> hs(self);
192   Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException()));
193   self->ClearException();
194   // Default to handler not found.
195   uint32_t found_dex_pc = DexFile::kDexNoIndex;
196   // Iterate over the catch handlers associated with dex_pc.
197   size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
198   for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
199     uint16_t iter_type_idx = it.GetHandlerTypeIndex();
200     // Catch all case
201     if (iter_type_idx == DexFile::kDexNoIndex16) {
202       found_dex_pc = it.GetHandlerAddress();
203       break;
204     }
205     // Does this catch exception type apply?
206     mirror::Class* iter_exception_type = GetClassFromTypeIndex(iter_type_idx,
207                                                                true /* resolve */,
208                                                                pointer_size);
209     if (UNLIKELY(iter_exception_type == nullptr)) {
210       // Now have a NoClassDefFoundError as exception. Ignore in case the exception class was
211       // removed by a pro-guard like tool.
212       // Note: this is not RI behavior. RI would have failed when loading the class.
213       self->ClearException();
214       // Delete any long jump context as this routine is called during a stack walk which will
215       // release its in use context at the end.
216       delete self->GetLongJumpContext();
217       LOG(WARNING) << "Unresolved exception class when finding catch block: "
218         << DescriptorToDot(GetTypeDescriptorFromTypeIdx(iter_type_idx));
219     } else if (iter_exception_type->IsAssignableFrom(exception_type.Get())) {
220       found_dex_pc = it.GetHandlerAddress();
221       break;
222     }
223   }
224   if (found_dex_pc != DexFile::kDexNoIndex) {
225     const Instruction* first_catch_instr =
226         Instruction::At(&code_item->insns_[found_dex_pc]);
227     *has_no_move_exception = (first_catch_instr->Opcode() != Instruction::MOVE_EXCEPTION);
228   }
229   // Put the exception back.
230   if (exception.Get() != nullptr) {
231     self->SetException(exception.Get());
232   }
233   return found_dex_pc;
234 }
235 
Invoke(Thread * self,uint32_t * args,uint32_t args_size,JValue * result,const char * shorty)236 void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
237                        const char* shorty) {
238   if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
239     ThrowStackOverflowError(self);
240     return;
241   }
242 
243   if (kIsDebugBuild) {
244     self->AssertThreadSuspensionIsAllowable();
245     CHECK_EQ(kRunnable, self->GetState());
246     CHECK_STREQ(GetInterfaceMethodIfProxy(sizeof(void*))->GetShorty(), shorty);
247   }
248 
249   // Push a transition back into managed code onto the linked list in thread.
250   ManagedStack fragment;
251   self->PushManagedStackFragment(&fragment);
252 
253   Runtime* runtime = Runtime::Current();
254   // Call the invoke stub, passing everything as arguments.
255   // If the runtime is not yet started or it is required by the debugger, then perform the
256   // Invocation by the interpreter, explicitly forcing interpretation over JIT to prevent
257   // cycling around the various JIT/Interpreter methods that handle method invocation.
258   if (UNLIKELY(!runtime->IsStarted() || Dbg::IsForcedInterpreterNeededForCalling(self, this))) {
259     if (IsStatic()) {
260       art::interpreter::EnterInterpreterFromInvoke(
261           self, this, nullptr, args, result, /*stay_in_interpreter*/ true);
262     } else {
263       mirror::Object* receiver =
264           reinterpret_cast<StackReference<mirror::Object>*>(&args[0])->AsMirrorPtr();
265       art::interpreter::EnterInterpreterFromInvoke(
266           self, this, receiver, args + 1, result, /*stay_in_interpreter*/ true);
267     }
268   } else {
269     DCHECK_EQ(runtime->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
270 
271     constexpr bool kLogInvocationStartAndReturn = false;
272     bool have_quick_code = GetEntryPointFromQuickCompiledCode() != nullptr;
273     if (LIKELY(have_quick_code)) {
274       if (kLogInvocationStartAndReturn) {
275         LOG(INFO) << StringPrintf(
276             "Invoking '%s' quick code=%p static=%d", PrettyMethod(this).c_str(),
277             GetEntryPointFromQuickCompiledCode(), static_cast<int>(IsStatic() ? 1 : 0));
278       }
279 
280       // Ensure that we won't be accidentally calling quick compiled code when -Xint.
281       if (kIsDebugBuild && runtime->GetInstrumentation()->IsForcedInterpretOnly()) {
282         CHECK(!runtime->UseJitCompilation());
283         const void* oat_quick_code = runtime->GetClassLinker()->GetOatMethodQuickCodeFor(this);
284         CHECK(oat_quick_code == nullptr || oat_quick_code != GetEntryPointFromQuickCompiledCode())
285             << "Don't call compiled code when -Xint " << PrettyMethod(this);
286       }
287 
288       if (!IsStatic()) {
289         (*art_quick_invoke_stub)(this, args, args_size, self, result, shorty);
290       } else {
291         (*art_quick_invoke_static_stub)(this, args, args_size, self, result, shorty);
292       }
293       if (UNLIKELY(self->GetException() == Thread::GetDeoptimizationException())) {
294         // Unusual case where we were running generated code and an
295         // exception was thrown to force the activations to be removed from the
296         // stack. Continue execution in the interpreter.
297         self->DeoptimizeWithDeoptimizationException(result);
298       }
299       if (kLogInvocationStartAndReturn) {
300         LOG(INFO) << StringPrintf("Returned '%s' quick code=%p", PrettyMethod(this).c_str(),
301                                   GetEntryPointFromQuickCompiledCode());
302       }
303     } else {
304       LOG(INFO) << "Not invoking '" << PrettyMethod(this) << "' code=null";
305       if (result != nullptr) {
306         result->SetJ(0);
307       }
308     }
309   }
310 
311   // Pop transition.
312   self->PopManagedStackFragment(fragment);
313 }
314 
RegisterNative(const void * native_method,bool is_fast)315 void ArtMethod::RegisterNative(const void* native_method, bool is_fast) {
316   CHECK(IsNative()) << PrettyMethod(this);
317   CHECK(!IsFastNative()) << PrettyMethod(this);
318   CHECK(native_method != nullptr) << PrettyMethod(this);
319   if (is_fast) {
320     SetAccessFlags(GetAccessFlags() | kAccFastNative);
321   }
322   SetEntryPointFromJni(native_method);
323 }
324 
UnregisterNative()325 void ArtMethod::UnregisterNative() {
326   CHECK(IsNative() && !IsFastNative()) << PrettyMethod(this);
327   // restore stub to lookup native pointer via dlsym
328   RegisterNative(GetJniDlsymLookupStub(), false);
329 }
330 
IsOverridableByDefaultMethod()331 bool ArtMethod::IsOverridableByDefaultMethod() {
332   return GetDeclaringClass()->IsInterface();
333 }
334 
EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params)335 bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params) {
336   auto* dex_cache = GetDexCache();
337   auto* dex_file = dex_cache->GetDexFile();
338   const auto& method_id = dex_file->GetMethodId(GetDexMethodIndex());
339   const auto& proto_id = dex_file->GetMethodPrototype(method_id);
340   const DexFile::TypeList* proto_params = dex_file->GetProtoParameters(proto_id);
341   auto count = proto_params != nullptr ? proto_params->Size() : 0u;
342   auto param_len = params.Get() != nullptr ? params->GetLength() : 0u;
343   if (param_len != count) {
344     return false;
345   }
346   auto* cl = Runtime::Current()->GetClassLinker();
347   for (size_t i = 0; i < count; ++i) {
348     auto type_idx = proto_params->GetTypeItem(i).type_idx_;
349     auto* type = cl->ResolveType(type_idx, this);
350     if (type == nullptr) {
351       Thread::Current()->AssertPendingException();
352       return false;
353     }
354     if (type != params->GetWithoutChecks(i)) {
355       return false;
356     }
357   }
358   return true;
359 }
360 
GetQuickenedInfo()361 const uint8_t* ArtMethod::GetQuickenedInfo() {
362   bool found = false;
363   OatFile::OatMethod oat_method =
364       Runtime::Current()->GetClassLinker()->FindOatMethodFor(this, &found);
365   if (!found || (oat_method.GetQuickCode() != nullptr)) {
366     return nullptr;
367   }
368   return oat_method.GetVmapTable();
369 }
370 
GetOatQuickMethodHeader(uintptr_t pc)371 const OatQuickMethodHeader* ArtMethod::GetOatQuickMethodHeader(uintptr_t pc) {
372   // Our callers should make sure they don't pass the instrumentation exit pc,
373   // as this method does not look at the side instrumentation stack.
374   DCHECK_NE(pc, reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()));
375 
376   if (IsRuntimeMethod()) {
377     return nullptr;
378   }
379 
380   Runtime* runtime = Runtime::Current();
381   const void* existing_entry_point = GetEntryPointFromQuickCompiledCode();
382   CHECK(existing_entry_point != nullptr) << PrettyMethod(this) << "@" << this;
383   ClassLinker* class_linker = runtime->GetClassLinker();
384 
385   if (class_linker->IsQuickGenericJniStub(existing_entry_point)) {
386     // The generic JNI does not have any method header.
387     return nullptr;
388   }
389 
390   if (existing_entry_point == GetQuickProxyInvokeHandler()) {
391     DCHECK(IsProxyMethod() && !IsConstructor());
392     // The proxy entry point does not have any method header.
393     return nullptr;
394   }
395 
396   // Check whether the current entry point contains this pc.
397   if (!class_linker->IsQuickResolutionStub(existing_entry_point) &&
398       !class_linker->IsQuickToInterpreterBridge(existing_entry_point)) {
399     OatQuickMethodHeader* method_header =
400         OatQuickMethodHeader::FromEntryPoint(existing_entry_point);
401 
402     if (method_header->Contains(pc)) {
403       return method_header;
404     }
405   }
406 
407   // Check whether the pc is in the JIT code cache.
408   jit::Jit* jit = Runtime::Current()->GetJit();
409   if (jit != nullptr) {
410     jit::JitCodeCache* code_cache = jit->GetCodeCache();
411     OatQuickMethodHeader* method_header = code_cache->LookupMethodHeader(pc, this);
412     if (method_header != nullptr) {
413       DCHECK(method_header->Contains(pc));
414       return method_header;
415     } else {
416       DCHECK(!code_cache->ContainsPc(reinterpret_cast<const void*>(pc)))
417           << PrettyMethod(this)
418           << ", pc=" << std::hex << pc
419           << ", entry_point=" << std::hex << reinterpret_cast<uintptr_t>(existing_entry_point)
420           << ", copy=" << std::boolalpha << IsCopied()
421           << ", proxy=" << std::boolalpha << IsProxyMethod();
422     }
423   }
424 
425   // The code has to be in an oat file.
426   bool found;
427   OatFile::OatMethod oat_method = class_linker->FindOatMethodFor(this, &found);
428   if (!found) {
429     if (class_linker->IsQuickResolutionStub(existing_entry_point)) {
430       // We are running the generic jni stub, but the entry point of the method has not
431       // been updated yet.
432       DCHECK_EQ(pc, 0u) << "Should be a downcall";
433       DCHECK(IsNative());
434       return nullptr;
435     }
436     if (existing_entry_point == GetQuickInstrumentationEntryPoint()) {
437       // We are running the generic jni stub, but the method is being instrumented.
438       DCHECK_EQ(pc, 0u) << "Should be a downcall";
439       DCHECK(IsNative());
440       return nullptr;
441     }
442     // Only for unit tests.
443     // TODO(ngeoffray): Update these tests to pass the right pc?
444     return OatQuickMethodHeader::FromEntryPoint(existing_entry_point);
445   }
446   const void* oat_entry_point = oat_method.GetQuickCode();
447   if (oat_entry_point == nullptr || class_linker->IsQuickGenericJniStub(oat_entry_point)) {
448     DCHECK(IsNative()) << PrettyMethod(this);
449     return nullptr;
450   }
451 
452   OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromEntryPoint(oat_entry_point);
453   if (pc == 0) {
454     // This is a downcall, it can only happen for a native method.
455     DCHECK(IsNative());
456     return method_header;
457   }
458 
459   DCHECK(method_header->Contains(pc))
460       << PrettyMethod(this)
461       << std::hex << pc << " " << oat_entry_point
462       << " " << (uintptr_t)(method_header->code_ + method_header->code_size_);
463   return method_header;
464 }
465 
HasAnyCompiledCode()466 bool ArtMethod::HasAnyCompiledCode() {
467   // Check whether the JIT has compiled it.
468   jit::Jit* jit = Runtime::Current()->GetJit();
469   if (jit != nullptr && jit->GetCodeCache()->ContainsMethod(this)) {
470     return true;
471   }
472 
473   // Check whether we have AOT code.
474   return Runtime::Current()->GetClassLinker()->GetOatMethodQuickCodeFor(this) != nullptr;
475 }
476 
CopyFrom(ArtMethod * src,size_t image_pointer_size)477 void ArtMethod::CopyFrom(ArtMethod* src, size_t image_pointer_size) {
478   memcpy(reinterpret_cast<void*>(this), reinterpret_cast<const void*>(src),
479          Size(image_pointer_size));
480   declaring_class_ = GcRoot<mirror::Class>(const_cast<ArtMethod*>(src)->GetDeclaringClass());
481 
482   // If the entry point of the method we are copying from is from JIT code, we just
483   // put the entry point of the new method to interpreter. We could set the entry point
484   // to the JIT code, but this would require taking the JIT code cache lock to notify
485   // it, which we do not want at this level.
486   Runtime* runtime = Runtime::Current();
487   if (runtime->UseJitCompilation()) {
488     if (runtime->GetJit()->GetCodeCache()->ContainsPc(GetEntryPointFromQuickCompiledCode())) {
489       SetEntryPointFromQuickCompiledCodePtrSize(GetQuickToInterpreterBridge(), image_pointer_size);
490     }
491   }
492   // Clear the profiling info for the same reasons as the JIT code.
493   if (!src->IsNative()) {
494     SetProfilingInfoPtrSize(nullptr, image_pointer_size);
495   }
496   // Clear hotness to let the JIT properly decide when to compile this method.
497   hotness_count_ = 0;
498 }
499 
500 }  // namespace art
501