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"