diff options
-rw-r--r-- | compiler/optimizing/instruction_builder.cc | 10 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler_stats.h | 1 | ||||
-rw-r--r-- | test/563-checker-fakestring/smali/TestCase.smali | 43 | ||||
-rw-r--r-- | test/563-checker-fakestring/src/Main.java | 11 |
4 files changed, 45 insertions, 20 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 9647dd5d41..a36e80379d 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -1360,9 +1360,15 @@ bool HInstructionBuilder::HandleStringInit(HInvoke* invoke, if (arg_this->IsNewInstance()) { ssa_builder_->AddUninitializedString(arg_this->AsNewInstance()); } else { + // The only reason a HPhi can flow in a String.<init> is when there is an + // irreducible loop, which will create HPhi for all dex registers at loop entry. DCHECK(arg_this->IsPhi()); - // NewInstance is not the direct input of the StringFactory call. It might - // be redundant but optimizing this case is not worth the effort. + DCHECK(graph_->HasIrreducibleLoops()); + // Don't bother compiling a method in that situation. While we could look at all + // phis related to the HNewInstance, it's not worth the trouble. + MaybeRecordStat(compilation_stats_, + MethodCompilationStat::kNotCompiledIrreducibleAndStringInit); + return false; } // Walk over all vregs and replace any occurrence of `arg_this` with `invoke`. diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h index 9a26f2f6c4..f246228074 100644 --- a/compiler/optimizing/optimizing_compiler_stats.h +++ b/compiler/optimizing/optimizing_compiler_stats.h @@ -50,6 +50,7 @@ enum class MethodCompilationStat { kNotCompiledThrowCatchLoop, kNotCompiledAmbiguousArrayOp, kNotCompiledHugeMethod, + kNotCompiledIrreducibleAndStringInit, kNotCompiledLargeMethodNoBranches, kNotCompiledMalformedOpcode, kNotCompiledNoCodegen, diff --git a/test/563-checker-fakestring/smali/TestCase.smali b/test/563-checker-fakestring/smali/TestCase.smali index adafb78bd7..8898c48ea1 100644 --- a/test/563-checker-fakestring/smali/TestCase.smali +++ b/test/563-checker-fakestring/smali/TestCase.smali @@ -133,17 +133,8 @@ .end method -# Test that the compiler does not assume that the first argument of String.<init> -# is a NewInstance by inserting an irreducible loop between them (b/26676472). - -# We verify the type of the input instruction (Phi) in debuggable mode, because -# it is eliminated by later stages of SsaBuilder otherwise. - -## CHECK-START-DEBUGGABLE: java.lang.String TestCase.thisNotNewInstance1(byte[], boolean) register (after) -## CHECK-DAG: InvokeStaticOrDirect env:[[<<Phi:l\d+>>,{{.*]]}} -## CHECK-DAG: <<Phi>> Phi - -.method public static thisNotNewInstance1([BZ)Ljava/lang/String; +# Test #1 for irreducible loops and String.<init>. +.method public static irreducibleLoopAndStringInit1([BZ)Ljava/lang/String; .registers 5 new-instance v0, Ljava/lang/String; @@ -164,11 +155,8 @@ .end method -## CHECK-START-DEBUGGABLE: java.lang.String TestCase.thisNotNewInstance2(byte[], boolean) register (after) -## CHECK-DAG: InvokeStaticOrDirect env:[[<<Phi:l\d+>>,{{.*]]}} -## CHECK-DAG: <<Phi>> Phi - -.method public static thisNotNewInstance2([BZ)Ljava/lang/String; +# Test #2 for irreducible loops and String.<init>. +.method public static irreducibleLoopAndStringInit2([BZ)Ljava/lang/String; .registers 5 new-instance v0, Ljava/lang/String; @@ -188,3 +176,26 @@ return-object v0 .end method + +# Test #3 for irreducible loops and String.<init> alias. +.method public static irreducibleLoopAndStringInit3([BZ)Ljava/lang/String; + .registers 5 + + new-instance v0, Ljava/lang/String; + move-object v2, v0 + + # Irreducible loop + if-eqz p1, :loop_entry + :loop_header + const v1, 0x1 + xor-int p1, p1, v1 + :loop_entry + if-eqz p1, :string_init + goto :loop_header + + :string_init + const-string v1, "UTF8" + invoke-direct {v0, p0, v1}, Ljava/lang/String;-><init>([BLjava/lang/String;)V + return-object v2 + +.end method diff --git a/test/563-checker-fakestring/src/Main.java b/test/563-checker-fakestring/src/Main.java index 78cb37ae09..d38b7f4f23 100644 --- a/test/563-checker-fakestring/src/Main.java +++ b/test/563-checker-fakestring/src/Main.java @@ -65,14 +65,21 @@ public class Main { } { - Method m = c.getMethod("thisNotNewInstance1", byte[].class, boolean.class); + Method m = c.getMethod("irreducibleLoopAndStringInit1", byte[].class, boolean.class); String result = (String) m.invoke(null, new Object[] { testData, true }); assertEqual(testString, result); result = (String) m.invoke(null, new Object[] { testData, false }); assertEqual(testString, result); } { - Method m = c.getMethod("thisNotNewInstance2", byte[].class, boolean.class); + Method m = c.getMethod("irreducibleLoopAndStringInit2", byte[].class, boolean.class); + String result = (String) m.invoke(null, new Object[] { testData, true }); + assertEqual(testString, result); + result = (String) m.invoke(null, new Object[] { testData, false }); + assertEqual(testString, result); + } + { + Method m = c.getMethod("irreducibleLoopAndStringInit3", byte[].class, boolean.class); String result = (String) m.invoke(null, new Object[] { testData, true }); assertEqual(testString, result); result = (String) m.invoke(null, new Object[] { testData, false }); |