From bdb12ceeb7c23d7d2293e8006d0aa7127a91b973 Mon Sep 17 00:00:00 2001 From: kmb Date: Tue, 3 Oct 2017 02:14:25 +0200 Subject: add flags to desugar to emit metadata that can be used for double-checking correctness of default and static interface desugaring. RELNOTES: none PiperOrigin-RevId: 170779637 --- .../build/android/desugar/InterfaceDesugaring.java | 40 ++++++++++++++++------ 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'src/tools/android/java/com/google/devtools/build/android/desugar/InterfaceDesugaring.java') diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/InterfaceDesugaring.java b/src/tools/android/java/com/google/devtools/build/android/desugar/InterfaceDesugaring.java index 6bac9edb26..0f03236e72 100644 --- a/src/tools/android/java/com/google/devtools/build/android/desugar/InterfaceDesugaring.java +++ b/src/tools/android/java/com/google/devtools/build/android/desugar/InterfaceDesugaring.java @@ -42,9 +42,9 @@ class InterfaceDesugaring extends ClassVisitor { static final String COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_NAME = "$$triggerInterfaceInit"; static final String COMPANION_METHOD_TO_TRIGGER_INTERFACE_CLINIT_DESC = "()V"; - static final String COMPANION_SUFFIX = "$$CC"; static final String INTERFACE_STATIC_COMPANION_METHOD_SUFFIX = "$$STATIC$$"; + private final DependencyCollector depsCollector; private final ClassReaderFactory bootclasspath; private final GeneratedClassStore store; private final boolean legacyJaCoCo; @@ -52,13 +52,18 @@ class InterfaceDesugaring extends ClassVisitor { private String internalName; private int bytecodeVersion; private int accessFlags; + private int numberOfDefaultMethods; @Nullable private ClassVisitor companion; @Nullable private FieldInfo interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit; public InterfaceDesugaring( - ClassVisitor dest, ClassReaderFactory bootclasspath, GeneratedClassStore store, + ClassVisitor dest, + DependencyCollector depsCollector, + ClassReaderFactory bootclasspath, + GeneratedClassStore store, boolean legacyJaCoCo) { super(Opcodes.ASM5, dest); + this.depsCollector = depsCollector; this.bootclasspath = bootclasspath; this.store = store; this.legacyJaCoCo = legacyJaCoCo; @@ -73,15 +78,26 @@ class InterfaceDesugaring extends ClassVisitor { String superName, String[] interfaces) { companion = null; + numberOfDefaultMethods = 0; internalName = name; bytecodeVersion = version; accessFlags = access; + if (isInterface()) { + // Record interface hierarchy. This helps avoid parsing .class files when double-checking + // desugaring results later using collected dependency information. + depsCollector.recordExtendedInterfaces(name, interfaces); + } super.visit(version, access, name, signature, superName, interfaces); } @Override public void visitEnd() { if (companion != null) { + // Record classes with default methods. This increases precision when double-checking + // desugaring results later, without parsing .class files again, compared to just looking + // for companion classes in a given desugared Jar which may only contain static methods. + depsCollector.recordDefaultMethods(internalName, numberOfDefaultMethods); + // Emit a method to access the fields of the interfaces that need initialization. emitInterfaceFieldAccessInCompanionMethodToTriggerInterfaceClinit(); companion.visitEnd(); @@ -185,6 +201,7 @@ class InterfaceDesugaring extends ClassVisitor { name, internalName, desc); + ++numberOfDefaultMethods; abstractDest = super.visitMethod(access | Opcodes.ACC_ABSTRACT, name, desc, signature, exceptions); } @@ -228,7 +245,7 @@ class InterfaceDesugaring extends ClassVisitor { // Rename lambda method to reflect the new owner. Not doing so confuses LambdaDesugaring // if it's run over this class again. LambdaDesugaring has already renamed the method from // its original name to include the interface name at this point. - suffix = COMPANION_SUFFIX; + suffix = DependencyCollector.INTERFACE_COMPANION_SUFFIX; } else if (isStatic) { suffix = INTERFACE_STATIC_COMPANION_METHOD_SUFFIX; } else { @@ -238,7 +255,7 @@ class InterfaceDesugaring extends ClassVisitor { } static String getCompanionClassName(String interfaceName) { - return interfaceName + COMPANION_SUFFIX; + return interfaceName + DependencyCollector.INTERFACE_COMPANION_SUFFIX; } /** @@ -329,8 +346,8 @@ class InterfaceDesugaring extends ClassVisitor { name = normalizeInterfaceMethodName(name, isLambda, opcode == Opcodes.INVOKESTATIC); if (isLambda) { // Redirect lambda invocations to completely remove all lambda methods from interfaces. - checkArgument( - !owner.endsWith(COMPANION_SUFFIX), "shouldn't consider %s an interface", owner); + checkArgument(!owner.endsWith(DependencyCollector.INTERFACE_COMPANION_SUFFIX), + "shouldn't consider %s an interface", owner); checkArgument(!bootclasspath.isKnown(owner)); // must be in current input if (opcode == Opcodes.INVOKEINTERFACE) { opcode = Opcodes.INVOKESTATIC; @@ -344,7 +361,7 @@ class InterfaceDesugaring extends ClassVisitor { name); } // Reflect that InterfaceDesugaring moves and renames the lambda body method - owner += COMPANION_SUFFIX; + owner += DependencyCollector.INTERFACE_COMPANION_SUFFIX; String expectedLambdaMethodName = LambdaDesugaring.uniqueInPackage(owner, name); checkState( name.equals(expectedLambdaMethodName), @@ -355,14 +372,14 @@ class InterfaceDesugaring extends ClassVisitor { itf = false; } else if ((opcode == Opcodes.INVOKESTATIC || opcode == Opcodes.INVOKESPECIAL) && !bootclasspath.isKnown(owner)) { - checkArgument( - !owner.endsWith(COMPANION_SUFFIX), "shouldn't consider %s an interface", owner); + checkArgument(!owner.endsWith(DependencyCollector.INTERFACE_COMPANION_SUFFIX), + "shouldn't consider %s an interface", owner); if (opcode == Opcodes.INVOKESPECIAL) { // Turn Interface.super.m() into Interface$$CC.m(receiver) opcode = Opcodes.INVOKESTATIC; desc = companionDefaultMethodDescriptor(owner, desc); } - owner += COMPANION_SUFFIX; + owner += DependencyCollector.INTERFACE_COMPANION_SUFFIX; itf = false; } } @@ -384,7 +401,8 @@ class InterfaceDesugaring extends ClassVisitor { @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { if ("$jacocoData".equals(name)) { - checkState(!owner.endsWith(COMPANION_SUFFIX), "Expected interface: %s", owner); + checkState(!owner.endsWith(DependencyCollector.INTERFACE_COMPANION_SUFFIX), + "Expected interface: %s", owner); owner = getCompanionClassName(owner); } super.visitFieldInsn(opcode, owner, name, desc); -- cgit v1.2.3