Merge "Fix accidental IMT and root marking regression"
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 5e784d7..a381315 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -802,9 +802,9 @@
current->SetRegister(reg);
if (!current->IsDeadAt(free_until[reg])) {
// If the register is only available for a subset of live ranges
- // covered by `current`, split `current` at the position where
+ // covered by `current`, split `current` before the position where
// the register is not available anymore.
- LiveInterval* split = Split(current, free_until[reg]);
+ LiveInterval* split = SplitBetween(current, current->GetStart(), free_until[reg]);
DCHECK(split != nullptr);
AddSorted(unhandled_, split);
}
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index d07a14a..b7da362 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -426,6 +426,13 @@
// Add an artifical range to cover the temps that will be put in the unhandled list.
LiveInterval* unhandled = graph->GetEntryBlock()->GetFirstInstruction()->GetLiveInterval();
unhandled->AddLoopRange(0, 60);
+
+ // Populate the instructions in the liveness object, to please the register allocator.
+ for (size_t i = 0; i < 60; ++i) {
+ liveness.instructions_from_lifetime_position_.Add(
+ graph->GetEntryBlock()->GetFirstInstruction());
+ }
+
// For SSA value intervals, only an interval resulted from a split may intersect
// with inactive intervals.
unhandled = register_allocator.Split(unhandled, 5);
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 250eb04..d5f977f 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -341,6 +341,7 @@
// starts at. If one location is a register we return it as a hint. This
// will avoid a move between the two blocks.
HBasicBlock* block = liveness.GetBlockFromPosition(GetStart() / 2);
+ size_t next_register_use = FirstRegisterUse();
for (size_t i = 0; i < block->GetPredecessors().Size(); ++i) {
size_t position = block->GetPredecessors().Get(i)->GetLifetimeEnd() - 1;
// We know positions above GetStart() do not have a location yet.
@@ -348,7 +349,9 @@
LiveInterval* existing = GetParent()->GetSiblingAt(position);
if (existing != nullptr
&& existing->HasRegister()
- && (free_until[existing->GetRegister()] > GetStart())) {
+ // It's worth using that register if it is available until
+ // the next use.
+ && (free_until[existing->GetRegister()] >= next_register_use)) {
return existing->GetRegister();
}
}
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 4cbe29a..4667825 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -1219,6 +1219,7 @@
size_t number_of_ssa_values_;
ART_FRIEND_TEST(RegisterAllocatorTest, SpillInactive);
+ ART_FRIEND_TEST(RegisterAllocatorTest, FreeUntil);
DISALLOW_COPY_AND_ASSIGN(SsaLivenessAnalysis);
};
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f25e4ee..9faaa4a 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2860,7 +2860,16 @@
if (have_pending_hard_failure_) {
if (Runtime::Current()->IsAotCompiler()) {
/* When AOT compiling, check that the last failure is a hard failure */
- CHECK_EQ(failures_[failures_.size() - 1], VERIFY_ERROR_BAD_CLASS_HARD);
+ if (failures_[failures_.size() - 1] != VERIFY_ERROR_BAD_CLASS_HARD) {
+ LOG(ERROR) << "Pending failures:";
+ for (auto& error : failures_) {
+ LOG(ERROR) << error;
+ }
+ for (auto& error_msg : failure_messages_) {
+ LOG(ERROR) << error_msg->str();
+ }
+ LOG(FATAL) << "Pending hard failure, but last failure not hard.";
+ }
}
/* immediate failure, reject class */
info_messages_ << "Rejecting opcode " << inst->DumpString(dex_file_);
@@ -3358,13 +3367,13 @@
if (!src_type.IsIntegralTypes()) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "register v" << get_reg << " has type " << src_type
<< " but expected " << reg_type;
- return res_method;
+ return nullptr;
}
} else if (!work_line_->VerifyRegisterType(this, get_reg, reg_type)) {
// Continue on soft failures. We need to find possible hard failures to avoid problems in the
// compiler.
if (have_pending_hard_failure_) {
- return res_method;
+ return nullptr;
}
}
sig_registers += reg_type.IsLongOrDoubleTypes() ? 2 : 1;
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index 5922257..a6b216b 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -15,4 +15,5 @@
MoveExc
MoveExceptionOnEntry
EmptySparseSwitch
+b/20224106
Done!
diff --git a/test/800-smali/smali/b_20224106.smali b/test/800-smali/smali/b_20224106.smali
new file mode 100644
index 0000000..78009db
--- /dev/null
+++ b/test/800-smali/smali/b_20224106.smali
@@ -0,0 +1,16 @@
+.class public LB20224106;
+
+# Test that a hard + soft verifier failure in invoke-interface does not lead to
+# an order abort (the last failure must be hard).
+
+.super Ljava/lang/Object;
+
+.method public static run(LB20224106;Ljava/lang/Object;)V
+ .registers 4
+ # Two failure points here:
+ # 1) There is a parameter type mismatch. The formal type is integral (int), but the actual
+ # type is reference.
+ # 2) The receiver is not an interface or Object
+ invoke-interface {v2, v3}, Ljava/net/DatagramSocket;->checkPort(I)V
+ return-void
+.end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 3e0b1f9..3e88364 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -79,6 +79,8 @@
"moveExceptionOnEntry", new Object[]{0}, new VerifyError(), null));
testCases.add(new TestCase("EmptySparseSwitch", "EmptySparseSwitch", "run", null, null,
null));
+ testCases.add(new TestCase("b/20224106", "B20224106", "run", null, new VerifyError(),
+ 0));
}
public void runTests() {
diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh
index a19fd15..344d2ded 100755
--- a/tools/run-libcore-tests.sh
+++ b/tools/run-libcore-tests.sh
@@ -19,11 +19,16 @@
exit 1
fi
-# Jar containing all the tests.
+# Jar containing jsr166 tests.
+jsr166_test_jar=out/target/common/obj/JAVA_LIBRARIES/jsr166-tests_intermediates/javalib.jar
+
+# Jar containing all the other tests.
test_jar=out/target/common/obj/JAVA_LIBRARIES/core-tests_intermediates/javalib.jar
+
if [ ! -f $test_jar ]; then
- echo "Before running, you must build core-tests and vogar: make core-tests vogar vogar.jar"
+ echo "Before running, you must build core-tests, jsr166-tests and vogar: \
+ make core-tests jsr166-tests vogar vogar.jar"
exit 1
fi
@@ -54,9 +59,10 @@
"org.apache.harmony.tests.java.util"
"org.apache.harmony.tests.java.text"
"org.apache.harmony.tests.javax.security"
- "tests.java.lang.String")
+ "tests.java.lang.String"
+ "jsr166")
# Run the tests using vogar.
echo "Running tests for the following test packages:"
echo ${working_packages[@]} | tr " " "\n"
-vogar $@ --expectations art/tools/libcore_failures.txt --classpath $test_jar ${working_packages[@]}
+vogar $@ --expectations art/tools/libcore_failures.txt --classpath $jsr166_test_jar --classpath $test_jar ${working_packages[@]}