ART: Special form of lock aliasing
Check whether the instruction immediately before a monitor-enter
is a move-object, establishing previously untracked lock aliasing
in a low-overhead manner.
Bug: 20102779
Bug: 21169615
Bug: 21988678
Bug: 23300986
Change-Id: Ia10d6219357e7bce29f58134637b07d3f4857b2f
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 1828b91..a506071 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -1956,6 +1956,32 @@
}
case Instruction::MONITOR_ENTER:
work_line_->PushMonitor(this, inst->VRegA_11x(), work_insn_idx_);
+ // Check whether the previous instruction is a move-object with vAA as a source, creating
+ // untracked lock aliasing.
+ if (0 != work_insn_idx_ && !insn_flags_[work_insn_idx_].IsBranchTarget()) {
+ uint32_t prev_idx = work_insn_idx_ - 1;
+ while (0 != prev_idx && !insn_flags_[prev_idx].IsOpcode()) {
+ prev_idx--;
+ }
+ const Instruction* prev_inst = Instruction::At(code_item_->insns_ + prev_idx);
+ switch (prev_inst->Opcode()) {
+ case Instruction::MOVE_OBJECT:
+ case Instruction::MOVE_OBJECT_16:
+ case Instruction::MOVE_OBJECT_FROM16:
+ if (prev_inst->VRegB() == inst->VRegA_11x()) {
+ // Redo the copy. This won't change the register types, but update the lock status
+ // for the aliased register.
+ work_line_->CopyRegister1(this,
+ prev_inst->VRegA(),
+ prev_inst->VRegB(),
+ kTypeCategoryRef);
+ }
+ break;
+
+ default: // Other instruction types ignored.
+ break;
+ }
+ }
break;
case Instruction::MONITOR_EXIT:
/*