Merge "Revert "Revert "Revert "Revert some flaky unloading""""
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 5e691c7..f2286e4 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -381,10 +381,11 @@
   // If the operation requests a specific type, we make sure its input is of that type.
   if (type != value->GetType()) {
     if (Primitive::IsFloatingPointType(type)) {
-      return ssa_builder_->GetFloatOrDoubleEquivalent(value, type);
+      value = ssa_builder_->GetFloatOrDoubleEquivalent(value, type);
     } else if (type == Primitive::kPrimNot) {
-      return ssa_builder_->GetReferenceTypeEquivalent(value);
+      value = ssa_builder_->GetReferenceTypeEquivalent(value);
     }
+    DCHECK(value != nullptr);
   }
 
   return value;
@@ -832,7 +833,8 @@
                         register_index,
                         is_range,
                         descriptor,
-                        nullptr /* clinit_check */);
+                        nullptr, /* clinit_check */
+                        true /* is_unresolved */);
   }
 
   // Potential class initialization check, in the case of a static method call.
@@ -897,7 +899,8 @@
                       register_index,
                       is_range,
                       descriptor,
-                      clinit_check);
+                      clinit_check,
+                      false /* is_unresolved */);
 }
 
 bool HInstructionBuilder::BuildNewInstance(uint16_t type_index, uint32_t dex_pc) {
@@ -1090,14 +1093,17 @@
                                        uint32_t register_index,
                                        bool is_range,
                                        const char* descriptor,
-                                       HClinitCheck* clinit_check) {
+                                       HClinitCheck* clinit_check,
+                                       bool is_unresolved) {
   DCHECK(!invoke->IsInvokeStaticOrDirect() || !invoke->AsInvokeStaticOrDirect()->IsStringInit());
 
   size_t start_index = 0;
   size_t argument_index = 0;
   if (invoke->GetOriginalInvokeType() != InvokeType::kStatic) {  // Instance call.
-    HInstruction* arg = LoadNullCheckedLocal(is_range ? register_index : args[0],
-                                             invoke->GetDexPc());
+    uint32_t obj_reg = is_range ? register_index : args[0];
+    HInstruction* arg = is_unresolved
+        ? LoadLocal(obj_reg, Primitive::kPrimNot)
+        : LoadNullCheckedLocal(obj_reg, invoke->GetDexPc());
     invoke->SetArgumentAt(0, arg);
     start_index = 1;
     argument_index = 1;
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index 0e3e5a7..9cfc065 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -237,7 +237,8 @@
                     uint32_t register_index,
                     bool is_range,
                     const char* descriptor,
-                    HClinitCheck* clinit_check);
+                    HClinitCheck* clinit_check,
+                    bool is_unresolved);
 
   bool HandleStringInit(HInvoke* invoke,
                         uint32_t number_of_vreg_arguments,
diff --git a/profman/profman.cc b/profman/profman.cc
index 4d9276f..754e431 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -31,8 +31,10 @@
 #include "base/stringprintf.h"
 #include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
+#include "dex_file.h"
 #include "jit/offline_profiling_info.h"
 #include "utils.h"
+#include "zip_archive.h"
 #include "profile_assistant.h"
 
 namespace art {
@@ -48,6 +50,12 @@
   return Join(command, ' ');
 }
 
+static constexpr int kInvalidFd = -1;
+
+static bool FdIsValid(int fd) {
+  return fd != kInvalidFd;
+}
+
 static void UsageErrorV(const char* fmt, va_list ap) {
   std::string error;
   StringAppendV(&error, fmt, ap);
@@ -70,8 +78,11 @@
   UsageError("Command: %s", CommandLine().c_str());
   UsageError("Usage: profman [options]...");
   UsageError("");
-  UsageError("  --dump-info-for=<filename>: dumps the content of the profile file");
-  UsageError("      to standard output in a human readable form.");
+  UsageError("  --dump-only: dumps the content of the specified profile files");
+  UsageError("      to standard output (default) in a human readable form.");
+  UsageError("");
+  UsageError("  --dump-output-to-fd=<number>: redirects --dump-info-for output to a file");
+  UsageError("      descriptor.");
   UsageError("");
   UsageError("  --profile-file=<filename>: specify profiler output file to use for compilation.");
   UsageError("      Can be specified multiple time, in which case the data from the different");
@@ -90,6 +101,12 @@
   UsageError("      accepts a file descriptor. Cannot be used together with");
   UsageError("      --reference-profile-file.");
   UsageError("");
+  UsageError("  --dex-location=<string>: location string to use with corresponding");
+  UsageError("      apk-fd to find dex files");
+  UsageError("");
+  UsageError("  --apk-fd=<number>: file descriptor containing an open APK to");
+  UsageError("      search for dex files");
+  UsageError("");
 
   exit(EXIT_FAILURE);
 }
@@ -97,7 +114,9 @@
 class ProfMan FINAL {
  public:
   ProfMan() :
-      reference_profile_file_fd_(-1),
+      reference_profile_file_fd_(kInvalidFd),
+      dump_only_(false),
+      dump_output_to_fd_(kInvalidFd),
       start_ns_(NanoTime()) {}
 
   ~ProfMan() {
@@ -124,8 +143,10 @@
       if (log_options) {
         LOG(INFO) << "profman: option[" << i << "]=" << argv[i];
       }
-      if (option.starts_with("--dump-info-for=")) {
-        dump_info_for_ = option.substr(strlen("--dump-info-for=")).ToString();
+      if (option == "--dump-only") {
+        dump_only_ = true;
+      } else if (option.starts_with("--dump-output-to-fd=")) {
+        ParseUintOption(option, "--dump-output-to-fd", &dump_output_to_fd_, Usage);
       } else if (option.starts_with("--profile-file=")) {
         profile_files_.push_back(option.substr(strlen("--profile-file=")).ToString());
       } else if (option.starts_with("--profile-file-fd=")) {
@@ -134,32 +155,37 @@
         reference_profile_file_ = option.substr(strlen("--reference-profile-file=")).ToString();
       } else if (option.starts_with("--reference-profile-file-fd=")) {
         ParseUintOption(option, "--reference-profile-file-fd", &reference_profile_file_fd_, Usage);
+      } else if (option.starts_with("--dex-location=")) {
+        dex_locations_.push_back(option.substr(strlen("--dex-location=")).ToString());
+      } else if (option.starts_with("--apk-fd=")) {
+        ParseFdForCollection(option, "--apk-fd", &apks_fd_);
       } else {
-        Usage("Unknown argument %s", option.data());
+        Usage("Unknown argument '%s'", option.data());
       }
     }
 
     bool has_profiles = !profile_files_.empty() || !profile_files_fd_.empty();
     bool has_reference_profile = !reference_profile_file_.empty() ||
-        (reference_profile_file_fd_ != -1);
+        FdIsValid(reference_profile_file_fd_);
 
-    if (!dump_info_for_.empty()) {
-      if (has_profiles || has_reference_profile) {
-        Usage("dump-info-for cannot be specified together with other options");
-      }
-      return;
-    }
-    if (!has_profiles) {
+    // --dump-only may be specified with only --reference-profiles present.
+    if (!dump_only_ && !has_profiles) {
       Usage("No profile files specified.");
     }
     if (!profile_files_.empty() && !profile_files_fd_.empty()) {
       Usage("Profile files should not be specified with both --profile-file-fd and --profile-file");
     }
-    if (!has_reference_profile) {
-      Usage("--reference-profile-file-fd should only be supplied with --profile-file-fd");
+    if (!dump_only_ && !has_reference_profile) {
+      Usage("No reference profile file specified.");
     }
-    if (reference_profile_file_.empty() && (reference_profile_file_fd_ == -1)) {
-      Usage("Reference profile file not specified");
+    if (!reference_profile_file_.empty() && FdIsValid(reference_profile_file_fd_)) {
+      Usage("Reference profile should not be specified with both "
+            "--reference-profile-file-fd and --reference-profile-file");
+    }
+    if ((!profile_files_.empty() && FdIsValid(reference_profile_file_fd_)) ||
+        (!dump_only_ && !profile_files_fd_.empty() && !FdIsValid(reference_profile_file_fd_))) {
+      Usage("Options --profile-file-fd and --reference-profile-file-fd "
+            "should only be used together");
     }
   }
 
@@ -177,24 +203,116 @@
     return result;
   }
 
-  int DumpProfileInfo() {
-    int fd = open(dump_info_for_.c_str(), O_RDWR);
-    if (fd < 0) {
-      std::cerr << "Cannot open " << dump_info_for_ << strerror(errno);
-      return -1;
+  int DumpOneProfile(const std::string& banner, const std::string& filename, int fd,
+                     const std::vector<const DexFile*>* dex_files, std::string* dump) {
+    if (!filename.empty()) {
+      fd = open(filename.c_str(), O_RDWR);
+      if (fd < 0) {
+        std::cerr << "Cannot open " << filename << strerror(errno);
+        return -1;
+      }
     }
     ProfileCompilationInfo info;
     if (!info.Load(fd)) {
-      std::cerr << "Cannot load profile info from " << dump_info_for_;
+      std::cerr << "Cannot load profile info from fd=" << fd << "\n";
       return -1;
     }
-    std::string dump = info.DumpInfo(/*dex_files*/ nullptr);
-    std::cout << dump << "\n";
+    std::string this_dump = banner + "\n" + info.DumpInfo(dex_files) + "\n";
+    *dump += this_dump;
+    if (close(fd) < 0) {
+      PLOG(WARNING) << "Failed to close descriptor";
+    }
+    return 0;
+  }
+
+  int DumpProfileInfo() {
+    static const char* kEmptyString = "";
+    static const char* kOrdinaryProfile = "=== profile ===";
+    static const char* kReferenceProfile = "=== reference profile ===";
+
+    // Open apk/zip files and and read dex files.
+    MemMap::Init();  // for ZipArchive::OpenFromFd
+    std::vector<const DexFile*> dex_files;
+    assert(dex_locations_.size() == apks_fd_.size());
+    for (size_t i = 0; i < dex_locations_.size(); ++i) {
+      std::string error_msg;
+      std::vector<std::unique_ptr<const DexFile>> dex_files_for_location;
+      std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(apks_fd_[i],
+                                                                     dex_locations_[i].c_str(),
+                                                                     &error_msg));
+      if (zip_archive == nullptr) {
+        LOG(WARNING) << "OpenFromFd failed for '" << dex_locations_[i] << "' " << error_msg;
+        continue;
+      }
+      if (DexFile::OpenFromZip(*zip_archive,
+                               dex_locations_[i],
+                               &error_msg,
+                               &dex_files_for_location)) {
+      } else {
+        LOG(WARNING) << "OpenFromZip failed for '" << dex_locations_[i] << "' " << error_msg;
+        continue;
+      }
+      for (std::unique_ptr<const DexFile>& dex_file : dex_files_for_location) {
+        dex_files.push_back(dex_file.release());
+      }
+    }
+
+    std::string dump;
+    // Dump individual profile files.
+    if (!profile_files_fd_.empty()) {
+      for (int profile_file_fd : profile_files_fd_) {
+        int ret = DumpOneProfile(kOrdinaryProfile,
+                                 kEmptyString,
+                                 profile_file_fd,
+                                 &dex_files,
+                                 &dump);
+        if (ret != 0) {
+          return ret;
+        }
+      }
+    }
+    if (!profile_files_.empty()) {
+      for (const std::string& profile_file : profile_files_) {
+        int ret = DumpOneProfile(kOrdinaryProfile, profile_file, kInvalidFd, &dex_files, &dump);
+        if (ret != 0) {
+          return ret;
+        }
+      }
+    }
+    // Dump reference profile file.
+    if (FdIsValid(reference_profile_file_fd_)) {
+      int ret = DumpOneProfile(kReferenceProfile,
+                               kEmptyString,
+                               reference_profile_file_fd_,
+                               &dex_files,
+                               &dump);
+      if (ret != 0) {
+        return ret;
+      }
+    }
+    if (!reference_profile_file_.empty()) {
+      int ret = DumpOneProfile(kReferenceProfile,
+                               reference_profile_file_,
+                               kInvalidFd,
+                               &dex_files,
+                               &dump);
+      if (ret != 0) {
+        return ret;
+      }
+    }
+    if (!FdIsValid(dump_output_to_fd_)) {
+      std::cout << dump;
+    } else {
+      unix_file::FdFile out_fd(dump_output_to_fd_, false /*check_usage*/);
+      if (!out_fd.WriteFully(dump.c_str(), dump.length())) {
+        return -1;
+      }
+    }
     return 0;
   }
 
   bool ShouldOnlyDumpProfile() {
-    return !dump_info_for_.empty();
+    return dump_only_;
   }
 
  private:
@@ -224,10 +342,13 @@
 
   std::vector<std::string> profile_files_;
   std::vector<int> profile_files_fd_;
+  std::vector<std::string> dex_locations_;
+  std::vector<int> apks_fd_;
   std::string reference_profile_file_;
   int reference_profile_file_fd_;
+  bool dump_only_;
+  int dump_output_to_fd_;
   uint64_t start_ns_;
-  std::string dump_info_for_;
 };
 
 // See ProfileAssistant::ProcessingResult for return codes.
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 0715bab..cd1ca7f 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -641,6 +641,12 @@
       REQUIRES(!Locks::classlinker_classes_lock_)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
+  // Throw the class initialization failure recorded when first trying to initialize the given
+  // class.
+  void ThrowEarlierClassFailure(mirror::Class* c, bool wrap_in_no_class_def = false)
+      SHARED_REQUIRES(Locks::mutator_lock_)
+      REQUIRES(!dex_lock_);
+
   struct DexCacheData {
     // Weak root to the DexCache. Note: Do not decode this unnecessarily or else class unloading may
     // not work properly.
@@ -1057,12 +1063,6 @@
   // Return the quick generic JNI stub for testing.
   const void* GetRuntimeQuickGenericJniStub() const;
 
-  // Throw the class initialization failure recorded when first trying to initialize the given
-  // class.
-  void ThrowEarlierClassFailure(mirror::Class* c, bool wrap_in_no_class_def = false)
-      SHARED_REQUIRES(Locks::mutator_lock_)
-      REQUIRES(!dex_lock_);
-
   bool CanWeInitializeClass(mirror::Class* klass, bool can_init_statics, bool can_init_parents)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 1515630..6f735aa 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -41,6 +41,23 @@
   if (c != nullptr && c->IsResolved()) {
     return soa.AddLocalReference<jclass>(c);
   }
+  // If class is erroneous, throw the earlier failure, wrapped in certain cases. See b/28787733.
+  if (c != nullptr && c->IsErroneous()) {
+    cl->ThrowEarlierClassFailure(c);
+    Thread* self = soa.Self();
+    mirror::Class* eiie_class =
+        self->DecodeJObject(WellKnownClasses::java_lang_ExceptionInInitializerError)->AsClass();
+    mirror::Class* iae_class =
+        self->DecodeJObject(WellKnownClasses::java_lang_IllegalAccessError)->AsClass();
+    mirror::Class* ncdfe_class =
+        self->DecodeJObject(WellKnownClasses::java_lang_NoClassDefFoundError)->AsClass();
+    mirror::Class* exception = self->GetException()->GetClass();
+    if (exception == eiie_class || exception == iae_class || exception == ncdfe_class) {
+      self->ThrowNewWrappedException("Ljava/lang/ClassNotFoundException;",
+                                     PrettyDescriptor(c).c_str());
+    }
+    return nullptr;
+  }
   if (loader != nullptr) {
     // Try the common case.
     StackHandleScope<1> hs(soa.Self());
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 8ad79fb..f2ae85a 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -4528,7 +4528,7 @@
 
 ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) {
   const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
-  // Check access to class
+  // Check access to class.
   const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_);
   if (klass_type.IsConflict()) {
     AppendToLastFailMessage(StringPrintf(" in attempt to access instance field %d (%s) in %s",
@@ -4549,20 +4549,11 @@
     DCHECK(self_->IsExceptionPending());
     self_->ClearException();
     return nullptr;
-  } else if (!GetDeclaringClass().CanAccessMember(field->GetDeclaringClass(),
-                                                  field->GetAccessFlags())) {
-    Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot access instance field " << PrettyField(field)
-                                    << " from " << GetDeclaringClass();
-    return nullptr;
-  } else if (field->IsStatic()) {
-    Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected field " << PrettyField(field)
-                                    << " to not be static";
-    return nullptr;
   } else if (obj_type.IsZero()) {
-    // Cannot infer and check type, however, access will cause null pointer exception
-    return field;
+    // Cannot infer and check type, however, access will cause null pointer exception.
+    // Fall through into a few last soft failure checks below.
   } else if (!obj_type.IsReferenceTypes()) {
-    // Trying to read a field from something that isn't a reference
+    // Trying to read a field from something that isn't a reference.
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "instance field access on object that has "
                                       << "non-reference type " << obj_type;
     return nullptr;
@@ -4584,7 +4575,6 @@
                                           << " of " << PrettyMethod(dex_method_idx_, *dex_file_);
         return nullptr;
       }
-      return field;
     } else if (!field_klass.IsAssignableFrom(obj_type)) {
       // Trying to access C1.field1 using reference of type C2, which is neither C1 or a sub-class
       // of C1. For resolution to occur the declared class of the field must be compatible with
@@ -4602,10 +4592,22 @@
       Fail(type) << "cannot access instance field " << PrettyField(field)
                  << " from object of type " << obj_type;
       return nullptr;
-    } else {
-      return field;
     }
   }
+
+  // Few last soft failure checks.
+  if (!GetDeclaringClass().CanAccessMember(field->GetDeclaringClass(),
+                                           field->GetAccessFlags())) {
+    Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot access instance field " << PrettyField(field)
+                                    << " from " << GetDeclaringClass();
+    return nullptr;
+  } else if (field->IsStatic()) {
+    Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected field " << PrettyField(field)
+                                    << " to not be static";
+    return nullptr;
+  }
+
+  return field;
 }
 
 template <MethodVerifier::FieldAccessType kAccType>
@@ -4928,6 +4930,7 @@
       // Initialize them as conflicts so they don't add to GC and deoptimization information.
       const Instruction* ret_inst = Instruction::At(code_item_->insns_ + next_insn);
       AdjustReturnLine(this, ret_inst, target_line);
+      // Directly bail if a hard failure was found.
       if (have_pending_hard_failure_) {
         return false;
       }
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index d288943..355d552 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -41,6 +41,9 @@
 jclass WellKnownClasses::java_lang_ClassNotFoundException;
 jclass WellKnownClasses::java_lang_Daemons;
 jclass WellKnownClasses::java_lang_Error;
+jclass WellKnownClasses::java_lang_ExceptionInInitializerError;
+jclass WellKnownClasses::java_lang_IllegalAccessError;
+jclass WellKnownClasses::java_lang_NoClassDefFoundError;
 jclass WellKnownClasses::java_lang_Object;
 jclass WellKnownClasses::java_lang_OutOfMemoryError;
 jclass WellKnownClasses::java_lang_reflect_AbstractMethod;
@@ -228,6 +231,9 @@
   java_lang_Object = CacheClass(env, "java/lang/Object");
   java_lang_OutOfMemoryError = CacheClass(env, "java/lang/OutOfMemoryError");
   java_lang_Error = CacheClass(env, "java/lang/Error");
+  java_lang_ExceptionInInitializerError = CacheClass(env, "java/lang/ExceptionInInitializerError");
+  java_lang_IllegalAccessError = CacheClass(env, "java/lang/IllegalAccessError");
+  java_lang_NoClassDefFoundError = CacheClass(env, "java/lang/NoClassDefFoundError");
   java_lang_reflect_AbstractMethod = CacheClass(env, "java/lang/reflect/AbstractMethod");
   java_lang_reflect_Constructor = CacheClass(env, "java/lang/reflect/Constructor");
   java_lang_reflect_Field = CacheClass(env, "java/lang/reflect/Field");
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 482ff0a..cc60b4d 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -52,6 +52,9 @@
   static jclass java_lang_ClassNotFoundException;
   static jclass java_lang_Daemons;
   static jclass java_lang_Error;
+  static jclass java_lang_ExceptionInInitializerError;
+  static jclass java_lang_IllegalAccessError;
+  static jclass java_lang_NoClassDefFoundError;
   static jclass java_lang_Object;
   static jclass java_lang_OutOfMemoryError;
   static jclass java_lang_reflect_AbstractMethod;
diff --git a/test/142-classloader2/smali/B.smali b/test/142-classloader2/smali/B.smali
new file mode 100644
index 0000000..01bd593
--- /dev/null
+++ b/test/142-classloader2/smali/B.smali
@@ -0,0 +1,10 @@
+.class public LB;
+
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+  .registers 1
+  invoke-direct {p1}, Ljava/lang/Object;-><init>()V
+  return-void
+.end method
+
diff --git a/test/142-classloader2/src/Main.java b/test/142-classloader2/src/Main.java
index 86c61eb..89dadce 100644
--- a/test/142-classloader2/src/Main.java
+++ b/test/142-classloader2/src/Main.java
@@ -71,6 +71,21 @@
             throw new IllegalStateException("Expected Ex-A, found " + exValue);
         }
 
+        // Try to load a dex file with bad dex code. Use new instance to force verification.
+        try {
+          Class<?> badClass = Main.class.getClassLoader().loadClass("B");
+          badClass.newInstance();
+          System.out.println("Should not be able to load class from bad dex file.");
+        } catch (VerifyError e) {
+        }
+
+        // Make sure the same error is rethrown when reloading the bad class.
+        try {
+          Class<?> badClass = Main.class.getClassLoader().loadClass("B");
+          System.out.println("Should not be able to load class from bad dex file.");
+        } catch (VerifyError e) {
+        }
+
         System.out.println("Everything OK.");
     }
 }
diff --git a/test/529-checker-unresolved/src/Main.java b/test/529-checker-unresolved/src/Main.java
index a934377..5a36ba5 100644
--- a/test/529-checker-unresolved/src/Main.java
+++ b/test/529-checker-unresolved/src/Main.java
@@ -114,19 +114,31 @@
     expectEquals(o, c.instanceObject);
   }
 
+  /// CHECK-START: void Main.callUnresolvedNull(UnresolvedClass) register (before)
+  /// CHECK-NOT: NullCheck
   static public void callUnresolvedNull(UnresolvedClass c) {
     int x = 0;
     try {
       x = c.instanceInt;
       throw new Error("Expected NPE");
     } catch (NullPointerException e) {
+      x -= 1;
     }
-    expectEquals(0, x);
+    expectEquals(-1, x);
     try {
       c.instanceInt = -1;
       throw new Error("Expected NPE");
     } catch (NullPointerException e) {
+      x -= 1;
     }
+    expectEquals(-2, x);
+    try {
+      c.virtualMethod();
+      throw new Error("Expected NPE");
+    } catch (NullPointerException e) {
+      x -= 1;
+    }
+    expectEquals(-3, x);
   }
 
   static public void testInstanceOf(Object o) {
diff --git a/test/600-verifier-fails/expected.txt b/test/600-verifier-fails/expected.txt
index 010f1b7..eaa0c93 100644
--- a/test/600-verifier-fails/expected.txt
+++ b/test/600-verifier-fails/expected.txt
@@ -1,3 +1,5 @@
 passed A
 passed B
 passed C
+passed D
+passed E
diff --git a/test/600-verifier-fails/info.txt b/test/600-verifier-fails/info.txt
index 677b477..df2396e 100644
--- a/test/600-verifier-fails/info.txt
+++ b/test/600-verifier-fails/info.txt
@@ -1,14 +1,20 @@
 The situations in these tests were discovered by running the mutating
 dexfuzz on the DEX files of fuzzingly random generated Java test.
 
-(1) b/28908555:
-    soft verification fail (on the final field modification) should
-    not hide the hard verification fail (on the type mismatch) to
+(A) b/28908555:
+    soft verification failure (on the final field modification) should
+    not hide the hard verification failure (on the type mismatch) to
     avoid compiler crash later on
-(2) b/29070461:
-    hard failure (not calling super in constructor) should bail
-    immediately and not allow soft fails to pile up behind it to
-    avoid fatal message later on
-(3) b/29068831:
-    access validation should occur prior to null reference check
+(B) b/29070461:
+    hard verification failure (not calling super in constructor) should
+    bail immediately and not allow soft verification failures to pile up
+    behind it to avoid fatal message later on
+(C) b/29068831:
+    access validation on field should occur prior to null reference check
+(D) b/29126870:
+    soft verification failure (cannot access) should not hide the hard
+    verification failure (non-reference type) to avoid a compiler crash
+    later on
+(E) b/29068831:
+    access validation on method should occur prior to null reference check
 
diff --git a/test/600-verifier-fails/smali/iget.smali b/test/600-verifier-fails/smali/iget.smali
new file mode 100644
index 0000000..5c045e6
--- /dev/null
+++ b/test/600-verifier-fails/smali/iget.smali
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LD;
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+    .registers 2
+    invoke-direct {v1}, Ljava/lang/Object;-><init>()V
+    const v0, 2
+    iget v1, v0, LMain;->privateField:I
+    return-void
+.end method
diff --git a/test/600-verifier-fails/smali/invoke.smali b/test/600-verifier-fails/smali/invoke.smali
new file mode 100644
index 0000000..616d63c
--- /dev/null
+++ b/test/600-verifier-fails/smali/invoke.smali
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LE;
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+    .registers 2
+    invoke-direct {v1}, Ljava/lang/Object;-><init>()V
+    const v0, 0
+    invoke-virtual {v0}, LMain;->privateMethod()V
+    return-void
+.end method
diff --git a/test/600-verifier-fails/src/Main.java b/test/600-verifier-fails/src/Main.java
index 0a8c5a1..fa25d58 100644
--- a/test/600-verifier-fails/src/Main.java
+++ b/test/600-verifier-fails/src/Main.java
@@ -20,6 +20,10 @@
 
   private static String staticPrivateField = null;
 
+  private int privateField = 0;
+
+  private void privateMethod() { }
+
   private static void test(String name) throws Exception {
     try {
       Class<?> a = Class.forName(name);
@@ -33,5 +37,7 @@
     test("A");
     test("B");
     test("C");
+    test("D");
+    test("E");
   }
 }
diff --git a/test/604-hot-static-interface/hot_static_interface.cc b/test/604-hot-static-interface/hot_static_interface.cc
index 9c51ca6..71877f5 100644
--- a/test/604-hot-static-interface/hot_static_interface.cc
+++ b/test/604-hot-static-interface/hot_static_interface.cc
@@ -48,8 +48,10 @@
     if (code_cache->ContainsPc(header->GetCode())) {
       break;
     } else {
-      // yield to scheduler to give time to the JIT compiler.
-      sched_yield();
+      // Sleep to yield to the compiler thread.
+      sleep(0);
+      // Will either ensure it's compiled or do the compilation itself.
+      jit->CompileMethod(method, Thread::Current(), /* osr */ false);
     }
   }
 }