ART: Handle clobbering in verifier peephole
Bug: 121191566
Test: art/test/testrunner/testrunner.py -b --host -t 800
Test: m test-art-host
Change-Id: I1c983fca5f92570f9dba4fb8ef3bcd3c7d3854f2
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 1679821..91eba21 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2654,6 +2654,7 @@
// See if instance-of was preceded by a move-object operation, common due to the small
// register encoding space of instance-of, and propagate type information to the source
// of the move-object.
+ // Note: this is only valid if the move source was not clobbered.
uint32_t move_idx = instance_of_idx - 1;
while (0 != move_idx && !GetInstructionFlags(move_idx).IsOpcode()) {
move_idx--;
@@ -2663,28 +2664,25 @@
work_insn_idx_)) {
break;
}
+ auto maybe_update_fn = [&instance_of_inst, update_line, this, &cast_type](
+ uint16_t move_src,
+ uint16_t move_trg)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (move_trg == instance_of_inst.VRegB_22c() &&
+ move_src != instance_of_inst.VRegA_22c()) {
+ update_line->SetRegisterType<LockOp::kKeep>(this, move_src, cast_type);
+ }
+ };
const Instruction& move_inst = code_item_accessor_.InstructionAt(move_idx);
switch (move_inst.Opcode()) {
case Instruction::MOVE_OBJECT:
- if (move_inst.VRegA_12x() == instance_of_inst.VRegB_22c()) {
- update_line->SetRegisterType<LockOp::kKeep>(this,
- move_inst.VRegB_12x(),
- cast_type);
- }
+ maybe_update_fn(move_inst.VRegB_12x(), move_inst.VRegA_12x());
break;
case Instruction::MOVE_OBJECT_FROM16:
- if (move_inst.VRegA_22x() == instance_of_inst.VRegB_22c()) {
- update_line->SetRegisterType<LockOp::kKeep>(this,
- move_inst.VRegB_22x(),
- cast_type);
- }
+ maybe_update_fn(move_inst.VRegB_22x(), move_inst.VRegA_22x());
break;
case Instruction::MOVE_OBJECT_16:
- if (move_inst.VRegA_32x() == instance_of_inst.VRegB_22c()) {
- update_line->SetRegisterType<LockOp::kKeep>(this,
- move_inst.VRegB_32x(),
- cast_type);
- }
+ maybe_update_fn(move_inst.VRegB_32x(), move_inst.VRegA_32x());
break;
default:
break;
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index f3c3f03..291de72 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -73,4 +73,5 @@
b/30458218
b/31313170
ConstClassAliasing
+b/121191566
Done!
diff --git a/test/800-smali/smali/b_121191566.smali b/test/800-smali/smali/b_121191566.smali
new file mode 100644
index 0000000..bcf9ef5
--- /dev/null
+++ b/test/800-smali/smali/b_121191566.smali
@@ -0,0 +1,26 @@
+.class public LB121191566;
+.super Ljava/lang/Object;
+
+
+.method public constructor <init>()V
+.registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public static run(Ljava/lang/Object;)Z
+.registers 5
+ move-object v3, v4
+ instance-of v4, v3, Ljava/lang/String;
+ if-eqz v4, :Branch
+ # The peephole must not overwrite v4 (from the move-object). Use an integral move
+ # to check.
+ move v0, v4
+ goto :End
+:Branch
+ # See above.
+ move v0, v4
+:End
+ # Triple-check: the merge should be consistent.
+ return v0
+.end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 9b06e9e..d7979e1 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -193,6 +193,8 @@
testCases.add(new TestCase("b/31313170", "B31313170", "run", null, null, 0));
testCases.add(new TestCase("ConstClassAliasing", "ConstClassAliasing", "run", null, null,
null, true));
+ testCases.add(new TestCase("b/121191566", "B121191566", "run", new Object[] { "a" }, null,
+ true, false));
}
public void runTests() {