Remove InitClass instructions in output
Change-Id: I315ad5618e388a1ea874174b7aa331737a89fdbf
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInitClass.java b/src/main/java/com/android/tools/r8/dex/code/DexInitClass.java
deleted file mode 100644
index 47a4392..0000000
--- a/src/main/java/com/android/tools/r8/dex/code/DexInitClass.java
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.dex.code;
-
-import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.ObjectToOffsetMapping;
-import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.graph.UseRegistry;
-import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.ir.code.FieldMemberType;
-import com.android.tools.r8.ir.conversion.IRBuilder;
-import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
-import com.android.tools.r8.utils.RetracerForCodePrinting;
-import com.android.tools.r8.utils.structural.CompareToVisitor;
-import com.android.tools.r8.utils.structural.HashingVisitor;
-import com.android.tools.r8.utils.structural.StructuralSpecification;
-import java.nio.ShortBuffer;
-
-public class DexInitClass extends DexBase2Format {
-
- public static final int OPCODE = 0x60;
- public static final String NAME = "InitClass";
- public static final String SMALI_NAME = "initclass";
-
- private final int dest;
- private final DexType clazz;
-
- private static void specify(StructuralSpecification<DexInitClass, ?> spec) {
- spec.withInt(i -> i.dest).withItem(i -> i.clazz);
- }
-
- public DexInitClass(int dest, DexType clazz) {
- assert clazz.isClassType();
- this.dest = dest;
- this.clazz = clazz;
- }
-
- @Override
- public void buildIR(IRBuilder builder) {
- builder.addInitClass(dest, clazz);
- }
-
- @Override
- public void collectIndexedItems(
- AppView<?> appView,
- GraphLens codeLens,
- IndexedItemCollection indexedItems,
- ProgramMethod context,
- LensCodeRewriterUtils rewriter) {
- // We intentionally apply the graph lens first, and then the init class lens, using the fact
- // that the init class lens maps classes in the final program to fields in the final program.
- DexType rewrittenClass = appView.graphLens().lookupType(clazz, codeLens);
- DexField clinitField = appView.initClassLens().getInitClassField(rewrittenClass);
- clinitField.collectIndexedItems(appView, indexedItems);
- }
-
- @Override
- public boolean canThrow() {
- return true;
- }
-
- @Override
- public String getName() {
- return NAME;
- }
-
- @Override
- public String getSmaliName() {
- return SMALI_NAME;
- }
-
- @Override
- public int getOpcode() {
- throw new Unreachable();
- }
-
- @Override
- int getCompareToId() {
- return DexCompareHelper.INIT_CLASS_COMPARE_ID;
- }
-
- private int getOpcode(DexField field) {
- FieldMemberType type = FieldMemberType.fromDexType(field.type);
- switch (type) {
- case INT:
- case FLOAT:
- return DexSget.OPCODE;
- case LONG:
- case DOUBLE:
- return DexSgetWide.OPCODE;
- case OBJECT:
- return DexSgetObject.OPCODE;
- case BOOLEAN:
- return DexSgetBoolean.OPCODE;
- case BYTE:
- return DexSgetByte.OPCODE;
- case CHAR:
- return DexSgetChar.OPCODE;
- case SHORT:
- return DexSgetShort.OPCODE;
- default:
- throw new Unreachable("Unexpected type: " + type);
- }
- }
-
- @Override
- public void registerUse(UseRegistry<?> registry) {
- registry.registerInitClass(clazz);
- }
-
- @Override
- public void write(
- ShortBuffer buffer,
- ProgramMethod context,
- GraphLens graphLens,
- GraphLens codeLens,
- ObjectToOffsetMapping mapping,
- LensCodeRewriterUtils rewriter) {
- // We intentionally apply the graph lens first, and then the init class lens, using the fact
- // that the init class lens maps classes in the final program to fields in the final program.
- DexType rewrittenClass = graphLens.lookupType(clazz, codeLens);
- DexField clinitField = mapping.getClinitField(rewrittenClass);
- writeFirst(dest, buffer, getOpcode(clinitField));
- write16BitReference(clinitField, buffer, mapping);
- }
-
- @Override
- public int hashCode() {
- return ((clazz.hashCode() << 8) | dest) ^ getClass().hashCode();
- }
-
- @Override
- final int internalAcceptCompareTo(DexInstruction other, CompareToVisitor visitor) {
- return visitor.visit(this, (DexInitClass) other, DexInitClass::specify);
- }
-
- @Override
- void internalAcceptHashing(HashingVisitor visitor) {
- visitor.visit(this, DexInitClass::specify);
- }
-
- @Override
- public String toSmaliString(RetracerForCodePrinting retracer) {
- return formatSmaliString("v" + dest + ", " + clazz.toSmaliString());
- }
-
- @Override
- public String toString(RetracerForCodePrinting retracer) {
- return formatString("v" + dest + ", " + retracer.toDescriptor(clazz));
- }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InitClass.java b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
index bb3e50d..c9039c1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InitClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
@@ -5,9 +5,8 @@
package com.android.tools.r8.ir.code;
import com.android.tools.r8.cf.LoadStoreHelper;
-import com.android.tools.r8.cf.code.CfInitClass;
import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.dex.code.DexInitClass;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AccessControl;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
@@ -73,13 +72,12 @@
@Override
public void buildDex(DexBuilder builder) {
- int dest = builder.allocatedRegister(outValue(), getNumber());
- builder.add(this, new DexInitClass(dest, clazz));
+ throw new Unreachable();
}
@Override
public void buildCf(CfBuilder builder) {
- builder.add(new CfInitClass(clazz), this);
+ throw new Unreachable();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
index f168d4e..941930c 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.ir.conversion.passes.ConstResourceNumberRewriter;
import com.android.tools.r8.ir.conversion.passes.DexItemBasedConstStringRemover;
import com.android.tools.r8.ir.conversion.passes.FilledNewArrayRewriter;
+import com.android.tools.r8.ir.conversion.passes.InitClassRemover;
import com.android.tools.r8.ir.conversion.passes.StringSwitchRemover;
import com.android.tools.r8.ir.optimize.ConstantCanonicalizer;
import com.android.tools.r8.ir.optimize.DeadCodeRemover;
@@ -143,6 +144,7 @@
new AdaptClassStringsRewriter(appView),
new ConstResourceNumberRemover(appView),
new DexItemBasedConstStringRemover(appView),
+ new InitClassRemover(appView),
new RecordInvokeDynamicInvokeCustomRewriter(appView),
new FilledNewArrayRewriter(appView),
new StringSwitchRemover(appView));
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/InitClassRemover.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/InitClassRemover.java
new file mode 100644
index 0000000..bde3df6
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/InitClassRemover.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.ir.conversion.passes;
+
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.InitClass;
+import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.StaticGet;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
+import com.android.tools.r8.ir.conversion.passes.result.CodeRewriterResult;
+
+public class InitClassRemover extends CodeRewriterPass<AppInfoWithClassHierarchy> {
+
+ public InitClassRemover(AppView<? extends AppInfoWithClassHierarchy> appView) {
+ super(appView);
+ }
+
+ @Override
+ protected String getRewriterId() {
+ return "InitClassRemover";
+ }
+
+ @Override
+ protected boolean shouldRewriteCode(IRCode code, MethodProcessor methodProcessor) {
+ return code.metadata().mayHaveInitClass();
+ }
+
+ @Override
+ protected CodeRewriterResult rewriteCode(IRCode code) {
+ boolean hasChanged = false;
+ InstructionListIterator iterator = code.instructionListIterator();
+ while (iterator.hasNext()) {
+ InitClass instruction = iterator.next().asInitClass();
+ if (instruction != null) {
+ DexField field = appView.initClassLens().getInitClassField(instruction.getClassValue());
+ StaticGet replacement =
+ StaticGet.builder()
+ .setField(field)
+ .setFreshOutValue(code, field.getType().toTypeElement(appView))
+ .build();
+ iterator.replaceCurrentInstruction(replacement);
+ hasChanged = true;
+ }
+ }
+ return CodeRewriterResult.hasChanged(hasChanged);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/classinit/InitClassPopCfTest.java b/src/test/java/com/android/tools/r8/debug/classinit/InitClassPopCfTest.java
index 86ff2c4..7ffe710 100644
--- a/src/test/java/com/android/tools/r8/debug/classinit/InitClassPopCfTest.java
+++ b/src/test/java/com/android/tools/r8/debug/classinit/InitClassPopCfTest.java
@@ -4,9 +4,6 @@
package com.android.tools.r8.debug.classinit;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import com.android.tools.r8.AlwaysInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
@@ -17,10 +14,6 @@
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.InstructionSubject;
-import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import java.util.Iterator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -52,7 +45,8 @@
.addKeepRules("-keep class * { static java.lang.Object f; }")
.addKeepMainRule(Main.class)
.compile()
- .inspect(InitClassPopCfTest::verifyInitClassFollowedByPopInCf);
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("0", "clinit A", "5504", "5");
}
private void modifyIR(IRCode irCode, AppView<?> appView) {
@@ -73,22 +67,6 @@
}
}
- private static void verifyInitClassFollowedByPopInCf(CodeInspector i) {
- MethodSubject main = i.clazz(Main.class).mainMethod();
- Iterator<InstructionSubject> iterator = main.iterateInstructions();
- int index = 0;
- while (iterator.hasNext()) {
- InstructionSubject next = iterator.next();
- // All static gets on non System are init class.
- if (next.isStaticGet()
- && !next.getField().getHolderType().toString().equals("java.lang.System")) {
- assertTrue(iterator.next().isPop());
- index++;
- }
- }
- assertEquals(4, index);
- }
-
public static class A {
static {
System.out.println("clinit A");