aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassFixer.java
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-03-03 19:09:57 +0000
committerGravatar Yue Gan <yueg@google.com>2017-03-06 09:46:16 +0000
commit48e3825aa5a655247f3bfc9fdbcdc23d6ab9187e (patch)
treeab567d1604ae86a14d386a2c801e95bf5325f0f3 /src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassFixer.java
parentccd0ffb28676fb5943ae3a364ea40219160b86f8 (diff)
Avoid factory methods when desugaring stateless lambdas for Android
RELNOTES: Avoid factory methods when desugaring stateless lambdas for Android -- PiperOrigin-RevId: 149131637 MOS_MIGRATED_REVID=149131637
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassFixer.java')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassFixer.java39
1 files changed, 13 insertions, 26 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassFixer.java b/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassFixer.java
index 12f735d896..e942c95b6e 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassFixer.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaClassFixer.java
@@ -27,7 +27,6 @@ import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TypeInsnNode;
@@ -41,8 +40,10 @@ import org.objectweb.asm.tree.TypeInsnNode;
*/
class LambdaClassFixer extends ClassVisitor {
- /** Magic method name used by {@link java.lang.invoke.LambdaMetafactory} */
+ /** Magic method name used by {@link java.lang.invoke.LambdaMetafactory}. */
public static final String FACTORY_METHOD_NAME = "get$Lambda";
+ /** Field name we'll use to hold singleton instances where possible. */
+ public static final String SINGLETON_FIELD_NAME = "$instance";
private final LambdaInfo lambdaInfo;
private final ClassReaderFactory factory;
@@ -59,7 +60,6 @@ class LambdaClassFixer extends ClassVisitor {
private String desc;
private String signature;
- private String[] exceptions;
public LambdaClassFixer(ClassVisitor dest, LambdaInfo lambdaInfo, ClassReaderFactory factory,
@@ -86,7 +86,6 @@ class LambdaClassFixer extends ClassVisitor {
hasFactory = false;
desc = null;
this.signature = null;
- exceptions = null;
this.interfaces = ImmutableList.copyOf(interfaces);
// Rename to desired name
super.visit(version, access, getInternalName(), signature, superName, interfaces);
@@ -122,7 +121,6 @@ class LambdaClassFixer extends ClassVisitor {
} else if ("<init>".equals(name)) {
this.desc = desc;
this.signature = signature;
- this.exceptions = exceptions;
}
MethodVisitor methodVisitor =
new LambdaClassMethodRewriter(super.visitMethod(access, name, desc, signature, exceptions));
@@ -141,16 +139,18 @@ class LambdaClassFixer extends ClassVisitor {
public void visitEnd() {
checkState(!hasState || hasFactory,
"Expected factory method for capturing lambda %s", getInternalName());
- if (!hasFactory) {
- // Fake factory method if LambdaMetafactory didn't generate it
+ if (!hasState) {
checkState(signature == null,
"Didn't expect generic constructor signature %s %s", getInternalName(), signature);
-
- // Since this is a stateless class we populate and use a static singleton field "$instance"
- String singletonFieldDesc = Type.getObjectType(getInternalName()).getDescriptor();
+ checkState(lambdaInfo.factoryMethodDesc().startsWith("()"),
+ "Expected 0-arg factory method for %s but found %s", getInternalName(),
+ lambdaInfo.factoryMethodDesc());
+ // Since this is a stateless class we populate and use a static singleton field "$instance".
+ // Field is package-private so we can read it from the class that had the invokedynamic.
+ String singletonFieldDesc = lambdaInfo.factoryMethodDesc().substring("()".length());
super.visitField(
- Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL,
- "$instance",
+ Opcodes.ACC_STATIC | Opcodes.ACC_FINAL,
+ SINGLETON_FIELD_NAME,
singletonFieldDesc,
(String) null,
(Object) null)
@@ -168,26 +168,13 @@ class LambdaClassFixer extends ClassVisitor {
codeBuilder.visitMethodInsn(Opcodes.INVOKESPECIAL, getInternalName(), "<init>",
checkNotNull(desc, "didn't see a constructor for %s", getInternalName()), /*itf*/ false);
codeBuilder.visitFieldInsn(
- Opcodes.PUTSTATIC, getInternalName(), "$instance", singletonFieldDesc);
+ Opcodes.PUTSTATIC, getInternalName(), SINGLETON_FIELD_NAME, singletonFieldDesc);
codeBuilder.visitInsn(Opcodes.RETURN);
codeBuilder.visitMaxs(2, 0); // two values are pushed onto the stack
codeBuilder.visitEnd();
-
- codeBuilder = // reuse codeBuilder variable to avoid accidental additions to previous method
- super.visitMethod(
- Opcodes.ACC_STATIC,
- FACTORY_METHOD_NAME,
- lambdaInfo.factoryMethodDesc(),
- (String) null,
- exceptions);
- codeBuilder.visitFieldInsn(
- Opcodes.GETSTATIC, getInternalName(), "$instance", singletonFieldDesc);
- codeBuilder.visitInsn(Opcodes.ARETURN);
- codeBuilder.visitMaxs(1, 0); // one value on the stack
}
copyRewrittenLambdaMethods();
-
if (!allowDefaultMethods) {
copyBridgeMethods(interfaces);
}