OSDN Git Service

Expect less in the presence of a string init call.
authorNicolas Geoffray <ngeoffray@google.com>
Mon, 15 Feb 2016 15:56:11 +0000 (15:56 +0000)
committerNicolas Geoffray <ngeoffray@google.com>
Mon, 15 Feb 2016 16:17:11 +0000 (16:17 +0000)
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.<init> 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

index 2d0a399..a7dc76d 100644 (file)
@@ -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);
       }
     }