diff options
author | 2016-01-20 16:48:30 +0000 | |
---|---|---|
committer | 2016-01-20 16:48:30 +0000 | |
commit | 440ef2cbc76d7e2bc76cf5f15b69fc0478d7e853 (patch) | |
tree | b2c457e09b6ebff0e1c7504d4bb1bf4bcfe1b8e6 | |
parent | 5b98e3c84ab634ff259a94fe6148f10533b467da (diff) | |
parent | bc9ab1630a198efbbf730275541291321ac3d2d4 (diff) |
Merge "ART: Cannot assume String.<init> called on NewInstance"
-rw-r--r-- | compiler/optimizing/nodes.h | 12 | ||||
-rw-r--r-- | compiler/optimizing/ssa_builder.cc | 15 | ||||
-rw-r--r-- | test/563-checker-fakestring/smali/TestCase.smali | 28 | ||||
-rw-r--r-- | test/563-checker-fakestring/src/Main.java | 8 |
4 files changed, 49 insertions, 14 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 48201e3d23..5246fd1f05 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -3693,19 +3693,13 @@ class HInvokeStaticOrDirect : public HInvoke { DCHECK(!IsStaticWithExplicitClinitCheck()); } - HNewInstance* GetThisArgumentOfStringInit() const { + HInstruction* GetAndRemoveThisArgumentOfStringInit() { DCHECK(IsStringInit()); size_t index = InputCount() - 1; - DCHECK(InputAt(index)->IsNewInstance()); - return InputAt(index)->AsNewInstance(); - } - - void RemoveThisArgumentOfStringInit() { - DCHECK(IsStringInit()); - size_t index = InputCount() - 1; - DCHECK(InputAt(index)->IsNewInstance()); + HInstruction* input = InputAt(index); RemoveAsUserOfInput(index); inputs_.pop_back(); + return input; } // Is this a call to a static method whose declaring class has an diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc index c0011cde8d..c8244aa800 100644 --- a/compiler/optimizing/ssa_builder.cc +++ b/compiler/optimizing/ssa_builder.cc @@ -927,16 +927,21 @@ void SsaBuilder::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) { if (invoke->IsStringInit()) { // This is a StringFactory call which acts as a String constructor. Its // result replaces the empty String pre-allocated by NewInstance. - HNewInstance* new_instance = invoke->GetThisArgumentOfStringInit(); - invoke->RemoveThisArgumentOfStringInit(); + HInstruction* arg_this = invoke->GetAndRemoveThisArgumentOfStringInit(); // 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. - uninitialized_strings_.push_back(new_instance); + if (arg_this->IsNewInstance()) { + uninitialized_strings_.push_back(arg_this->AsNewInstance()); + } else { + DCHECK(arg_this->IsIrreducibleLoopHeaderPhi()); + // NewInstance is not the direct input of the StringFactory call. It might + // be redundant but optimizing this case is not worth the effort. + } - // Walk over all vregs and replace any occurrence of `new_instance` with `invoke`. + // Walk over all vregs and replace any occurrence of `arg_this` with `invoke`. for (size_t vreg = 0, e = current_locals_->size(); vreg < e; ++vreg) { - if ((*current_locals_)[vreg] == new_instance) { + if ((*current_locals_)[vreg] == arg_this) { (*current_locals_)[vreg] = invoke; } } diff --git a/test/563-checker-fakestring/smali/TestCase.smali b/test/563-checker-fakestring/smali/TestCase.smali index 4bd804da26..823ed1e25a 100644 --- a/test/563-checker-fakestring/smali/TestCase.smali +++ b/test/563-checker-fakestring/smali/TestCase.smali @@ -124,3 +124,31 @@ return-object v0 .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). + +## CHECK-START-DEBUGGABLE: java.lang.String TestCase.thisNotNewInstance(byte[], boolean) register (after) +## CHECK-DAG: InvokeStaticOrDirect env:[[<<Phi:l\d+>>,{{.*]]}} +## CHECK-DAG: <<Phi>> Phi + +.method public static thisNotNewInstance([BZ)Ljava/lang/String; + .registers 5 + + new-instance v0, Ljava/lang/String; + + # 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 v0 + +.end method diff --git a/test/563-checker-fakestring/src/Main.java b/test/563-checker-fakestring/src/Main.java index 04df0f637c..5489a0d60d 100644 --- a/test/563-checker-fakestring/src/Main.java +++ b/test/563-checker-fakestring/src/Main.java @@ -63,5 +63,13 @@ public class Main { String result = (String) m.invoke(null, new Object[] { testData }); assertEqual(testString, result); } + + { + Method m = c.getMethod("thisNotNewInstance", 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); + } } } |