Merge "ART: Change InstructionSetFeatures to return unique_ptr"
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 61f682c..0b14859 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -342,6 +342,7 @@
         "utils/string_reference_test.cc",
         "utils/swap_space_test.cc",
         "utils/test_dex_file_builder_test.cc",
+        "verifier_deps_test.cc",
 
         "jni/jni_cfi_test.cc",
         "optimizing/codegen_test.cc",
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index dbde41c..56b4ebd 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -72,6 +72,7 @@
 #include "verifier/method_verifier.h"
 #include "verifier/method_verifier-inl.h"
 #include "verifier/verifier_log_mode.h"
+#include "verifier/verifier_deps.h"
 
 namespace art {
 
@@ -1968,6 +1969,7 @@
         hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
     Handle<mirror::Class> klass(
         hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader)));
+    verifier::MethodVerifier::FailureKind failure_kind;
     if (klass.Get() == nullptr) {
       CHECK(soa.Self()->IsExceptionPending());
       soa.Self()->ClearException();
@@ -1980,7 +1982,8 @@
       Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(
           soa.Self(), dex_file, false)));
       std::string error_msg;
-      if (verifier::MethodVerifier::VerifyClass(soa.Self(),
+      failure_kind =
+          verifier::MethodVerifier::VerifyClass(soa.Self(),
                                                 &dex_file,
                                                 dex_cache,
                                                 class_loader,
@@ -1988,15 +1991,15 @@
                                                 Runtime::Current()->GetCompilerCallbacks(),
                                                 true /* allow soft failures */,
                                                 log_level_,
-                                                &error_msg) ==
-                                                    verifier::MethodVerifier::kHardFailure) {
+                                                &error_msg);
+      if (failure_kind == verifier::MethodVerifier::kHardFailure) {
         LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
                    << " because: " << error_msg;
         manager_->GetCompiler()->SetHadHardVerifierFailure();
       }
     } else if (!SkipClass(jclass_loader, dex_file, klass.Get())) {
       CHECK(klass->IsResolved()) << klass->PrettyClass();
-      class_linker->VerifyClass(soa.Self(), klass, log_level_);
+      failure_kind = class_linker->VerifyClass(soa.Self(), klass, log_level_);
 
       if (klass->IsErroneous()) {
         // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
@@ -2008,13 +2011,18 @@
       CHECK(klass->IsCompileTimeVerified() || klass->IsErroneous())
           << klass->PrettyDescriptor() << ": state=" << klass->GetStatus();
 
-      // It is *very* problematic if there are verification errors in the boot classpath. For example,
-      // we rely on things working OK without verification when the decryption dialog is brought up.
-      // So abort in a debug build if we find this violated.
+      // It is *very* problematic if there are verification errors in the boot classpath.
+      // For example, we rely on things working OK without verification when the
+      // decryption dialog is brought up. So abort in a debug build if we find this violated.
       DCHECK(!manager_->GetCompiler()->GetCompilerOptions().IsBootImage() || klass->IsVerified())
           << "Boot classpath class " << klass->PrettyClass()
           << " failed to fully verify.";
+    } else {
+      // Make the skip a soft failure, essentially being considered as verify at runtime.
+      failure_kind = verifier::MethodVerifier::kSoftFailure;
     }
+    verifier::VerifierDeps::MaybeRecordVerificationStatus(
+        dex_file, class_def.class_idx_, failure_kind);
     soa.Self()->AssertNoPendingException();
   }
 
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 9a4dd85..4a48f9c 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -50,6 +50,7 @@
 
 namespace verifier {
 class MethodVerifier;
+class VerifierDepsTest;
 }  // namespace verifier
 
 class BitVector;
@@ -578,6 +579,7 @@
   const BitVector* current_dex_to_dex_methods_;
 
   friend class CompileClassVisitor;
+  friend class verifier::VerifierDepsTest;
   DISALLOW_COPY_AND_ASSIGN(CompilerDriver);
 };
 
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 4eb6954..56b632d 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -29,6 +29,10 @@
 
 namespace art {
 
+namespace verifier {
+  class VerifierDepsTest;
+}
+
 class DexFile;
 
 class CompilerOptions FINAL {
@@ -338,6 +342,7 @@
 
   friend class Dex2Oat;
   friend class CommonCompilerTest;
+  friend class verifier::VerifierDepsTest;
 
   DISALLOW_COPY_AND_ASSIGN(CompilerOptions);
 };
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 32287a0..bfade3c 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -488,6 +488,15 @@
       isa_features_(isa_features) {
   // Always save the LR register to mimic Quick.
   AddAllocatedRegister(Location::RegisterLocation(LR));
+  // Give d14 and d15 as scratch registers to VIXL.
+  // They are removed from the register allocator in `SetupBlockedRegisters()`.
+  // TODO(VIXL): We need two scratch D registers for `EmitSwap` when swapping two double stack
+  // slots. If that is sufficiently rare, and we have pressure on FP registers, we could instead
+  // spill in `EmitSwap`. But if we actually are guaranteed to have 32 D registers, we could give
+  // d30 and d31 to VIXL to avoid removing registers from the allocator. If that is the case, we may
+  // also want to investigate giving those 14 other D registers to the allocator.
+  GetVIXLAssembler()->GetScratchVRegisterList()->Combine(d14);
+  GetVIXLAssembler()->GetScratchVRegisterList()->Combine(d15);
 }
 
 #define __ reinterpret_cast<ArmVIXLAssembler*>(GetAssembler())->GetVIXLAssembler()->
@@ -509,6 +518,13 @@
   // Reserve temp register.
   blocked_core_registers_[IP] = true;
 
+  // Registers s28-s31 (d14-d15) are left to VIXL for scratch registers.
+  // (They are given to the `MacroAssembler` in `CodeGeneratorARMVIXL::CodeGeneratorARMVIXL`.)
+  blocked_fpu_registers_[28] = true;
+  blocked_fpu_registers_[29] = true;
+  blocked_fpu_registers_[30] = true;
+  blocked_fpu_registers_[31] = true;
+
   if (GetGraph()->IsDebuggable()) {
     // Stubs do not save callee-save floating point registers. If the graph
     // is debuggable, we need to deal with these registers differently. For
@@ -2161,6 +2177,92 @@
   }
 }
 
+void LocationsBuilderARMVIXL::VisitCompare(HCompare* compare) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
+  switch (compare->InputAt(0)->GetType()) {
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimShort:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimInt:
+    case Primitive::kPrimLong: {
+      locations->SetInAt(0, Location::RequiresRegister());
+      locations->SetInAt(1, Location::RequiresRegister());
+      // Output overlaps because it is written before doing the low comparison.
+      locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
+      break;
+    }
+    case Primitive::kPrimFloat:
+    case Primitive::kPrimDouble: {
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, ArithmeticZeroOrFpuRegister(compare->InputAt(1)));
+      locations->SetOut(Location::RequiresRegister());
+      break;
+    }
+    default:
+      LOG(FATAL) << "Unexpected type for compare operation " << compare->InputAt(0)->GetType();
+  }
+}
+
+void InstructionCodeGeneratorARMVIXL::VisitCompare(HCompare* compare) {
+  LocationSummary* locations = compare->GetLocations();
+  vixl32::Register out = OutputRegister(compare);
+  Location left = locations->InAt(0);
+  Location right = locations->InAt(1);
+
+  vixl32::Label less, greater, done;
+  Primitive::Type type = compare->InputAt(0)->GetType();
+  vixl32::Condition less_cond = vixl32::Condition(kNone);
+  switch (type) {
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimShort:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimInt: {
+      // Emit move to `out` before the `Cmp`, as `Mov` might affect the status flags.
+      __ Mov(out, 0);
+      __ Cmp(RegisterFrom(left), RegisterFrom(right));  // Signed compare.
+      less_cond = lt;
+      break;
+    }
+    case Primitive::kPrimLong: {
+      __ Cmp(HighRegisterFrom(left), HighRegisterFrom(right));  // Signed compare.
+      __ B(lt, &less);
+      __ B(gt, &greater);
+      // Emit move to `out` before the last `Cmp`, as `Mov` might affect the status flags.
+      __ Mov(out, 0);
+      __ Cmp(LowRegisterFrom(left), LowRegisterFrom(right));  // Unsigned compare.
+      less_cond = lo;
+      break;
+    }
+    case Primitive::kPrimFloat:
+    case Primitive::kPrimDouble: {
+      __ Mov(out, 0);
+      GenerateVcmp(compare);
+      // To branch on the FP compare result we transfer FPSCR to APSR (encoded as PC in VMRS).
+      __ Vmrs(RegisterOrAPSR_nzcv(kPcCode), FPSCR);
+      less_cond = ARMFPCondition(kCondLT, compare->IsGtBias());
+      break;
+    }
+    default:
+      LOG(FATAL) << "Unexpected compare type " << type;
+      UNREACHABLE();
+  }
+
+  __ B(eq, &done);
+  __ B(less_cond, &less);
+
+  __ Bind(&greater);
+  __ Mov(out, 1);
+  __ B(&done);
+
+  __ Bind(&less);
+  __ Mov(out, -1);
+
+  __ Bind(&done);
+}
+
 void LocationsBuilderARMVIXL::VisitPhi(HPhi* instruction) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
@@ -2648,6 +2750,16 @@
   }
 }
 
+Location LocationsBuilderARMVIXL::ArithmeticZeroOrFpuRegister(HInstruction* input) {
+  DCHECK(Primitive::IsFloatingPointType(input->GetType())) << input->GetType();
+  if ((input->IsFloatConstant() && (input->AsFloatConstant()->IsArithmeticZero())) ||
+      (input->IsDoubleConstant() && (input->AsDoubleConstant()->IsArithmeticZero()))) {
+    return Location::ConstantLocation(input->AsConstant());
+  } else {
+    return Location::RequiresFpuRegister();
+  }
+}
+
 void LocationsBuilderARMVIXL::HandleFieldGet(HInstruction* instruction,
                                              const FieldInfo& field_info) {
   DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
@@ -2991,7 +3103,17 @@
   } else if (source.IsFpuRegister()) {
     TODO_VIXL32(FATAL);
   } else if (source.IsDoubleStackSlot()) {
-    TODO_VIXL32(FATAL);
+    if (destination.IsDoubleStackSlot()) {
+      vixl32::DRegister temp = temps.AcquireD();
+      GetAssembler()->LoadDFromOffset(temp, sp, source.GetStackIndex());
+      GetAssembler()->StoreDToOffset(temp, sp, destination.GetStackIndex());
+    } else if (destination.IsRegisterPair()) {
+      DCHECK(ExpectedPairLayout(destination));
+      GetAssembler()->LoadFromOffset(
+          kLoadWordPair, LowRegisterFrom(destination), sp, source.GetStackIndex());
+    } else {
+      TODO_VIXL32(FATAL);
+    }
   } else if (source.IsRegisterPair()) {
     if (destination.IsRegisterPair()) {
       __ Mov(LowRegisterFrom(destination), LowRegisterFrom(source));
@@ -3070,18 +3192,77 @@
   }
 }
 
-void ParallelMoveResolverARMVIXL::Exchange(Register reg ATTRIBUTE_UNUSED,
-                                           int mem ATTRIBUTE_UNUSED) {
-  TODO_VIXL32(FATAL);
+void ParallelMoveResolverARMVIXL::Exchange(vixl32::Register reg, int mem) {
+  UseScratchRegisterScope temps(GetAssembler()->GetVIXLAssembler());
+  vixl32::Register temp = temps.Acquire();
+  __ Mov(temp, reg);
+  GetAssembler()->LoadFromOffset(kLoadWord, reg, sp, mem);
+  GetAssembler()->StoreToOffset(kStoreWord, temp, sp, mem);
 }
 
-void ParallelMoveResolverARMVIXL::Exchange(int mem1 ATTRIBUTE_UNUSED,
-                                           int mem2 ATTRIBUTE_UNUSED) {
-  TODO_VIXL32(FATAL);
+void ParallelMoveResolverARMVIXL::Exchange(int mem1, int mem2) {
+  // TODO(VIXL32): Double check the performance of this implementation.
+  UseScratchRegisterScope temps(GetAssembler()->GetVIXLAssembler());
+  vixl32::Register temp = temps.Acquire();
+  vixl32::SRegister temp_s = temps.AcquireS();
+
+  __ Ldr(temp, MemOperand(sp, mem1));
+  __ Vldr(temp_s, MemOperand(sp, mem2));
+  __ Str(temp, MemOperand(sp, mem2));
+  __ Vstr(temp_s, MemOperand(sp, mem1));
 }
 
-void ParallelMoveResolverARMVIXL::EmitSwap(size_t index ATTRIBUTE_UNUSED) {
-  TODO_VIXL32(FATAL);
+void ParallelMoveResolverARMVIXL::EmitSwap(size_t index) {
+  MoveOperands* move = moves_[index];
+  Location source = move->GetSource();
+  Location destination = move->GetDestination();
+  UseScratchRegisterScope temps(GetAssembler()->GetVIXLAssembler());
+
+  if (source.IsRegister() && destination.IsRegister()) {
+    vixl32::Register temp = temps.Acquire();
+    DCHECK(!RegisterFrom(source).Is(temp));
+    DCHECK(!RegisterFrom(destination).Is(temp));
+    __ Mov(temp, RegisterFrom(destination));
+    __ Mov(RegisterFrom(destination), RegisterFrom(source));
+    __ Mov(RegisterFrom(source), temp);
+  } else if (source.IsRegister() && destination.IsStackSlot()) {
+    Exchange(RegisterFrom(source), destination.GetStackIndex());
+  } else if (source.IsStackSlot() && destination.IsRegister()) {
+    Exchange(RegisterFrom(destination), source.GetStackIndex());
+  } else if (source.IsStackSlot() && destination.IsStackSlot()) {
+    TODO_VIXL32(FATAL);
+  } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
+    TODO_VIXL32(FATAL);
+  } else if (source.IsRegisterPair() && destination.IsRegisterPair()) {
+    vixl32::DRegister temp = temps.AcquireD();
+    __ Vmov(temp, LowRegisterFrom(source), HighRegisterFrom(source));
+    __ Mov(LowRegisterFrom(source), LowRegisterFrom(destination));
+    __ Mov(HighRegisterFrom(source), HighRegisterFrom(destination));
+    __ Vmov(LowRegisterFrom(destination), HighRegisterFrom(destination), temp);
+  } else if (source.IsRegisterPair() || destination.IsRegisterPair()) {
+    vixl32::Register low_reg = LowRegisterFrom(source.IsRegisterPair() ? source : destination);
+    int mem = source.IsRegisterPair() ? destination.GetStackIndex() : source.GetStackIndex();
+    DCHECK(ExpectedPairLayout(source.IsRegisterPair() ? source : destination));
+    vixl32::DRegister temp = temps.AcquireD();
+    __ Vmov(temp, low_reg, vixl32::Register(low_reg.GetCode() + 1));
+    GetAssembler()->LoadFromOffset(kLoadWordPair, low_reg, sp, mem);
+    GetAssembler()->StoreDToOffset(temp, sp, mem);
+  } else if (source.IsFpuRegisterPair() && destination.IsFpuRegisterPair()) {
+    TODO_VIXL32(FATAL);
+  } else if (source.IsFpuRegisterPair() || destination.IsFpuRegisterPair()) {
+    TODO_VIXL32(FATAL);
+  } else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
+    TODO_VIXL32(FATAL);
+  } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
+    vixl32::DRegister temp1 = temps.AcquireD();
+    vixl32::DRegister temp2 = temps.AcquireD();
+    __ Vldr(temp1, MemOperand(sp, source.GetStackIndex()));
+    __ Vldr(temp2, MemOperand(sp, destination.GetStackIndex()));
+    __ Vstr(temp1, MemOperand(sp, destination.GetStackIndex()));
+    __ Vstr(temp2, MemOperand(sp, source.GetStackIndex()));
+  } else {
+    LOG(FATAL) << "Unimplemented" << source << " <-> " << destination;
+  }
 }
 
 void ParallelMoveResolverARMVIXL::SpillScratch(int reg ATTRIBUTE_UNUSED) {
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index c749f86..7815db2 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -110,6 +110,7 @@
   M(BelowOrEqual)                               \
   M(ClearException)                             \
   M(ClinitCheck)                                \
+  M(Compare)                                    \
   M(CurrentMethod)                              \
   M(Div)                                        \
   M(DivZeroCheck)                               \
@@ -161,7 +162,6 @@
   M(BoundType)                                  \
   M(CheckCast)                                  \
   M(ClassTableGet)                              \
-  M(Compare)                                    \
   M(Deoptimize)                                 \
   M(DoubleConstant)                             \
   M(FloatConstant)                              \
@@ -246,7 +246,7 @@
   ArmVIXLAssembler* GetAssembler() const;
 
  private:
-  void Exchange(Register reg, int mem);
+  void Exchange(vixl32::Register reg, int mem);
   void Exchange(int mem1, int mem2);
 
   CodeGeneratorARMVIXL* const codegen_;
@@ -280,6 +280,8 @@
   void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
 
+  Location ArithmeticZeroOrFpuRegister(HInstruction* input);
+
   CodeGeneratorARMVIXL* const codegen_;
   InvokeDexCallingConventionVisitorARM parameter_visitor_;
 
diff --git a/runtime/verifier/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
similarity index 94%
rename from runtime/verifier/verifier_deps_test.cc
rename to compiler/verifier_deps_test.cc
index 71203e6..9664e43 100644
--- a/runtime/verifier/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -14,14 +14,17 @@
  * limitations under the License.
  */
 
-#include "verifier_deps.h"
+// Test is in compiler, as it uses compiler related code.
+#include "verifier/verifier_deps.h"
 
 #include "class_linker.h"
-#include "common_runtime_test.h"
+#include "compiler/common_compiler_test.h"
+#include "compiler/driver/compiler_options.h"
+#include "compiler/driver/compiler_driver.h"
 #include "compiler_callbacks.h"
 #include "dex_file.h"
 #include "handle_scope-inl.h"
-#include "method_verifier-inl.h"
+#include "verifier/method_verifier-inl.h"
 #include "mirror/class_loader.h"
 #include "runtime.h"
 #include "thread.h"
@@ -47,10 +50,10 @@
   verifier::VerifierDeps* deps_;
 };
 
-class VerifierDepsTest : public CommonRuntimeTest {
+class VerifierDepsTest : public CommonCompilerTest {
  public:
   void SetUpRuntimeOptions(RuntimeOptions* options) {
-    CommonRuntimeTest::SetUpRuntimeOptions(options);
+    CommonCompilerTest::SetUpRuntimeOptions(options);
     callbacks_.reset(new VerifierDepsCompilerCallbacks());
   }
 
@@ -147,23 +150,17 @@
 
   void VerifyDexFile() {
     std::string error_msg;
-    ScopedObjectAccess soa(Thread::Current());
-
-    LoadDexFile(&soa);
-    SetVerifierDeps({ dex_file_ });
-
-    for (size_t i = 0; i < dex_file_->NumClassDefs(); i++) {
-      const char* descriptor = dex_file_->GetClassDescriptor(dex_file_->GetClassDef(i));
-      mirror::Class* klass = FindClassByName(descriptor, &soa);
-      if (klass != nullptr) {
-        MethodVerifier::VerifyClass(Thread::Current(),
-                                    klass,
-                                    nullptr,
-                                    true,
-                                    HardFailLogMode::kLogWarning,
-                                    &error_msg);
-      }
+    {
+      ScopedObjectAccess soa(Thread::Current());
+      LoadDexFile(&soa);
     }
+    SetVerifierDeps({ dex_file_ });
+    TimingLogger timings("Verify", false, false);
+    std::vector<const DexFile*> dex_files;
+    dex_files.push_back(dex_file_);
+    compiler_options_->boot_image_ = false;
+    compiler_driver_->InitializeThreadPools();
+    compiler_driver_->Verify(class_loader_, dex_files, &timings);
   }
 
   bool TestAssignabilityRecording(const std::string& dst,
@@ -184,6 +181,21 @@
     return true;
   }
 
+  bool HasUnverifiedClass(const std::string& cls) {
+    const DexFile::TypeId* type_id = dex_file_->FindTypeId(cls.c_str());
+    DCHECK(type_id != nullptr);
+    uint16_t index = dex_file_->GetIndexForTypeId(*type_id);
+    MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
+    for (const auto& dex_dep : verifier_deps_->dex_deps_) {
+      for (uint16_t entry : dex_dep.second->unverified_classes_) {
+        if (index == entry) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
   // Iterates over all assignability records and tries to find an entry which
   // matches the expected destination/source pair.
   bool HasAssignable(const std::string& expected_destination,
@@ -361,6 +373,7 @@
     bool has_classes = false;
     bool has_fields = false;
     bool has_methods = false;
+    bool has_unverified_classes = false;
 
     for (auto& entry : verifier_deps_->dex_deps_) {
       has_strings |= !entry.second->strings_.empty();
@@ -371,9 +384,15 @@
       has_methods |= !entry.second->direct_methods_.empty();
       has_methods |= !entry.second->virtual_methods_.empty();
       has_methods |= !entry.second->interface_methods_.empty();
+      has_unverified_classes |= !entry.second->unverified_classes_.empty();
     }
 
-    return has_strings && has_assignability && has_classes && has_fields && has_methods;
+    return has_strings &&
+           has_assignability &&
+           has_classes &&
+           has_fields &&
+           has_methods &&
+           has_unverified_classes;
   }
 
   std::unique_ptr<verifier::VerifierDeps> verifier_deps_;
@@ -1056,5 +1075,18 @@
   ASSERT_TRUE(verifier_deps_->Equals(decoded_deps));
 }
 
+TEST_F(VerifierDepsTest, UnverifiedClasses) {
+  VerifyDexFile();
+  ASSERT_FALSE(HasUnverifiedClass("LMyThread;"));
+  // Test that a class with a soft failure is recorded.
+  ASSERT_TRUE(HasUnverifiedClass("LMain;"));
+  // Test that a class with hard failure is recorded.
+  ASSERT_TRUE(HasUnverifiedClass("LMyVerificationFailure;"));
+  // Test that a class with unresolved super is recorded.
+  ASSERT_FALSE(HasUnverifiedClass("LMyClassWithNoSuper;"));
+  // Test that a class with unresolved super and hard failure is recorded.
+  ASSERT_TRUE(HasUnverifiedClass("LMyClassWithNoSuperButFailures;"));
+}
+
 }  // namespace verifier
 }  // namespace art
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 6945eb0..b498573 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -565,7 +565,6 @@
         "utils_test.cc",
         "verifier/method_verifier_test.cc",
         "verifier/reg_type_test.cc",
-        "verifier/verifier_deps_test.cc",
         "zip_archive_test.cc",
     ],
     shared_libs: [
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f29ed1f..c23b1b1 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1239,6 +1239,20 @@
   gc::accounting::HeapBitmap* const live_bitmap_;
 };
 
+// Copies data from one array to another array at the same position
+// if pred returns false. If there is a page of continuous data in
+// the src array for which pred consistently returns true then
+// corresponding page in the dst array will not be touched.
+// This should reduce number of allocated physical pages.
+template <class T, class NullPred>
+static void CopyNonNull(const T* src, size_t count, T* dst, const NullPred& pred) {
+  for (size_t i = 0; i < count; ++i) {
+    if (!pred(src[i])) {
+      dst[i] = src[i];
+    }
+  }
+}
+
 bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
     gc::space::ImageSpace* space,
     Handle<mirror::ClassLoader> class_loader,
@@ -1330,7 +1344,12 @@
           for (size_t j = 0; kIsDebugBuild && j < num_types; ++j) {
             DCHECK(types[j].IsNull());
           }
-          std::copy_n(image_resolved_types, num_types, types);
+          CopyNonNull(image_resolved_types,
+                      num_types,
+                      types,
+                      [](const GcRoot<mirror::Class>& elem) {
+                          return elem.IsNull();
+                      });
           dex_cache->SetResolvedTypes(types);
         }
         if (num_methods != 0u) {
@@ -1340,7 +1359,12 @@
           for (size_t j = 0; kIsDebugBuild && j < num_methods; ++j) {
             DCHECK(methods[j] == nullptr);
           }
-          std::copy_n(image_resolved_methods, num_methods, methods);
+          CopyNonNull(image_resolved_methods,
+                      num_methods,
+                      methods,
+                      [] (const ArtMethod* method) {
+                          return method == nullptr;
+                      });
           dex_cache->SetResolvedMethods(methods);
         }
         if (num_fields != 0u) {
@@ -1349,7 +1373,12 @@
           for (size_t j = 0; kIsDebugBuild && j < num_fields; ++j) {
             DCHECK(fields[j] == nullptr);
           }
-          std::copy_n(dex_cache->GetResolvedFields(), num_fields, fields);
+          CopyNonNull(dex_cache->GetResolvedFields(),
+                      num_fields,
+                      fields,
+                      [] (const ArtField* field) {
+                          return field == nullptr;
+                      });
           dex_cache->SetResolvedFields(fields);
         }
         if (num_method_types != 0u) {
@@ -3701,9 +3730,8 @@
   return false;
 }
 
-void ClassLinker::VerifyClass(Thread* self,
-                              Handle<mirror::Class> klass,
-                              verifier::HardFailLogMode log_level) {
+verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass(
+    Thread* self, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level) {
   {
     // TODO: assert that the monitor on the Class is held
     ObjectLock<mirror::Class> lock(self, klass);
@@ -3724,16 +3752,16 @@
     // this class as a parent to another.
     if (klass->IsErroneous()) {
       ThrowEarlierClassFailure(klass.Get());
-      return;
+      return verifier::MethodVerifier::kHardFailure;
     }
 
     // Don't attempt to re-verify if already sufficiently verified.
     if (klass->IsVerified()) {
       EnsureSkipAccessChecksMethods(klass);
-      return;
+      return verifier::MethodVerifier::kNoFailure;
     }
     if (klass->IsCompileTimeVerified() && Runtime::Current()->IsAotCompiler()) {
-      return;
+      return verifier::MethodVerifier::kNoFailure;
     }
 
     if (klass->GetStatus() == mirror::Class::kStatusResolved) {
@@ -3749,7 +3777,7 @@
     if (!Runtime::Current()->IsVerificationEnabled()) {
       mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self);
       EnsureSkipAccessChecksMethods(klass);
-      return;
+      return verifier::MethodVerifier::kNoFailure;
     }
   }
 
@@ -3759,7 +3787,7 @@
   // If we have a superclass and we get a hard verification failure we can return immediately.
   if (supertype.Get() != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) {
     CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
-    return;
+    return verifier::MethodVerifier::kHardFailure;
   }
 
   // Verify all default super-interfaces.
@@ -3786,7 +3814,7 @@
       } else if (UNLIKELY(!AttemptSupertypeVerification(self, klass, iface))) {
         // We had a hard failure while verifying this interface. Just return immediately.
         CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
-        return;
+        return verifier::MethodVerifier::kHardFailure;
       } else if (UNLIKELY(!iface->IsVerified())) {
         // We softly failed to verify the iface. Stop checking and clean up.
         // Put the iface into the supertype handle so we know what caused us to fail.
@@ -3812,8 +3840,8 @@
   //     oat_file_class_status == mirror::Class::kStatusError => !preverified
   DCHECK(!(oat_file_class_status == mirror::Class::kStatusError) || !preverified);
 
-  verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
   std::string error_msg;
+  verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
   if (!preverified) {
     Runtime* runtime = Runtime::Current();
     verifier_failure = verifier::MethodVerifier::VerifyClass(self,
@@ -3886,6 +3914,7 @@
       EnsureSkipAccessChecksMethods(klass);
     }
   }
+  return verifier_failure;
 }
 
 void ClassLinker::EnsureSkipAccessChecksMethods(Handle<mirror::Class> klass) {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index f2bf581..e99dfe3 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -36,6 +36,7 @@
 #include "jni.h"
 #include "mirror/class.h"
 #include "object_callbacks.h"
+#include "verifier/method_verifier.h"
 #include "verifier/verifier_log_mode.h"
 
 namespace art {
@@ -470,9 +471,10 @@
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
-  void VerifyClass(Thread* self,
-                   Handle<mirror::Class> klass,
-                   verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone)
+  verifier::MethodVerifier::FailureKind VerifyClass(
+      Thread* self,
+      Handle<mirror::Class> klass,
+      verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!dex_lock_);
   bool VerifyClassUsingOatFile(const DexFile& dex_file,
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 72722dd..a0d712e 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -33,6 +33,7 @@
 #include "stack.h"
 #include "unstarted_runtime.h"
 #include "verifier/method_verifier.h"
+#include "well_known_classes.h"
 
 namespace art {
 namespace interpreter {
@@ -491,7 +492,12 @@
   Runtime::Current()->AbortTransactionAndThrowAbortError(self, abort_msg);
 }
 
-// Separate declaration is required solely for the attributes.
+// START DECLARATIONS :
+//
+// These additional declarations are required because clang complains
+// about ALWAYS_INLINE (-Werror, -Wgcc-compat) in definitions.
+//
+
 template <bool is_range, bool do_assignability_check>
     REQUIRES_SHARED(Locks::mutator_lock_)
 static inline bool DoCallCommon(ArtMethod* called_method,
@@ -502,7 +508,6 @@
                                 uint32_t (&arg)[Instruction::kMaxVarArgRegs],
                                 uint32_t vregC) ALWAYS_INLINE;
 
-// Separate declaration is required solely for the attributes.
 template <bool is_range> REQUIRES_SHARED(Locks::mutator_lock_)
 static inline bool DoCallPolymorphic(ArtMethod* called_method,
                                      Handle<mirror::MethodType> callsite_type,
@@ -513,6 +518,33 @@
                                      uint32_t (&arg)[Instruction::kMaxVarArgRegs],
                                      uint32_t vregC) ALWAYS_INLINE;
 
+REQUIRES_SHARED(Locks::mutator_lock_)
+static inline bool DoCallTransform(ArtMethod* called_method,
+                                   Handle<mirror::MethodType> callsite_type,
+                                   Thread* self,
+                                   ShadowFrame& shadow_frame,
+                                   Handle<mirror::MethodHandleImpl> receiver,
+                                   JValue* result) ALWAYS_INLINE;
+
+REQUIRES_SHARED(Locks::mutator_lock_)
+inline void PerformCall(Thread* self,
+                        const DexFile::CodeItem* code_item,
+                        ArtMethod* caller_method,
+                        const size_t first_dest_reg,
+                        ShadowFrame* callee_frame,
+                        JValue* result) ALWAYS_INLINE;
+
+template <bool is_range>
+REQUIRES_SHARED(Locks::mutator_lock_)
+inline void CopyRegisters(ShadowFrame& caller_frame,
+                          ShadowFrame* callee_frame,
+                          const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
+                          const size_t first_src_reg,
+                          const size_t first_dest_reg,
+                          const size_t num_regs) ALWAYS_INLINE;
+
+// END DECLARATIONS.
+
 void ArtInterpreterToCompiledCodeBridge(Thread* self,
                                         ArtMethod* caller,
                                         const DexFile::CodeItem* code_item,
@@ -635,12 +667,6 @@
   CHECK(called_method != nullptr);
   CHECK(handle_type.Get() != nullptr);
 
-  // We now have to massage the number of inputs to the target function.
-  // It's always one less than the number of inputs to the signature polymorphic
-  // invoke, the first input being a reference to the MethodHandle itself.
-  const uint16_t number_of_inputs =
-      ((is_range) ? inst->VRegA_4rcc(inst_data) : inst->VRegA_45cc(inst_data)) - 1;
-
   uint32_t arg[Instruction::kMaxVarArgRegs] = {};
   uint32_t receiver_vregC = 0;
   if (is_range) {
@@ -702,18 +728,22 @@
       CHECK(called_method != nullptr);
     }
 
-    // NOTE: handle_kind == kInvokeStatic needs no special treatment here. We
-    // can directly make the call. handle_kind == kInvokeSuper doesn't have any
-    // particular use and can probably be dropped.
-
-    if (callsite_type->IsExactMatch(handle_type.Get())) {
-      return DoCallCommon<is_range, do_access_check>(
-          called_method, self, shadow_frame, result, number_of_inputs,
-          arg, receiver_vregC);
+    if (handle_kind == kInvokeTransform) {
+      return DoCallTransform(called_method,
+                             callsite_type,
+                             self,
+                             shadow_frame,
+                             method_handle /* receiver */,
+                             result);
     } else {
-      return DoCallPolymorphic<is_range>(
-          called_method, callsite_type, handle_type, self, shadow_frame,
-          result, arg, receiver_vregC);
+      return DoCallPolymorphic<is_range>(called_method,
+                                         callsite_type,
+                                         handle_type,
+                                         self,
+                                         shadow_frame,
+                                         result,
+                                         arg,
+                                         receiver_vregC);
     }
   } else {
     // TODO(narayan): Implement field getters and setters.
@@ -749,6 +779,64 @@
   return num_ins;
 }
 
+
+inline void PerformCall(Thread* self,
+                        const DexFile::CodeItem* code_item,
+                        ArtMethod* caller_method,
+                        const size_t first_dest_reg,
+                        ShadowFrame* callee_frame,
+                        JValue* result) {
+  if (LIKELY(Runtime::Current()->IsStarted())) {
+    ArtMethod* target = callee_frame->GetMethod();
+    if (ClassLinker::ShouldUseInterpreterEntrypoint(
+        target,
+        target->GetEntryPointFromQuickCompiledCode())) {
+      ArtInterpreterToInterpreterBridge(self, code_item, callee_frame, result);
+    } else {
+      ArtInterpreterToCompiledCodeBridge(
+          self, caller_method, code_item, callee_frame, result);
+    }
+  } else {
+    UnstartedRuntime::Invoke(self, code_item, callee_frame, result, first_dest_reg);
+  }
+}
+
+template <bool is_range>
+inline void CopyRegisters(ShadowFrame& caller_frame,
+                          ShadowFrame* callee_frame,
+                          const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
+                          const size_t first_src_reg,
+                          const size_t first_dest_reg,
+                          const size_t num_regs) {
+  if (is_range) {
+    const size_t dest_reg_bound = first_dest_reg + num_regs;
+    for (size_t src_reg = first_src_reg, dest_reg = first_dest_reg; dest_reg < dest_reg_bound;
+        ++dest_reg, ++src_reg) {
+      AssignRegister(callee_frame, caller_frame, dest_reg, src_reg);
+    }
+  } else {
+    DCHECK_LE(num_regs, arraysize(arg));
+
+    for (size_t arg_index = 0; arg_index < num_regs; ++arg_index) {
+      AssignRegister(callee_frame, caller_frame, first_dest_reg + arg_index, arg[arg_index]);
+    }
+  }
+}
+
+// Returns true iff. the callsite type for a polymorphic invoke is transformer
+// like, i.e that it has a single input argument whose type is
+// dalvik.system.EmulatedStackFrame.
+static inline bool IsCallerTransformer(Handle<mirror::MethodType> callsite_type)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  ObjPtr<mirror::ObjectArray<mirror::Class>> param_types(callsite_type->GetPTypes());
+  if (param_types->GetLength() == 1) {
+    ObjPtr<mirror::Class> param(param_types->GetWithoutChecks(0));
+    return param == WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_EmulatedStackFrame);
+  }
+
+  return false;
+}
+
 template <bool is_range>
 static inline bool DoCallPolymorphic(ArtMethod* called_method,
                                      Handle<mirror::MethodType> callsite_type,
@@ -757,7 +845,7 @@
                                      ShadowFrame& shadow_frame,
                                      JValue* result,
                                      uint32_t (&arg)[Instruction::kMaxVarArgRegs],
-                                     uint32_t vregC) {
+                                     uint32_t first_src_reg) {
   // TODO(narayan): Wire in the String.init hacks.
 
   // Compute method information.
@@ -770,16 +858,18 @@
   // some transformations (such as boxing a long -> Long or wideining an
   // int -> long will change that number.
   uint16_t num_regs;
+  size_t num_input_regs;
   size_t first_dest_reg;
   if (LIKELY(code_item != nullptr)) {
     num_regs = code_item->registers_size_;
     first_dest_reg = num_regs - code_item->ins_size_;
+    num_input_regs = code_item->ins_size_;
     // Parameter registers go at the end of the shadow frame.
     DCHECK_NE(first_dest_reg, (size_t)-1);
   } else {
     // No local regs for proxy and native methods.
     DCHECK(called_method->IsNative() || called_method->IsProxyMethod());
-    num_regs = GetInsForProxyOrNativeMethod(called_method);
+    num_regs = num_input_regs = GetInsForProxyOrNativeMethod(called_method);
     first_dest_reg = 0;
   }
 
@@ -793,35 +883,109 @@
   {
     ScopedStackedShadowFramePusher pusher(
         self, new_shadow_frame, StackedShadowFrameType::kShadowFrameUnderConstruction);
-    if (!PerformArgumentConversions<is_range>(self, callsite_type, target_type,
-                                              shadow_frame, vregC, first_dest_reg,
-                                              arg, new_shadow_frame)) {
-      DCHECK(self->IsExceptionPending());
-      result->SetL(0);
-      return false;
+    if (callsite_type->IsExactMatch(target_type.Get())) {
+      // This is an exact invoke, we can take the fast path of just copying all
+      // registers without performing any argument conversions.
+      CopyRegisters<is_range>(shadow_frame,
+                              new_shadow_frame,
+                              arg,
+                              first_src_reg,
+                              first_dest_reg,
+                              num_input_regs);
+    } else {
+      // This includes the case where we're entering this invoke-polymorphic
+      // from a transformer method. In that case, the callsite_type will contain
+      // a single argument of type dalvik.system.EmulatedStackFrame. In that
+      // case, we'll have to unmarshal the EmulatedStackFrame into the
+      // new_shadow_frame and perform argument conversions on it.
+      if (IsCallerTransformer(callsite_type)) {
+        // The emulated stack frame will be the first ahnd only argument
+        // when we're coming through from a transformer.
+        //
+        // TODO(narayan): This should be a mirror::EmulatedStackFrame after that
+        // type is introduced.
+        ObjPtr<mirror::Object> emulated_stack_frame(
+            shadow_frame.GetVRegReference(first_src_reg));
+        if (!ConvertAndCopyArgumentsFromEmulatedStackFrame<is_range>(self,
+                                                                     emulated_stack_frame,
+                                                                     target_type,
+                                                                     first_dest_reg,
+                                                                     new_shadow_frame)) {
+          DCHECK(self->IsExceptionPending());
+          result->SetL(0);
+          return false;
+        }
+      } else if (!ConvertAndCopyArgumentsFromCallerFrame<is_range>(self,
+                                                                   callsite_type,
+                                                                   target_type,
+                                                                   shadow_frame,
+                                                                   first_src_reg,
+                                                                   first_dest_reg,
+                                                                   arg,
+                                                                   new_shadow_frame)) {
+        DCHECK(self->IsExceptionPending());
+        result->SetL(0);
+        return false;
+      }
     }
   }
 
-  // Do the call now.
-  if (LIKELY(Runtime::Current()->IsStarted())) {
-    ArtMethod* target = new_shadow_frame->GetMethod();
-    if (ClassLinker::ShouldUseInterpreterEntrypoint(
-        target,
-        target->GetEntryPointFromQuickCompiledCode())) {
-      ArtInterpreterToInterpreterBridge(self, code_item, new_shadow_frame, result);
-    } else {
-      ArtInterpreterToCompiledCodeBridge(
-          self, shadow_frame.GetMethod(), code_item, new_shadow_frame, result);
-    }
-  } else {
-    UnstartedRuntime::Invoke(self, code_item, new_shadow_frame, result, first_dest_reg);
-  }
+  PerformCall(self, code_item, shadow_frame.GetMethod(), first_dest_reg, new_shadow_frame, result);
 
   // TODO(narayan): Perform return value conversions.
 
   return !self->IsExceptionPending();
 }
 
+static inline bool DoCallTransform(ArtMethod* called_method,
+                                   Handle<mirror::MethodType> callsite_type,
+                                   Thread* self,
+                                   ShadowFrame& shadow_frame,
+                                   Handle<mirror::MethodHandleImpl> receiver,
+                                   JValue* result) {
+  // This can be fixed, because the method we're calling here
+  // (MethodHandle.transformInternal) doesn't have any locals and the signature
+  // is known :
+  //
+  // private MethodHandle.transformInternal(EmulatedStackFrame sf);
+  //
+  // This means we need only two vregs :
+  // - One for the receiver object.
+  // - One for the only method argument (an EmulatedStackFrame).
+  static constexpr size_t kNumRegsForTransform = 2;
+
+  const DexFile::CodeItem* code_item = called_method->GetCodeItem();
+  DCHECK(code_item != nullptr);
+  DCHECK_EQ(kNumRegsForTransform, code_item->registers_size_);
+  DCHECK_EQ(kNumRegsForTransform, code_item->ins_size_);
+
+  ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
+      CREATE_SHADOW_FRAME(kNumRegsForTransform, &shadow_frame, called_method, /* dex pc */ 0);
+  ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get();
+
+  // TODO(narayan): Perform argument conversions first (if this is an inexact invoke), and
+  // then construct an argument list object that's passed through to the
+  // method. Note that the ArgumentList reference is currently a nullptr.
+  //
+  // NOTE(narayan): If the caller is a transformer method (i.e, there is only
+  // one argument and its type is EmulatedStackFrame), we can directly pass that
+  // through without having to do any additional work.
+  UNUSED(callsite_type);
+
+  new_shadow_frame->SetVRegReference(0, receiver.Get());
+  // TODO(narayan): This is the EmulatedStackFrame, currently nullptr.
+  new_shadow_frame->SetVRegReference(1, nullptr);
+
+  PerformCall(self,
+              code_item,
+              shadow_frame.GetMethod(),
+              0 /* first dest reg */,
+              new_shadow_frame,
+              result);
+
+  return !self->IsExceptionPending();
+}
+
 template <bool is_range,
           bool do_assignability_check>
 static inline bool DoCallCommon(ArtMethod* called_method,
@@ -982,40 +1146,20 @@
       }
     }
   } else {
-    size_t arg_index = 0;
-
-    // Fast path: no extra checks.
     if (is_range) {
-      uint16_t first_src_reg = vregC;
-
-      for (size_t src_reg = first_src_reg, dest_reg = first_dest_reg; dest_reg < num_regs;
-          ++dest_reg, ++src_reg) {
-        AssignRegister(new_shadow_frame, shadow_frame, dest_reg, src_reg);
-      }
-    } else {
-      DCHECK_LE(number_of_inputs, arraysize(arg));
-
-      for (; arg_index < number_of_inputs; ++arg_index) {
-        AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + arg_index, arg[arg_index]);
-      }
+      DCHECK_EQ(num_regs, first_dest_reg + number_of_inputs);
     }
+
+    CopyRegisters<is_range>(shadow_frame,
+                            new_shadow_frame,
+                            arg,
+                            vregC,
+                            first_dest_reg,
+                            number_of_inputs);
     self->EndAssertNoThreadSuspension(old_cause);
   }
 
-  // Do the call now.
-  if (LIKELY(Runtime::Current()->IsStarted())) {
-    ArtMethod* target = new_shadow_frame->GetMethod();
-    if (ClassLinker::ShouldUseInterpreterEntrypoint(
-        target,
-        target->GetEntryPointFromQuickCompiledCode())) {
-      ArtInterpreterToInterpreterBridge(self, code_item, new_shadow_frame, result);
-    } else {
-      ArtInterpreterToCompiledCodeBridge(
-          self, shadow_frame.GetMethod(), code_item, new_shadow_frame, result);
-    }
-  } else {
-    UnstartedRuntime::Invoke(self, code_item, new_shadow_frame, result, first_dest_reg);
-  }
+  PerformCall(self, code_item, shadow_frame.GetMethod(), first_dest_reg, new_shadow_frame, result);
 
   if (string_init && !self->IsExceptionPending()) {
     SetStringInitValueToAllAliases(&shadow_frame, string_init_vreg_this, *result);
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index e4c67e0..1ec59b3 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -318,11 +318,18 @@
     debug_friendly_name += name;
     fd.Reset(ashmem_create_region(debug_friendly_name.c_str(), page_aligned_byte_count),
              /* check_usage */ false);
+
     if (fd.Fd() == -1) {
-      *error_msg = StringPrintf("ashmem_create_region failed for '%s': %s", name, strerror(errno));
-      return nullptr;
+      // We failed to create the ashmem region. Print a warning, but continue
+      // anyway by creating a true anonymous mmap with an fd of -1. It is
+      // better to use an unlabelled anonymous map than to fail to create a
+      // map at all.
+      PLOG(WARNING) << "ashmem_create_region failed for '" << name << "'";
+    } else {
+      // We succeeded in creating the ashmem region. Use the created ashmem
+      // region as backing for the mmap.
+      flags &= ~MAP_ANONYMOUS;
     }
-    flags &= ~MAP_ANONYMOUS;
   }
 
   // We need to store and potentially set an error number for pretty printing of errors
@@ -354,7 +361,6 @@
     }
     return nullptr;
   }
-  std::ostringstream check_map_request_error_msg;
   if (!CheckMapRequest(expected_ptr, actual, page_aligned_byte_count, error_msg)) {
     return nullptr;
   }
@@ -441,7 +447,6 @@
     }
     return nullptr;
   }
-  std::ostringstream check_map_request_error_msg;
   if (!CheckMapRequest(expected_ptr, actual, page_aligned_byte_count, error_msg)) {
     return nullptr;
   }
diff --git a/runtime/method_handles-inl.h b/runtime/method_handles-inl.h
index 7a77bda..b488133 100644
--- a/runtime/method_handles-inl.h
+++ b/runtime/method_handles-inl.h
@@ -162,14 +162,14 @@
 }
 
 template <bool is_range>
-bool PerformArgumentConversions(Thread* self,
-                                Handle<mirror::MethodType> callsite_type,
-                                Handle<mirror::MethodType> callee_type,
-                                const ShadowFrame& caller_frame,
-                                uint32_t first_src_reg,
-                                uint32_t first_dest_reg,
-                                const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
-                                ShadowFrame* callee_frame) {
+bool ConvertAndCopyArgumentsFromCallerFrame(Thread* self,
+                                            Handle<mirror::MethodType> callsite_type,
+                                            Handle<mirror::MethodType> callee_type,
+                                            const ShadowFrame& caller_frame,
+                                            uint32_t first_src_reg,
+                                            uint32_t first_dest_reg,
+                                            const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
+                                            ShadowFrame* callee_frame) {
   StackHandleScope<4> hs(self);
   Handle<mirror::ObjectArray<mirror::Class>> from_types(hs.NewHandle(callsite_type->GetPTypes()));
   Handle<mirror::ObjectArray<mirror::Class>> to_types(hs.NewHandle(callee_type->GetPTypes()));
@@ -244,6 +244,25 @@
   return true;
 }
 
+// Similar to |ConvertAndCopyArgumentsFromCallerFrame|, except that the
+// arguments are copied from an |EmulatedStackFrame|.
+template <bool is_range>
+bool ConvertAndCopyArgumentsFromEmulatedStackFrame(Thread* self,
+                                                   ObjPtr<mirror::Object> emulated_stack_frame,
+                                                   Handle<mirror::MethodType> callee_type,
+                                                   const uint32_t first_dest_reg,
+                                                   ShadowFrame* callee_frame) {
+  UNUSED(self);
+  UNUSED(emulated_stack_frame);
+  UNUSED(callee_type);
+  UNUSED(first_dest_reg);
+  UNUSED(callee_frame);
+
+  UNIMPLEMENTED(FATAL) << "ConvertAndCopyArgumentsFromEmulatedStackFrame is unimplemented";
+  return false;
+}
+
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_METHOD_HANDLES_INL_H_
diff --git a/runtime/method_handles.h b/runtime/method_handles.h
index 26a29b3..5175dce 100644
--- a/runtime/method_handles.h
+++ b/runtime/method_handles.h
@@ -42,12 +42,13 @@
   kInvokeDirect,
   kInvokeStatic,
   kInvokeInterface,
+  kInvokeTransform,
   kInstanceGet,
   kInstancePut,
   kStaticGet,
   kStaticPut,
   kLastValidKind = kStaticPut,
-  kLastInvokeKind = kInvokeInterface
+  kLastInvokeKind = kInvokeTransform
 };
 
 // Whether the given method handle kind is some variant of an invoke.
@@ -69,14 +70,24 @@
 // boxing and unboxing. Returns true on success, on false on failure. A
 // pending exception will always be set on failure.
 template <bool is_range> REQUIRES_SHARED(Locks::mutator_lock_)
-bool PerformArgumentConversions(Thread* self,
-                                Handle<mirror::MethodType> callsite_type,
-                                Handle<mirror::MethodType> callee_type,
-                                const ShadowFrame& caller_frame,
-                                uint32_t first_src_reg,
-                                uint32_t first_dest_reg,
-                                const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
-                                ShadowFrame* callee_frame);
+bool ConvertAndCopyArgumentsFromCallerFrame(Thread* self,
+                                            Handle<mirror::MethodType> callsite_type,
+                                            Handle<mirror::MethodType> callee_type,
+                                            const ShadowFrame& caller_frame,
+                                            uint32_t first_src_reg,
+                                            uint32_t first_dest_reg,
+                                            const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
+                                            ShadowFrame* callee_frame);
+
+// Similar to |ConvertAndCopyArgumentsFromCallerFrame|, except that the
+// arguments are copied from an |EmulatedStackFrame|.
+template <bool is_range> REQUIRES_SHARED(Locks::mutator_lock_)
+bool ConvertAndCopyArgumentsFromEmulatedStackFrame(Thread* self,
+                                                   ObjPtr<mirror::Object> emulated_stack_frame,
+                                                   Handle<mirror::MethodType> callee_type,
+                                                   const uint32_t first_dest_reg,
+                                                   ShadowFrame* callee_frame);
+
 
 }  // namespace art
 
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index 3c7fb7a..4d1e337 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -280,6 +280,22 @@
   return callbacks->GetVerifierDeps();
 }
 
+void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file,
+                                                 uint16_t type_idx,
+                                                 MethodVerifier::FailureKind failure_kind) {
+  if (failure_kind == MethodVerifier::kNoFailure) {
+    // We only record classes that did not fully verify at compile time.
+    return;
+  }
+
+  VerifierDeps* singleton = GetVerifierDepsSingleton();
+  if (singleton != nullptr) {
+    DexFileDeps* dex_deps = singleton->GetDexFileDeps(dex_file);
+    MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
+    dex_deps->unverified_classes_.push_back(type_idx);
+  }
+}
+
 void VerifierDeps::MaybeRecordClassResolution(const DexFile& dex_file,
                                               uint16_t type_idx,
                                               mirror::Class* klass) {
@@ -360,6 +376,14 @@
   }
 }
 
+static inline void EncodeUint16Vector(std::vector<uint8_t>* out,
+                                      const std::vector<uint16_t>& vector) {
+  EncodeUnsignedLeb128(out, vector.size());
+  for (uint16_t entry : vector) {
+    EncodeUnsignedLeb128(out, entry);
+  }
+}
+
 template<typename T>
 static inline void DecodeSet(const uint8_t** in, const uint8_t* end, std::set<T>* set) {
   DCHECK(set->empty());
@@ -371,6 +395,17 @@
   }
 }
 
+static inline void DecodeUint16Vector(const uint8_t** in,
+                                      const uint8_t* end,
+                                      std::vector<uint16_t>* vector) {
+  DCHECK(vector->empty());
+  size_t num_entries = DecodeUint32WithOverflowCheck(in, end);
+  vector->reserve(num_entries);
+  for (size_t i = 0; i < num_entries; ++i) {
+    vector->push_back(dchecked_integral_cast<uint16_t>(DecodeUint32WithOverflowCheck(in, end)));
+  }
+}
+
 static inline void EncodeStringVector(std::vector<uint8_t>* out,
                                       const std::vector<std::string>& strings) {
   EncodeUnsignedLeb128(out, strings.size());
@@ -407,6 +442,7 @@
     EncodeSet(buffer, entry.second->direct_methods_);
     EncodeSet(buffer, entry.second->virtual_methods_);
     EncodeSet(buffer, entry.second->interface_methods_);
+    EncodeUint16Vector(buffer, entry.second->unverified_classes_);
   }
 }
 
@@ -423,6 +459,7 @@
     DecodeSet(&data_start, data_end, &entry.second->direct_methods_);
     DecodeSet(&data_start, data_end, &entry.second->virtual_methods_);
     DecodeSet(&data_start, data_end, &entry.second->interface_methods_);
+    DecodeUint16Vector(&data_start, data_end, &entry.second->unverified_classes_);
   }
   CHECK_LE(data_start, data_end);
 }
@@ -463,7 +500,8 @@
          (fields_ == rhs.fields_) &&
          (direct_methods_ == rhs.direct_methods_) &&
          (virtual_methods_ == rhs.virtual_methods_) &&
-         (interface_methods_ == rhs.interface_methods_);
+         (interface_methods_ == rhs.interface_methods_) &&
+         (unverified_classes_ == rhs.unverified_classes_);
 }
 
 }  // namespace verifier
diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h
index 3223f6f..9d2622d 100644
--- a/runtime/verifier/verifier_deps.h
+++ b/runtime/verifier/verifier_deps.h
@@ -26,6 +26,7 @@
 #include "base/array_ref.h"
 #include "base/mutex.h"
 #include "method_resolution_kind.h"
+#include "method_verifier.h"  // For MethodVerifier::FailureKind.
 #include "obj_ptr.h"
 #include "os.h"
 
@@ -49,6 +50,12 @@
   explicit VerifierDeps(const std::vector<const DexFile*>& dex_files)
       REQUIRES(!Locks::verifier_deps_lock_);
 
+  // Record the verification status of the class at `type_idx`.
+  static void MaybeRecordVerificationStatus(const DexFile& dex_file,
+                                            uint16_t type_idx,
+                                            MethodVerifier::FailureKind failure_kind)
+      REQUIRES(!Locks::verifier_deps_lock_);
+
   // Record the outcome `klass` of resolving type `type_idx` from `dex_file`.
   // If `klass` is null, the class is assumed unresolved.
   static void MaybeRecordClassResolution(const DexFile& dex_file,
@@ -136,7 +143,7 @@
   };
 
   using TypeAssignabilityBase = std::tuple<uint32_t, uint32_t>;
-  struct TypeAssignability : public std::tuple<uint32_t, uint32_t> {
+  struct TypeAssignability : public TypeAssignabilityBase {
     TypeAssignability() = default;
     TypeAssignability(const TypeAssignability&) = default;
     TypeAssignability(uint32_t destination_idx, uint32_t source_idx)
@@ -165,6 +172,9 @@
     std::set<MethodResolution> virtual_methods_;
     std::set<MethodResolution> interface_methods_;
 
+    // List of classes that were not fully verified in that dex file.
+    std::vector<uint16_t> unverified_classes_;
+
     bool Equals(const DexFileDeps& rhs) const;
   };
 
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 78fc53a..153c7ef 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -37,6 +37,7 @@
 jclass WellKnownClasses::dalvik_system_DexFile;
 jclass WellKnownClasses::dalvik_system_DexPathList;
 jclass WellKnownClasses::dalvik_system_DexPathList__Element;
+jclass WellKnownClasses::dalvik_system_EmulatedStackFrame;
 jclass WellKnownClasses::dalvik_system_PathClassLoader;
 jclass WellKnownClasses::dalvik_system_VMRuntime;
 jclass WellKnownClasses::java_lang_annotation_Annotation__array;
@@ -266,6 +267,7 @@
   dalvik_system_DexFile = CacheClass(env, "dalvik/system/DexFile");
   dalvik_system_DexPathList = CacheClass(env, "dalvik/system/DexPathList");
   dalvik_system_DexPathList__Element = CacheClass(env, "dalvik/system/DexPathList$Element");
+  dalvik_system_EmulatedStackFrame = CacheClass(env, "dalvik/system/EmulatedStackFrame");
   dalvik_system_PathClassLoader = CacheClass(env, "dalvik/system/PathClassLoader");
   dalvik_system_VMRuntime = CacheClass(env, "dalvik/system/VMRuntime");
 
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 248ba7f..2fb5bb4 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -50,6 +50,7 @@
   static jclass dalvik_system_DexFile;
   static jclass dalvik_system_DexPathList;
   static jclass dalvik_system_DexPathList__Element;
+  static jclass dalvik_system_EmulatedStackFrame;
   static jclass dalvik_system_PathClassLoader;
   static jclass dalvik_system_VMRuntime;
   static jclass java_lang_annotation_Annotation__array;
diff --git a/test/151-OpenFileLimit/expected.txt b/test/151-OpenFileLimit/expected.txt
index 971e472..6bc45ef 100644
--- a/test/151-OpenFileLimit/expected.txt
+++ b/test/151-OpenFileLimit/expected.txt
@@ -1,3 +1,3 @@
 Message includes "Too many open files"
-Message includes "Too many open files"
+thread run.
 done.
diff --git a/test/151-OpenFileLimit/info.txt b/test/151-OpenFileLimit/info.txt
index 56ed396..9af393d 100644
--- a/test/151-OpenFileLimit/info.txt
+++ b/test/151-OpenFileLimit/info.txt
@@ -1,3 +1,2 @@
-This test verifies the exception message is informative for failure to launch
-a thread due to the number of available file descriptors in the process being
-exceeded.
+This test verifies that running out of file descriptors in the process doesn't
+prevent us from launching a new thread.
diff --git a/test/151-OpenFileLimit/src/Main.java b/test/151-OpenFileLimit/src/Main.java
index 01a9a4e..9fe47c8 100644
--- a/test/151-OpenFileLimit/src/Main.java
+++ b/test/151-OpenFileLimit/src/Main.java
@@ -52,11 +52,7 @@
             thread.start();
             thread.join();
         } catch (Throwable e) {
-            if (e.getMessage().contains("Too many open files")) {
-                System.out.println("Message includes \"Too many open files\"");
-            } else {
-                System.out.println(e.getMessage());
-            }
+            System.out.println(e.getMessage());
         }
 
         for (int i = 0; i < files.size(); i++) {
diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java
index 2802dfa..badea53 100644
--- a/test/956-methodhandles/src/Main.java
+++ b/test/956-methodhandles/src/Main.java
@@ -57,6 +57,8 @@
   public static void main(String[] args) throws Throwable {
     testfindSpecial_invokeSuperBehaviour();
     testfindSpecial_invokeDirectBehaviour();
+
+    testThrowException();
   }
 
   public static void testfindSpecial_invokeSuperBehaviour() throws Throwable {
@@ -131,6 +133,21 @@
     } catch (IllegalAccessException expected) {
     }
   }
+
+  public static void testThrowException() throws Throwable {
+    MethodHandle handle = MethodHandles.throwException(String.class,
+        IllegalArgumentException.class);
+    if (handle.type().returnType() != String.class) {
+      System.out.println("Unexpected return type for handle: " + handle
+          + " [ " + handle.type() + "]");
+    }
+
+    try {
+      handle.invoke();
+      System.out.println("Expected an exception of type: java.lang.IllegalArgumentException");
+    } catch (IllegalArgumentException expected) {
+    }
+  }
 }
 
 
diff --git a/test/Android.arm_vixl.mk b/test/Android.arm_vixl.mk
index 0bbcb64..5e1b953 100644
--- a/test/Android.arm_vixl.mk
+++ b/test/Android.arm_vixl.mk
@@ -52,7 +52,6 @@
   037-inherit \
   041-narrowing \
   042-new-instance \
-  043-privates \
   044-proxy \
   045-reflect-array \
   046-reflect \
@@ -62,7 +61,6 @@
   050-sync-test \
   051-thread \
   052-verifier-fun \
-  053-wait-some \
   054-uncaught \
   058-enum-order \
   059-finalizer-throw \
@@ -137,9 +135,6 @@
   201-built-in-except-detail-messages \
   302-float-conversion \
   304-method-tracing \
-  403-optimizing-long \
-  404-optimizing-allocator \
-  405-optimizing-long-allocator \
   406-fields \
   407-arrays \
   410-floats \
@@ -153,7 +148,6 @@
   417-optimizing-arith-div \
   419-long-parameter \
   421-exceptions \
-  421-large-frame \
   422-instanceof \
   422-type-conversion \
   423-invoke-interface \
@@ -180,7 +174,6 @@
   442-checker-constant-folding \
   444-checker-nce \
   445-checker-licm \
-  446-checker-inliner2 \
   447-checker-inliner3 \
   448-multiple-returns \
   449-checker-bce \
@@ -197,33 +190,24 @@
   459-dead-phi \
   460-multiple-returns3 \
   461-get-reference-vreg \
-  462-checker-inlining-dex-files \
   463-checker-boolean-simplifier \
-  464-checker-inline-sharpen-calls \
   466-get-live-vreg \
   467-regalloc-pair \
   468-checker-bool-simplif-regression \
   469-condition-materialization \
-  470-huge-method \
   471-deopt-environment \
   472-type-propagation \
-  473-checker-inliner-constants \
   474-checker-boolean-input \
   474-fp-sub-neg \
   475-regression-inliner-ids \
-  476-checker-ctor-memory-barrier \
   477-checker-bound-type \
   477-long-2-float-convers-precision \
   478-checker-clinit-check-pruning \
-  478-checker-inliner-nested-loop \
-  480-checker-dead-blocks \
-  482-checker-loop-back-edge-use \
   483-dce-block \
   484-checker-register-hints \
   485-checker-dce-loop-update \
   485-checker-dce-switch \
   486-checker-must-do-null-check \
-  487-checker-inline-calls \
   488-checker-inline-recursive-calls \
   490-checker-inline \
   491-current-method \
@@ -273,7 +257,6 @@
   535-regression-const-val \
   536-checker-intrinsic-optimization \
   536-checker-needs-access-check \
-  537-checker-arraycopy \
   537-checker-inline-and-unverified \
   537-checker-jump-over-jump \
   538-checker-embed-constants \
@@ -285,10 +268,8 @@
   543-env-long-ref \
   545-tracing-and-jit \
   546-regression-simplify-catch \
-  548-checker-inlining-and-dce \
   550-checker-multiply-accumulate \
   550-checker-regression-wide-store \
-  551-checker-clinit \
   551-checker-shifter-operand \
   551-implicit-null-checks \
   551-invoke-super \
@@ -311,17 +292,13 @@
   562-no-intermediate \
   563-checker-fakestring \
   564-checker-bitcount \
-  564-checker-inline-loop \
   564-checker-irreducible-loop \
   564-checker-negbitwise \
   565-checker-condition-liveness \
   565-checker-doublenegbitwise \
   565-checker-irreducible-loop \
   565-checker-rotate \
-  566-checker-codegen-select \
-  566-checker-signum \
   566-polymorphic-inlining \
-  567-checker-compare \
   568-checker-onebit \
   570-checker-osr \
   570-checker-select \
@@ -346,7 +323,6 @@
   590-checker-arr-set-null-regression \
   591-new-instance-string \
   592-checker-regression-bool-input \
-  593-checker-boolean-2-integral-conv \
   593-checker-long-2-float-regression \
   593-checker-shift-and-simplifier \
   594-checker-array-alias \
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 9b456c1..1e3a997 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -232,11 +232,9 @@
 
 
 # Disable 149-suspend-all-stress, its output is flaky (b/28988206).
-# Disable 151-OpenFileLimit (b/32302133)
 # Disable 577-profile-foreign-dex (b/27454772).
 TEST_ART_BROKEN_ALL_TARGET_TESTS := \
   149-suspend-all-stress \
-  151-OpenFileLimit \
   577-profile-foreign-dex \
 
 ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
diff --git a/test/VerifierDeps/MyClassWithNoSuper.smali b/test/VerifierDeps/MyClassWithNoSuper.smali
new file mode 100644
index 0000000..d8509bc
--- /dev/null
+++ b/test/VerifierDeps/MyClassWithNoSuper.smali
@@ -0,0 +1,16 @@
+# 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 LMyClassWithNoSuper;
+.super LNoSuper;
diff --git a/test/VerifierDeps/MyClassWithNoSuperButFailures.smali b/test/VerifierDeps/MyClassWithNoSuperButFailures.smali
new file mode 100644
index 0000000..1dbe9d1
--- /dev/null
+++ b/test/VerifierDeps/MyClassWithNoSuperButFailures.smali
@@ -0,0 +1,21 @@
+# 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 LMyClassWithNoSuperButFailures;
+.super LNoSuper;
+
+.method public final foo()I
+  .registers 1
+  return-void
+.end method
diff --git a/test/VerifierDeps/MyVerificationFailure.smali b/test/VerifierDeps/MyVerificationFailure.smali
new file mode 100644
index 0000000..187b1ad
--- /dev/null
+++ b/test/VerifierDeps/MyVerificationFailure.smali
@@ -0,0 +1,21 @@
+# 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 LMyVerificationFailure;
+.super Ljava/lang/Object;
+
+.method public final foo()I
+  .registers 1
+  return-void
+.end method