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(