Merge "Pass the fd to OatFile::Setup to avoid selinux errors." into pi-dev
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 270bce2..137eb4f 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -70,45 +70,41 @@
   }
 
   // Find which method did the call in the inlining hierarchy.
-  ArtMethod* caller = outer_method;
-  if (inlining_depth != 0) {
-    caller = GetResolvedMethod(outer_method,
-                               method_info,
-                               inline_info,
-                               encoding,
-                               inlining_depth - 1);
-  }
-
-  // Lookup the declaring class of the inlined method.
-  ObjPtr<mirror::DexCache> dex_cache = caller->GetDexCache();
-  ArtMethod* inlined_method = dex_cache->GetResolvedMethod(method_index, kRuntimePointerSize);
-  if (inlined_method != nullptr) {
-    DCHECK(!inlined_method->IsRuntimeMethod());
-    return inlined_method;
-  }
-  // TODO: Use ClassLoader::LookupResolvedMethod() instead.
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  const DexFile::MethodId& method_id = dex_file->GetMethodId(method_index);
-  const char* descriptor = dex_file->StringByTypeIdx(method_id.class_idx_);
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Thread* self = Thread::Current();
-  mirror::ClassLoader* class_loader = caller->GetDeclaringClass()->GetClassLoader();
-  mirror::Class* klass = class_linker->LookupClass(self, descriptor, class_loader);
-  if (klass == nullptr) {
-    LOG(FATAL) << "Could not find an inlined method from an .oat file: the class " << descriptor
-               << " was not found in the class loader of " << caller->PrettyMethod() << ". "
-               << "This must be due to playing wrongly with class loaders";
+  ArtMethod* method = outer_method;
+  for (uint32_t depth = 0, end = inlining_depth + 1u; depth != end; ++depth) {
+    DCHECK(!inline_info.EncodesArtMethodAtDepth(encoding, depth));
+    DCHECK_NE(inline_info.GetDexPcAtDepth(encoding, depth), static_cast<uint32_t>(-1));
+    method_index = inline_info.GetMethodIndexAtDepth(encoding, method_info, depth);
+    ArtMethod* inlined_method = class_linker->LookupResolvedMethod(method_index,
+                                                                   method->GetDexCache(),
+                                                                   method->GetClassLoader());
+    if (UNLIKELY(inlined_method == nullptr)) {
+      LOG(FATAL) << "Could not find an inlined method from an .oat file: "
+                 << method->GetDexFile()->PrettyMethod(method_index) << " . "
+                 << "This must be due to duplicate classes or playing wrongly with class loaders";
+      UNREACHABLE();
+    }
+    DCHECK(!inlined_method->IsRuntimeMethod());
+    if (UNLIKELY(inlined_method->GetDexFile() != method->GetDexFile())) {
+      // TODO: We could permit inlining within a multi-dex oat file and the boot image,
+      // even going back from boot image methods to the same oat file. However, this is
+      // not currently implemented in the compiler. Therefore crossing dex file boundary
+      // indicates that the inlined definition is not the same as the one used at runtime.
+      LOG(FATAL) << "Inlined method resolution crossed dex file boundary: from "
+                 << method->PrettyMethod()
+                 << " in " << method->GetDexFile()->GetLocation() << "/"
+                 << static_cast<const void*>(method->GetDexFile())
+                 << " to " << inlined_method->PrettyMethod()
+                 << " in " << inlined_method->GetDexFile()->GetLocation() << "/"
+                 << static_cast<const void*>(inlined_method->GetDexFile()) << ". "
+                 << "This must be due to duplicate classes or playing wrongly with class loaders";
+      UNREACHABLE();
+    }
+    method = inlined_method;
   }
 
-  inlined_method = class_linker->FindResolvedMethod(klass, dex_cache, class_loader, method_index);
-  if (inlined_method == nullptr) {
-    LOG(FATAL) << "Could not find an inlined method from an .oat file: the class " << descriptor
-               << " does not have " << dex_file->GetMethodName(method_id)
-               << dex_file->GetMethodSignature(method_id) << " declared. "
-               << "This must be due to duplicate classes or playing wrongly with class loaders";
-  }
-
-  return inlined_method;
+  return method;
 }
 
 ALWAYS_INLINE inline mirror::Class* CheckObjectAlloc(mirror::Class* klass,
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 66cec71..56ccfae 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1170,7 +1170,7 @@
   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
   TwoWordReturn return_or_deoptimize_pc = instrumentation->PopInstrumentationStackFrame(
       self, return_pc, gpr_result, fpr_result);
-  if (self->IsExceptionPending()) {
+  if (self->IsExceptionPending() || self->ObserveAsyncException()) {
     return GetTwoWordFailureValue();
   }
   return return_or_deoptimize_pc;
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index bc6a8f2..e8918e7 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -171,6 +171,23 @@
   log_maker.Record();
 }
 
+static ALWAYS_INLINE bool CanUpdateMemberAccessFlags(ArtField*) {
+  return true;
+}
+
+static ALWAYS_INLINE bool CanUpdateMemberAccessFlags(ArtMethod* method) {
+  return !method->IsIntrinsic();
+}
+
+template<typename T>
+static ALWAYS_INLINE void MaybeWhitelistMember(Runtime* runtime, T* member)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  if (CanUpdateMemberAccessFlags(member) && runtime->ShouldDedupeHiddenApiWarnings()) {
+    member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
+        member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
+  }
+}
+
 template<typename T>
 Action GetMemberActionImpl(T* member,
                            HiddenApiAccessFlags::ApiList api_list,
@@ -195,10 +212,7 @@
       // Avoid re-examining the exemption list next time.
       // Note this results in no warning for the member, which seems like what one would expect.
       // Exemptions effectively adds new members to the whitelist.
-      if (runtime->ShouldDedupeHiddenApiWarnings()) {
-        member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
-                member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
-      }
+      MaybeWhitelistMember(runtime, member);
       return kAllow;
     }
 
@@ -230,10 +244,7 @@
   if (access_method != kNone) {
     // Depending on a runtime flag, we might move the member into whitelist and
     // skip the warning the next time the member is accessed.
-    if (runtime->ShouldDedupeHiddenApiWarnings()) {
-      member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
-          member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
-    }
+    MaybeWhitelistMember(runtime, member);
 
     // If this action requires a UI warning, set the appropriate flag.
     if (action == kAllowButWarnAndToast || runtime->ShouldAlwaysSetHiddenApiWarningFlag()) {
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index 1bbce4f..a473f3f 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -1352,7 +1352,7 @@
     if (!filter_fn(profile_line_headers[k].dex_location, profile_line_headers[k].checksum)) {
       // We have to skip the line. Advanced the current pointer of the buffer.
       size_t profile_line_size =
-           profile_line_headers[k].class_set_size +
+           profile_line_headers[k].class_set_size * sizeof(uint16_t) +
            profile_line_headers[k].method_region_size_bytes +
            DexFileData::ComputeBitmapStorage(profile_line_headers[k].num_method_ids);
       uncompressed_data.Advance(profile_line_size);
diff --git a/runtime/jit/profile_compilation_info_test.cc b/runtime/jit/profile_compilation_info_test.cc
index 4e3774e..0ebadc0 100644
--- a/runtime/jit/profile_compilation_info_test.cc
+++ b/runtime/jit/profile_compilation_info_test.cc
@@ -1160,7 +1160,7 @@
   ProfileCompilationInfo loaded_info;
   ASSERT_TRUE(profile.GetFile()->ResetOffset());
 
-  // Filter out dex locations. Keep only dex_location1 and dex_location2.
+  // Filter out dex locations. Keep only dex_location1 and dex_location3.
   ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
       [](const std::string& dex_location, uint32_t checksum) -> bool {
           return (dex_location == "dex_location1" && checksum == 1)
@@ -1303,4 +1303,40 @@
   }
 }
 
+// Regression test: we were failing to do a filtering loading when the filtered dex file
+// contained profiled classes.
+TEST_F(ProfileCompilationInfoTest, FilteredLoadingWithClasses) {
+  ScratchFile profile;
+
+  // Save a profile with 2 dex files containing just classes.
+  ProfileCompilationInfo saved_info;
+  uint16_t item_count = 1000;
+  for (uint16_t i = 0; i < item_count; i++) {
+    ASSERT_TRUE(AddClass("dex_location1", /* checksum */ 1, dex::TypeIndex(i), &saved_info));
+    ASSERT_TRUE(AddClass("dex_location2", /* checksum */ 2, dex::TypeIndex(i), &saved_info));
+  }
+
+  ASSERT_TRUE(saved_info.Save(GetFd(profile)));
+  ASSERT_EQ(0, profile.GetFile()->Flush());
+
+
+  // Filter out dex locations: kepp only dex_location2.
+  ProfileCompilationInfo loaded_info;
+  ASSERT_TRUE(profile.GetFile()->ResetOffset());
+  ProfileCompilationInfo::ProfileLoadFilterFn filter_fn =
+      [](const std::string& dex_location, uint32_t checksum) -> bool {
+          return (dex_location == "dex_location2" && checksum == 2);
+        };
+  ASSERT_TRUE(loaded_info.Load(GetFd(profile), true, filter_fn));
+
+  // Compute the expectation.
+  ProfileCompilationInfo expected_info;
+  for (uint16_t i = 0; i < item_count; i++) {
+    ASSERT_TRUE(AddClass("dex_location2", /* checksum */ 2, dex::TypeIndex(i), &expected_info));
+  }
+
+  // Validate the expectation.
+  ASSERT_TRUE(loaded_info.Equals(expected_info));
+}
+
 }  // namespace art
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 006405f..077aa33 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -143,14 +143,14 @@
 
 void QuickExceptionHandler::FindCatch(ObjPtr<mirror::Throwable> exception) {
   DCHECK(!is_deoptimization_);
-  if (kDebugExceptionDelivery) {
-    mirror::String* msg = exception->GetDetailMessage();
-    std::string str_msg(msg != nullptr ? msg->ToModifiedUtf8() : "");
-    self_->DumpStack(LOG_STREAM(INFO) << "Delivering exception: " << exception->PrettyTypeOf()
-                     << ": " << str_msg << "\n");
-  }
   StackHandleScope<1> hs(self_);
   Handle<mirror::Throwable> exception_ref(hs.NewHandle(exception));
+  if (kDebugExceptionDelivery) {
+    ObjPtr<mirror::String> msg = exception_ref->GetDetailMessage();
+    std::string str_msg(msg != nullptr ? msg->ToModifiedUtf8() : "");
+    self_->DumpStack(LOG_STREAM(INFO) << "Delivering exception: " << exception_ref->PrettyTypeOf()
+                     << ": " << str_msg << "\n");
+  }
 
   // Walk the stack to find catch handler.
   CatchBlockStackVisitor visitor(self_, context_, &exception_ref, this);