From 5e08e3643230ff89f3d7e9b5d7660db6fd94bec9 Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Mon, 15 Feb 2016 15:56:11 +0000 Subject: Expect less in the presence of a string init call. The compiler currently relies on the dex cache being populated for doing proper type propagation. If it hasn't, we may end up in the situation where the DexMethodInliner has recognized a String. call (because DexMethodInliner only looks at signatures, and does not resolve types), but the graph builder doesn't see a type and assume it needs to do access checks and clinit checks on it. Change-Id: Id79313b0610b127909e3e057305b6632b0b172f7 --- compiler/optimizing/ssa_builder.cc | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'compiler/optimizing/ssa_builder.cc') diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc index 2d0a399290..a7dc76d7c1 100644 --- a/compiler/optimizing/ssa_builder.cc +++ b/compiler/optimizing/ssa_builder.cc @@ -430,8 +430,6 @@ void SsaBuilder::RemoveRedundantUninitializedStrings() { } for (HNewInstance* new_instance : uninitialized_strings_) { - DCHECK(new_instance->IsStringAlloc()); - // 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. @@ -440,10 +438,26 @@ void SsaBuilder::RemoveRedundantUninitializedStrings() { new_instance->GetBlock()->RemoveInstruction(new_instance); // Remove LoadClass if not needed any more. - HLoadClass* load_class = new_instance->InputAt(0)->AsLoadClass(); + HInstruction* input = new_instance->InputAt(0); + HLoadClass* load_class = nullptr; + + // If the class was not present in the dex cache at the point of building + // the graph, the builder inserted a HClinitCheck in between. Since the String + // class is always initialized at the point of running Java code, we can remove + // that check. + if (input->IsClinitCheck()) { + load_class = input->InputAt(0)->AsLoadClass(); + input->ReplaceWith(load_class); + input->GetBlock()->RemoveInstruction(input); + } else { + load_class = input->AsLoadClass(); + DCHECK(new_instance->IsStringAlloc()); + DCHECK(!load_class->NeedsAccessCheck()) << "String class is always accessible"; + } DCHECK(load_class != nullptr); - DCHECK(!load_class->NeedsAccessCheck()) << "String class is always accessible"; if (!load_class->HasUses()) { + // Even if the HLoadClass needs access check, we can remove it, as we know the + // String class does not need it. load_class->GetBlock()->RemoveInstruction(load_class); } } -- cgit v1.2.3-59-g8ed1b