diff options
author | Lars Bak <bak@google.com> | 2017-08-17 07:49:50 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-08-17 07:49:50 +0000 |
commit | db4cd66df157eed15eba1bdb0ec069ecb96db833 (patch) | |
tree | baa6d9df928b7286f9795f9071f05978f717f486 | |
parent | cebde9e728adf87aae7fd565f1992ad11e703758 (diff) | |
parent | 4ac80d334b7faaa98eae061d0174a142c9785a3e (diff) | |
download | r8-db4cd66df157eed15eba1bdb0ec069ecb96db833.tar.gz |
Merge "Added accessors for fields and methods in DexClass."
11 files changed, 80 insertions, 67 deletions
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java index a8f56a71e..f1162a929 100644 --- a/src/main/java/com/android/tools/r8/dex/FileWriter.java +++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java @@ -253,10 +253,10 @@ public class FileWriter { private void sortClassData(Collection<DexProgramClass> classesWithData) { for (DexProgramClass clazz : classesWithData) { - sortEncodedFields(clazz.instanceFields); - sortEncodedFields(clazz.staticFields); - sortEncodedMethods(clazz.directMethods); - sortEncodedMethods(clazz.virtualMethods); + sortEncodedFields(clazz.instanceFields()); + sortEncodedFields(clazz.staticFields()); + sortEncodedMethods(clazz.directMethods()); + sortEncodedMethods(clazz.virtualMethods()); } } diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java index d09d39522..d9040afc8 100644 --- a/src/main/java/com/android/tools/r8/graph/DexClass.java +++ b/src/main/java/com/android/tools/r8/graph/DexClass.java @@ -22,10 +22,10 @@ public abstract class DexClass extends DexItem { public DexType superType; public DexTypeList interfaces; public final DexString sourceFile; - public DexEncodedField[] staticFields; - public DexEncodedField[] instanceFields; - public DexEncodedMethod[] directMethods; - public DexEncodedMethod[] virtualMethods; + protected DexEncodedField[] staticFields; + protected DexEncodedField[] instanceFields; + protected DexEncodedMethod[] directMethods; + protected DexEncodedMethod[] virtualMethods; public DexAnnotationSet annotations; public DexClass( @@ -39,10 +39,10 @@ public abstract class DexClass extends DexItem { this.accessFlags = accessFlags; this.superType = superType; this.type = type; - this.staticFields = staticFields; - this.instanceFields = instanceFields; - this.directMethods = directMethods; - this.virtualMethods = virtualMethods; + setStaticFields(staticFields); + setInstanceFields(instanceFields); + setDirectMethods(directMethods); + setVirtualMethods(virtualMethods); this.annotations = annotations; if (type == superType) { throw new CompilationError("Class " + type.toString() + " cannot extend itself"); @@ -66,13 +66,22 @@ public abstract class DexClass extends DexItem { } public DexEncodedMethod[] directMethods() { - return MoreObjects.firstNonNull(directMethods, NO_METHODS); + return directMethods; + } + + public void setDirectMethods(DexEncodedMethod[] values) { + directMethods = MoreObjects.firstNonNull(values, NO_METHODS); } public DexEncodedMethod[] virtualMethods() { - return MoreObjects.firstNonNull(virtualMethods, NO_METHODS); + return virtualMethods; } + public void setVirtualMethods(DexEncodedMethod[] values) { + virtualMethods = MoreObjects.firstNonNull(values, NO_METHODS); + } + + public void forEachMethod(Consumer<DexEncodedMethod> consumer) { for (DexEncodedMethod method : directMethods()) { consumer.accept(method); @@ -103,11 +112,19 @@ public abstract class DexClass extends DexItem { } public DexEncodedField[] staticFields() { - return MoreObjects.firstNonNull(staticFields, NO_FIELDS); + return staticFields; + } + + public void setStaticFields(DexEncodedField[] values) { + staticFields = MoreObjects.firstNonNull(values, NO_FIELDS); } public DexEncodedField[] instanceFields() { - return MoreObjects.firstNonNull(instanceFields, NO_FIELDS); + return instanceFields; + } + + public void setInstanceFields(DexEncodedField[] values) { + instanceFields = MoreObjects.firstNonNull(values, NO_FIELDS); } /** diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java index 236c9e555..b7036f521 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java @@ -80,15 +80,15 @@ final class ClassProcessor { } // Add the methods. - DexEncodedMethod[] existing = clazz.virtualMethods; - clazz.virtualMethods = new DexEncodedMethod[existing.length + methodsToImplement.size()]; - System.arraycopy(existing, 0, clazz.virtualMethods, 0, existing.length); + DexEncodedMethod[] existing = clazz.virtualMethods(); + clazz.setVirtualMethods(new DexEncodedMethod[existing.length + methodsToImplement.size()]); + System.arraycopy(existing, 0, clazz.virtualMethods(), 0, existing.length); for (int i = 0; i < methodsToImplement.size(); i++) { DexEncodedMethod method = methodsToImplement.get(i); assert method.accessFlags.isPublic() && !method.accessFlags.isAbstract(); DexEncodedMethod newMethod = addForwardingMethod(method, clazz); - clazz.virtualMethods[existing.length + i] = newMethod; + clazz.virtualMethods()[existing.length + i] = newMethod; createdMethods.put(newMethod, method); } } @@ -142,7 +142,7 @@ final class ClassProcessor { current = clazz; while (true) { // Hide candidates by virtual method of the class. - hideCandidates(current.virtualMethods, candidates, toBeImplemented); + hideCandidates(current.virtualMethods(), candidates, toBeImplemented); if (candidates.isEmpty()) { return toBeImplemented; } @@ -218,12 +218,12 @@ final class ClassProcessor { } // Hide by virtual methods of this interface. - for (DexEncodedMethod virtual : clazz.virtualMethods) { + for (DexEncodedMethod virtual : clazz.virtualMethods()) { helper.hideMatches(virtual.method); } // Add all default methods of this interface. - for (DexEncodedMethod encoded : clazz.virtualMethods) { + for (DexEncodedMethod encoded : clazz.virtualMethods()) { if (rewriter.isDefaultMethod(encoded)) { helper.addDefaultMethod(encoded); } diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java index a84e082e4..2d06abe6f 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java @@ -44,7 +44,7 @@ final class InterfaceProcessor { // Process virtual interface methods first. List<DexEncodedMethod> remainingMethods = new ArrayList<>(); - for (DexEncodedMethod virtual : iface.virtualMethods) { + for (DexEncodedMethod virtual : iface.virtualMethods()) { if (rewriter.isDefaultMethod(virtual)) { // Create a new method in a companion class to represent default method implementation. DexMethod companionMethod = rewriter.defaultAsMethodOfCompanionClass(virtual.method); @@ -79,14 +79,14 @@ final class InterfaceProcessor { } // If at least one bridge methods was removed update the table. - if (remainingMethods.size() < iface.virtualMethods.length) { - iface.virtualMethods = remainingMethods.toArray( - new DexEncodedMethod[remainingMethods.size()]); + if (remainingMethods.size() < iface.virtualMethods().length) { + iface.setVirtualMethods(remainingMethods.toArray( + new DexEncodedMethod[remainingMethods.size()])); } remainingMethods.clear(); // Process static methods, move them into companion class as well. - for (DexEncodedMethod direct : iface.directMethods) { + for (DexEncodedMethod direct : iface.directMethods()) { if (direct.accessFlags.isPrivate()) { // We only expect to see private methods which are lambda$ methods, // and they are supposed to be relaxed to package private static methods @@ -105,9 +105,9 @@ final class InterfaceProcessor { remainingMethods.add(direct); } } - if (remainingMethods.size() < iface.directMethods.length) { - iface.directMethods = remainingMethods.toArray( - new DexEncodedMethod[remainingMethods.size()]); + if (remainingMethods.size() < iface.directMethods().length) { + iface.setDirectMethods(remainingMethods.toArray( + new DexEncodedMethod[remainingMethods.size()])); } if (companionMethods.isEmpty()) { diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java index 0a6ea7ebe..be6252a8b 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java @@ -444,7 +444,7 @@ final class LambdaClass { DexMethod implMethod = descriptor.implHandle.asMethod(); DexClass implMethodHolder = definitionFor(implMethod.holder); - DexEncodedMethod[] directMethods = implMethodHolder.directMethods; + DexEncodedMethod[] directMethods = implMethodHolder.directMethods(); for (int i = 0; i < directMethods.length; i++) { DexEncodedMethod encodedMethod = directMethods[i]; if (implMethod.match(encodedMethod)) { @@ -491,8 +491,8 @@ final class LambdaClass { DexEncodedMethod accessorEncodedMethod = new DexEncodedMethod( callTarget, accessorFlags, DexAnnotationSet.empty(), DexAnnotationSetRefList.empty(), new SynthesizedCode(new AccessorMethodSourceCode(LambdaClass.this))); - accessorClass.directMethods = appendMethod( - accessorClass.directMethods, accessorEncodedMethod); + accessorClass.setDirectMethods(appendMethod( + accessorClass.directMethods(), accessorEncodedMethod)); rewriter.converter.optimizeSynthesizedMethod(accessorEncodedMethod); return true; } diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java index af32cb701..f6f8f2c8c 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java @@ -162,7 +162,7 @@ public class LambdaRewriter { public void removeLambdaDeserializationMethods(Iterable<DexProgramClass> classes) { for (DexProgramClass clazz : classes) { // Search for a lambda deserialization method and remove it if found. - DexEncodedMethod[] directMethods = clazz.directMethods; + DexEncodedMethod[] directMethods = clazz.directMethods(); if (directMethods != null) { int methodCount = directMethods.length; for (int i = 0; i < methodCount; i++) { @@ -177,7 +177,7 @@ public class LambdaRewriter { DexEncodedMethod[] newMethods = new DexEncodedMethod[methodCount - 1]; System.arraycopy(directMethods, 0, newMethods, 0, i); System.arraycopy(directMethods, i + 1, newMethods, i, methodCount - i - 1); - clazz.directMethods = newMethods; + clazz.setDirectMethods(newMethods); // We assume there is only one such method in the class. break; diff --git a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java index 31c7f1f15..300f18e70 100644 --- a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java +++ b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java @@ -60,7 +60,7 @@ public class VisibilityBridgeRemover { .collect(Collectors.toSet()); for (DexType type : classes) { DexClass clazz = appInfo.definitionFor(type); - clazz.virtualMethods = removeMethods(clazz.virtualMethods, unneededVisibilityBridges); + clazz.setVirtualMethods(removeMethods(clazz.virtualMethods(), unneededVisibilityBridges)); } } diff --git a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java index 28507903d..3fd54702b 100644 --- a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java +++ b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java @@ -35,7 +35,7 @@ public class AbstractMethodRemover { DexClass holder = appInfo.definitionFor(type); scope = new ScopedDexItemSet(scope); if (holder != null) { - holder.virtualMethods = processMethods(holder.virtualMethods); + holder.setVirtualMethods(processMethods(holder.virtualMethods())); } type.forAllExtendsSubtypes(this::processClass); scope = scope.getParent(); @@ -74,10 +74,6 @@ public class AbstractMethodRemover { private final ScopedDexItemSet parent; private final Set<Wrapper<DexMethod>> items = new HashSet<>(); - private ScopedDexItemSet() { - this(null); - } - private ScopedDexItemSet(ScopedDexItemSet parent) { this.parent = parent; } diff --git a/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java b/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java index d3306d965..c04b29a5f 100644 --- a/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java +++ b/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java @@ -257,20 +257,20 @@ public class SimpleClassMerger { ? DexTypeList.empty() : new DexTypeList(interfaces.toArray(new DexType[interfaces.size()])); // Step 2: replace fields and methods. - target.directMethods = mergedDirectMethods - .toArray(new DexEncodedMethod[mergedDirectMethods.size()]); - target.virtualMethods = mergedVirtualMethods - .toArray(new DexEncodedMethod[mergedVirtualMethods.size()]); - target.staticFields = mergedStaticFields - .toArray(new DexEncodedField[mergedStaticFields.size()]); - target.instanceFields = mergedInstanceFields - .toArray(new DexEncodedField[mergedInstanceFields.size()]); + target.setDirectMethods(mergedDirectMethods + .toArray(new DexEncodedMethod[mergedDirectMethods.size()])); + target.setVirtualMethods(mergedVirtualMethods + .toArray(new DexEncodedMethod[mergedVirtualMethods.size()])); + target.setStaticFields(mergedStaticFields + .toArray(new DexEncodedField[mergedStaticFields.size()])); + target.setInstanceFields(mergedInstanceFields + .toArray(new DexEncodedField[mergedInstanceFields.size()])); // Step 3: Unlink old class to ease tree shaking. source.superType = application.dexItemFactory.objectType; - source.directMethods = null; - source.virtualMethods = null; - source.instanceFields = null; - source.staticFields = null; + source.setDirectMethods(null); + source.setVirtualMethods(null); + source.setInstanceFields(null); + source.setStaticFields(null); source.interfaces = DexTypeList.empty(); // Step 4: Record merging. mergedClasses.put(source.type, target.type); @@ -427,11 +427,11 @@ public class SimpleClassMerger { private GraphLense fixupTypeReferences(GraphLense graphLense) { // Globally substitute merged class types in protos and holders. for (DexProgramClass clazz : appInfo.classes()) { - clazz.directMethods = substituteTypesIn(clazz.directMethods); - clazz.virtualMethods = substituteTypesIn(clazz.virtualMethods); - clazz.virtualMethods = removeDupes(clazz.virtualMethods); - clazz.staticFields = substituteTypesIn(clazz.staticFields); - clazz.instanceFields = substituteTypesIn(clazz.instanceFields); + clazz.setDirectMethods(substituteTypesIn(clazz.directMethods())); + clazz.setVirtualMethods(substituteTypesIn(clazz.virtualMethods())); + clazz.setVirtualMethods(removeDupes(clazz.virtualMethods())); + clazz.setStaticFields(substituteTypesIn(clazz.staticFields())); + clazz.setInstanceFields(substituteTypesIn(clazz.instanceFields())); } // Record type renamings so instanceof and checkcast checks are also fixed. for (DexType type : mergedClasses.keySet()) { diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java index 58646a8c3..64294bd10 100644 --- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java +++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java @@ -84,10 +84,10 @@ public class TreePruner { // The class is used and must be kept. Remove the unused fields and methods from // the class. usagePrinter.visiting(clazz); - clazz.directMethods = reachableMethods(clazz.directMethods(), clazz); - clazz.virtualMethods = reachableMethods(clazz.virtualMethods(), clazz); - clazz.instanceFields = reachableFields(clazz.instanceFields()); - clazz.staticFields = reachableFields(clazz.staticFields()); + clazz.setDirectMethods(reachableMethods(clazz.directMethods(), clazz)); + clazz.setVirtualMethods(reachableMethods(clazz.virtualMethods(), clazz)); + clazz.setInstanceFields(reachableFields(clazz.instanceFields())); + clazz.setStaticFields(reachableFields(clazz.staticFields())); usagePrinter.visited(); } } diff --git a/src/test/java/com/android/tools/r8/smali/OutlineTest.java b/src/test/java/com/android/tools/r8/smali/OutlineTest.java index 4656cd6d9..c726aadbd 100644 --- a/src/test/java/com/android/tools/r8/smali/OutlineTest.java +++ b/src/test/java/com/android/tools/r8/smali/OutlineTest.java @@ -828,13 +828,13 @@ public class OutlineTest extends SmaliTestBase { DexInspector inspector = new DexInspector(processedApplication); ClassSubject clazz = inspector.clazz(options.outline.className); assertTrue(clazz.isPresent()); - assertEquals(3, clazz.getDexClass().directMethods.length); + assertEquals(3, clazz.getDexClass().directMethods().length); // Collect the return types of the putlines for the body of method1 and method2. List<DexType> r = new ArrayList<>(); - for (int i = 0; i < clazz.getDexClass().directMethods.length; i++) { - if (clazz.getDexClass().directMethods[i].getCode().asDexCode().instructions[0] + for (int i = 0; i < clazz.getDexClass().directMethods().length; i++) { + if (clazz.getDexClass().directMethods()[i].getCode().asDexCode().instructions[0] instanceof InvokeVirtual) { - r.add(clazz.getDexClass().directMethods[i].method.proto.returnType); + r.add(clazz.getDexClass().directMethods()[i].method.proto.returnType); } } assert r.size() == 2; |