diff options
author | Colin Cross <ccross@android.com> | 2017-05-02 17:13:34 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-05-02 17:13:34 +0000 |
commit | 17df38ab042e1294f828333b0cd7f06a0858ac42 (patch) | |
tree | 6c0ec8bf5208bfe19fc41292a29cd914f350ba25 | |
parent | ce7ccb0464c16d761f6e395bef9d35e9f78edec6 (diff) | |
parent | deaba3bcbb075ef523ec09592af745a2be944290 (diff) | |
download | desugar-17df38ab042e1294f828333b0cd7f06a0858ac42.tar.gz |
Merge remote-tracking branch 'aosp/upstream-master' into desugar am: e3fedeb000 am: 36c2d50414
am: deaba3bcbb
Change-Id: I6b6426a8d3dfa528cb4545a712c420de53edb8bc
3 files changed, 43 insertions, 11 deletions
diff --git a/java/com/google/devtools/build/android/desugar/DefaultMethodClassFixer.java b/java/com/google/devtools/build/android/desugar/DefaultMethodClassFixer.java index 8ad5dc2..732f064 100644 --- a/java/com/google/devtools/build/android/desugar/DefaultMethodClassFixer.java +++ b/java/com/google/devtools/build/android/desugar/DefaultMethodClassFixer.java @@ -132,6 +132,19 @@ public class DefaultMethodClassFixer extends ClassVisitor { return false; } + /** + * Returns {@code true} for non-bridge default methods not in {@link #instanceMethods}. + */ + private boolean shouldStub(int access, String name, String desc) { + // Ignore private methods, which technically aren't default methods and can only be called from + // other methods defined in the interface. This also ignores lambda body methods, which is fine + // as we don't want or need to stub those. Also ignore bridge methods as javac adds them to + // concrete classes as needed anyway and we handle them separately for generated lambda classes. + return BitFlags.noneSet(access, + Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_PRIVATE) + && !instanceMethods.contains(name + ":" + desc); + } + private void stubMissingDefaultMethods(ImmutableList<String> interfaces) { for (String implemented : interfaces) { if (!seenInterfaces.add(implemented)) { @@ -183,12 +196,10 @@ public class DefaultMethodClassFixer extends ClassVisitor { @Override public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions) { - if (BitFlags.noneSet(access, Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC | Opcodes.ACC_BRIDGE) - && !instanceMethods.contains(name + ":" + desc)) { + if (shouldStub(access, name, desc)) { // Add this method to the class we're desugaring and stub in a body to call the default // implementation in the interface's companion class. ijar omits these methods when setting - // ACC_SYNTHETIC modifier, so don't. Don't do this for bridge methods, which we handle - // separately. + // ACC_SYNTHETIC modifier, so don't. // Signatures can be wrong, e.g., when type variables are introduced, instantiated, or // refined in the class we're processing, so drop them. MethodVisitor stubMethod = @@ -255,8 +266,7 @@ public class DefaultMethodClassFixer extends ClassVisitor { @Override public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions) { - if (BitFlags.noneSet(access, Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC | Opcodes.ACC_BRIDGE) - && !instanceMethods.contains(name + ":" + desc)) { + if (!found && shouldStub(access, name, desc)) { // Found a default method we're not ignoring (instanceMethods at this point contains methods // the top-level visited class implements itself). found = true; diff --git a/java/com/google/devtools/build/android/desugar/Desugar.java b/java/com/google/devtools/build/android/desugar/Desugar.java index c4528ae..ca7032e 100644 --- a/java/com/google/devtools/build/android/desugar/Desugar.java +++ b/java/com/google/devtools/build/android/desugar/Desugar.java @@ -522,15 +522,19 @@ class Desugar { * LambdaClassMaker generates lambda classes for us, but it does so by essentially simulating the * call to LambdaMetafactory that the JVM would make when encountering an invokedynamic. * LambdaMetafactory is in the JDK and its implementation has a property to write out ("dump") - * generated classes, which we take advantage of here. Set property before doing anything else - * since the property is read in the static initializer; if this breaks we can investigate setting - * the property when calling the tool. + * generated classes, which we take advantage of here. This property can be set externally, and in + * that case the specified directory is used as a temporary dir. Otherwise, it will be set here, + * before doing anything else since the property is read in the static initializer. */ private static Path createAndRegisterLambdaDumpDirectory() throws IOException { + String propertyValue = System.getProperty(LambdaClassMaker.LAMBDA_METAFACTORY_DUMPER_PROPERTY); + if (propertyValue != null) { + return Paths.get(propertyValue); + } + Path dumpDirectory = Files.createTempDirectory("lambdas"); System.setProperty( LambdaClassMaker.LAMBDA_METAFACTORY_DUMPER_PROPERTY, dumpDirectory.toString()); - deleteTreeOnExit(dumpDirectory); return dumpDirectory; } diff --git a/java/com/google/devtools/build/android/desugar/TryWithResourcesRewriter.java b/java/com/google/devtools/build/android/desugar/TryWithResourcesRewriter.java index 2429d2f..cde223e 100644 --- a/java/com/google/devtools/build/android/desugar/TryWithResourcesRewriter.java +++ b/java/com/google/devtools/build/android/desugar/TryWithResourcesRewriter.java @@ -85,6 +85,11 @@ public class TryWithResourcesRewriter extends ClassVisitor { private final ClassLoader classLoader; private final AtomicInteger numOfTryWithResourcesInvoked; + /** + * Indicate whether the current class being desugared should be ignored. If the current class is + * one of the runtime extension classes, then it should be ignored. + */ + private boolean shouldCurrentClassBeIgnored; public TryWithResourcesRewriter( ClassVisitor classVisitor, @@ -96,10 +101,23 @@ public class TryWithResourcesRewriter extends ClassVisitor { } @Override + public void visit( + int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces); + shouldCurrentClassBeIgnored = THROWABLE_EXT_CLASS_INTERNAL_NAMES.contains(name); + } + + + @Override public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor visitor = super.cv.visitMethod(access, name, desc, signature, exceptions); - return visitor == null || THROWABLE_EXT_CLASS_INTERNAL_NAMES.contains(name) + return visitor == null || shouldCurrentClassBeIgnored ? visitor : new TryWithResourceVisitor(visitor, classLoader); } |