diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/dependencies/DesugarDependencyInfoWrapper.java b/src/tools/android/java/com/google/devtools/build/android/desugar/dependencies/DesugarDependencyInfoWrapper.java new file mode 100644 index 00000000000000..c796db2b7612c6 --- /dev/null +++ b/src/tools/android/java/com/google/devtools/build/android/desugar/dependencies/DesugarDependencyInfoWrapper.java @@ -0,0 +1,72 @@ +package src.tools.android.java.com.google.devtools.build.android.desugar.dependencies; + +import com.google.devtools.build.android.desugar.proto.DesugarDeps; + +import java.util.ArrayList; +import java.util.Comparator; + +/** + * a wrapper that is responsible to sort desugar dependency collector items + * since this items will be add to the jar file as metadata it should be deterministic so it won't + * cause cache misses + */ +public class DesugarDependencyInfoWrapper { + public final DesugarDeps.DesugarDepsInfo.Builder info = DesugarDeps.DesugarDepsInfo.newBuilder(); + + public ArrayList assume_present = new ArrayList<>(); + public ArrayList missing_interface = new ArrayList<>(); + public ArrayList interface_with_supertypes = new ArrayList<>(); + public ArrayList interface_with_companion = new ArrayList<>(); + + public void assumeCompanionClass(DesugarDeps.Dependency dependency) { + assume_present.add(dependency); + } + + public void missingImplementedInterface(DesugarDeps.Dependency dependency) { + missing_interface.add(dependency); + } + + public void recordExtendedInterfaces(DesugarDeps.InterfaceDetails interfaceDetails) { + interface_with_supertypes.add(interfaceDetails); + } + + public void recordDefaultMethods(DesugarDeps.InterfaceWithCompanion interfaceWithCompanion) { + interface_with_companion.add(interfaceWithCompanion); + } + + public byte[] toByteArray() { + DesugarDeps.DesugarDepsInfo result = buildInfo(); + return DesugarDeps.DesugarDepsInfo.getDefaultInstance().equals(result) ? null : result.toByteArray(); + } + + private DesugarDeps.DesugarDepsInfo buildInfo() { + + assume_present.sort(dependencyComparator); + missing_interface.sort(dependencyComparator); + + interface_with_supertypes.sort(interfaceDetailComparator); + + interface_with_companion.sort(interFaceWithCompanionComparator); + + info.addAllAssumePresent(assume_present); + info.addAllMissingInterface(missing_interface); + info.addAllInterfaceWithSupertypes(interface_with_supertypes); + info.addAllInterfaceWithCompanion(interface_with_companion); + return info.build(); + } + + Comparator dependencyComparator = + (Comparator) (o1, o2) -> { + int diff = o1.getOrigin().getBinaryName().compareTo(o2.getOrigin().getBinaryName()); + if (diff == 0) { + return o1.getTarget().getBinaryName().compareTo(o2.getTarget().getBinaryName()); + } + return diff; + }; + Comparator interfaceDetailComparator = + (Comparator) + Comparator.comparing((DesugarDeps.InterfaceDetails o) -> + o.getOrigin().getBinaryName()); + Comparator interFaceWithCompanionComparator = + Comparator.comparing(o -> o.getOrigin().getBinaryName()); +} diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/dependencies/MetadataCollector.java b/src/tools/android/java/com/google/devtools/build/android/desugar/dependencies/MetadataCollector.java index 2a8a0e3bd95819..9557aaab8d3591 100644 --- a/src/tools/android/java/com/google/devtools/build/android/desugar/dependencies/MetadataCollector.java +++ b/src/tools/android/java/com/google/devtools/build/android/desugar/dependencies/MetadataCollector.java @@ -22,72 +22,79 @@ import com.google.devtools.build.android.desugar.proto.DesugarDeps.InterfaceDetails; import com.google.devtools.build.android.desugar.proto.DesugarDeps.InterfaceWithCompanion; import com.google.devtools.build.android.r8.DependencyCollector; + +import java.util.ArrayList; +import java.util.Comparator; + import javax.annotation.Nullable; +import src.tools.android.java.com.google.devtools.build.android.desugar.dependencies.DesugarDependencyInfoWrapper; + /** Dependency collector that emits collected metadata as a {@link DesugarDepsInfo} proto. */ public final class MetadataCollector implements DependencyCollector { private final boolean tolerateMissingDeps; - private final DesugarDepsInfo.Builder info = DesugarDeps.DesugarDepsInfo.newBuilder(); - + private DesugarDependencyInfoWrapper info = new DesugarDependencyInfoWrapper(); public MetadataCollector(boolean tolerateMissingDeps) { this.tolerateMissingDeps = tolerateMissingDeps; } private static boolean isInterfaceCompanionClass(String name) { return name.endsWith(INTERFACE_COMPANION_SUFFIX) - || name.endsWith(D8_INTERFACE_COMPANION_SUFFIX); + || name.endsWith(D8_INTERFACE_COMPANION_SUFFIX); } @Override public void assumeCompanionClass(String origin, String target) { checkArgument( - isInterfaceCompanionClass(target), "target not a companion: %s -> %s", origin, target); - info.addAssumePresent( - Dependency.newBuilder().setOrigin(wrapType(origin)).setTarget(wrapType(target))); + isInterfaceCompanionClass(target), "target not a companion: %s -> %s", origin, target); + info.assumeCompanionClass( + Dependency.newBuilder().setOrigin(wrapType(origin)).setTarget(wrapType(target)).build()); } @Override public void missingImplementedInterface(String origin, String target) { checkArgument( - !isInterfaceCompanionClass(target), - "target seems to be a companion: %s -> %s", - origin, - target); + !isInterfaceCompanionClass(target), + "target seems to be a companion: %s -> %s", + origin, + target); checkState( - tolerateMissingDeps, - "Couldn't find interface %s on the classpath for desugaring %s", - target, - origin); - info.addMissingInterface( - Dependency.newBuilder().setOrigin(wrapType(origin)).setTarget(wrapType(target))); + tolerateMissingDeps, + "Couldn't find interface %s on the classpath for desugaring %s", + target, + origin); + info.missingImplementedInterface( + Dependency.newBuilder().setOrigin(wrapType(origin)).setTarget(wrapType(target)).build()); } @Override public void recordExtendedInterfaces(String origin, String... targets) { if (targets.length > 0) { InterfaceDetails.Builder details = InterfaceDetails.newBuilder().setOrigin(wrapType(origin)); + ArrayList types = new ArrayList<>(); for (String target : targets) { - details.addExtendedInterface(wrapType(target)); + types.add(wrapType(target)); } - info.addInterfaceWithSupertypes(details); + types.sort(Comparator.comparing(DesugarDeps.Type::getBinaryName)); + details.addAllExtendedInterface(types); + info.recordExtendedInterfaces(details.build()); } } @Override public void recordDefaultMethods(String origin, int count) { checkArgument(!isInterfaceCompanionClass(origin), "seems to be a companion: %s", origin); - info.addInterfaceWithCompanion( - InterfaceWithCompanion.newBuilder() - .setOrigin(wrapType(origin)) - .setNumDefaultMethods(count)); + info.recordDefaultMethods( + InterfaceWithCompanion.newBuilder() + .setOrigin(wrapType(origin)) + .setNumDefaultMethods(count).build()); } @Override @Nullable public byte[] toByteArray() { - DesugarDepsInfo result = info.build(); - return DesugarDepsInfo.getDefaultInstance().equals(result) ? null : result.toByteArray(); + return info.toByteArray(); } private static DesugarDeps.Type wrapType(String internalName) {