Avoid removing new-instance instruction twice.
Includes a fail-before/pass-after regression test.
Rationale:
In some corner cases, one new instance reached more than one
java.lang.String.<init> method call. As a result, the new
instance instruction appeared multiple times in the vector
uninitialized_strings_. A second removal crashes the compiler.
This change list avoid the crash by simply skipping instructions
that are already removed.
BUG=27847265
Change-Id: I7f8a4f84ea3c184e1529ec3e90bd6749c83c445b
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 09ca8b7..294d00f 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -458,6 +458,7 @@
}
for (HNewInstance* new_instance : uninitialized_strings_) {
+ DCHECK(new_instance->IsInBlock());
// Replace NewInstance of String with NullConstant if not used prior to
// calling StringFactory. In case of deoptimization, the interpreter is
// expected to skip null check on the `this` argument of the StringFactory call.
@@ -972,7 +973,13 @@
// Replacing the NewInstance might render it redundant. Keep a list of these
// to be visited once it is clear whether it is has remaining uses.
if (arg_this->IsNewInstance()) {
- uninitialized_strings_.push_back(arg_this->AsNewInstance());
+ HNewInstance* new_instance = arg_this->AsNewInstance();
+ // Note that in some rare cases (b/27847265), the same NewInstance may be seen
+ // multiple times. We should only consider it once for removal, so we
+ // ensure it is not added more than once.
+ if (!ContainsElement(uninitialized_strings_, new_instance)) {
+ uninitialized_strings_.push_back(new_instance);
+ }
} else {
DCHECK(arg_this->IsPhi());
// NewInstance is not the direct input of the StringFactory call. It might