Rename default value of static fields with -identifiernamestring rule.

Bug: 36799092, 69360658
Change-Id: I0bc62ab5967a278a3b5543d7e3169687556f2810
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 8547206..d598000 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -395,6 +395,11 @@
       timing.end();
     }
     clearDexMethodCompilationState();
+
+    if (identifierNameStringMarker != null) {
+      identifierNameStringMarker.decoupleIdentifierNameStringsInFields();
+    }
+
     return builder.build();
   }
 
@@ -525,7 +530,7 @@
     }
 
     if (identifierNameStringMarker != null) {
-      identifierNameStringMarker.decoupleIdentifierNameStrings(method, code);
+      identifierNameStringMarker.decoupleIdentifierNameStringsInMethod(method, code);
       assert code.isConsistentSSA();
     }
 
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
index 92c2560..f766061 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
@@ -56,37 +56,42 @@
       if (!adaptClassStrings.matches(clazz.type)) {
         continue;
       }
-      for (DexEncodedField encodedField : clazz.allFieldsSorted()) {
-        if (encodedField.staticValue instanceof DexValueString) {
-          DexString original = ((DexValueString) encodedField.staticValue).getValue();
-          DexString renamed = getRenamedStringLiteral(original);
-          if (renamed != original) {
-            encodedField.staticValue = new DexValueString(renamed);
-          }
-        }
-      }
-      for (DexEncodedMethod encodedMethod : clazz.allMethodsSorted()) {
-        // Abstract methods do not have code_item.
-        if (encodedMethod.accessFlags.isAbstract()) {
-          continue;
-        }
-        Code code = encodedMethod.getCode();
-        if (code == null) {
-          continue;
-        }
-        assert code.isDexCode();
-        DexCode dexCode = code.asDexCode();
-        for (Instruction instr : dexCode.instructions) {
-          if (instr instanceof ConstString) {
-            ConstString cnst = (ConstString) instr;
-            DexString dexString = cnst.getString();
-            cnst.BBBB = getRenamedStringLiteral(dexString);
-          } else if (instr instanceof ConstStringJumbo) {
-            ConstStringJumbo cnst = (ConstStringJumbo) instr;
-            DexString dexString = cnst.getString();
-            cnst.BBBBBBBB = getRenamedStringLiteral(dexString);
-          }
-        }
+      clazz.forEachField(this::adaptClassStringsInField);
+      clazz.forEachMethod(this::adaptClassStringsInMethod);
+    }
+  }
+
+  private void adaptClassStringsInField(DexEncodedField encodedField) {
+    if (!(encodedField.staticValue instanceof DexValueString)) {
+      return;
+    }
+    DexString original = ((DexValueString) encodedField.staticValue).getValue();
+    DexString renamed = getRenamedStringLiteral(original);
+    if (renamed != original) {
+      encodedField.staticValue = new DexValueString(renamed);
+    }
+  }
+
+  private void adaptClassStringsInMethod(DexEncodedMethod encodedMethod) {
+    // Abstract methods do not have code_item.
+    if (encodedMethod.accessFlags.isAbstract()) {
+      return;
+    }
+    Code code = encodedMethod.getCode();
+    if (code == null) {
+      return;
+    }
+    assert code.isDexCode();
+    DexCode dexCode = code.asDexCode();
+    for (Instruction instr : dexCode.instructions) {
+      if (instr instanceof ConstString) {
+        ConstString cnst = (ConstString) instr;
+        DexString dexString = cnst.getString();
+        cnst.BBBB = getRenamedStringLiteral(dexString);
+      } else if (instr instanceof ConstStringJumbo) {
+        ConstStringJumbo cnst = (ConstStringJumbo) instr;
+        DexString dexString = cnst.getString();
+        cnst.BBBBBBBB = getRenamedStringLiteral(dexString);
       }
     }
   }
@@ -111,43 +116,47 @@
 
   private void replaceIdentifierNameString() {
     for (DexProgramClass clazz : appInfo.classes()) {
-      for (DexEncodedMethod encodedMethod : clazz.allMethodsSorted()) {
-        if (!encodedMethod.getOptimizationInfo().useIdentifierNameString()) {
-          continue;
-        }
-        Code code = encodedMethod.getCode();
-        if (code == null) {
-          continue;
-        }
-        assert code.isDexCode();
-        DexCode dexCode = code.asDexCode();
-        for (Instruction instr : dexCode.instructions) {
-          if (instr instanceof ConstString
-              && ((ConstString) instr).getString() instanceof DexItemBasedString) {
-            ConstString cnst = (ConstString) instr;
-            DexItemBasedString itemBasedString = (DexItemBasedString) cnst.getString();
-            cnst.BBBB = materialize(itemBasedString);
-          } else if (instr instanceof ConstStringJumbo
-              && ((ConstStringJumbo) instr).getString() instanceof DexItemBasedString) {
-            ConstStringJumbo cnst = (ConstStringJumbo) instr;
-            DexItemBasedString itemBasedString = (DexItemBasedString) cnst.getString();
-            cnst.BBBBBBBB = materialize(itemBasedString);
-          }
-        }
-      }
+      // Some const strings could be moved to field's static value (from <clinit>).
+      clazz.forEachField(this::replaceIdentifierNameStringInField);
+      clazz.forEachMethod(this::replaceIdentifierNameStringInMethod);
     }
-    // Some const strings could be moved to field's static value (from <clinit>).
-    for (DexItem dexItem : identifierNameStrings) {
-      if (!(dexItem instanceof DexField)) {
-        continue;
-      }
-      DexEncodedField encodedField = appInfo.definitionFor((DexField) dexItem);
-      if (!(encodedField.staticValue instanceof DexValueString)) {
-        continue;
-      }
-      DexString original = ((DexValueString) encodedField.staticValue).getValue();
-      if (original instanceof DexItemBasedString) {
-        encodedField.staticValue = new DexValueString(materialize((DexItemBasedString) original));
+  }
+
+  private void replaceIdentifierNameStringInField(DexEncodedField encodedField) {
+    if (!(encodedField.staticValue instanceof DexValueString)) {
+      return;
+    }
+    DexString original = ((DexValueString) encodedField.staticValue).getValue();
+    if (original instanceof DexItemBasedString) {
+      encodedField.staticValue = new DexValueString(materialize((DexItemBasedString) original));
+    }
+  }
+
+  private void replaceIdentifierNameStringInMethod(DexEncodedMethod encodedMethod) {
+    if (!encodedMethod.getOptimizationInfo().useIdentifierNameString()) {
+      return;
+    }
+    // Abstract methods do not have code_item.
+    if (encodedMethod.accessFlags.isAbstract()) {
+      return;
+    }
+    Code code = encodedMethod.getCode();
+    if (code == null) {
+      return;
+    }
+    assert code.isDexCode();
+    DexCode dexCode = code.asDexCode();
+    for (Instruction instr : dexCode.instructions) {
+      if (instr instanceof ConstString
+          && ((ConstString) instr).getString() instanceof DexItemBasedString) {
+        ConstString cnst = (ConstString) instr;
+        DexItemBasedString itemBasedString = (DexItemBasedString) cnst.getString();
+        cnst.BBBB = materialize(itemBasedString);
+      } else if (instr instanceof ConstStringJumbo
+          && ((ConstStringJumbo) instr).getString() instanceof DexItemBasedString) {
+        ConstStringJumbo cnst = (ConstStringJumbo) instr;
+        DexItemBasedString itemBasedString = (DexItemBasedString) cnst.getString();
+        cnst.BBBBBBBB = materialize(itemBasedString);
       }
     }
   }
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
index 2f48083..f3c36aa 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
@@ -3,14 +3,18 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
+import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItem;
 import com.android.tools.r8.graph.DexItemBasedString;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.ConstString;
 import com.android.tools.r8.ir.code.IRCode;
@@ -39,7 +43,31 @@
     this.identifierNameStrings = appInfo.identifierNameStrings;
   }
 
-  public void decoupleIdentifierNameStrings(DexEncodedMethod encodedMethod, IRCode code) {
+  public void decoupleIdentifierNameStringsInFields() {
+    for (DexProgramClass clazz : appInfo.classes()) {
+      clazz.forEachField(this::decoupleIdentifierNameStringInField);
+    }
+  }
+
+  private void decoupleIdentifierNameStringInField(DexEncodedField encodedField) {
+    if (!identifierNameStrings.contains(encodedField.field)) {
+      return;
+    }
+    if (!(encodedField.staticValue instanceof DexValueString)) {
+      return;
+    }
+    DexString original = ((DexValueString) encodedField.staticValue).getValue();
+    String maybeDescriptor =
+        DescriptorUtils.javaTypeToDescriptorIfValidJavaType(original.toString());
+    if (maybeDescriptor == null) {
+      return;
+    }
+    DexType type = dexItemFactory.createType(maybeDescriptor);
+    DexItemBasedString typeString = dexItemFactory.createItemBasedString(type);
+    encodedField.staticValue = new DexValueString(typeString);
+  }
+
+  public void decoupleIdentifierNameStringsInMethod(DexEncodedMethod encodedMethod, IRCode code) {
     for (BasicBlock block : code.blocks) {
       InstructionListIterator iterator = block.listIterator();
       while (iterator.hasNext()) {
diff --git a/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java b/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
index 1431dd9..cc7dad2 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
@@ -17,10 +17,15 @@
 import com.android.tools.r8.code.SgetObject;
 import com.android.tools.r8.code.SputObject;
 import com.android.tools.r8.graph.DexCode;
+import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.smali.SmaliBuilder;
 import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
 import com.android.tools.r8.smali.SmaliTestBase;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import com.android.tools.r8.utils.DexInspector.FieldSubject;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
 import java.util.List;
@@ -233,6 +238,54 @@
   }
 
   @Test
+  public void staticFieldWithDefaultValue() throws Exception {
+    SmaliBuilder builder = new SmaliBuilder("Example");
+    builder.addStaticField("sClassName", "Ljava/lang/String;", BOO);
+
+    List<String> pgConfigs = ImmutableList.of(
+        "-identifiernamestring class Example { static java.lang.String sClassName; }",
+        "-keep class Example { static java.lang.String sClassName; }",
+        "-dontshrink",
+        "-dontoptimize");
+    Path processedApp = runR8(builder, pgConfigs);
+
+    DexInspector inspector = new DexInspector(processedApp);
+
+    ClassSubject clazz = inspector.clazz("Example");
+    assertTrue(clazz.isPresent());
+    FieldSubject field = clazz.field("java.lang.String", "sClassName");
+    assertTrue(field.isPresent());
+    assertTrue(field.getStaticValue() instanceof DexValueString);
+    String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+    assertEquals(BOO, defaultValue);
+  }
+
+  @Test
+  public void staticFieldWithDefaultValue_renamed() throws Exception {
+    SmaliBuilder builder = new SmaliBuilder("Example");
+    builder.addStaticField("sClassName", "Ljava/lang/String;", BOO);
+    builder.addClass(BOO);
+
+    List<String> pgConfigs = ImmutableList.of(
+        "-identifiernamestring class Example { static java.lang.String sClassName; }",
+        "-keep class Example { static java.lang.String sClassName; }",
+        "-keep,allowobfuscation class " + BOO,
+        "-dontshrink",
+        "-dontoptimize");
+    Path processedApp = runR8(builder, pgConfigs);
+
+    DexInspector inspector = new DexInspector(processedApp);
+
+    ClassSubject clazz = inspector.clazz("Example");
+    assertTrue(clazz.isPresent());
+    FieldSubject field = clazz.field("java.lang.String", "sClassName");
+    assertTrue(field.isPresent());
+    assertTrue(field.getStaticValue() instanceof DexValueString);
+    String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+    assertNotEquals(BOO, defaultValue);
+  }
+
+  @Test
   public void invoke_singleUseOperand() throws Exception {
     SmaliBuilder builder = new SmaliBuilder("Example");
     builder.addStaticMethod(