Merge "Revert "Revert "Fix issue with proxy invocation on default methods"""
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 9acaa1d..3b643a3 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -4796,6 +4796,7 @@
         int32_t v = CodeGenerator::GetInt32ValueOf(value.GetConstant());
         __ movl(Address(base, offset), Immediate(v));
       } else {
+        DCHECK(value.IsRegister()) << value;
         __ movl(Address(base, offset), value.AsRegister<Register>());
       }
       break;
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 8eaac0b..561dcfb 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -728,6 +728,23 @@
       // This acts like GVN but with better aliasing analysis.
       heap_values[idx] = instruction;
     } else {
+      if (Primitive::PrimitiveKind(heap_value->GetType())
+              != Primitive::PrimitiveKind(instruction->GetType())) {
+        // The only situation where the same heap location has different type is when
+        // we do an array get from a null constant. In order to stay properly typed
+        // we do not merge the array gets.
+        if (kIsDebugBuild) {
+          DCHECK(heap_value->IsArrayGet()) << heap_value->DebugName();
+          DCHECK(instruction->IsArrayGet()) << instruction->DebugName();
+          HInstruction* array = instruction->AsArrayGet()->GetArray();
+          DCHECK(array->IsNullCheck()) << array->DebugName();
+          DCHECK(array->InputAt(0)->IsNullConstant()) << array->InputAt(0)->DebugName();
+          array = heap_value->AsArrayGet()->GetArray();
+          DCHECK(array->IsNullCheck()) << array->DebugName();
+          DCHECK(array->InputAt(0)->IsNullConstant()) << array->InputAt(0)->DebugName();
+        }
+        return;
+      }
       removed_loads_.push_back(instruction);
       substitute_instructions_for_loads_.push_back(heap_value);
       TryRemovingNullCheck(instruction);
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 64135d8..82ec0b7 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -1125,9 +1125,8 @@
     // r0: type_idx/return value, r1: ArtMethod*, r9: Thread::Current
     // r2, r3, r12: free.
 #if defined(USE_READ_BARRIER)
-    eor    r0, r0, r0                                         // Read barrier not supported here.
-    sub    r0, r0, #1                                         // Return -1.
-    bx     lr
+    mvn    r0, #0                                             // Read barrier not supported here.
+    bx     lr                                                 // Return -1.
 #endif
     ldr    r2, [r1, #ART_METHOD_DEX_CACHE_TYPES_OFFSET_32]    // Load dex cache resolved types array
                                                               // Load the class (r2)
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index e4c2558..65d5b46 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -1638,7 +1638,79 @@
     RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
 END art_quick_alloc_object_rosalloc
 
-GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB)
+// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB).
+ENTRY art_quick_alloc_object_tlab
+    // Fast path tlab allocation.
+    // x0: type_idx/return value, x1: ArtMethod*, xSELF(x19): Thread::Current
+    // x2-x7: free.
+#if defined(USE_READ_BARRIER)
+    mvn    x0, xzr                                            // Read barrier not supported here.
+    ret                                                       // Return -1.
+#endif
+    ldr    x2, [x1, #ART_METHOD_DEX_CACHE_TYPES_OFFSET_64]    // Load dex cache resolved types array
+                                                              // Load the class (x2)
+    ldr    w2, [x2, x0, lsl #COMPRESSED_REFERENCE_SIZE_SHIFT]
+    cbz    x2, .Lart_quick_alloc_object_tlab_slow_path        // Check null class
+                                                              // Check class status.
+    ldr    w3, [x2, #MIRROR_CLASS_STATUS_OFFSET]
+    cmp    x3, #MIRROR_CLASS_STATUS_INITIALIZED
+    bne    .Lart_quick_alloc_object_tlab_slow_path
+                                                              // Add a fake dependence from the
+                                                              // following access flag and size
+                                                              // loads to the status load.
+                                                              // This is to prevent those loads
+                                                              // from being reordered above the
+                                                              // status load and reading wrong
+                                                              // values (an alternative is to use
+                                                              // a load-acquire for the status).
+    eor    x3, x3, x3
+    add    x2, x2, x3
+                                                              // Check access flags has
+                                                              // kAccClassIsFinalizable.
+    ldr    w3, [x2, #MIRROR_CLASS_ACCESS_FLAGS_OFFSET]
+    tbnz   x3, #ACCESS_FLAGS_CLASS_IS_FINALIZABLE_BIT, .Lart_quick_alloc_object_tlab_slow_path
+                                                              // Load thread_local_pos (x4) and
+                                                              // thread_local_end (x5).
+    ldr    x4, [xSELF, #THREAD_LOCAL_POS_OFFSET]
+    ldr    x5, [xSELF, #THREAD_LOCAL_END_OFFSET]
+    sub    x6, x5, x4                                         // Compute the remaining buf size.
+    ldr    w7, [x2, #MIRROR_CLASS_OBJECT_SIZE_OFFSET]         // Load the object size (x7).
+    cmp    x7, x6                                             // Check if it fits. OK to do this
+                                                              // before rounding up the object size
+                                                              // assuming the buf size alignment.
+    bhi    .Lart_quick_alloc_object_tlab_slow_path
+    // "Point of no slow path". Won't go to the slow path from here on. OK to clobber x0 and x1.
+                                                              // Round up the object size by the
+                                                              // object alignment. (addr + 7) & ~7.
+    add    x7, x7, #OBJECT_ALIGNMENT_MASK
+    and    x7, x7, #OBJECT_ALIGNMENT_MASK_TOGGLED
+                                                              // Move old thread_local_pos to x0
+                                                              // for the return value.
+    mov    x0, x4
+    add    x5, x0, x7
+    str    x5, [xSELF, #THREAD_LOCAL_POS_OFFSET]              // Store new thread_local_pos.
+    ldr    x5, [xSELF, #THREAD_LOCAL_OBJECTS_OFFSET]          // Increment thread_local_objects.
+    add    x5, x5, #1
+    str    x5, [xSELF, #THREAD_LOCAL_OBJECTS_OFFSET]
+    POISON_HEAP_REF w2
+    str    w2, [x0, #MIRROR_OBJECT_CLASS_OFFSET]              // Store the class pointer.
+                                                              // Fence. This is "ish" not "ishst" so
+                                                              // that the code after this allocation
+                                                              // site will see the right values in
+                                                              // the fields of the class.
+                                                              // Alternatively we could use "ishst"
+                                                              // if we use load-acquire for the
+                                                              // class status load.)
+    dmb    ish
+    ret
+.Lart_quick_alloc_object_tlab_slow_path:
+    SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    // Save callee saves in case of GC.
+    mov    x2, xSELF                     // Pass Thread::Current.
+    bl     artAllocObjectFromCodeTLAB    // (uint32_t type_idx, Method* method, Thread*)
+    RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
+    RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER
+END art_quick_alloc_object_tlab
+
 GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_region_tlab, RegionTLAB)
 
     /*
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index d5f0dff..1f24f45 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -230,6 +230,9 @@
 #define ACCESS_FLAGS_CLASS_IS_FINALIZABLE 0x80000000
 ADD_TEST_EQ(static_cast<uint32_t>(ACCESS_FLAGS_CLASS_IS_FINALIZABLE),
             static_cast<uint32_t>(art::kAccClassIsFinalizable))
+#define ACCESS_FLAGS_CLASS_IS_FINALIZABLE_BIT 31
+ADD_TEST_EQ(static_cast<uint32_t>(ACCESS_FLAGS_CLASS_IS_FINALIZABLE),
+            static_cast<uint32_t>(1U << ACCESS_FLAGS_CLASS_IS_FINALIZABLE_BIT))
 
 // Array offsets.
 #define MIRROR_ARRAY_LENGTH_OFFSET      MIRROR_OBJECT_HEADER_SIZE
diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h
index ec4bf92..5237466 100644
--- a/runtime/gc/space/image_space_fs.h
+++ b/runtime/gc/space/image_space_fs.h
@@ -26,6 +26,7 @@
 #include "base/unix_file/fd_file.h"
 #include "globals.h"
 #include "os.h"
+#include "runtime.h"
 #include "utils.h"
 
 namespace art {
@@ -200,6 +201,11 @@
   impl::DeleteDirectoryContents(GetDalvikCacheOrDie(".", false), false);
   // Prune /data/dalvik-cache/<isa>.
   impl::DeleteDirectoryContents(GetDalvikCacheOrDie(GetInstructionSetString(isa), false), false);
+
+  // Be defensive. There should be a runtime created here, but this may be called in a test.
+  if (Runtime::Current() != nullptr) {
+    Runtime::Current()->SetPrunedDalvikCache(true);
+  }
 }
 
 // We write out an empty file to the zygote's ISA specific cache dir at the start of
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index f6b2f21..4ac28ae 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -622,6 +622,11 @@
   return env->NewStringUTF(GetInstructionSetString(kRuntimeISA));
 }
 
+static jboolean VMRuntime_didPruneDalvikCache(JNIEnv* env ATTRIBUTE_UNUSED,
+                                              jclass klass ATTRIBUTE_UNUSED) {
+  return Runtime::Current()->GetPrunedDalvikCache() ? JNI_TRUE : JNI_FALSE;
+}
+
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(VMRuntime, addressOf, "!(Ljava/lang/Object;)J"),
   NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"),
@@ -657,6 +662,7 @@
                 "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V"),
   NATIVE_METHOD(VMRuntime, isBootClassPathOnDisk, "(Ljava/lang/String;)Z"),
   NATIVE_METHOD(VMRuntime, getCurrentInstructionSet, "()Ljava/lang/String;"),
+  NATIVE_METHOD(VMRuntime, didPruneDalvikCache, "()Z"),
 };
 
 void register_dalvik_system_VMRuntime(JNIEnv* env) {
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index e57125b..3ec3826 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -477,4 +477,23 @@
   }
 }
 
+void OatFileManager::DumpForSigQuit(std::ostream& os) {
+  ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
+  std::vector<const OatFile*> boot_oat_files = GetBootOatFiles();
+  for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
+    if (ContainsElement(boot_oat_files, oat_file.get())) {
+      continue;
+    }
+    // Use "platform-default" if it's neither extract nor profile guided.
+    // Saying 'full' could be misleading if for example the platform uses
+    // compiler filters.
+    const char* status = oat_file->IsExtractOnly()
+        ? OatHeader::kExtractOnlyValue
+        : oat_file->IsProfileGuideCompiled()
+            ? OatHeader::kProfileGuideCompiledValue
+            : "platform-default";
+    os << oat_file->GetLocation() << ": " << status << "\n";
+  }
+}
+
 }  // namespace art
diff --git a/runtime/oat_file_manager.h b/runtime/oat_file_manager.h
index c508c4b..a541d10 100644
--- a/runtime/oat_file_manager.h
+++ b/runtime/oat_file_manager.h
@@ -108,6 +108,8 @@
       /*out*/ std::vector<std::string>* error_msgs)
       REQUIRES(!Locks::oat_file_manager_lock_, !Locks::mutator_lock_);
 
+  void DumpForSigQuit(std::ostream& os);
+
  private:
   // Check for duplicate class definitions of the given oat file against all open oat files.
   // Return true if there are any class definition collisions in the oat_file.
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c8085fb..901f2f55 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -207,7 +207,8 @@
       experimental_flags_(ExperimentalFlags::kNone),
       oat_file_manager_(nullptr),
       is_low_memory_mode_(false),
-      safe_mode_(false) {
+      safe_mode_(false),
+      pruned_dalvik_cache_(false) {
   CheckAsmSupportOffsetsAndSizes();
   std::fill(callee_save_methods_, callee_save_methods_ + arraysize(callee_save_methods_), 0u);
   interpreter::CheckInterpreterAsmConstants();
@@ -1362,6 +1363,7 @@
   GetInternTable()->DumpForSigQuit(os);
   GetJavaVM()->DumpForSigQuit(os);
   GetHeap()->DumpForSigQuit(os);
+  oat_file_manager_->DumpForSigQuit(os);
   if (GetJit() != nullptr) {
     GetJit()->DumpForSigQuit(os);
   } else {
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 8e99f80..aebfad7 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -610,6 +610,14 @@
     return dump_native_stack_on_sig_quit_;
   }
 
+  bool GetPrunedDalvikCache() const {
+    return pruned_dalvik_cache_;
+  }
+
+  void SetPrunedDalvikCache(bool pruned) {
+    pruned_dalvik_cache_ = pruned;
+  }
+
  private:
   static void InitPlatformSignalHandlers();
 
@@ -822,6 +830,9 @@
   // Whether threads should dump their native stack on SIGQUIT.
   bool dump_native_stack_on_sig_quit_;
 
+  // Whether the dalvik cache was pruned when initializing the runtime.
+  bool pruned_dalvik_cache_;
+
   DISALLOW_COPY_AND_ASSIGN(Runtime);
 };
 std::ostream& operator<<(std::ostream& os, const Runtime::CalleeSaveType& rhs);
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index afb11d3..a9ce056 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -133,22 +133,24 @@
       suspend_all_historam_.PrintConfidenceIntervals(os, 0.99, data);  // Dump time to suspend.
     }
   }
-  Dump(os, Runtime::Current()->GetDumpNativeStackOnSigQuit());
-  DumpUnattachedThreads(os);
+  bool dump_native_stack = Runtime::Current()->GetDumpNativeStackOnSigQuit();
+  Dump(os, dump_native_stack);
+  DumpUnattachedThreads(os, dump_native_stack);
 }
 
-static void DumpUnattachedThread(std::ostream& os, pid_t tid) NO_THREAD_SAFETY_ANALYSIS {
+static void DumpUnattachedThread(std::ostream& os, pid_t tid, bool dump_native_stack)
+    NO_THREAD_SAFETY_ANALYSIS {
   // TODO: No thread safety analysis as DumpState with a null thread won't access fields, should
   // refactor DumpState to avoid skipping analysis.
   Thread::DumpState(os, nullptr, tid);
   DumpKernelStack(os, tid, "  kernel: ", false);
-  if (kDumpUnattachedThreadNativeStack) {
+  if (dump_native_stack && kDumpUnattachedThreadNativeStack) {
     DumpNativeStack(os, tid, nullptr, "  native: ");
   }
   os << "\n";
 }
 
-void ThreadList::DumpUnattachedThreads(std::ostream& os) {
+void ThreadList::DumpUnattachedThreads(std::ostream& os, bool dump_native_stack) {
   DIR* d = opendir("/proc/self/task");
   if (!d) {
     return;
@@ -166,7 +168,7 @@
         contains = Contains(tid);
       }
       if (!contains) {
-        DumpUnattachedThread(os, tid);
+        DumpUnattachedThread(os, tid, dump_native_stack);
       }
     }
   }
diff --git a/runtime/thread_list.h b/runtime/thread_list.h
index 363cab8..f97ecd3 100644
--- a/runtime/thread_list.h
+++ b/runtime/thread_list.h
@@ -161,7 +161,7 @@
   size_t RunCheckpoint(Closure* checkpoint_function, bool includeSuspended)
       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
 
-  void DumpUnattachedThreads(std::ostream& os)
+  void DumpUnattachedThreads(std::ostream& os, bool dump_native_stack)
       REQUIRES(!Locks::thread_list_lock_);
 
   void SuspendAllDaemonThreadsForShutdown()
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 4019656..537d9c9 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3992,13 +3992,17 @@
       // TODO Can we verify anything else.
       if (class_idx == class_def_->class_idx_) {
         Fail(VERIFY_ERROR_CLASS_CHANGE) << "Cannot invoke-super on self as interface";
+        return nullptr;
       }
       // TODO Revisit whether we want to allow invoke-super on direct interfaces only like the JLS
       // does.
-      mirror::Class* this_class = GetDeclaringClass().GetClass();
-      if (!reference_class->IsAssignableFrom(this_class)) {
+      if (!GetDeclaringClass().HasClass()) {
+        Fail(VERIFY_ERROR_NO_CLASS) << "Unable to resolve the full class of 'this' used in an"
+                                    << "interface invoke-super";
+        return nullptr;
+      } else if (!reference_class->IsAssignableFrom(GetDeclaringClass().GetClass())) {
         Fail(VERIFY_ERROR_CLASS_CHANGE)
-            << "invoke-super in " << PrettyClass(this_class) << " in method "
+            << "invoke-super in " << PrettyClass(GetDeclaringClass().GetClass()) << " in method "
             << PrettyMethod(dex_method_idx_, *dex_file_) << " to method "
             << PrettyMethod(method_idx, *dex_file_) << " references "
             << "non-super-interface type " << PrettyClass(reference_class);
diff --git a/test/586-checker-null-array-get/expected.txt b/test/586-checker-null-array-get/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/586-checker-null-array-get/expected.txt
diff --git a/test/586-checker-null-array-get/info.txt b/test/586-checker-null-array-get/info.txt
new file mode 100644
index 0000000..81b42e9
--- /dev/null
+++ b/test/586-checker-null-array-get/info.txt
@@ -0,0 +1,3 @@
+Regression test for the load store elimination of optimizing
+that used to merge two array gets that have the same inputs but
+not the same type. Note that this only happens if the array is null.
diff --git a/test/586-checker-null-array-get/src/Main.java b/test/586-checker-null-array-get/src/Main.java
new file mode 100644
index 0000000..4b03ff2
--- /dev/null
+++ b/test/586-checker-null-array-get/src/Main.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+public class Main {
+  public static Object[] getObjectArray() { return null; }
+  public static long[] getLongArray() { return null; }
+
+  public static void main(String[] args) {
+    try {
+      foo();
+      throw new Error("Expected NullPointerException");
+    } catch (NullPointerException e) {
+      // Expected.
+    }
+  }
+
+  /// CHECK-START: void Main.foo() load_store_elimination (after)
+  /// CHECK-DAG: <<Null:l\d+>>  NullConstant
+  /// CHECK-DAG: <<Check:l\d+>> NullCheck [<<Null>>]
+  /// CHECK-DAG: <<Get1:j\d+>>  ArrayGet [<<Check>>,{{i\d+}}]
+  /// CHECK-DAG: <<Get2:l\d+>>  ArrayGet [<<Check>>,{{i\d+}}]
+  public static void foo() {
+    longField = getLongArray()[0];
+    objectField = getObjectArray()[0];
+  }
+
+  public static long longField;
+  public static Object objectField;
+}
diff --git a/test/974-verify-interface-super/expected.txt b/test/974-verify-interface-super/expected.txt
new file mode 100644
index 0000000..7ba7491
--- /dev/null
+++ b/test/974-verify-interface-super/expected.txt
@@ -0,0 +1 @@
+OK. No exception before invoke!
diff --git a/test/974-verify-interface-super/info.txt b/test/974-verify-interface-super/info.txt
new file mode 100644
index 0000000..c5ff1f6
--- /dev/null
+++ b/test/974-verify-interface-super/info.txt
@@ -0,0 +1,3 @@
+Test that we do the right thing with invoke-super on interfaces when there are
+verifier errors.
+
diff --git a/test/974-verify-interface-super/smali/base.smali b/test/974-verify-interface-super/smali/base.smali
new file mode 100644
index 0000000..c7875de
--- /dev/null
+++ b/test/974-verify-interface-super/smali/base.smali
@@ -0,0 +1,31 @@
+# Copyright 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 LBase;
+
+.super La/klass/that/does/not/Exist;
+
+.method public static run()V
+    .locals 4
+    new-instance v0, LBase;
+    invoke-direct {v0}, LBase;-><init>()V
+    invoke-virtual {v0}, LBase;->SayHi()V
+    return-void
+.end method
+
+.method public SayHi()V
+.locals 2
+  invoke-super {p0}, LIface;->SayHi()V
+  return-void
+.end method
diff --git a/test/974-verify-interface-super/smali/iface.smali b/test/974-verify-interface-super/smali/iface.smali
new file mode 100644
index 0000000..89f9c0b
--- /dev/null
+++ b/test/974-verify-interface-super/smali/iface.smali
@@ -0,0 +1,22 @@
+# Copyright 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 abstract interface LIface;
+
+.super Ljava/lang/Object;
+
+.method public SayHi()V
+.locals 0
+    return-void
+.end method
diff --git a/test/974-verify-interface-super/smali/main.smali b/test/974-verify-interface-super/smali/main.smali
new file mode 100644
index 0000000..be4016c
--- /dev/null
+++ b/test/974-verify-interface-super/smali/main.smali
@@ -0,0 +1,40 @@
+# Copyright 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 LMain;
+
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+    .locals 4
+    const-string v0, "OK. No exception before invoke!"
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+    invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+    :try_start
+        invoke-static {}, LBase;->run()V
+        const-string v0, "FAIL: no exception!"
+        sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+        invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+        goto :end
+    :try_end
+    .catch Ljava/lang/LinkageError; {:try_start .. :try_end} :end
+    .catch Ljava/lang/Throwable; {:try_start .. :try_end} :error
+    :error
+        move-exception v0
+        sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+        invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+        invoke-virtual {v0}, Ljava/lang/Throwable;->printStackTrace()V
+    :end
+    return-void
+.end method
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 2db1e6c..b360f67 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -66,6 +66,10 @@
         fi
         LIB="$1"
         shift
+    elif [ "x$1" = "x--gc-stress" ]; then
+        # Give an extra 5 mins if we are gc-stress.
+        TIME_OUT_VALUE=$((${TIME_OUT_VALUE} + 300))
+        shift
     elif [ "x$1" = "x--testlib" ]; then
         shift
         if [ "x$1" = "x" ]; then
diff --git a/test/run-test b/test/run-test
index 6bb1549..3350b35 100755
--- a/test/run-test
+++ b/test/run-test
@@ -389,7 +389,7 @@
   run_args="${run_args} --runtime-option -Xgc:preverify_rosalloc --runtime-option -Xgc:postverify_rosalloc"
 fi
 if [ "$gc_stress" = "true" ]; then
-  run_args="${run_args} --runtime-option -Xgc:SS,gcstress --runtime-option -Xms2m --runtime-option -Xmx16m"
+  run_args="${run_args} --gc-stress --runtime-option -Xgc:SS,gcstress --runtime-option -Xms2m --runtime-option -Xmx16m"
 fi
 if [ "$trace" = "true" ]; then
     run_args="${run_args} --runtime-option -Xmethod-trace --runtime-option -Xmethod-trace-file-size:2000000"