diff options
Diffstat (limited to 'runtime/art_method.cc')
| -rw-r--r-- | runtime/art_method.cc | 106 | 
1 files changed, 98 insertions, 8 deletions
diff --git a/runtime/art_method.cc b/runtime/art_method.cc index c97c32837d..937dcee473 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -283,7 +283,9 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*        // Ensure that we won't be accidentally calling quick compiled code when -Xint.        if (kIsDebugBuild && runtime->GetInstrumentation()->IsForcedInterpretOnly()) {          CHECK(!runtime->UseJitCompilation()); -        const void* oat_quick_code = runtime->GetClassLinker()->GetOatMethodQuickCodeFor(this); +        const void* oat_quick_code = (IsNative() || !IsInvokable() || IsProxyMethod()) +            ? nullptr +            : GetOatMethodQuickCode(runtime->GetClassLinker()->GetImagePointerSize());          CHECK(oat_quick_code == nullptr || oat_quick_code != GetEntryPointFromQuickCompiledCode())              << "Don't call compiled code when -Xint " << PrettyMethod(this);        } @@ -360,6 +362,80 @@ bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) {    return annotations::IsMethodAnnotationPresent(this, annotation_handle, visibility);  } +static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, +                                                 uint16_t class_def_idx, +                                                 uint32_t method_idx) { +  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx); +  const uint8_t* class_data = dex_file.GetClassData(class_def); +  CHECK(class_data != nullptr); +  ClassDataItemIterator it(dex_file, class_data); +  // Skip fields +  while (it.HasNextStaticField()) { +    it.Next(); +  } +  while (it.HasNextInstanceField()) { +    it.Next(); +  } +  // Process methods +  size_t class_def_method_index = 0; +  while (it.HasNextDirectMethod()) { +    if (it.GetMemberIndex() == method_idx) { +      return class_def_method_index; +    } +    class_def_method_index++; +    it.Next(); +  } +  while (it.HasNextVirtualMethod()) { +    if (it.GetMemberIndex() == method_idx) { +      return class_def_method_index; +    } +    class_def_method_index++; +    it.Next(); +  } +  DCHECK(!it.HasNext()); +  LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation(); +  UNREACHABLE(); +} + +static const OatFile::OatMethod FindOatMethodFor(ArtMethod* method, +                                                 PointerSize pointer_size, +                                                 bool* found) +    REQUIRES_SHARED(Locks::mutator_lock_) { +  // Although we overwrite the trampoline of non-static methods, we may get here via the resolution +  // method for direct methods (or virtual methods made direct). +  mirror::Class* declaring_class = method->GetDeclaringClass(); +  size_t oat_method_index; +  if (method->IsStatic() || method->IsDirect()) { +    // Simple case where the oat method index was stashed at load time. +    oat_method_index = method->GetMethodIndex(); +  } else { +    // Compute the oat_method_index by search for its position in the declared virtual methods. +    oat_method_index = declaring_class->NumDirectMethods(); +    bool found_virtual = false; +    for (ArtMethod& art_method : declaring_class->GetVirtualMethods(pointer_size)) { +      // Check method index instead of identity in case of duplicate method definitions. +      if (method->GetDexMethodIndex() == art_method.GetDexMethodIndex()) { +        found_virtual = true; +        break; +      } +      oat_method_index++; +    } +    CHECK(found_virtual) << "Didn't find oat method index for virtual method: " +                         << PrettyMethod(method); +  } +  DCHECK_EQ(oat_method_index, +            GetOatMethodIndexFromMethodIndex(*declaring_class->GetDexCache()->GetDexFile(), +                                             method->GetDeclaringClass()->GetDexClassDefIndex(), +                                             method->GetDexMethodIndex())); +  OatFile::OatClass oat_class = OatFile::FindOatClass(*declaring_class->GetDexCache()->GetDexFile(), +                                                      declaring_class->GetDexClassDefIndex(), +                                                      found); +  if (!(*found)) { +    return OatFile::OatMethod::Invalid(); +  } +  return oat_class.GetOatMethod(oat_method_index); +} +  bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params) {    auto* dex_cache = GetDexCache();    auto* dex_file = dex_cache->GetDexFile(); @@ -386,10 +462,9 @@ bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> param    return true;  } -const uint8_t* ArtMethod::GetQuickenedInfo() { +const uint8_t* ArtMethod::GetQuickenedInfo(PointerSize pointer_size) {    bool found = false; -  OatFile::OatMethod oat_method = -      Runtime::Current()->GetClassLinker()->FindOatMethodFor(this, &found); +  OatFile::OatMethod oat_method = FindOatMethodFor(this, pointer_size, &found);    if (!found || (oat_method.GetQuickCode() != nullptr)) {      return nullptr;    } @@ -433,7 +508,7 @@ const OatQuickMethodHeader* ArtMethod::GetOatQuickMethodHeader(uintptr_t pc) {    }    // Check whether the pc is in the JIT code cache. -  jit::Jit* jit = Runtime::Current()->GetJit(); +  jit::Jit* jit = runtime->GetJit();    if (jit != nullptr) {      jit::JitCodeCache* code_cache = jit->GetCodeCache();      OatQuickMethodHeader* method_header = code_cache->LookupMethodHeader(pc, this); @@ -452,7 +527,8 @@ const OatQuickMethodHeader* ArtMethod::GetOatQuickMethodHeader(uintptr_t pc) {    // The code has to be in an oat file.    bool found; -  OatFile::OatMethod oat_method = class_linker->FindOatMethodFor(this, &found); +  OatFile::OatMethod oat_method = +      FindOatMethodFor(this, class_linker->GetImagePointerSize(), &found);    if (!found) {      if (class_linker->IsQuickResolutionStub(existing_entry_point)) {        // We are running the generic jni stub, but the entry point of the method has not @@ -491,15 +567,29 @@ const OatQuickMethodHeader* ArtMethod::GetOatQuickMethodHeader(uintptr_t pc) {    return method_header;  } +const void* ArtMethod::GetOatMethodQuickCode(PointerSize pointer_size) { +  bool found; +  OatFile::OatMethod oat_method = FindOatMethodFor(this, pointer_size, &found); +  if (found) { +    return oat_method.GetQuickCode(); +  } +  return nullptr; +} +  bool ArtMethod::HasAnyCompiledCode() { +  if (IsNative() || !IsInvokable() || IsProxyMethod()) { +    return false; +  } +    // Check whether the JIT has compiled it. -  jit::Jit* jit = Runtime::Current()->GetJit(); +  Runtime* runtime = Runtime::Current(); +  jit::Jit* jit = runtime->GetJit();    if (jit != nullptr && jit->GetCodeCache()->ContainsMethod(this)) {      return true;    }    // Check whether we have AOT code. -  return Runtime::Current()->GetClassLinker()->GetOatMethodQuickCodeFor(this) != nullptr; +  return GetOatMethodQuickCode(runtime->GetClassLinker()->GetImagePointerSize()) != nullptr;  }  void ArtMethod::CopyFrom(ArtMethod* src, PointerSize image_pointer_size) {  |