Merge "Implemented signum() on ARM64."
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index afc8463..e4bfac9 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -122,16 +122,7 @@
   int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
   CHECK_EQ(result, 0);
 
-  // Flush instruction cache
-  // Only uses __builtin___clear_cache if GCC >= 4.3.3
-#if GCC_VERSION >= 40303
-  __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len));
-#else
-  // Only warn if not Intel as Intel doesn't have cache flush instructions.
-#if !defined(__i386__) && !defined(__x86_64__)
-  UNIMPLEMENTED(WARNING) << "cache flush";
-#endif
-#endif
+  FlushInstructionCache(reinterpret_cast<char*>(base), reinterpret_cast<char*>(base + len));
 }
 
 void CommonCompilerTest::MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name) {
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 39372b3..a220959 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -116,6 +116,10 @@
     return compiler_filter_ == CompilerOptions::kVerifyNone;
   }
 
+  bool IsExtractOnly() const {
+    return compiler_filter_ == CompilerOptions::kVerifyAtRuntime;
+  }
+
   size_t GetHugeMethodThreshold() const {
     return huge_method_threshold_;
   }
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index d90c1fb..b808347 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4450,9 +4450,6 @@
   Primitive::Type GetInputType() const { return GetInput()->GetType(); }
   Primitive::Type GetResultType() const { return GetType(); }
 
-  // Required by the x86, ARM, MIPS and MIPS64 code generators when producing calls
-  // to the runtime.
-
   bool CanBeMoved() const OVERRIDE { return true; }
   bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
 
@@ -4819,8 +4816,7 @@
   }
 
   bool NeedsEnvironment() const OVERRIDE {
-    // We currently always call a runtime method to catch array store
-    // exceptions.
+    // We call a runtime method to throw ArrayStoreException.
     return needs_type_check_;
   }
 
@@ -5131,11 +5127,13 @@
 
   uint32_t GetStringIndex() const { return string_index_; }
 
-  // TODO: Can we deopt or debug when we resolve a string?
-  bool NeedsEnvironment() const OVERRIDE { return false; }
+  // Will call the runtime if the string is not already in the dex cache.
+  bool NeedsEnvironment() const OVERRIDE { return !IsInDexCache(); }
+
   bool NeedsDexCacheOfDeclaringClass() const OVERRIDE { return true; }
   bool CanBeNull() const OVERRIDE { return false; }
   bool IsInDexCache() const { return is_in_dex_cache_; }
+  bool CanThrow() const OVERRIDE { return !IsInDexCache(); }
 
   static SideEffects SideEffectsForArchRuntimeCalls() {
     return SideEffects::CanTriggerGC();
@@ -5465,7 +5463,7 @@
   }
 
   bool NeedsEnvironment() const OVERRIDE {
-    return false;
+    return CanCallRuntime(check_kind_);
   }
 
   bool IsExactCheck() const { return check_kind_ == TypeCheckKind::kExactCheck; }
@@ -5476,11 +5474,13 @@
   bool MustDoNullCheck() const { return must_do_null_check_; }
   void ClearMustDoNullCheck() { must_do_null_check_ = false; }
 
+  static bool CanCallRuntime(TypeCheckKind check_kind) {
+    // Mips currently does runtime calls for any other checks.
+    return check_kind != TypeCheckKind::kExactCheck;
+  }
+
   static SideEffects SideEffectsForArchRuntimeCalls(TypeCheckKind check_kind) {
-    return (check_kind == TypeCheckKind::kExactCheck)
-        ? SideEffects::None()
-        // Mips currently does runtime calls for any other checks.
-        : SideEffects::CanTriggerGC();
+    return CanCallRuntime(check_kind) ? SideEffects::CanTriggerGC() : SideEffects::None();
   }
 
   DECLARE_INSTRUCTION(InstanceOf);
@@ -5605,8 +5605,8 @@
     SetRawInputAt(0, object);
   }
 
-  // Instruction may throw a Java exception, so we need an environment.
-  bool NeedsEnvironment() const OVERRIDE { return CanThrow(); }
+  // Instruction may go into runtime, so we need an environment.
+  bool NeedsEnvironment() const OVERRIDE { return true; }
 
   bool CanThrow() const OVERRIDE {
     // Verifier guarantees that monitor-exit cannot throw.
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 4871648..8e80961 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1055,6 +1055,9 @@
     key_value_store_->Put(
         OatHeader::kDebuggableKey,
         compiler_options_->debuggable_ ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+    key_value_store_->Put(
+        OatHeader::kExtractOnlyKey,
+        compiler_options_->IsExtractOnly() ? OatHeader::kTrueValue : OatHeader::kFalseValue);
   }
 
   // Parse the arguments from the command line. In case of an unrecognized option or impossible
@@ -1332,7 +1335,13 @@
         return false;
       }
 
-      {
+      if (compiler_options_->IsExtractOnly()) {
+        // ExtractOnly oat files only contain non-quickened DEX code and are
+        // therefore independent of the image file.
+        image_file_location_oat_checksum_ = 0u;
+        image_file_location_oat_data_begin_ = 0u;
+        image_patch_delta_ = 0;
+      } else {
         TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
         std::vector<gc::space::ImageSpace*> image_spaces =
             Runtime::Current()->GetHeap()->GetBootImageSpaces();
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index 52ccbee..5345b89 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -146,43 +146,13 @@
   }
 }
 
-void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
-  // BE CAREFUL ALLOCATING HERE INCLUDING USING LOG(...)
-  //
-  // If malloc calls abort, it will be holding its lock.
-  // If the handler tries to call malloc, it will deadlock.
-  VLOG(signals) << "Handling fault";
-  if (IsInGeneratedCode(info, context, true)) {
-    VLOG(signals) << "in generated code, looking for handler";
-    for (const auto& handler : generated_code_handlers_) {
-      VLOG(signals) << "invoking Action on handler " << handler;
-      if (handler->Action(sig, info, context)) {
-#ifdef TEST_NESTED_SIGNAL
-        // In test mode we want to fall through to stack trace handler
-        // on every signal (in reality this will cause a crash on the first
-        // signal).
-        break;
-#else
-        // We have handled a signal so it's time to return from the
-        // signal handler to the appropriate place.
-        return;
-#endif
-      }
-    }
-  }
-
-  // We hit a signal we didn't handle.  This might be something for which
-  // we can give more information about so call all registered handlers to see
-  // if it is.
-
+bool FaultManager::HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context) {
   Thread* self = Thread::Current();
 
-  // If ART is not running, or the thread is not attached to ART pass the
-  // signal on to the next handler in the chain.
-  if (self == nullptr || Runtime::Current() == nullptr || !Runtime::Current()->IsStarted()) {
-    InvokeUserSignalHandler(sig, info, context);
-    return;
-  }
+  DCHECK(self != nullptr);
+  DCHECK(Runtime::Current() != nullptr);
+  DCHECK(Runtime::Current()->IsStarted());
+
   // Now set up the nested signal handler.
 
   // TODO: add SIGSEGV back to the nested signals when we can handle running out stack gracefully.
@@ -231,6 +201,7 @@
       break;
     }
   }
+
   if (success) {
     // Save the current state and call the handlers.  If anything causes a signal
     // our nested signal handler will be invoked and this will longjmp to the saved
@@ -247,7 +218,7 @@
             }
           }
           fault_manager.Init();
-          return;
+          return true;
         }
       }
     } else {
@@ -265,6 +236,40 @@
 
   // Now put the fault manager back in place.
   fault_manager.Init();
+  return false;
+}
+
+void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
+  // BE CAREFUL ALLOCATING HERE INCLUDING USING LOG(...)
+  //
+  // If malloc calls abort, it will be holding its lock.
+  // If the handler tries to call malloc, it will deadlock.
+  VLOG(signals) << "Handling fault";
+  if (IsInGeneratedCode(info, context, true)) {
+    VLOG(signals) << "in generated code, looking for handler";
+    for (const auto& handler : generated_code_handlers_) {
+      VLOG(signals) << "invoking Action on handler " << handler;
+      if (handler->Action(sig, info, context)) {
+#ifdef TEST_NESTED_SIGNAL
+        // In test mode we want to fall through to stack trace handler
+        // on every signal (in reality this will cause a crash on the first
+        // signal).
+        break;
+#else
+        // We have handled a signal so it's time to return from the
+        // signal handler to the appropriate place.
+        return;
+#endif
+      }
+    }
+
+    // We hit a signal we didn't handle.  This might be something for which
+    // we can give more information about so call all registered handlers to see
+    // if it is.
+    if (HandleFaultByOtherHandlers(sig, info, context)) {
+        return;
+    }
+  }
 
   // Set a breakpoint in this function to catch unhandled signals.
   art_sigsegv_fault();
diff --git a/runtime/fault_handler.h b/runtime/fault_handler.h
index 3b03a14..625b1e8 100644
--- a/runtime/fault_handler.h
+++ b/runtime/fault_handler.h
@@ -62,6 +62,10 @@
                          NO_THREAD_SAFETY_ANALYSIS;
 
  private:
+  // The HandleFaultByOtherHandlers function is only called by HandleFault function for generated code.
+  bool HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context)
+                                  NO_THREAD_SAFETY_ANALYSIS;
+
   std::vector<FaultHandler*> generated_code_handlers_;
   std::vector<FaultHandler*> other_handlers_;
   struct sigaction oldaction_;
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index b0e5fde..f325949 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -321,8 +321,8 @@
           code_size);
     }
 
-    __builtin___clear_cache(reinterpret_cast<char*>(code_ptr),
-                            reinterpret_cast<char*>(code_ptr + code_size));
+    FlushInstructionCache(reinterpret_cast<char*>(code_ptr),
+                          reinterpret_cast<char*>(code_ptr + code_size));
     number_of_compilations_++;
   }
   // We need to update the entry point in the runnable state for the instrumentation.
diff --git a/runtime/jni_internal.h b/runtime/jni_internal.h
index 3429962..b829934 100644
--- a/runtime/jni_internal.h
+++ b/runtime/jni_internal.h
@@ -24,6 +24,13 @@
 #define NATIVE_METHOD(className, functionName, signature) \
   { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
 #endif
+
+// TODO: Can we do a better job of supporting overloading ?
+#ifndef OVERLOADED_NATIVE_METHOD
+#define OVERLOADED_NATIVE_METHOD(className, functionName, signature, identifier) \
+    { #functionName, signature, reinterpret_cast<void*>(className ## _ ## identifier) }
+#endif
+
 #define REGISTER_NATIVE_METHODS(jni_class_name) \
   RegisterNativeMethods(env, jni_class_name, gMethods, arraysize(gMethods))
 
diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc
index 49cacdf..2a36059 100644
--- a/runtime/native/java_lang_Object.cc
+++ b/runtime/native/java_lang_Object.cc
@@ -20,10 +20,6 @@
 #include "mirror/object-inl.h"
 #include "scoped_fast_native_object_access.h"
 
-// TODO: better support for overloading.
-#undef NATIVE_METHOD
-#define NATIVE_METHOD(className, functionName, signature, identifier) \
-    { #functionName, signature, reinterpret_cast<void*>(className ## _ ## identifier) }
 
 namespace art {
 
@@ -58,11 +54,11 @@
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(Object, internalClone, "!()Ljava/lang/Object;", internalClone),
-  NATIVE_METHOD(Object, notify, "!()V", notify),
-  NATIVE_METHOD(Object, notifyAll, "!()V", notifyAll),
-  NATIVE_METHOD(Object, wait, "!()V", wait),
-  NATIVE_METHOD(Object, wait, "!(JI)V", waitJI),
+  NATIVE_METHOD(Object, internalClone, "!()Ljava/lang/Object;"),
+  NATIVE_METHOD(Object, notify, "!()V"),
+  NATIVE_METHOD(Object, notifyAll, "!()V"),
+  OVERLOADED_NATIVE_METHOD(Object, wait, "!()V", wait),
+  OVERLOADED_NATIVE_METHOD(Object, wait, "!(JI)V", waitJI),
 };
 
 void register_java_lang_Object(JNIEnv* env) {
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index 8a2c7e4..6ffd476 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -231,58 +231,58 @@
   memset(reinterpret_cast<void*>(static_cast<uintptr_t>(address)), value, bytes);
 }
 
-static jbyte Unsafe_getByte$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
+static jbyte Unsafe_getByteJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
   return *reinterpret_cast<jbyte*>(address);
 }
 
-static void Unsafe_putByte$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jbyte value) {
+static void Unsafe_putByteJB(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jbyte value) {
   *reinterpret_cast<jbyte*>(address) = value;
 }
 
-static jshort Unsafe_getShort$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
+static jshort Unsafe_getShortJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
   return *reinterpret_cast<jshort*>(address);
 }
 
-static void Unsafe_putShort$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jshort value) {
+static void Unsafe_putShortJS(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jshort value) {
   *reinterpret_cast<jshort*>(address) = value;
 }
 
-static jchar Unsafe_getChar$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
+static jchar Unsafe_getCharJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
   return *reinterpret_cast<jchar*>(address);
 }
 
-static void Unsafe_putChar$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jchar value) {
+static void Unsafe_putCharJC(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jchar value) {
   *reinterpret_cast<jchar*>(address) = value;
 }
 
-static jint Unsafe_getInt$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
+static jint Unsafe_getIntJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
   return *reinterpret_cast<jint*>(address);
 }
 
-static void Unsafe_putInt$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jint value) {
+static void Unsafe_putIntJI(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jint value) {
   *reinterpret_cast<jint*>(address) = value;
 }
 
-static jlong Unsafe_getLong$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
+static jlong Unsafe_getLongJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
   return *reinterpret_cast<jlong*>(address);
 }
 
-static void Unsafe_putLong$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jlong value) {
+static void Unsafe_putLongJJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jlong value) {
   *reinterpret_cast<jlong*>(address) = value;
 }
 
-static jfloat Unsafe_getFloat$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
+static jfloat Unsafe_getFloatJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
   return *reinterpret_cast<jfloat*>(address);
 }
 
-static void Unsafe_putFloat$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jfloat value) {
+static void Unsafe_putFloatJF(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jfloat value) {
   *reinterpret_cast<jfloat*>(address) = value;
 }
-static jdouble Unsafe_getDouble$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
+static jdouble Unsafe_getDoubleJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
   return *reinterpret_cast<jdouble*>(address);
 }
 
-static void Unsafe_putDouble$(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jdouble value) {
+static void Unsafe_putDoubleJD(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jdouble value) {
   *reinterpret_cast<jdouble*>(address) = value;
 }
 
@@ -499,24 +499,11 @@
   NATIVE_METHOD(Unsafe, allocateMemory, "!(J)J"),
   NATIVE_METHOD(Unsafe, freeMemory, "!(J)V"),
   NATIVE_METHOD(Unsafe, setMemory, "!(JJB)V"),
-  NATIVE_METHOD(Unsafe, getByte$, "!(J)B"),
-  NATIVE_METHOD(Unsafe, putByte$, "!(JB)V"),
-  NATIVE_METHOD(Unsafe, getShort$, "!(J)S"),
-  NATIVE_METHOD(Unsafe, putShort$, "!(JS)V"),
-  NATIVE_METHOD(Unsafe, getChar$, "!(J)C"),
-  NATIVE_METHOD(Unsafe, putChar$, "!(JC)V"),
-  NATIVE_METHOD(Unsafe, getInt$, "!(J)I"),
-  NATIVE_METHOD(Unsafe, putInt$, "!(JI)V"),
-  NATIVE_METHOD(Unsafe, getLong$, "!(J)J"),
-  NATIVE_METHOD(Unsafe, putLong$, "!(JJ)V"),
-  NATIVE_METHOD(Unsafe, getFloat$, "!(J)F"),
-  NATIVE_METHOD(Unsafe, putFloat$, "!(JF)V"),
-  NATIVE_METHOD(Unsafe, getDouble$, "!(J)D"),
-  NATIVE_METHOD(Unsafe, putDouble$, "!(JD)V"),
   NATIVE_METHOD(Unsafe, copyMemory, "!(JJJ)V"),
   NATIVE_METHOD(Unsafe, copyMemoryToPrimitiveArray, "!(JLjava/lang/Object;JJ)V"),
   NATIVE_METHOD(Unsafe, copyMemoryFromPrimitiveArray, "!(Ljava/lang/Object;JJJ)V"),
   NATIVE_METHOD(Unsafe, getBoolean, "!(Ljava/lang/Object;J)Z"),
+
   NATIVE_METHOD(Unsafe, getByte, "!(Ljava/lang/Object;J)B"),
   NATIVE_METHOD(Unsafe, getChar, "!(Ljava/lang/Object;J)C"),
   NATIVE_METHOD(Unsafe, getShort, "!(Ljava/lang/Object;J)S"),
@@ -528,6 +515,23 @@
   NATIVE_METHOD(Unsafe, putShort, "!(Ljava/lang/Object;JS)V"),
   NATIVE_METHOD(Unsafe, putFloat, "!(Ljava/lang/Object;JF)V"),
   NATIVE_METHOD(Unsafe, putDouble, "!(Ljava/lang/Object;JD)V"),
+
+  // Each of the getFoo variants are overloaded with a call that operates
+  // directively on a native pointer.
+  OVERLOADED_NATIVE_METHOD(Unsafe, getByte, "!(J)B", getByteJ),
+  OVERLOADED_NATIVE_METHOD(Unsafe, getChar, "!(J)C", getCharJ),
+  OVERLOADED_NATIVE_METHOD(Unsafe, getShort, "!(J)S", getShortJ),
+  OVERLOADED_NATIVE_METHOD(Unsafe, getInt, "!(J)I", getIntJ),
+  OVERLOADED_NATIVE_METHOD(Unsafe, getLong, "!(J)J", getLongJ),
+  OVERLOADED_NATIVE_METHOD(Unsafe, getFloat, "!(J)F", getFloatJ),
+  OVERLOADED_NATIVE_METHOD(Unsafe, getDouble, "!(J)D", getDoubleJ),
+  OVERLOADED_NATIVE_METHOD(Unsafe, putByte, "!(JB)V", putByteJB),
+  OVERLOADED_NATIVE_METHOD(Unsafe, putChar, "!(JC)V", putCharJC),
+  OVERLOADED_NATIVE_METHOD(Unsafe, putShort, "!(JS)V", putShortJS),
+  OVERLOADED_NATIVE_METHOD(Unsafe, putInt, "!(JI)V", putIntJI),
+  OVERLOADED_NATIVE_METHOD(Unsafe, putLong, "!(JJ)V", putLongJJ),
+  OVERLOADED_NATIVE_METHOD(Unsafe, putFloat, "!(JF)V", putFloatJF),
+  OVERLOADED_NATIVE_METHOD(Unsafe, putDouble, "!(JD)V", putDoubleJD),
 };
 
 void register_sun_misc_Unsafe(JNIEnv* env) {
diff --git a/runtime/oat.cc b/runtime/oat.cc
index c787b9a..4948558 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -466,6 +466,10 @@
   return IsKeyEnabled(OatHeader::kDebuggableKey);
 }
 
+bool OatHeader::IsExtractOnly() const {
+  return IsKeyEnabled(OatHeader::kExtractOnlyKey);
+}
+
 bool OatHeader::IsKeyEnabled(const char* key) const {
   const char* key_value = GetStoreValueByKey(key);
   return (key_value != nullptr && strncmp(key_value, kTrueValue, sizeof(kTrueValue)) == 0);
diff --git a/runtime/oat.h b/runtime/oat.h
index 989e3f9..fde386f 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -38,6 +38,7 @@
   static constexpr const char* kDex2OatHostKey = "dex2oat-host";
   static constexpr const char* kPicKey = "pic";
   static constexpr const char* kDebuggableKey = "debuggable";
+  static constexpr const char* kExtractOnlyKey = "extract-only";
   static constexpr const char* kClassPathKey = "classpath";
   static constexpr const char* kBootClassPath = "bootclasspath";
 
@@ -106,6 +107,7 @@
   size_t GetHeaderSize() const;
   bool IsPic() const;
   bool IsDebuggable() const;
+  bool IsExtractOnly() const;
 
  private:
   OatHeader(InstructionSet instruction_set,
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 8f321a0..f912598 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -1221,6 +1221,10 @@
   return GetOatHeader().IsDebuggable();
 }
 
+bool OatFile::IsExtractOnly() const {
+  return GetOatHeader().IsExtractOnly();
+}
+
 static constexpr char kDexClassPathEncodingSeparator = '*';
 
 std::string OatFile::EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files) {
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index dbd7541..bcc2d33 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -85,6 +85,8 @@
   // Indicates whether the oat file was compiled with full debugging capability.
   bool IsDebuggable() const;
 
+  bool IsExtractOnly() const;
+
   const std::string& GetLocation() const {
     return location_;
   }
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index a8f84a2..262c932 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -461,6 +461,23 @@
     }
   }
 
+  if (file.IsExtractOnly()) {
+    VLOG(oat) << "Oat file is extract-only. Image checksum test skipped.";
+    if (kIsDebugBuild) {
+      // Sanity check that no classes have compiled code. Does not test that
+      // the DEX code has not been quickened.
+      std::string error_msg;
+      for (const OatFile::OatDexFile* current : file.GetOatDexFiles()) {
+        std::unique_ptr<const DexFile> dex_file = current->OpenDexFile(&error_msg);
+        DCHECK(dex_file != nullptr);
+        for (size_t i = 0, e = dex_file->NumClassDefs(); i < e; ++i) {
+          DCHECK_EQ(current->GetOatClass(i).GetType(), kOatClassNoneCompiled);
+        }
+      }
+    }
+    return false;
+  }
+
   // Verify the image checksum
   const ImageInfo* image_info = GetImageInfo();
   if (image_info == nullptr) {
@@ -486,7 +503,10 @@
     return false;
   }
 
-  if (file.IsPic()) {
+  if (file.IsPic() || file.IsExtractOnly()) {
+    // Oat files compiled in PIC mode do not require relocation and extract-only
+    // oat files do not contain any compiled code. Skip the relocation test.
+    VLOG(oat) << "Oat relocation test skipped.";
     return true;
   }
 
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 25dcbe4..83d4457 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -259,6 +259,26 @@
     EXPECT_TRUE(odex_file->IsPic());
   }
 
+  void GenerateExtractOnlyOdexForTest(const std::string& dex_location,
+                                          const std::string& odex_location) {
+    std::vector<std::string> args;
+    args.push_back("--dex-file=" + dex_location);
+    args.push_back("--oat-file=" + odex_location);
+    args.push_back("--compiler-filter=verify-at-runtime");
+    std::string error_msg;
+    ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
+
+    // Verify the odex file was generated as expected.
+    std::unique_ptr<OatFile> odex_file(OatFile::Open(
+        odex_location.c_str(), odex_location.c_str(), nullptr, nullptr,
+        false, dex_location.c_str(), &error_msg));
+    ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
+    EXPECT_TRUE(odex_file->IsExtractOnly());
+    EXPECT_EQ(odex_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0u);
+    EXPECT_EQ(odex_file->GetOatHeader().GetImageFileLocationOatDataBegin(), 0u);
+    EXPECT_EQ(odex_file->GetOatHeader().GetImagePatchDelta(), 0);
+}
+
  private:
   // Reserve memory around where the image will be loaded so other memory
   // won't conflict when it comes time to load the image.
@@ -488,6 +508,32 @@
   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
 }
 
+// Case: We have a DEX file and an extract-only ODEX file out of date relative
+//       to the DEX file.
+// Expect: The status is kDex2OatNeeded.
+TEST_F(OatFileAssistantTest, ExtractOnlyOdexOutOfDate) {
+  std::string dex_location = GetScratchDir() + "/ExtractOnlyOdexOutOfDate.jar";
+  std::string odex_location = GetOdexDir() + "/ExtractOnlyOdexOutOfDate.odex";
+
+  // We create a dex, generate an oat for it, then overwrite the dex with a
+  // different dex to make the oat out of date.
+  Copy(GetDexSrc1(), dex_location);
+  GenerateExtractOnlyOdexForTest(dex_location.c_str(), odex_location.c_str());
+  Copy(GetDexSrc2(), dex_location);
+
+  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
+
+  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
+  EXPECT_TRUE(oat_file_assistant.OdexFileExists());
+  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
+  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
+  EXPECT_FALSE(oat_file_assistant.OatFileExists());
+  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
+  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
+  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+}
+
 // Case: We have a DEX file and an ODEX file, but no OAT file.
 // Expect: The status is kPatchOatNeeded.
 TEST_F(OatFileAssistantTest, DexOdexNoOat) {
@@ -784,6 +830,31 @@
   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
 }
 
+// Case: We have a DEX file and a ExtractOnly ODEX file, but no OAT file.
+// Expect: The status is kNoDexOptNeeded, because ExtractOnly contains no code.
+TEST_F(OatFileAssistantTest, DexExtractOnlyOdexNoOat) {
+  std::string dex_location = GetScratchDir() + "/DexExtractOnlyOdexNoOat.jar";
+  std::string odex_location = GetOdexDir() + "/DexExtractOnlyOdexNoOat.odex";
+
+  // Create the dex and odex files
+  Copy(GetDexSrc1(), dex_location);
+  GenerateExtractOnlyOdexForTest(dex_location, odex_location);
+
+  // Verify the status.
+  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
+
+  EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
+
+  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
+  EXPECT_TRUE(oat_file_assistant.OdexFileExists());
+  EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
+  EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate());
+  EXPECT_FALSE(oat_file_assistant.OatFileExists());
+  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
+  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
+  EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
+}
+
 // Case: We have a DEX file and up-to-date OAT file for it.
 // Expect: We should load an executable dex file.
 TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
diff --git a/runtime/utils.h b/runtime/utils.h
index 153749e..c00db11 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -388,6 +388,24 @@
 // Sleep forever and never come back.
 NO_RETURN void SleepForever();
 
+inline void FlushInstructionCache(char* begin, char* end) {
+  // Only use __builtin___clear_cache with Clang or with GCC >= 4.3.0
+  // (__builtin___clear_cache was introduced in GCC 4.3.0).
+#if defined(__clang__) || GCC_VERSION >= 40300
+  __builtin___clear_cache(begin, end);
+#else
+  // Only warn on non-Intel platforms, as x86 and x86-64 do not need
+  // cache flush instructions, as long as the "code uses the same
+  // linear address for modifying and fetching the instruction". See
+  // "Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+  // Volume 3A: System Programming Guide, Part 1", section 11.6
+  // "Self-Modifying Code".
+#if !defined(__i386__) && !defined(__x86_64__)
+  UNIMPLEMENTED(WARNING) << "cache flush";
+#endif
+#endif
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_UTILS_H_
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 5f40123..56154c6 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2076,7 +2076,7 @@
           } else if (reg_type.IsConflict()) {
             Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning register with conflict";
           } else if (reg_type.IsUninitializedTypes()) {
-            Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "returning uninitialized object '"
+            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning uninitialized object '"
                                               << reg_type << "'";
           } else if (!reg_type.IsReferenceTypes()) {
             // We really do expect a reference here.
@@ -2233,7 +2233,6 @@
       opcode_flags &= ~Instruction::kThrow;
       work_line_->PopMonitor(this, inst->VRegA_11x());
       break;
-
     case Instruction::CHECK_CAST:
     case Instruction::INSTANCE_OF: {
       /*
@@ -2279,6 +2278,14 @@
         } else {
           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "instance-of on non-reference in v" << orig_type_reg;
         }
+      } else if (orig_type.IsUninitializedTypes()) {
+        if (is_checkcast) {
+          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "check-cast on uninitialized reference in v"
+                                            << orig_type_reg;
+        } else {
+          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "instance-of on uninitialized reference in v"
+                                            << orig_type_reg;
+        }
       } else {
         if (is_checkcast) {
           work_line_->SetRegisterType<LockOp::kKeep>(this, inst->VRegA_21c(), res_type);
@@ -2373,8 +2380,12 @@
     case Instruction::THROW: {
       const RegType& res_type = work_line_->GetRegisterType(this, inst->VRegA_11x());
       if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(res_type)) {
-        Fail(res_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS : VERIFY_ERROR_BAD_CLASS_SOFT)
-            << "thrown class " << res_type << " not instanceof Throwable";
+        if (res_type.IsUninitializedTypes()) {
+          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "thrown exception not initialized";
+        } else {
+          Fail(res_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS : VERIFY_ERROR_BAD_CLASS_SOFT)
+                << "thrown class " << res_type << " not instanceof Throwable";
+        }
       }
       break;
     }
@@ -3596,6 +3607,7 @@
           } else {
             const RegType& exception = ResolveClassAndCheckAccess(iterator.GetHandlerTypeIndex());
             if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(exception)) {
+              DCHECK(!exception.IsUninitializedTypes());  // Comes from dex, shouldn't be uninit.
               if (exception.IsUnresolvedTypes()) {
                 // We don't know enough about the type. Fail here and let runtime handle it.
                 Fail(VERIFY_ERROR_NO_CLASS) << "unresolved exception class " << exception;
@@ -3786,7 +3798,8 @@
       CHECK(have_pending_hard_failure_);
       return nullptr;
     }
-    if (actual_arg_type.IsUninitializedReference()) {
+    bool is_init = false;
+    if (actual_arg_type.IsUninitializedTypes()) {
       if (res_method) {
         if (!res_method->IsConstructor()) {
           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "'this' arg must be initialized";
@@ -3800,8 +3813,12 @@
           return nullptr;
         }
       }
+      is_init = true;
     }
-    if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) {
+    const RegType& adjusted_type = is_init
+                                       ? GetRegTypeCache()->FromUninitialized(actual_arg_type)
+                                       : actual_arg_type;
+    if (method_type != METHOD_INTERFACE && !adjusted_type.IsZero()) {
       const RegType* res_method_class;
       // Miranda methods have the declaring interface as their declaring class, not the abstract
       // class. It would be wrong to use this for the type check (interface type checks are
@@ -3819,10 +3836,12 @@
             dex_file_->StringByTypeIdx(class_idx),
             false);
       }
-      if (!res_method_class->IsAssignableFrom(actual_arg_type)) {
-        Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS:
-            VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
-                << "' not instance of '" << *res_method_class << "'";
+      if (!res_method_class->IsAssignableFrom(adjusted_type)) {
+        Fail(adjusted_type.IsUnresolvedTypes()
+                 ? VERIFY_ERROR_NO_CLASS
+                 : VERIFY_ERROR_BAD_CLASS_SOFT)
+            << "'this' argument '" << actual_arg_type << "' not instance of '"
+            << *res_method_class << "'";
         // Continue on soft failures. We need to find possible hard failures to avoid problems in
         // the compiler.
         if (have_pending_hard_failure_) {
@@ -4083,7 +4102,8 @@
    * For an interface class, we don't do the full interface merge (see JoinClass), so we can't do a
    * rigorous check here (which is okay since we have to do it at runtime).
    */
-  if (actual_arg_type.IsUninitializedReference() && !res_method->IsConstructor()) {
+  // Note: given an uninitialized type, this should always fail. Constructors aren't virtual.
+  if (actual_arg_type.IsUninitializedTypes() && !res_method->IsConstructor()) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "'this' arg must be initialized";
     return nullptr;
   }
@@ -4093,8 +4113,11 @@
     const RegType& res_method_class =
         FromClass(klass->GetDescriptor(&temp), klass, klass->CannotBeAssignedFromOtherTypes());
     if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
-      Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS :
-          VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
+      Fail(actual_arg_type.IsUninitializedTypes()    // Just overcautious - should have never
+               ? VERIFY_ERROR_BAD_CLASS_HARD         // quickened this.
+               : actual_arg_type.IsUnresolvedTypes()
+                     ? VERIFY_ERROR_NO_CLASS
+                     : VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
           << "' not instance of '" << res_method_class << "'";
       return nullptr;
     }
@@ -4421,15 +4444,20 @@
     const RegType& field_klass =
         FromClass(dex_file_->GetFieldDeclaringClassDescriptor(field_id),
                   klass, klass->CannotBeAssignedFromOtherTypes());
-    if (obj_type.IsUninitializedTypes() &&
-        (!IsConstructor() || GetDeclaringClass().Equals(obj_type) ||
-            !field_klass.Equals(GetDeclaringClass()))) {
+    if (obj_type.IsUninitializedTypes()) {
       // Field accesses through uninitialized references are only allowable for constructors where
-      // the field is declared in this class
-      Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "cannot access instance field " << PrettyField(field)
-                                        << " of a not fully initialized object within the context"
-                                        << " of " << PrettyMethod(dex_method_idx_, *dex_file_);
-      return nullptr;
+      // the field is declared in this class.
+      // Note: this IsConstructor check is technically redundant, as UninitializedThis should only
+      //       appear in constructors.
+      if (!obj_type.IsUninitializedThisReference() ||
+          !IsConstructor() ||
+          !field_klass.Equals(GetDeclaringClass())) {
+        Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "cannot access instance field " << PrettyField(field)
+                                          << " of a not fully initialized object within the context"
+                                          << " 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
@@ -4452,7 +4480,18 @@
     field = GetStaticField(field_idx);
   } else {
     const RegType& object_type = work_line_->GetRegisterType(this, inst->VRegB_22c());
-    field = GetInstanceField(object_type, field_idx);
+
+    // One is not allowed to access fields on uninitialized references, except to write to
+    // fields in the constructor (before calling another constructor).
+    // GetInstanceField does an assignability check which will fail for uninitialized types.
+    // We thus modify the type if the uninitialized reference is a "this" reference (this also
+    // checks at the same time that we're verifying a constructor).
+    bool should_adjust = (kAccType == FieldAccessType::kAccPut) &&
+                         object_type.IsUninitializedThisReference();
+    const RegType& adjusted_type = should_adjust
+                                       ? GetRegTypeCache()->FromUninitialized(object_type)
+                                       : object_type;
+    field = GetInstanceField(adjusted_type, field_idx);
     if (UNLIKELY(have_pending_hard_failure_)) {
       return;
     }
diff --git a/runtime/verifier/reg_type-inl.h b/runtime/verifier/reg_type-inl.h
index 11a53e5..861db3c 100644
--- a/runtime/verifier/reg_type-inl.h
+++ b/runtime/verifier/reg_type-inl.h
@@ -93,6 +93,10 @@
         return true;  // All reference types can be assigned null.
       } else if (!rhs.IsReferenceTypes()) {
         return false;  // Expect rhs to be a reference type.
+      } else if (lhs.IsUninitializedTypes() || rhs.IsUninitializedTypes()) {
+        // Uninitialized types are only allowed to be assigned to themselves.
+        // TODO: Once we have a proper "reference" super type, this needs to be extended.
+        return false;
       } else if (lhs.IsJavaLangObject()) {
         return true;  // All reference types can be assigned to Object.
       } else if (!strict && !lhs.IsUnresolvedTypes() && lhs.GetClass()->IsInterface()) {
diff --git a/runtime/verifier/register_line-inl.h b/runtime/verifier/register_line-inl.h
index 57fb701..08f85b3 100644
--- a/runtime/verifier/register_line-inl.h
+++ b/runtime/verifier/register_line-inl.h
@@ -147,6 +147,9 @@
     if (!check_type.IsNonZeroReferenceTypes() || !src_type.IsNonZeroReferenceTypes()) {
       // Hard fail if one of the types is primitive, since they are concretely known.
       fail_type = VERIFY_ERROR_BAD_CLASS_HARD;
+    } else if (check_type.IsUninitializedTypes() || src_type.IsUninitializedTypes()) {
+      // Hard fail for uninitialized types, which don't match anything but themselves.
+      fail_type = VERIFY_ERROR_BAD_CLASS_HARD;
     } else if (check_type.IsUnresolvedTypes() || src_type.IsUnresolvedTypes()) {
       fail_type = VERIFY_ERROR_NO_CLASS;
     } else {
diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc
index 1337442..82e1fc8 100644
--- a/test/117-nopatchoat/nopatchoat.cc
+++ b/test/117-nopatchoat/nopatchoat.cc
@@ -46,7 +46,7 @@
     return oat_dex_file != nullptr && oat_dex_file->GetOatFile()->IsExecutable();
   }
 
-  static bool isPic(jclass cls) {
+  static bool needsRelocation(jclass cls) {
     const OatFile::OatDexFile* oat_dex_file = getOatDexFile(cls);
 
     if (oat_dex_file == nullptr) {
@@ -54,7 +54,7 @@
     }
 
     const OatFile* oat_file = oat_dex_file->GetOatFile();
-    return oat_file->IsPic();
+    return !oat_file->IsPic() && !oat_file->IsExtractOnly();
   }
 };
 
@@ -66,8 +66,8 @@
   return NoPatchoatTest::hasExecutableOat(cls);
 }
 
-extern "C" JNIEXPORT jboolean JNICALL Java_Main_isPic(JNIEnv*, jclass cls) {
-  return NoPatchoatTest::isPic(cls);
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_needsRelocation(JNIEnv*, jclass cls) {
+  return NoPatchoatTest::needsRelocation(cls);
 }
 
 }  // namespace art
diff --git a/test/117-nopatchoat/src/Main.java b/test/117-nopatchoat/src/Main.java
index 425cf48..816eb17 100644
--- a/test/117-nopatchoat/src/Main.java
+++ b/test/117-nopatchoat/src/Main.java
@@ -22,9 +22,9 @@
     // ANDROID_DATA has been relocated, since a non-relocated oat file always has a 0 delta.
     // Hitting this condition should be rare and ideally we would prevent it from happening but
     // there is no way to do so without major changes to the run-test framework.
-    boolean executable_correct = (isPic() ?
-        hasExecutableOat() == true :
-        hasExecutableOat() == (isDex2OatEnabled() || isRelocationDeltaZero()));
+    boolean executable_correct = (needsRelocation() ?
+        hasExecutableOat() == (isDex2OatEnabled() || isRelocationDeltaZero()) :
+        hasExecutableOat() == true);
 
     System.out.println(
         "dex2oat & patchoat are " + ((isDex2OatEnabled()) ? "enabled" : "disabled") +
@@ -49,7 +49,7 @@
 
   private native static boolean isDex2OatEnabled();
 
-  private native static boolean isPic();
+  private native static boolean needsRelocation();
 
   private native static boolean hasOatFile();
 
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index 2e66af5..73ce307 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -50,4 +50,12 @@
 b/21869691
 b/26143249
 b/26579108
+b/26594149 (1)
+b/26594149 (2)
+b/26594149 (3)
+b/26594149 (4)
+b/26594149 (5)
+b/26594149 (6)
+b/26594149 (7)
+b/26594149 (8)
 Done!
diff --git a/test/800-smali/smali/b_26594149_1.smali b/test/800-smali/smali/b_26594149_1.smali
new file mode 100644
index 0000000..c465859
--- /dev/null
+++ b/test/800-smali/smali/b_26594149_1.smali
@@ -0,0 +1,26 @@
+# 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 LB26594149_1;
+.super Ljava/lang/Object;
+
+.method public static run()V
+    .registers 2
+    new-instance v0, Ljava/lang/String;
+
+    # Illegal operation.
+    instance-of v1, v0, Ljava/lang/String;
+
+    return-void
+  .end method
diff --git a/test/800-smali/smali/b_26594149_2.smali b/test/800-smali/smali/b_26594149_2.smali
new file mode 100644
index 0000000..765afe2
--- /dev/null
+++ b/test/800-smali/smali/b_26594149_2.smali
@@ -0,0 +1,26 @@
+# 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 LB26594149_2;
+.super Ljava/lang/Object;
+
+.method public static run()V
+    .registers 2
+    new-instance v0, Ljava/lang/String;
+
+    # Illegal operation.
+    check-cast v0, Ljava/lang/String;
+
+    return-void
+  .end method
diff --git a/test/800-smali/smali/b_26594149_3.smali b/test/800-smali/smali/b_26594149_3.smali
new file mode 100644
index 0000000..42b5675
--- /dev/null
+++ b/test/800-smali/smali/b_26594149_3.smali
@@ -0,0 +1,28 @@
+# 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 LB26594149_3;
+.super Ljava/lang/Object;
+
+.field public static field:Ljava/lang/String;
+
+.method public static run()V
+    .registers 2
+    new-instance v0, Ljava/lang/String;
+
+    # Illegal operation.
+    sput-object v0, LB26594149_3;->field:Ljava/lang/String;
+
+    return-void
+  .end method
diff --git a/test/800-smali/smali/b_26594149_4.smali b/test/800-smali/smali/b_26594149_4.smali
new file mode 100644
index 0000000..5b2f99b
--- /dev/null
+++ b/test/800-smali/smali/b_26594149_4.smali
@@ -0,0 +1,38 @@
+# 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 LB26594149_4;
+.super Ljava/lang/Object;
+
+.field public field:Ljava/lang/String;
+
+.method public constructor <init>()V
+    .registers 4
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
+.method public static run()V
+    .registers 4
+
+    new-instance v1, LB26594149_4;
+    invoke-direct {v1}, LB26594149_4;-><init>()V
+
+    new-instance v0, Ljava/lang/String;
+
+    # Illegal operation.
+    iput-object v0, v1, LB26594149_4;->field:Ljava/lang/String;
+
+    return-void
+  .end method
diff --git a/test/800-smali/smali/b_26594149_5.smali b/test/800-smali/smali/b_26594149_5.smali
new file mode 100644
index 0000000..27d6255
--- /dev/null
+++ b/test/800-smali/smali/b_26594149_5.smali
@@ -0,0 +1,28 @@
+# 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 LB26594149_5;
+.super Ljava/lang/Object;
+
+.method public static run()V
+    .registers 4
+
+    new-instance v0, Ljava/lang/Object;
+
+    # Allowed operation on uninitialized objects.
+    monitor-enter v0
+    monitor-exit v0
+
+    return-void
+  .end method
diff --git a/test/800-smali/smali/b_26594149_6.smali b/test/800-smali/smali/b_26594149_6.smali
new file mode 100644
index 0000000..8d26ee8
--- /dev/null
+++ b/test/800-smali/smali/b_26594149_6.smali
@@ -0,0 +1,24 @@
+# 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 LB26594149_6;
+.super Ljava/lang/Object;
+
+.method public static run()V
+    .registers 4
+
+    new-instance v0, Ljava/lang/Exception;
+    throw v0
+
+  .end method
diff --git a/test/800-smali/smali/b_26594149_7.smali b/test/800-smali/smali/b_26594149_7.smali
new file mode 100644
index 0000000..f624d1a
--- /dev/null
+++ b/test/800-smali/smali/b_26594149_7.smali
@@ -0,0 +1,30 @@
+# 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 LB26594149_7;
+.super Ljava/lang/Object;
+
+.method private static foo(Ljava/lang/Object;)V
+    .registers 1
+    return-void
+.end method
+
+.method public static run()V
+    .registers 4
+
+    new-instance v0, Ljava/lang/Object;
+    invoke-static {v0}, LB26594149_7;->foo(Ljava/lang/Object;)V
+    return-void
+
+  .end method
diff --git a/test/800-smali/smali/b_26594149_8.smali b/test/800-smali/smali/b_26594149_8.smali
new file mode 100644
index 0000000..e366de4
--- /dev/null
+++ b/test/800-smali/smali/b_26594149_8.smali
@@ -0,0 +1,24 @@
+# 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 LB26594149_8;
+.super Ljava/lang/Object;
+
+.method public static run()Ljava/lang/Object;
+    .registers 4
+
+    new-instance v0, Ljava/lang/Object;
+    return-object v0
+
+  .end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 38aa58d..b0eff5d 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -145,6 +145,21 @@
                 new AbstractMethodError(), null));
         testCases.add(new TestCase("b/26579108", "B26579108", "run", null, new VerifyError(),
                 null));
+        testCases.add(new TestCase("b/26594149 (1)", "B26594149_1", "run", null, new VerifyError(),
+                null));
+        testCases.add(new TestCase("b/26594149 (2)", "B26594149_2", "run", null, new VerifyError(),
+                null));
+        testCases.add(new TestCase("b/26594149 (3)", "B26594149_3", "run", null, new VerifyError(),
+                null));
+        testCases.add(new TestCase("b/26594149 (4)", "B26594149_4", "run", null, new VerifyError(),
+                null));
+        testCases.add(new TestCase("b/26594149 (5)", "B26594149_5", "run", null, null, null));
+        testCases.add(new TestCase("b/26594149 (6)", "B26594149_6", "run", null, new VerifyError(),
+                null));
+        testCases.add(new TestCase("b/26594149 (7)", "B26594149_7", "run", null, new VerifyError(),
+                null));
+        testCases.add(new TestCase("b/26594149 (8)", "B26594149_8", "run", null, new VerifyError(),
+                null));
     }
 
     public void runTests() {
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index f0afba5..6d67f84 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -266,11 +266,5 @@
           "libcore.util.NativeAllocationRegistryTest#testNativeAllocationNoAllocatorAndNoSharedRegistry",
           "libcore.util.NativeAllocationRegistryTest#testNativeAllocationNoAllocatorAndSharedRegistry",
           "libcore.util.NativeAllocationRegistryTest#testNullArguments"]
-},
-{
-  description: "Expected to fail",
-  bug: 26869497,
-  result: EXEC_FAILED,
-  names: ["libcore.java.util.CalendarTest#testSetHourOfDayInEuropeLondon"]
 }
 ]