Merge "Increase test 961 dex2oat timeout to 2 minutes"
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 6c918a3..7e37018 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -71,6 +71,12 @@
return false;
}
+// Forward declaration.
+static bool IsZeroExtensionAndGet(HInstruction* instruction,
+ DataType::Type type,
+ /*out*/ HInstruction** operand,
+ bool to64 = false);
+
// Detect a sign extension in instruction from the given type. The to64 parameter
// denotes if result is long, and thus sign extension from int can be included.
// Returns the promoted operand on success.
@@ -124,9 +130,19 @@
return false;
}
}
- // Explicit type conversion to long.
- if (instruction->IsTypeConversion() && instruction->GetType() == DataType::Type::kInt64) {
- return IsSignExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true);
+ // Explicit type conversions.
+ if (instruction->IsTypeConversion()) {
+ DataType::Type from = instruction->InputAt(0)->GetType();
+ switch (instruction->GetType()) {
+ case DataType::Type::kInt64:
+ return IsSignExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true);
+ case DataType::Type::kInt16:
+ return type == DataType::Type::kUint16 &&
+ from == DataType::Type::kUint16 &&
+ IsZeroExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, to64);
+ default:
+ return false;
+ }
}
return false;
}
@@ -137,7 +153,7 @@
static bool IsZeroExtensionAndGet(HInstruction* instruction,
DataType::Type type,
/*out*/ HInstruction** operand,
- bool to64 = false) {
+ bool to64) {
// Accept any already wider constant that would be handled properly by zero
// extension when represented in the *width* of the given narrower data type
// (the fact that byte/short/int normally sign extend does not matter here).
@@ -200,9 +216,19 @@
}
}
}
- // Explicit type conversion to long.
- if (instruction->IsTypeConversion() && instruction->GetType() == DataType::Type::kInt64) {
- return IsZeroExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true);
+ // Explicit type conversions.
+ if (instruction->IsTypeConversion()) {
+ DataType::Type from = instruction->InputAt(0)->GetType();
+ switch (instruction->GetType()) {
+ case DataType::Type::kInt64:
+ return IsZeroExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true);
+ case DataType::Type::kUint16:
+ return type == DataType::Type::kInt16 &&
+ from == DataType::Type::kInt16 &&
+ IsSignExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, to64);
+ default:
+ return false;
+ }
}
return false;
}
@@ -1885,9 +1911,17 @@
bool is_unsigned = false;
DataType::Type sub_type = a->GetType();
if (a->IsTypeConversion()) {
- sub_type = a->InputAt(0)->GetType();
+ HInstruction* hunt = a;
+ while (hunt->IsTypeConversion()) {
+ hunt = hunt->InputAt(0);
+ }
+ sub_type = hunt->GetType();
} else if (b->IsTypeConversion()) {
- sub_type = b->InputAt(0)->GetType();
+ HInstruction* hunt = a;
+ while (hunt->IsTypeConversion()) {
+ hunt = hunt->InputAt(0);
+ }
+ sub_type = hunt->GetType();
}
if (reduction_type != sub_type &&
(!IsNarrowerOperands(a, b, sub_type, &r, &s, &is_unsigned) || is_unsigned)) {
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index aeb2b03..10b3fe1 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -671,13 +671,29 @@
case kMips: {
mips::PcRelativeFixups* pc_relative_fixups =
new (arena) mips::PcRelativeFixups(graph, codegen, stats);
+ SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph);
+ GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN$after_arch");
HOptimization* mips_optimizations[] = {
+ side_effects,
+ gvn,
pc_relative_fixups,
};
RunOptimizations(mips_optimizations, arraysize(mips_optimizations), pass_observer);
break;
}
#endif
+#ifdef ART_ENABLE_CODEGEN_mips64
+ case kMips64: {
+ SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph);
+ GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN$after_arch");
+ HOptimization* mips64_optimizations[] = {
+ side_effects,
+ gvn,
+ };
+ RunOptimizations(mips64_optimizations, arraysize(mips64_optimizations), pass_observer);
+ break;
+ }
+#endif
#ifdef ART_ENABLE_CODEGEN_x86
case kX86: {
x86::PcRelativeFixups* pc_relative_fixups =
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index e544ab7..7b46531 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1357,7 +1357,7 @@
DCHECK(!oat_filenames_.empty());
for (const char* oat_filename : oat_filenames_) {
std::unique_ptr<File> oat_file(OS::CreateEmptyFile(oat_filename));
- if (oat_file.get() == nullptr) {
+ if (oat_file == nullptr) {
PLOG(ERROR) << "Failed to create oat file: " << oat_filename;
return false;
}
@@ -1387,7 +1387,7 @@
vdex_files_.push_back(std::move(vdex_file));
} else {
std::unique_ptr<File> vdex_file(OS::CreateEmptyFile(vdex_filename.c_str()));
- if (vdex_file.get() == nullptr) {
+ if (vdex_file == nullptr) {
PLOG(ERROR) << "Failed to open vdex file: " << vdex_filename;
return false;
}
@@ -1401,13 +1401,15 @@
}
} else {
std::unique_ptr<File> oat_file(new File(oat_fd_, oat_location_, /* check_usage */ true));
- if (oat_file.get() == nullptr) {
+ if (oat_file == nullptr) {
PLOG(ERROR) << "Failed to create oat file: " << oat_location_;
return false;
}
oat_file->DisableAutoClose();
if (oat_file->SetLength(0) != 0) {
PLOG(WARNING) << "Truncating oat file " << oat_location_ << " failed.";
+ oat_file->Erase();
+ return false;
}
oat_files_.push_back(std::move(oat_file));
@@ -1436,7 +1438,7 @@
DCHECK_NE(output_vdex_fd_, -1);
std::string vdex_location = ReplaceFileExtension(oat_location_, "vdex");
std::unique_ptr<File> vdex_file(new File(output_vdex_fd_, vdex_location, /* check_usage */ true));
- if (vdex_file.get() == nullptr) {
+ if (vdex_file == nullptr) {
PLOG(ERROR) << "Failed to create vdex file: " << vdex_location;
return false;
}
@@ -1446,6 +1448,7 @@
} else {
if (vdex_file->SetLength(0) != 0) {
PLOG(ERROR) << "Truncating vdex file " << vdex_location << " failed.";
+ vdex_file->Erase();
return false;
}
}
diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc
index eb8ced0..6d1de00 100644
--- a/runtime/base/unix_file/fd_file.cc
+++ b/runtime/base/unix_file/fd_file.cc
@@ -70,7 +70,7 @@
if (guard_state_ < GuardState::kClosed) {
LOG(ERROR) << "File " << file_path_ << " wasn't explicitly closed before destruction.";
}
- CHECK_GE(guard_state_, GuardState::kClosed);
+ DCHECK_GE(guard_state_, GuardState::kClosed);
}
if (auto_close_ && fd_ != -1) {
if (Close() != 0) {
@@ -135,7 +135,7 @@
bool FdFile::Open(const std::string& path, int flags, mode_t mode) {
static_assert(O_RDONLY == 0, "Readonly flag has unexpected value.");
- CHECK_EQ(fd_, -1) << path;
+ DCHECK_EQ(fd_, -1) << path;
read_only_mode_ = ((flags & O_ACCMODE) == O_RDONLY);
fd_ = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
if (fd_ == -1) {
@@ -158,7 +158,7 @@
// Test here, so the file is closed and not leaked.
if (kCheckSafeUsage) {
- CHECK_GE(guard_state_, GuardState::kFlushed) << "File " << file_path_
+ DCHECK_GE(guard_state_, GuardState::kFlushed) << "File " << file_path_
<< " has not been flushed before closing.";
moveUp(GuardState::kClosed, nullptr);
}
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index cff3ea7..2dd4db3 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -237,7 +237,8 @@
}
IndirectRef IndirectReferenceTable::Add(IRTSegmentState previous_state,
- ObjPtr<mirror::Object> obj) {
+ ObjPtr<mirror::Object> obj,
+ std::string* error_msg) {
if (kDebugIRT) {
LOG(INFO) << "+++ Add: previous_state=" << previous_state.top_index
<< " top_index=" << segment_state_.top_index
@@ -253,28 +254,34 @@
if (top_index == max_entries_) {
if (resizable_ == ResizableCapacity::kNo) {
- LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow "
- << "(max=" << max_entries_ << ")\n"
- << MutatorLockedDumpable<IndirectReferenceTable>(*this);
- UNREACHABLE();
+ std::ostringstream oss;
+ oss << "JNI ERROR (app bug): " << kind_ << " table overflow "
+ << "(max=" << max_entries_ << ")"
+ << MutatorLockedDumpable<IndirectReferenceTable>(*this);
+ *error_msg = oss.str();
+ return nullptr;
}
// Try to double space.
if (std::numeric_limits<size_t>::max() / 2 < max_entries_) {
- LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow "
- << "(max=" << max_entries_ << ")" << std::endl
- << MutatorLockedDumpable<IndirectReferenceTable>(*this)
- << " Resizing failed: exceeds size_t";
- UNREACHABLE();
+ std::ostringstream oss;
+ oss << "JNI ERROR (app bug): " << kind_ << " table overflow "
+ << "(max=" << max_entries_ << ")" << std::endl
+ << MutatorLockedDumpable<IndirectReferenceTable>(*this)
+ << " Resizing failed: exceeds size_t";
+ *error_msg = oss.str();
+ return nullptr;
}
- std::string error_msg;
- if (!Resize(max_entries_ * 2, &error_msg)) {
- LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow "
- << "(max=" << max_entries_ << ")" << std::endl
- << MutatorLockedDumpable<IndirectReferenceTable>(*this)
- << " Resizing failed: " << error_msg;
- UNREACHABLE();
+ std::string inner_error_msg;
+ if (!Resize(max_entries_ * 2, &inner_error_msg)) {
+ std::ostringstream oss;
+ oss << "JNI ERROR (app bug): " << kind_ << " table overflow "
+ << "(max=" << max_entries_ << ")" << std::endl
+ << MutatorLockedDumpable<IndirectReferenceTable>(*this)
+ << " Resizing failed: " << inner_error_msg;
+ *error_msg = oss.str();
+ return nullptr;
}
}
diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h
index 6d52d95..bf287b1 100644
--- a/runtime/indirect_reference_table.h
+++ b/runtime/indirect_reference_table.h
@@ -244,8 +244,10 @@
bool IsValid() const;
// Add a new entry. "obj" must be a valid non-null object reference. This function will
- // abort if the table is full (max entries reached, or expansion failed).
- IndirectRef Add(IRTSegmentState previous_state, ObjPtr<mirror::Object> obj)
+ // return null if an error happened (with an appropriate error message set).
+ IndirectRef Add(IRTSegmentState previous_state,
+ ObjPtr<mirror::Object> obj,
+ std::string* error_msg)
REQUIRES_SHARED(Locks::mutator_lock_);
// Given an IndirectRef in the table, return the Object it refers to.
diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc
index 6aefe23..9278509 100644
--- a/runtime/indirect_reference_table_test.cc
+++ b/runtime/indirect_reference_table_test.cc
@@ -80,13 +80,13 @@
EXPECT_FALSE(irt.Remove(cookie, iref0)) << "unexpectedly successful removal";
// Add three, check, remove in the order in which they were added.
- iref0 = irt.Add(cookie, obj0.Get());
+ iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
EXPECT_TRUE(iref0 != nullptr);
CheckDump(&irt, 1, 1);
- IndirectRef iref1 = irt.Add(cookie, obj1.Get());
+ IndirectRef iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
EXPECT_TRUE(iref1 != nullptr);
CheckDump(&irt, 2, 2);
- IndirectRef iref2 = irt.Add(cookie, obj2.Get());
+ IndirectRef iref2 = irt.Add(cookie, obj2.Get(), &error_msg);
EXPECT_TRUE(iref2 != nullptr);
CheckDump(&irt, 3, 3);
@@ -108,11 +108,11 @@
EXPECT_TRUE(irt.Get(iref0) == nullptr);
// Add three, remove in the opposite order.
- iref0 = irt.Add(cookie, obj0.Get());
+ iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
EXPECT_TRUE(iref0 != nullptr);
- iref1 = irt.Add(cookie, obj1.Get());
+ iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
EXPECT_TRUE(iref1 != nullptr);
- iref2 = irt.Add(cookie, obj2.Get());
+ iref2 = irt.Add(cookie, obj2.Get(), &error_msg);
EXPECT_TRUE(iref2 != nullptr);
CheckDump(&irt, 3, 3);
@@ -128,11 +128,11 @@
// Add three, remove middle / middle / bottom / top. (Second attempt
// to remove middle should fail.)
- iref0 = irt.Add(cookie, obj0.Get());
+ iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
EXPECT_TRUE(iref0 != nullptr);
- iref1 = irt.Add(cookie, obj1.Get());
+ iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
EXPECT_TRUE(iref1 != nullptr);
- iref2 = irt.Add(cookie, obj2.Get());
+ iref2 = irt.Add(cookie, obj2.Get(), &error_msg);
EXPECT_TRUE(iref2 != nullptr);
CheckDump(&irt, 3, 3);
@@ -157,20 +157,20 @@
// Add four entries. Remove #1, add new entry, verify that table size
// is still 4 (i.e. holes are getting filled). Remove #1 and #3, verify
// that we delete one and don't hole-compact the other.
- iref0 = irt.Add(cookie, obj0.Get());
+ iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
EXPECT_TRUE(iref0 != nullptr);
- iref1 = irt.Add(cookie, obj1.Get());
+ iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
EXPECT_TRUE(iref1 != nullptr);
- iref2 = irt.Add(cookie, obj2.Get());
+ iref2 = irt.Add(cookie, obj2.Get(), &error_msg);
EXPECT_TRUE(iref2 != nullptr);
- IndirectRef iref3 = irt.Add(cookie, obj3.Get());
+ IndirectRef iref3 = irt.Add(cookie, obj3.Get(), &error_msg);
EXPECT_TRUE(iref3 != nullptr);
CheckDump(&irt, 4, 4);
ASSERT_TRUE(irt.Remove(cookie, iref1));
CheckDump(&irt, 3, 3);
- iref1 = irt.Add(cookie, obj1.Get());
+ iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
EXPECT_TRUE(iref1 != nullptr);
ASSERT_EQ(4U, irt.Capacity()) << "hole not filled";
@@ -193,12 +193,12 @@
// Add an entry, remove it, add a new entry, and try to use the original
// iref. They have the same slot number but are for different objects.
// With the extended checks in place, this should fail.
- iref0 = irt.Add(cookie, obj0.Get());
+ iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
EXPECT_TRUE(iref0 != nullptr);
CheckDump(&irt, 1, 1);
ASSERT_TRUE(irt.Remove(cookie, iref0));
CheckDump(&irt, 0, 0);
- iref1 = irt.Add(cookie, obj1.Get());
+ iref1 = irt.Add(cookie, obj1.Get(), &error_msg);
EXPECT_TRUE(iref1 != nullptr);
CheckDump(&irt, 1, 1);
ASSERT_FALSE(irt.Remove(cookie, iref0)) << "mismatched del succeeded";
@@ -209,12 +209,12 @@
// Same as above, but with the same object. A more rigorous checker
// (e.g. with slot serialization) will catch this.
- iref0 = irt.Add(cookie, obj0.Get());
+ iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
EXPECT_TRUE(iref0 != nullptr);
CheckDump(&irt, 1, 1);
ASSERT_TRUE(irt.Remove(cookie, iref0));
CheckDump(&irt, 0, 0);
- iref1 = irt.Add(cookie, obj0.Get());
+ iref1 = irt.Add(cookie, obj0.Get(), &error_msg);
EXPECT_TRUE(iref1 != nullptr);
CheckDump(&irt, 1, 1);
if (iref0 != iref1) {
@@ -229,7 +229,7 @@
ASSERT_TRUE(irt.Get(nullptr) == nullptr);
// Stale lookup.
- iref0 = irt.Add(cookie, obj0.Get());
+ iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
EXPECT_TRUE(iref0 != nullptr);
CheckDump(&irt, 1, 1);
ASSERT_TRUE(irt.Remove(cookie, iref0));
@@ -241,12 +241,12 @@
static const size_t kTableInitial = kTableMax / 2;
IndirectRef manyRefs[kTableInitial];
for (size_t i = 0; i < kTableInitial; i++) {
- manyRefs[i] = irt.Add(cookie, obj0.Get());
+ manyRefs[i] = irt.Add(cookie, obj0.Get(), &error_msg);
ASSERT_TRUE(manyRefs[i] != nullptr) << "Failed adding " << i;
CheckDump(&irt, i + 1, 1);
}
// ...this one causes overflow.
- iref0 = irt.Add(cookie, obj0.Get());
+ iref0 = irt.Add(cookie, obj0.Get(), &error_msg);
ASSERT_TRUE(iref0 != nullptr);
ASSERT_EQ(kTableInitial + 1, irt.Capacity());
CheckDump(&irt, kTableInitial + 1, 1);
@@ -306,16 +306,16 @@
CheckDump(&irt, 0, 0);
- IndirectRef iref0 = irt.Add(cookie0, obj0.Get());
- IndirectRef iref1 = irt.Add(cookie0, obj1.Get());
- IndirectRef iref2 = irt.Add(cookie0, obj2.Get());
+ IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
+ IndirectRef iref1 = irt.Add(cookie0, obj1.Get(), &error_msg);
+ IndirectRef iref2 = irt.Add(cookie0, obj2.Get(), &error_msg);
EXPECT_TRUE(irt.Remove(cookie0, iref1));
// New segment.
const IRTSegmentState cookie1 = irt.GetSegmentState();
- IndirectRef iref3 = irt.Add(cookie1, obj3.Get());
+ IndirectRef iref3 = irt.Add(cookie1, obj3.Get(), &error_msg);
// Must not have filled the previous hole.
EXPECT_EQ(irt.Capacity(), 4u);
@@ -337,21 +337,21 @@
CheckDump(&irt, 0, 0);
- IndirectRef iref0 = irt.Add(cookie0, obj0.Get());
+ IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
// New segment.
const IRTSegmentState cookie1 = irt.GetSegmentState();
- IndirectRef iref1 = irt.Add(cookie1, obj1.Get());
- IndirectRef iref2 = irt.Add(cookie1, obj2.Get());
- IndirectRef iref3 = irt.Add(cookie1, obj3.Get());
+ IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg);
+ IndirectRef iref2 = irt.Add(cookie1, obj2.Get(), &error_msg);
+ IndirectRef iref3 = irt.Add(cookie1, obj3.Get(), &error_msg);
EXPECT_TRUE(irt.Remove(cookie1, iref2));
// Pop segment.
irt.SetSegmentState(cookie1);
- IndirectRef iref4 = irt.Add(cookie1, obj4.Get());
+ IndirectRef iref4 = irt.Add(cookie1, obj4.Get(), &error_msg);
EXPECT_EQ(irt.Capacity(), 2u);
EXPECT_TRUE(irt.Get(iref2) == nullptr);
@@ -373,25 +373,25 @@
CheckDump(&irt, 0, 0);
- IndirectRef iref0 = irt.Add(cookie0, obj0.Get());
+ IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
// New segment.
const IRTSegmentState cookie1 = irt.GetSegmentState();
- IndirectRef iref1 = irt.Add(cookie1, obj1.Get());
- IndirectRef iref2 = irt.Add(cookie1, obj2.Get());
+ IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg);
+ IndirectRef iref2 = irt.Add(cookie1, obj2.Get(), &error_msg);
EXPECT_TRUE(irt.Remove(cookie1, iref1));
// New segment.
const IRTSegmentState cookie2 = irt.GetSegmentState();
- IndirectRef iref3 = irt.Add(cookie2, obj3.Get());
+ IndirectRef iref3 = irt.Add(cookie2, obj3.Get(), &error_msg);
// Pop segment.
irt.SetSegmentState(cookie2);
- IndirectRef iref4 = irt.Add(cookie1, obj4.Get());
+ IndirectRef iref4 = irt.Add(cookie1, obj4.Get(), &error_msg);
EXPECT_EQ(irt.Capacity(), 3u);
EXPECT_TRUE(irt.Get(iref1) == nullptr);
@@ -412,20 +412,20 @@
CheckDump(&irt, 0, 0);
- IndirectRef iref0 = irt.Add(cookie0, obj0.Get());
+ IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
// New segment.
const IRTSegmentState cookie1 = irt.GetSegmentState();
- IndirectRef iref1 = irt.Add(cookie1, obj1.Get());
+ IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg);
EXPECT_TRUE(irt.Remove(cookie1, iref1));
// Emptied segment, push new one.
const IRTSegmentState cookie2 = irt.GetSegmentState();
- IndirectRef iref2 = irt.Add(cookie1, obj1.Get());
- IndirectRef iref3 = irt.Add(cookie1, obj2.Get());
- IndirectRef iref4 = irt.Add(cookie1, obj3.Get());
+ IndirectRef iref2 = irt.Add(cookie1, obj1.Get(), &error_msg);
+ IndirectRef iref3 = irt.Add(cookie1, obj2.Get(), &error_msg);
+ IndirectRef iref4 = irt.Add(cookie1, obj3.Get(), &error_msg);
EXPECT_TRUE(irt.Remove(cookie1, iref3));
@@ -433,7 +433,7 @@
UNUSED(cookie2);
irt.SetSegmentState(cookie1);
- IndirectRef iref5 = irt.Add(cookie1, obj4.Get());
+ IndirectRef iref5 = irt.Add(cookie1, obj4.Get(), &error_msg);
EXPECT_EQ(irt.Capacity(), 2u);
EXPECT_TRUE(irt.Get(iref3) == nullptr);
@@ -455,14 +455,14 @@
CheckDump(&irt, 0, 0);
- IndirectRef iref0 = irt.Add(cookie0, obj0.Get());
+ IndirectRef iref0 = irt.Add(cookie0, obj0.Get(), &error_msg);
// New segment.
const IRTSegmentState cookie1 = irt.GetSegmentState();
- IndirectRef iref1 = irt.Add(cookie1, obj1.Get());
- IndirectRef iref2 = irt.Add(cookie1, obj1.Get());
- IndirectRef iref3 = irt.Add(cookie1, obj2.Get());
+ IndirectRef iref1 = irt.Add(cookie1, obj1.Get(), &error_msg);
+ IndirectRef iref2 = irt.Add(cookie1, obj1.Get(), &error_msg);
+ IndirectRef iref3 = irt.Add(cookie1, obj2.Get(), &error_msg);
EXPECT_TRUE(irt.Remove(cookie1, iref2));
@@ -473,7 +473,7 @@
const IRTSegmentState cookie1_second = irt.GetSegmentState();
UNUSED(cookie1_second);
- IndirectRef iref4 = irt.Add(cookie1, obj3.Get());
+ IndirectRef iref4 = irt.Add(cookie1, obj3.Get(), &error_msg);
EXPECT_EQ(irt.Capacity(), 2u);
EXPECT_TRUE(irt.Get(iref3) == nullptr);
@@ -504,7 +504,7 @@
const IRTSegmentState cookie = kIRTFirstSegment;
for (size_t i = 0; i != kTableMax + 1; ++i) {
- irt.Add(cookie, obj0.Get());
+ irt.Add(cookie, obj0.Get(), &error_msg);
}
EXPECT_EQ(irt.Capacity(), kTableMax + 1);
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index c0d1861..5a16053 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -589,7 +589,12 @@
return nullptr;
}
WriterMutexLock mu(self, *Locks::jni_globals_lock_);
- IndirectRef ref = globals_.Add(kIRTFirstSegment, obj);
+ std::string error_msg;
+ IndirectRef ref = globals_.Add(kIRTFirstSegment, obj, &error_msg);
+ if (UNLIKELY(ref == nullptr)) {
+ LOG(FATAL) << error_msg;
+ UNREACHABLE();
+ }
return reinterpret_cast<jobject>(ref);
}
@@ -607,7 +612,12 @@
self->CheckEmptyCheckpointFromWeakRefAccess(Locks::jni_weak_globals_lock_);
weak_globals_add_condition_.WaitHoldingLocks(self);
}
- IndirectRef ref = weak_globals_.Add(kIRTFirstSegment, obj);
+ std::string error_msg;
+ IndirectRef ref = weak_globals_.Add(kIRTFirstSegment, obj, &error_msg);
+ if (UNLIKELY(ref == nullptr)) {
+ LOG(FATAL) << error_msg;
+ UNREACHABLE();
+ }
return reinterpret_cast<jweak>(ref);
}
diff --git a/runtime/jni_env_ext-inl.h b/runtime/jni_env_ext-inl.h
index 25893b7..d66df08 100644
--- a/runtime/jni_env_ext-inl.h
+++ b/runtime/jni_env_ext-inl.h
@@ -25,7 +25,13 @@
template<typename T>
inline T JNIEnvExt::AddLocalReference(ObjPtr<mirror::Object> obj) {
- IndirectRef ref = locals.Add(local_ref_cookie, obj);
+ std::string error_msg;
+ IndirectRef ref = locals.Add(local_ref_cookie, obj, &error_msg);
+ if (UNLIKELY(ref == nullptr)) {
+ // This is really unexpected if we allow resizing local IRTs...
+ LOG(FATAL) << error_msg;
+ UNREACHABLE();
+ }
// TODO: fix this to understand PushLocalFrame, so we can turn it on.
if (false) {
diff --git a/runtime/jni_env_ext.cc b/runtime/jni_env_ext.cc
index 3ff94f9..8352657 100644
--- a/runtime/jni_env_ext.cc
+++ b/runtime/jni_env_ext.cc
@@ -99,7 +99,14 @@
if (obj == nullptr) {
return nullptr;
}
- return reinterpret_cast<jobject>(locals.Add(local_ref_cookie, obj));
+ std::string error_msg;
+ jobject ref = reinterpret_cast<jobject>(locals.Add(local_ref_cookie, obj, &error_msg));
+ if (UNLIKELY(ref == nullptr)) {
+ // This is really unexpected if we allow resizing local IRTs...
+ LOG(FATAL) << error_msg;
+ UNREACHABLE();
+ }
+ return ref;
}
void JNIEnvExt::DeleteLocalRef(jobject obj) {
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 77a5b55..78f6b25 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -128,7 +128,8 @@
}
inline ArraySlice<ArtMethod> Class::GetDirectMethodsSliceUnchecked(PointerSize pointer_size) {
- return GetMethodsSliceRangeUnchecked(pointer_size,
+ return GetMethodsSliceRangeUnchecked(GetMethodsPtr(),
+ pointer_size,
GetDirectMethodsStartOffset(),
GetVirtualMethodsStartOffset());
}
@@ -140,7 +141,8 @@
}
inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSliceUnchecked(PointerSize pointer_size) {
- return GetMethodsSliceRangeUnchecked(pointer_size,
+ return GetMethodsSliceRangeUnchecked(GetMethodsPtr(),
+ pointer_size,
GetDirectMethodsStartOffset(),
GetCopiedMethodsStartOffset());
}
@@ -152,7 +154,8 @@
inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSliceUnchecked(
PointerSize pointer_size) {
- return GetMethodsSliceRangeUnchecked(pointer_size,
+ return GetMethodsSliceRangeUnchecked(GetMethodsPtr(),
+ pointer_size,
GetVirtualMethodsStartOffset(),
GetCopiedMethodsStartOffset());
}
@@ -164,9 +167,11 @@
}
inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSliceUnchecked(PointerSize pointer_size) {
- return GetMethodsSliceRangeUnchecked(pointer_size,
+ LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
+ return GetMethodsSliceRangeUnchecked(methods,
+ pointer_size,
GetVirtualMethodsStartOffset(),
- NumMethods());
+ NumMethods(methods));
}
template<VerifyObjectFlags kVerifyFlags>
@@ -176,7 +181,11 @@
}
inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSliceUnchecked(PointerSize pointer_size) {
- return GetMethodsSliceRangeUnchecked(pointer_size, GetCopiedMethodsStartOffset(), NumMethods());
+ LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
+ return GetMethodsSliceRangeUnchecked(methods,
+ pointer_size,
+ GetCopiedMethodsStartOffset(),
+ NumMethods(methods));
}
inline LengthPrefixedArray<ArtMethod>* Class::GetMethodsPtr() {
@@ -187,19 +196,21 @@
template<VerifyObjectFlags kVerifyFlags>
inline ArraySlice<ArtMethod> Class::GetMethodsSlice(PointerSize pointer_size) {
DCHECK(IsLoaded() || IsErroneous());
- return GetMethodsSliceRangeUnchecked(pointer_size, 0, NumMethods());
+ LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
+ return GetMethodsSliceRangeUnchecked(methods, pointer_size, 0, NumMethods(methods));
}
-inline ArraySlice<ArtMethod> Class::GetMethodsSliceRangeUnchecked(PointerSize pointer_size,
- uint32_t start_offset,
- uint32_t end_offset) {
+inline ArraySlice<ArtMethod> Class::GetMethodsSliceRangeUnchecked(
+ LengthPrefixedArray<ArtMethod>* methods,
+ PointerSize pointer_size,
+ uint32_t start_offset,
+ uint32_t end_offset) {
DCHECK_LE(start_offset, end_offset);
- DCHECK_LE(end_offset, NumMethods());
+ DCHECK_LE(end_offset, NumMethods(methods));
uint32_t size = end_offset - start_offset;
if (size == 0u) {
return ArraySlice<ArtMethod>();
}
- LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
DCHECK(methods != nullptr);
DCHECK_LE(end_offset, methods->size());
size_t method_size = ArtMethod::Size(pointer_size);
@@ -211,7 +222,10 @@
}
inline uint32_t Class::NumMethods() {
- LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
+ return NumMethods(GetMethodsPtr());
+}
+
+inline uint32_t Class::NumMethods(LengthPrefixedArray<ArtMethod>* methods) {
return (methods == nullptr) ? 0 : methods->size();
}
@@ -969,7 +983,8 @@
inline ArraySlice<ArtMethod> Class::GetMethods(PointerSize pointer_size) {
CheckPointerSize(pointer_size);
- return GetMethodsSliceRangeUnchecked(pointer_size, 0u, NumMethods());
+ LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
+ return GetMethodsSliceRangeUnchecked(methods, pointer_size, 0u, NumMethods(methods));
}
inline IterationRange<StrideIterator<ArtField>> Class::GetIFields() {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index c44b616..148273b 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -773,6 +773,8 @@
ALWAYS_INLINE uint32_t NumDeclaredVirtualMethods() REQUIRES_SHARED(Locks::mutator_lock_);
ALWAYS_INLINE uint32_t NumMethods() REQUIRES_SHARED(Locks::mutator_lock_);
+ static ALWAYS_INLINE uint32_t NumMethods(LengthPrefixedArray<ArtMethod>* methods)
+ REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ArtMethod* GetVirtualMethod(size_t i, PointerSize pointer_size)
@@ -1294,9 +1296,11 @@
ALWAYS_INLINE void SetMethodsPtrInternal(LengthPrefixedArray<ArtMethod>* new_methods)
REQUIRES_SHARED(Locks::mutator_lock_);
- ALWAYS_INLINE ArraySlice<ArtMethod> GetMethodsSliceRangeUnchecked(PointerSize pointer_size,
- uint32_t start_offset,
- uint32_t end_offset)
+ ALWAYS_INLINE static ArraySlice<ArtMethod> GetMethodsSliceRangeUnchecked(
+ LengthPrefixedArray<ArtMethod>* methods,
+ PointerSize pointer_size,
+ uint32_t start_offset,
+ uint32_t end_offset)
REQUIRES_SHARED(Locks::mutator_lock_);
template <bool throw_on_failure>
diff --git a/test/566-polymorphic-inlining/run b/test/566-polymorphic-inlining/run
new file mode 100644
index 0000000..2919f46
--- /dev/null
+++ b/test/566-polymorphic-inlining/run
@@ -0,0 +1,20 @@
+#!/bin/bash
+#
+# Copyright 2017 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.
+
+# -Xjitinitialsize:32M to prevent profiling info creation failure.
+exec ${RUN} \
+ --runtime-option -Xjitinitialsize:32M \
+ "${@}"
diff --git a/test/660-checker-simd-sad-char/src/Main.java b/test/660-checker-simd-sad-char/src/Main.java
index bb0c58f..2535d49 100644
--- a/test/660-checker-simd-sad-char/src/Main.java
+++ b/test/660-checker-simd-sad-char/src/Main.java
@@ -23,7 +23,7 @@
// TODO: consider unsigned SAD too, b/64091002
- private static char sadShort2Short(char[] s1, char[] s2) {
+ private static char sadChar2Char(char[] s1, char[] s2) {
int min_length = Math.min(s1.length, s2.length);
char sad = 0;
for (int i = 0; i < min_length; i++) {
@@ -32,7 +32,7 @@
return sad;
}
- private static char sadShort2ShortAlt(char[] s1, char[] s2) {
+ private static char sadChar2CharAlt(char[] s1, char[] s2) {
int min_length = Math.min(s1.length, s2.length);
char sad = 0;
for (int i = 0; i < min_length; i++) {
@@ -43,7 +43,7 @@
return sad;
}
- private static char sadShort2ShortAlt2(char[] s1, char[] s2) {
+ private static char sadChar2CharAlt2(char[] s1, char[] s2) {
int min_length = Math.min(s1.length, s2.length);
char sad = 0;
for (int i = 0; i < min_length; i++) {
@@ -56,7 +56,7 @@
return sad;
}
- /// CHECK-START: int Main.sadShort2Int(char[], char[]) loop_optimization (before)
+ /// CHECK-START: int Main.sadChar2Int(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
@@ -68,9 +68,9 @@
/// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
//
- /// CHECK-START-ARM64: int Main.sadShort2Int(char[], char[]) loop_optimization (after)
+ /// CHECK-START-ARM64: int Main.sadChar2Int(char[], char[]) loop_optimization (after)
/// CHECK-NOT: VecSADAccumulate
- private static int sadShort2Int(char[] s1, char[] s2) {
+ private static int sadChar2Int(char[] s1, char[] s2) {
int min_length = Math.min(s1.length, s2.length);
int sad = 0;
for (int i = 0; i < min_length; i++) {
@@ -79,7 +79,7 @@
return sad;
}
- /// CHECK-START: int Main.sadShort2IntAlt(char[], char[]) loop_optimization (before)
+ /// CHECK-START: int Main.sadChar2IntAlt(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
@@ -91,9 +91,9 @@
/// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
//
- /// CHECK-START-ARM64: int Main.sadShort2IntAlt(char[], char[]) loop_optimization (after)
+ /// CHECK-START-ARM64: int Main.sadChar2IntAlt(char[], char[]) loop_optimization (after)
/// CHECK-NOT: VecSADAccumulate
- private static int sadShort2IntAlt(char[] s1, char[] s2) {
+ private static int sadChar2IntAlt(char[] s1, char[] s2) {
int min_length = Math.min(s1.length, s2.length);
int sad = 0;
for (int i = 0; i < min_length; i++) {
@@ -104,7 +104,7 @@
return sad;
}
- /// CHECK-START: int Main.sadShort2IntAlt2(char[], char[]) loop_optimization (before)
+ /// CHECK-START: int Main.sadChar2IntAlt2(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
@@ -116,9 +116,9 @@
/// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
//
- /// CHECK-START-ARM64: int Main.sadShort2IntAlt2(char[], char[]) loop_optimization (after)
+ /// CHECK-START-ARM64: int Main.sadChar2IntAlt2(char[], char[]) loop_optimization (after)
/// CHECK-NOT: VecSADAccumulate
- private static int sadShort2IntAlt2(char[] s1, char[] s2) {
+ private static int sadChar2IntAlt2(char[] s1, char[] s2) {
int min_length = Math.min(s1.length, s2.length);
int sad = 0;
for (int i = 0; i < min_length; i++) {
@@ -131,7 +131,7 @@
return sad;
}
- /// CHECK-START: long Main.sadShort2Long(char[], char[]) loop_optimization (before)
+ /// CHECK-START: long Main.sadChar2Long(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
@@ -146,9 +146,9 @@
/// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
//
- /// CHECK-START-ARM64: long Main.sadShort2Long(char[], char[]) loop_optimization (after)
+ /// CHECK-START-ARM64: long Main.sadChar2Long(char[], char[]) loop_optimization (after)
/// CHECK-NOT: VecSADAccumulate
- private static long sadShort2Long(char[] s1, char[] s2) {
+ private static long sadChar2Long(char[] s1, char[] s2) {
int min_length = Math.min(s1.length, s2.length);
long sad = 0;
for (int i = 0; i < min_length; i++) {
@@ -159,7 +159,7 @@
return sad;
}
- /// CHECK-START: long Main.sadShort2LongAt1(char[], char[]) loop_optimization (before)
+ /// CHECK-START: long Main.sadChar2LongAt1(char[], char[]) loop_optimization (before)
/// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
/// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none
@@ -174,9 +174,9 @@
/// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
//
- /// CHECK-START-ARM64: long Main.sadShort2LongAt1(char[], char[]) loop_optimization (after)
+ /// CHECK-START-ARM64: long Main.sadChar2LongAt1(char[], char[]) loop_optimization (after)
/// CHECK-NOT: VecSADAccumulate
- private static long sadShort2LongAt1(char[] s1, char[] s2) {
+ private static long sadChar2LongAt1(char[] s1, char[] s2) {
int min_length = Math.min(s1.length, s2.length);
long sad = 1; // starts at 1
for (int i = 0; i < min_length; i++) {
@@ -191,22 +191,22 @@
// Cross-test the two most extreme values individually.
char[] s1 = { 0, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
char[] s2 = { 0, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- expectEquals(1, sadShort2Short(s1, s2));
- expectEquals(1, sadShort2Short(s2, s1));
- expectEquals(1, sadShort2ShortAlt(s1, s2));
- expectEquals(1, sadShort2ShortAlt(s2, s1));
- expectEquals(1, sadShort2ShortAlt2(s1, s2));
- expectEquals(1, sadShort2ShortAlt2(s2, s1));
- expectEquals(1, sadShort2Int(s1, s2));
- expectEquals(1, sadShort2Int(s2, s1));
- expectEquals(1, sadShort2IntAlt(s1, s2));
- expectEquals(1, sadShort2IntAlt(s2, s1));
- expectEquals(1, sadShort2IntAlt2(s1, s2));
- expectEquals(1, sadShort2IntAlt2(s2, s1));
- expectEquals(1L, sadShort2Long(s1, s2));
- expectEquals(1L, sadShort2Long(s2, s1));
- expectEquals(2L, sadShort2LongAt1(s1, s2));
- expectEquals(2L, sadShort2LongAt1(s2, s1));
+ expectEquals(1, sadChar2Char(s1, s2));
+ expectEquals(1, sadChar2Char(s2, s1));
+ expectEquals(1, sadChar2CharAlt(s1, s2));
+ expectEquals(1, sadChar2CharAlt(s2, s1));
+ expectEquals(1, sadChar2CharAlt2(s1, s2));
+ expectEquals(1, sadChar2CharAlt2(s2, s1));
+ expectEquals(1, sadChar2Int(s1, s2));
+ expectEquals(1, sadChar2Int(s2, s1));
+ expectEquals(1, sadChar2IntAlt(s1, s2));
+ expectEquals(1, sadChar2IntAlt(s2, s1));
+ expectEquals(1, sadChar2IntAlt2(s1, s2));
+ expectEquals(1, sadChar2IntAlt2(s2, s1));
+ expectEquals(1L, sadChar2Long(s1, s2));
+ expectEquals(1L, sadChar2Long(s2, s1));
+ expectEquals(2L, sadChar2LongAt1(s1, s2));
+ expectEquals(2L, sadChar2LongAt1(s2, s1));
// Use cross-values to test all cases.
char[] interesting = {
@@ -233,14 +233,14 @@
}
s1[k] = 10;
s2[k] = 2;
- expectEquals(56196, sadShort2Short(s1, s2));
- expectEquals(56196, sadShort2ShortAlt(s1, s2));
- expectEquals(56196, sadShort2ShortAlt2(s1, s2));
- expectEquals(1497988, sadShort2Int(s1, s2));
- expectEquals(1497988, sadShort2IntAlt(s1, s2));
- expectEquals(1497988, sadShort2IntAlt2(s1, s2));
- expectEquals(1497988L, sadShort2Long(s1, s2));
- expectEquals(1497989L, sadShort2LongAt1(s1, s2));
+ expectEquals(56196, sadChar2Char(s1, s2));
+ expectEquals(56196, sadChar2CharAlt(s1, s2));
+ expectEquals(56196, sadChar2CharAlt2(s1, s2));
+ expectEquals(1497988, sadChar2Int(s1, s2));
+ expectEquals(1497988, sadChar2IntAlt(s1, s2));
+ expectEquals(1497988, sadChar2IntAlt2(s1, s2));
+ expectEquals(1497988L, sadChar2Long(s1, s2));
+ expectEquals(1497989L, sadChar2LongAt1(s1, s2));
System.out.println("passed");
}
diff --git a/test/660-checker-simd-sad-short2/expected.txt b/test/660-checker-simd-sad-short2/expected.txt
new file mode 100644
index 0000000..b0aad4d
--- /dev/null
+++ b/test/660-checker-simd-sad-short2/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/660-checker-simd-sad-short2/info.txt b/test/660-checker-simd-sad-short2/info.txt
new file mode 100644
index 0000000..b56c119
--- /dev/null
+++ b/test/660-checker-simd-sad-short2/info.txt
@@ -0,0 +1 @@
+Functional tests on SAD vectorization.
diff --git a/test/660-checker-simd-sad-short2/src/Main.java b/test/660-checker-simd-sad-short2/src/Main.java
new file mode 100644
index 0000000..7acc490
--- /dev/null
+++ b/test/660-checker-simd-sad-short2/src/Main.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/**
+ * Tests for SAD (sum of absolute differences).
+ *
+ * Special case, char array that is first casted to short, forcing sign extension.
+ */
+public class Main {
+
+ // TODO: lower precision still coming, b/64091002
+
+ private static short sadCastedChar2Short(char[] s1, char[] s2) {
+ int min_length = Math.min(s1.length, s2.length);
+ short sad = 0;
+ for (int i = 0; i < min_length; i++) {
+ sad += Math.abs(((short) s1[i]) - ((short) s2[i]));
+ }
+ return sad;
+ }
+
+ private static short sadCastedChar2ShortAlt(char[] s1, char[] s2) {
+ int min_length = Math.min(s1.length, s2.length);
+ short sad = 0;
+ for (int i = 0; i < min_length; i++) {
+ short s = (short) s1[i];
+ short p = (short) s2[i];
+ sad += s >= p ? s - p : p - s;
+ }
+ return sad;
+ }
+
+ private static short sadCastedChar2ShortAlt2(char[] s1, char[] s2) {
+ int min_length = Math.min(s1.length, s2.length);
+ short sad = 0;
+ for (int i = 0; i < min_length; i++) {
+ short s = (short) s1[i];
+ short p = (short) s2[i];
+ int x = s - p;
+ if (x < 0) x = -x;
+ sad += x;
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadCastedChar2Int(char[], char[]) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START-ARM64: int Main.sadCastedChar2Int(char[], char[]) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static int sadCastedChar2Int(char[] s1, char[] s2) {
+ int min_length = Math.min(s1.length, s2.length);
+ int sad = 0;
+ for (int i = 0; i < min_length; i++) {
+ sad += Math.abs(((short) s1[i]) - ((short) s2[i]));
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadCastedChar2IntAlt(char[], char[]) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Cnv2>>,<<Cnv1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START-ARM64: int Main.sadCastedChar2IntAlt(char[], char[]) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static int sadCastedChar2IntAlt(char[] s1, char[] s2) {
+ int min_length = Math.min(s1.length, s2.length);
+ int sad = 0;
+ for (int i = 0; i < min_length; i++) {
+ short s = (short) s1[i];
+ short p = (short) s2[i];
+ sad += s >= p ? s - p : p - s;
+ }
+ return sad;
+ }
+
+ /// CHECK-START: int Main.sadCastedChar2IntAlt2(char[], char[]) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Cnv1>>,<<Cnv2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START-ARM64: int Main.sadCastedChar2IntAlt2(char[], char[]) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<Cons0>>] loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static int sadCastedChar2IntAlt2(char[] s1, char[] s2) {
+ int min_length = Math.min(s1.length, s2.length);
+ int sad = 0;
+ for (int i = 0; i < min_length; i++) {
+ short s = (short) s1[i];
+ short p = (short) s2[i];
+ int x = s - p;
+ if (x < 0) x = -x;
+ sad += x;
+ }
+ return sad;
+ }
+
+ /// CHECK-START: long Main.sadCastedChar2Long(char[], char[]) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv3:j\d+>> TypeConversion [<<Cnv1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv4:j\d+>> TypeConversion [<<Cnv2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv3>>,<<Cnv4>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START-ARM64: long Main.sadCastedChar2Long(char[], char[]) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 0 loop:none
+ /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static long sadCastedChar2Long(char[] s1, char[] s2) {
+ int min_length = Math.min(s1.length, s2.length);
+ long sad = 0;
+ for (int i = 0; i < min_length; i++) {
+ long x = (short) s1[i];
+ long y = (short) s2[i];
+ sad += Math.abs(x - y);
+ }
+ return sad;
+ }
+
+ /// CHECK-START: long Main.sadCastedChar2LongAt1(char[], char[]) loop_optimization (before)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:j\d+>> Phi [<<ConsL>>,{{j\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get2:c\d+>> ArrayGet [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv1:s\d+>> TypeConversion [<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv2:s\d+>> TypeConversion [<<Get2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv3:j\d+>> TypeConversion [<<Cnv1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Cnv4:j\d+>> TypeConversion [<<Cnv2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Cnv3>>,<<Cnv4>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi2>>,<<Intrin>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons1>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START-ARM64: long Main.sadCastedChar2LongAt1(char[], char[]) loop_optimization (after)
+ /// CHECK-DAG: <<Cons0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Cons8:i\d+>> IntConstant 8 loop:none
+ /// CHECK-DAG: <<ConsL:j\d+>> LongConstant 1 loop:none
+ /// CHECK-DAG: <<Set:d\d+>> VecSetScalars [<<ConsL>>] loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Cons0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:d\d+>> Phi [<<Set>>,{{d\d+}}] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load1:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Load2:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<SAD:d\d+>> VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: Add [<<Phi1>>,<<Cons8>>] loop:<<Loop>> outer_loop:none
+ private static long sadCastedChar2LongAt1(char[] s1, char[] s2) {
+ int min_length = Math.min(s1.length, s2.length);
+ long sad = 1; // starts at 1
+ for (int i = 0; i < min_length; i++) {
+ long x = (short) s1[i];
+ long y = (short) s2[i];
+ sad += Math.abs(x - y);
+ }
+ return sad;
+ }
+
+ public static void main(String[] args) {
+ // Cross-test the two most extreme values individually.
+ char[] s1 = { 0, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ char[] s2 = { 0, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ expectEquals(-1, sadCastedChar2Short(s1, s2));
+ expectEquals(-1, sadCastedChar2Short(s2, s1));
+ expectEquals(-1, sadCastedChar2ShortAlt(s1, s2));
+ expectEquals(-1, sadCastedChar2ShortAlt(s2, s1));
+ expectEquals(-1, sadCastedChar2ShortAlt2(s1, s2));
+ expectEquals(-1, sadCastedChar2ShortAlt2(s2, s1));
+ expectEquals(65535, sadCastedChar2Int(s1, s2));
+ expectEquals(65535, sadCastedChar2Int(s2, s1));
+ expectEquals(65535, sadCastedChar2IntAlt(s1, s2));
+ expectEquals(65535, sadCastedChar2IntAlt(s2, s1));
+ expectEquals(65535, sadCastedChar2IntAlt2(s1, s2));
+ expectEquals(65535, sadCastedChar2IntAlt2(s2, s1));
+ expectEquals(65535L, sadCastedChar2Long(s1, s2));
+ expectEquals(65535L, sadCastedChar2Long(s2, s1));
+ expectEquals(65536L, sadCastedChar2LongAt1(s1, s2));
+ expectEquals(65536L, sadCastedChar2LongAt1(s2, s1));
+
+ // Use cross-values to test all cases.
+ char[] interesting = {
+ (char) 0x0000,
+ (char) 0x0001,
+ (char) 0x0002,
+ (char) 0x1234,
+ (char) 0x8000,
+ (char) 0x8001,
+ (char) 0x7fff,
+ (char) 0xffff
+ };
+ int n = interesting.length;
+ int m = n * n + 1;
+ s1 = new char[m];
+ s2 = new char[m];
+ int k = 0;
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ s1[k] = interesting[i];
+ s2[k] = interesting[j];
+ k++;
+ }
+ }
+ s1[k] = 10;
+ s2[k] = 2;
+ expectEquals(-18932, sadCastedChar2Short(s1, s2));
+ expectEquals(-18932, sadCastedChar2ShortAlt(s1, s2));
+ expectEquals(-18932, sadCastedChar2ShortAlt2(s1, s2));
+ expectEquals(1291788, sadCastedChar2Int(s1, s2));
+ expectEquals(1291788, sadCastedChar2IntAlt(s1, s2));
+ expectEquals(1291788, sadCastedChar2IntAlt2(s1, s2));
+ expectEquals(1291788L, sadCastedChar2Long(s1, s2));
+ expectEquals(1291789L, sadCastedChar2LongAt1(s1, s2));
+
+ System.out.println("passed");
+ }
+
+ private static void expectEquals(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals(long expected, long result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+}
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index d45d009..cc19afc 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -115,82 +115,9 @@
# Keep going after encountering a test failure?
ART_TEST_KEEP_GOING = _getEnvBoolean('ART_TEST_KEEP_GOING', True)
-# Do you want all tests, even those that are time consuming?
-ART_TEST_FULL = _getEnvBoolean('ART_TEST_FULL', False)
-
-# Do you want interpreter tests run?
-ART_TEST_INTERPRETER = _getEnvBoolean('ART_TEST_INTERPRETER', ART_TEST_FULL)
-ART_TEST_INTERPRETER_ACCESS_CHECKS = _getEnvBoolean('ART_TEST_INTERPRETER_ACCESS_CHECKS',
- ART_TEST_FULL)
-
-# Do you want JIT tests run?
-ART_TEST_JIT = _getEnvBoolean('ART_TEST_JIT', ART_TEST_FULL)
-
-# Do you want optimizing compiler tests run?
-ART_TEST_OPTIMIZING = _getEnvBoolean('ART_TEST_OPTIMIZING', ART_TEST_FULL)
-
-# Do you want to test the optimizing compiler with graph coloring register allocation?
-ART_TEST_OPTIMIZING_GRAPH_COLOR = _getEnvBoolean('ART_TEST_OPTIMIZING_GRAPH_COLOR', ART_TEST_FULL)
-
-# Do you want to do run-tests with profiles?
-ART_TEST_SPEED_PROFILE = _getEnvBoolean('ART_TEST_SPEED_PROFILE', ART_TEST_FULL)
-
-# Do we want to test PIC-compiled tests ("apps")?
-ART_TEST_PIC_TEST = _getEnvBoolean('ART_TEST_PIC_TEST', ART_TEST_FULL)
-# Do you want tracing tests run?
-ART_TEST_TRACE = _getEnvBoolean('ART_TEST_TRACE', ART_TEST_FULL)
-
-# Do you want tracing tests (streaming mode) run?
-ART_TEST_TRACE_STREAM = _getEnvBoolean('ART_TEST_TRACE_STREAM', ART_TEST_FULL)
-
-# Do you want tests with GC verification enabled run?
-ART_TEST_GC_VERIFY = _getEnvBoolean('ART_TEST_GC_VERIFY', ART_TEST_FULL)
-
-# Do you want tests with the GC stress mode enabled run?
-ART_TEST_GC_STRESS = _getEnvBoolean('ART_TEST_GC_STRESS', ART_TEST_FULL)
-
-# Do you want tests with the JNI forcecopy mode enabled run?
-ART_TEST_JNI_FORCECOPY = _getEnvBoolean('ART_TEST_JNI_FORCECOPY', ART_TEST_FULL)
-
-# Do you want run-tests with relocation disabled run?
-ART_TEST_RUN_TEST_RELOCATE = _getEnvBoolean('ART_TEST_RUN_TEST_RELOCATE', ART_TEST_FULL)
-
-# Do you want run-tests with prebuilding?
-ART_TEST_RUN_TEST_PREBUILD = _getEnvBoolean('ART_TEST_RUN_TEST_PREBUILD', ART_TEST_FULL)
-
-# Do you want run-tests with no prebuilding enabled run?
-ART_TEST_RUN_TEST_NO_PREBUILD = _getEnvBoolean('ART_TEST_RUN_TEST_NO_PREBUILD', ART_TEST_FULL)
-
-# Do you want run-tests with a pregenerated core.art?
-ART_TEST_RUN_TEST_IMAGE = _getEnvBoolean('ART_TEST_RUN_TEST_IMAGE', ART_TEST_FULL)
-
-# Do you want run-tests without a pregenerated core.art?
-ART_TEST_RUN_TEST_NO_IMAGE = _getEnvBoolean('ART_TEST_RUN_TEST_NO_IMAGE', ART_TEST_FULL)
-
-# Do you want run-tests with relocation enabled but patchoat failing?
-ART_TEST_RUN_TEST_RELOCATE_NO_PATCHOAT = _getEnvBoolean('ART_TEST_RUN_TEST_RELOCATE_NO_PATCHOAT',
- ART_TEST_FULL)
-
-# Do you want run-tests without a dex2oat?
-ART_TEST_RUN_TEST_NO_DEX2OAT = _getEnvBoolean('ART_TEST_RUN_TEST_NO_DEX2OAT', ART_TEST_FULL)
-
-# Do you want run-tests with libartd.so?
-ART_TEST_RUN_TEST_DEBUG = _getEnvBoolean('ART_TEST_RUN_TEST_DEBUG', ART_TEST_FULL)
-
-# Do you want run-tests with libart.so?
-ART_TEST_RUN_TEST_NDEBUG = _getEnvBoolean('ART_TEST_RUN_TEST_NDEBUG', ART_TEST_FULL)
-
# Do you want failed tests to have their artifacts cleaned up?
ART_TEST_RUN_TEST_ALWAYS_CLEAN = _getEnvBoolean('ART_TEST_RUN_TEST_ALWAYS_CLEAN', True)
-# Do you want run-tests with the --debuggable flag
-ART_TEST_RUN_TEST_DEBUGGABLE = _getEnvBoolean('ART_TEST_RUN_TEST_DEBUGGABLE', ART_TEST_FULL)
-
-# Do you want to test multi-part boot-image functionality?
-ART_TEST_RUN_TEST_MULTI_IMAGE = _getEnvBoolean('ART_TEST_RUN_TEST_MULTI_IMAGE', ART_TEST_FULL)
-
-ART_TEST_DEBUG_GC = _getEnvBoolean('ART_TEST_DEBUG_GC', False)
-
ART_TEST_BISECTION = _getEnvBoolean('ART_TEST_BISECTION', False)
DEX2OAT_HOST_INSTRUCTION_SET_FEATURES = _env.get('DEX2OAT_HOST_INSTRUCTION_SET_FEATURES')
@@ -217,8 +144,6 @@
# Note: ART_2ND_PHONY_TEST_HOST_SUFFIX is 2ND_ART_PHONY_HOST_TARGET_SUFFIX in .mk files
# Python does not let us have variable names starting with a digit, so it has differ.
-ART_TEST_RUN_TEST_JVMTI_STRESS = _getEnvBoolean('ART_TEST_RUN_TEST_JVMTI_STRESS', ART_TEST_FULL)
-
if TARGET_2ND_ARCH:
if "64" in TARGET_ARCH:
ART_PHONY_TEST_TARGET_SUFFIX = "64"
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index e07198b..2a772ff 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -45,6 +45,7 @@
"""
import argparse
+import collections
import fnmatch
import itertools
import json
@@ -60,21 +61,6 @@
import env
from target_config import target_config
-TARGET_TYPES = set()
-RUN_TYPES = set()
-PREBUILD_TYPES = set()
-COMPILER_TYPES = set()
-RELOCATE_TYPES = set()
-TRACE_TYPES = set()
-GC_TYPES = set()
-JNI_TYPES = set()
-IMAGE_TYPES = set()
-PICTEST_TYPES = set()
-DEBUGGABLE_TYPES = set()
-ADDRESS_SIZES = set()
-OPTIMIZING_COMPILER_TYPES = set()
-JVMTI_TYPES = set()
-ADDRESS_SIZES_TARGET = {'host': set(), 'target': set()}
# timeout for individual tests.
# TODO: make it adjustable per tests and for buildbots
timeout = 3000 # 50 minutes
@@ -128,6 +114,12 @@
gdb_arg = ''
stop_testrunner = False
dex2oat_jobs = -1 # -1 corresponds to default threads for dex2oat
+run_all_configs = False
+
+# Dict to store user requested test variants.
+# key: variant_type.
+# value: set of variants user wants to run of type <key>.
+_user_input_variants = collections.defaultdict(set)
def gather_test_info():
"""The method gathers test information about the test to be run which includes
@@ -151,7 +143,7 @@
VARIANT_TYPE_DICT['jvmti'] = {'no-jvmti', 'jvmti-stress', 'redefine-stress', 'trace-stress',
'field-stress', 'step-stress'}
VARIANT_TYPE_DICT['compiler'] = {'interp-ac', 'interpreter', 'jit', 'optimizing',
- 'regalloc_gc', 'speed-profile'}
+ 'regalloc_gc', 'speed-profile'}
for v_type in VARIANT_TYPE_DICT:
TOTAL_VARIANTS_SET = TOTAL_VARIANTS_SET.union(VARIANT_TYPE_DICT.get(v_type))
@@ -173,106 +165,75 @@
# Bisection search writes to standard output.
env.ART_TEST_QUIET = False
- if not TARGET_TYPES:
- TARGET_TYPES.add('host')
- TARGET_TYPES.add('target')
+ global _user_input_variants
+ global run_all_configs
+ if run_all_configs:
+ target_types = _user_input_variants['target']
+ _user_input_variants = VARIANT_TYPE_DICT
+ _user_input_variants['target'] = target_types
- if env.ART_TEST_RUN_TEST_NO_PREBUILD:
- PREBUILD_TYPES.add('no-prebuild')
- if env.ART_TEST_RUN_TEST_NO_DEX2OAT:
- PREBUILD_TYPES.add('no-dex2oat')
- if env.ART_TEST_RUN_TEST_PREBUILD or not PREBUILD_TYPES: # Default
- PREBUILD_TYPES.add('prebuild')
+ if not _user_input_variants['target']:
+ _user_input_variants['target'].add('host')
+ _user_input_variants['target'].add('target')
- if env.ART_TEST_INTERPRETER_ACCESS_CHECKS:
- COMPILER_TYPES.add('interp-ac')
- if env.ART_TEST_INTERPRETER:
- COMPILER_TYPES.add('interpreter')
- if env.ART_TEST_JIT:
- COMPILER_TYPES.add('jit')
- if env.ART_TEST_OPTIMIZING_GRAPH_COLOR:
- COMPILER_TYPES.add('regalloc_gc')
- OPTIMIZING_COMPILER_TYPES.add('regalloc_gc')
- if env.ART_TEST_OPTIMIZING:
- COMPILER_TYPES.add('optimizing')
- OPTIMIZING_COMPILER_TYPES.add('optimizing')
- if env.ART_TEST_SPEED_PROFILE:
- COMPILER_TYPES.add('speed-profile')
+ if not _user_input_variants['prebuild']: # Default
+ _user_input_variants['prebuild'].add('prebuild')
# By default only run without jvmti
- if not JVMTI_TYPES:
- JVMTI_TYPES.add('no-jvmti')
+ if not _user_input_variants['jvmti']:
+ _user_input_variants['jvmti'].add('no-jvmti')
# By default we run all 'compiler' variants.
- if not COMPILER_TYPES:
- COMPILER_TYPES.add('optimizing')
- COMPILER_TYPES.add('jit')
- COMPILER_TYPES.add('interpreter')
- COMPILER_TYPES.add('interp-ac')
- COMPILER_TYPES.add('speed-profile')
- OPTIMIZING_COMPILER_TYPES.add('optimizing')
+ if not _user_input_variants['compiler']:
+ _user_input_variants['compiler'].add('optimizing')
+ _user_input_variants['compiler'].add('jit')
+ _user_input_variants['compiler'].add('interpreter')
+ _user_input_variants['compiler'].add('interp-ac')
+ _user_input_variants['compiler'].add('speed-profile')
- if env.ART_TEST_RUN_TEST_RELOCATE:
- RELOCATE_TYPES.add('relocate')
- if env.ART_TEST_RUN_TEST_RELOCATE_NO_PATCHOAT:
- RELOCATE_TYPES.add('relocate-npatchoat')
- if not RELOCATE_TYPES: # Default
- RELOCATE_TYPES.add('no-relocate')
+ if not _user_input_variants['relocate']: # Default
+ _user_input_variants['relocate'].add('no-relocate')
- if env.ART_TEST_TRACE:
- TRACE_TYPES.add('trace')
- if env.ART_TEST_TRACE_STREAM:
- TRACE_TYPES.add('stream')
- if not TRACE_TYPES: # Default
- TRACE_TYPES.add('ntrace')
+ if not _user_input_variants['trace']: # Default
+ _user_input_variants['trace'].add('ntrace')
- if env.ART_TEST_GC_STRESS:
- GC_TYPES.add('gcstress')
- if env.ART_TEST_GC_VERIFY:
- GC_TYPES.add('gcverify')
- if not GC_TYPES: # Default
- GC_TYPES.add('cms')
+ if not _user_input_variants['gc']: # Default
+ _user_input_variants['gc'].add('cms')
- if env.ART_TEST_JNI_FORCECOPY:
- JNI_TYPES.add('forcecopy')
- if not JNI_TYPES: # Default
- JNI_TYPES.add('checkjni')
+ if not _user_input_variants['jni']: # Default
+ _user_input_variants['jni'].add('checkjni')
- if env.ART_TEST_RUN_TEST_NO_IMAGE:
- IMAGE_TYPES.add('no-image')
- if env.ART_TEST_RUN_TEST_MULTI_IMAGE:
- IMAGE_TYPES.add('multipicimage')
- if env.ART_TEST_RUN_TEST_IMAGE or not IMAGE_TYPES: # Default
- IMAGE_TYPES.add('picimage')
+ if not _user_input_variants['image']: # Default
+ _user_input_variants['image'].add('picimage')
- if env.ART_TEST_PIC_TEST:
- PICTEST_TYPES.add('pictest')
- if not PICTEST_TYPES: # Default
- PICTEST_TYPES.add('npictest')
- if env.ART_TEST_RUN_TEST_NDEBUG:
- RUN_TYPES.add('ndebug')
- if env.ART_TEST_RUN_TEST_DEBUG or not RUN_TYPES: # Default
- RUN_TYPES.add('debug')
+ if not _user_input_variants['pictest']: # Default
+ _user_input_variants['pictest'].add('npictest')
- if env.ART_TEST_RUN_TEST_DEBUGGABLE:
- DEBUGGABLE_TYPES.add('debuggable')
- if not DEBUGGABLE_TYPES: # Default
- DEBUGGABLE_TYPES.add('ndebuggable')
+ if not _user_input_variants['debuggable']: # Default
+ _user_input_variants['debuggable'].add('ndebuggable')
- if not ADDRESS_SIZES:
- ADDRESS_SIZES_TARGET['target'].add(env.ART_PHONY_TEST_TARGET_SUFFIX)
- ADDRESS_SIZES_TARGET['host'].add(env.ART_PHONY_TEST_HOST_SUFFIX)
+ if not _user_input_variants['run']: # Default
+ _user_input_variants['run'].add('debug')
+
+ _user_input_variants['address_sizes_target'] = collections.defaultdict(set)
+ if not _user_input_variants['address_sizes']:
+ _user_input_variants['address_sizes_target']['target'].add(
+ env.ART_PHONY_TEST_TARGET_SUFFIX)
+ _user_input_variants['address_sizes_target']['host'].add(
+ env.ART_PHONY_TEST_HOST_SUFFIX)
if env.ART_TEST_RUN_TEST_2ND_ARCH:
- ADDRESS_SIZES_TARGET['host'].add(env.ART_2ND_PHONY_TEST_HOST_SUFFIX)
- ADDRESS_SIZES_TARGET['target'].add(env.ART_2ND_PHONY_TEST_TARGET_SUFFIX)
+ _user_input_variants['address_sizes_target']['host'].add(
+ env.ART_2ND_PHONY_TEST_HOST_SUFFIX)
+ _user_input_variants['address_sizes_target']['target'].add(
+ env.ART_2ND_PHONY_TEST_TARGET_SUFFIX)
else:
- ADDRESS_SIZES_TARGET['host'] = ADDRESS_SIZES_TARGET['host'].union(ADDRESS_SIZES)
- ADDRESS_SIZES_TARGET['target'] = ADDRESS_SIZES_TARGET['target'].union(ADDRESS_SIZES)
+ _user_input_variants['address_sizes_target']['host'] = _user_input_variants['address_sizes']
+ _user_input_variants['address_sizes_target']['target'] = _user_input_variants['address_sizes']
global n_thread
if n_thread is -1:
- if 'target' in TARGET_TYPES:
+ if 'target' in _user_input_variants['target']:
n_thread = get_default_threads('target')
else:
n_thread = get_default_threads('host')
@@ -308,20 +269,12 @@
options_all = ''
global total_test_count
total_test_count = len(tests)
- total_test_count *= len(RUN_TYPES)
- total_test_count *= len(PREBUILD_TYPES)
- total_test_count *= len(RELOCATE_TYPES)
- total_test_count *= len(TRACE_TYPES)
- total_test_count *= len(GC_TYPES)
- total_test_count *= len(JNI_TYPES)
- total_test_count *= len(IMAGE_TYPES)
- total_test_count *= len(PICTEST_TYPES)
- total_test_count *= len(DEBUGGABLE_TYPES)
- total_test_count *= len(COMPILER_TYPES)
- total_test_count *= len(JVMTI_TYPES)
+ for variant_type in VARIANT_TYPE_DICT:
+ if not (variant_type == 'target' or 'address_sizes' in variant_type):
+ total_test_count *= len(_user_input_variants[variant_type])
target_address_combinations = 0
- for target in TARGET_TYPES:
- for address_size in ADDRESS_SIZES_TARGET[target]:
+ for target in _user_input_variants['target']:
+ for address_size in _user_input_variants['address_sizes_target'][target]:
target_address_combinations += 1
total_test_count *= target_address_combinations
@@ -345,14 +298,16 @@
if dex2oat_jobs != -1:
options_all += ' --dex2oat-jobs ' + str(dex2oat_jobs)
- config = itertools.product(tests, TARGET_TYPES, RUN_TYPES, PREBUILD_TYPES,
- COMPILER_TYPES, RELOCATE_TYPES, TRACE_TYPES,
- GC_TYPES, JNI_TYPES, IMAGE_TYPES, PICTEST_TYPES,
- DEBUGGABLE_TYPES, JVMTI_TYPES)
+ config = itertools.product(tests, _user_input_variants['target'], _user_input_variants['run'],
+ _user_input_variants['prebuild'], _user_input_variants['compiler'],
+ _user_input_variants['relocate'], _user_input_variants['trace'],
+ _user_input_variants['gc'], _user_input_variants['jni'],
+ _user_input_variants['image'], _user_input_variants['pictest'],
+ _user_input_variants['debuggable'], _user_input_variants['jvmti'])
for test, target, run, prebuild, compiler, relocate, trace, gc, \
jni, image, pictest, debuggable, jvmti in config:
- for address_size in ADDRESS_SIZES_TARGET[target]:
+ for address_size in _user_input_variants['address_sizes_target'][target]:
if stop_testrunner:
# When ART_TEST_KEEP_GOING is set to false, then as soon as a test
# fails, stop_testrunner is set to True. When this happens, the method
@@ -577,11 +532,10 @@
total_test_count)
if result == 'FAIL' or result == 'TIMEOUT':
- info += ('%s %s %s\n%s\n') % (
+ info += ('%s %s %s\n') % (
progress_info,
test_name,
- COLOR_ERROR + result + COLOR_NORMAL,
- failed_test_info)
+ COLOR_ERROR + result + COLOR_NORMAL)
else:
result_text = ''
if result == 'PASS':
@@ -810,19 +764,19 @@
regex += '(' + '|'.join(VARIANT_TYPE_DICT['address_sizes']) + ')$'
match = re.match(regex, test_name)
if match:
- TARGET_TYPES.add(match.group(1))
- RUN_TYPES.add(match.group(2))
- PREBUILD_TYPES.add(match.group(3))
- COMPILER_TYPES.add(match.group(4))
- RELOCATE_TYPES.add(match.group(5))
- TRACE_TYPES.add(match.group(6))
- GC_TYPES.add(match.group(7))
- JNI_TYPES.add(match.group(8))
- IMAGE_TYPES.add(match.group(9))
- PICTEST_TYPES.add(match.group(10))
- DEBUGGABLE_TYPES.add(match.group(11))
- JVMTI_TYPES.add(match.group(12))
- ADDRESS_SIZES.add(match.group(14))
+ _user_input_variants['target'].add(match.group(1))
+ _user_input_variants['run'].add(match.group(2))
+ _user_input_variants['prebuild'].add(match.group(3))
+ _user_input_variants['compiler'].add(match.group(4))
+ _user_input_variants['relocate'].add(match.group(5))
+ _user_input_variants['trace'].add(match.group(6))
+ _user_input_variants['gc'].add(match.group(7))
+ _user_input_variants['jni'].add(match.group(8))
+ _user_input_variants['image'].add(match.group(9))
+ _user_input_variants['pictest'].add(match.group(10))
+ _user_input_variants['debuggable'].add(match.group(11))
+ _user_input_variants['jvmti'].add(match.group(12))
+ _user_input_variants['address_sizes'].add(match.group(14))
return {match.group(13)}
raise ValueError(test_name + " is not a valid test")
@@ -871,6 +825,7 @@
global gdb_arg
global timeout
global dex2oat_jobs
+ global run_all_configs
parser = argparse.ArgumentParser(description="Runs all or a subset of the ART test suite.")
parser.add_argument('-t', '--test', dest='test', help='name of the test')
@@ -878,10 +833,7 @@
parser.add_argument('--timeout', default=timeout, type=int, dest='timeout')
for variant in TOTAL_VARIANTS_SET:
flag = '--' + variant
- flag_dest = variant.replace('-', '_')
- if variant == '32' or variant == '64':
- flag_dest = 'n' + flag_dest
- parser.add_argument(flag, action='store_true', dest=flag_dest)
+ parser.add_argument(flag, action='store_true', dest=variant)
parser.add_argument('--verbose', '-v', action='store_true', dest='verbose')
parser.add_argument('--dry-run', action='store_true', dest='dry_run')
parser.add_argument("--skip", action="append", dest="skips", default=[],
@@ -900,6 +852,8 @@
parser.add_argument('--gdb-arg', dest='gdb_arg')
parser.add_argument('--dex2oat-jobs', type=int, dest='dex2oat_jobs',
help='Number of dex2oat jobs')
+ parser.add_argument('-a', '--all', action='store_true', dest='run_all',
+ help="Run all the possible configurations for the input test set")
options = vars(parser.parse_args())
if options['build_target']:
@@ -910,82 +864,12 @@
env.EXTRA_DISABLED_TESTS.update(set(options['skips']))
if options['test']:
test = parse_test_name(options['test'])
- if options['pictest']:
- PICTEST_TYPES.add('pictest')
- if options['ndebug']:
- RUN_TYPES.add('ndebug')
- if options['interp_ac']:
- COMPILER_TYPES.add('interp-ac')
- if options['picimage']:
- IMAGE_TYPES.add('picimage')
- if options['n64']:
- ADDRESS_SIZES.add('64')
- if options['interpreter']:
- COMPILER_TYPES.add('interpreter')
- if options['jni']:
- JNI_TYPES.add('jni')
- if options['relocate_npatchoat']:
- RELOCATE_TYPES.add('relocate-npatchoat')
- if options['no_prebuild']:
- PREBUILD_TYPES.add('no-prebuild')
- if options['npictest']:
- PICTEST_TYPES.add('npictest')
- if options['no_dex2oat']:
- PREBUILD_TYPES.add('no-dex2oat')
- if options['jit']:
- COMPILER_TYPES.add('jit')
- if options['relocate']:
- RELOCATE_TYPES.add('relocate')
- if options['ndebuggable']:
- DEBUGGABLE_TYPES.add('ndebuggable')
- if options['no_image']:
- IMAGE_TYPES.add('no-image')
- if options['optimizing']:
- COMPILER_TYPES.add('optimizing')
- if options['speed_profile']:
- COMPILER_TYPES.add('speed-profile')
- if options['trace']:
- TRACE_TYPES.add('trace')
- if options['gcstress']:
- GC_TYPES.add('gcstress')
- if options['no_relocate']:
- RELOCATE_TYPES.add('no-relocate')
- if options['target']:
- TARGET_TYPES.add('target')
- if options['forcecopy']:
- JNI_TYPES.add('forcecopy')
- if options['n32']:
- ADDRESS_SIZES.add('32')
- if options['host']:
- TARGET_TYPES.add('host')
- if options['gcverify']:
- GC_TYPES.add('gcverify')
- if options['debuggable']:
- DEBUGGABLE_TYPES.add('debuggable')
- if options['prebuild']:
- PREBUILD_TYPES.add('prebuild')
- if options['debug']:
- RUN_TYPES.add('debug')
- if options['checkjni']:
- JNI_TYPES.add('checkjni')
- if options['ntrace']:
- TRACE_TYPES.add('ntrace')
- if options['cms']:
- GC_TYPES.add('cms')
- if options['multipicimage']:
- IMAGE_TYPES.add('multipicimage')
- if options['jvmti_stress']:
- JVMTI_TYPES.add('jvmti-stress')
- if options['redefine_stress']:
- JVMTI_TYPES.add('redefine-stress')
- if options['field_stress']:
- JVMTI_TYPES.add('field-stress')
- if options['step_stress']:
- JVMTI_TYPES.add('step-stress')
- if options['trace_stress']:
- JVMTI_TYPES.add('trace-stress')
- if options['no_jvmti']:
- JVMTI_TYPES.add('no-jvmti')
+
+ for variant_type in VARIANT_TYPE_DICT:
+ for variant in VARIANT_TYPE_DICT[variant_type]:
+ if options.get(variant):
+ _user_input_variants[variant_type].add(variant)
+
if options['verbose']:
verbose = True
if options['n_thread']:
@@ -1002,6 +886,8 @@
timeout = options['timeout']
if options['dex2oat_jobs']:
dex2oat_jobs = options['dex2oat_jobs']
+ if options['run_all']:
+ run_all_configs = True
return test
@@ -1011,9 +897,9 @@
setup_test_env()
if build:
build_targets = ''
- if 'host' in TARGET_TYPES:
+ if 'host' in _user_input_variants['target']:
build_targets += 'test-art-host-run-test-dependencies'
- if 'target' in TARGET_TYPES:
+ if 'target' in _user_input_variants['target']:
build_targets += 'test-art-target-run-test-dependencies'
build_command = 'make'
build_command += ' -j'