diff options
author | Googler <noreply@google.com> | 2017-11-28 05:54:07 -0800 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2017-11-28 05:56:02 -0800 |
commit | af10f2a83bdda8406a8c0a012db6d38e19d022b0 (patch) | |
tree | d384623998a0096577b5c747d3bc9a97e135efcc /src/tools/android/java/com/google/devtools/build/android/desugar | |
parent | 683bdc7a069a8328676740798d2fb6abc2119a2f (diff) |
Let to push lambda arguments not only with *LOAD instructions but with SIPUSH and *CONST_*.
RELNOTES: None
PiperOrigin-RevId: 177149410
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/desugar')
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/desugar/LambdaDesugaring.java | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaDesugaring.java b/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaDesugaring.java index b1eefa80bb..86cc69245e 100644 --- a/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaDesugaring.java +++ b/src/tools/android/java/com/google/devtools/build/android/desugar/LambdaDesugaring.java @@ -533,12 +533,13 @@ class LambdaDesugaring extends ClassVisitor { i, internalName, insn.getOpcode()); - } else if (insn.getOpcode() != paramTypes[i].getOpcode(Opcodes.ILOAD)) { - // Otherwise expect load of a (effectively) final local variable. Not seeing that means - // we're dealing with a method reference on some arbitrary expression, <expression>::m. - // In that case we give up and keep using the factory method for now, since inserting - // the NEW/DUP so the new object ends up in the right stack slot is hard in that case. - // Note this still covers simple cases such as this::m or x::m, where x is a local. + } else if (!isPushForType(insn, paramTypes[i])) { + // Otherwise expect load of a (effectively) final local variable or a constant. Not seeing + // that means we're dealing with a method reference on some arbitrary expression, + // <expression>::m. In that case we give up and keep using the factory method for now, + // since inserting the NEW/DUP so the new object ends up in the right stack slot is hard + // in that case. Note this still covers simple cases such as this::m or x::m, where x is a + // local. checkState( paramTypes.length == 1, "Expected a load for %s to set up parameter %s for %s but got %s", @@ -562,6 +563,59 @@ class LambdaDesugaring extends ClassVisitor { return true; } + /** + * Returns whether a given instruction can be used to push argument of {@code type} on stack. + */ + private /* static */ boolean isPushForType(AbstractInsnNode insn, Type type) { + int opcode = insn.getOpcode(); + if (opcode == type.getOpcode(Opcodes.ILOAD)) { + return true; + } + // b/62060793: AsyncAwait rewrites bytecode to convert java methods into state machine with + // support of lambdas. Constant zero values are pushed on stack for all yet uninitialized + // local variables. And SIPUSH instruction is used to advance an internal state of a state + // machine. + switch (type.getSort()) { + case Type.BOOLEAN: + return opcode == Opcodes.ICONST_0 + || opcode == Opcodes.ICONST_1; + + case Type.BYTE: + case Type.CHAR: + case Type.SHORT: + case Type.INT: + return opcode == Opcodes.SIPUSH + || opcode == Opcodes.ICONST_0 + || opcode == Opcodes.ICONST_1 + || opcode == Opcodes.ICONST_2 + || opcode == Opcodes.ICONST_3 + || opcode == Opcodes.ICONST_4 + || opcode == Opcodes.ICONST_5 + || opcode == Opcodes.ICONST_M1; + + case Type.LONG: + return opcode == Opcodes.LCONST_0 + || opcode == Opcodes.LCONST_1; + + case Type.FLOAT: + return opcode == Opcodes.FCONST_0 + || opcode == Opcodes.FCONST_1 + || opcode == Opcodes.FCONST_2; + + case Type.DOUBLE: + return opcode == Opcodes.DCONST_0 + || opcode == Opcodes.DCONST_1; + + case Type.OBJECT: + case Type.ARRAY: + return opcode == Opcodes.ACONST_NULL; + + default: + // Support for BIPUSH and LDC* opcodes is not implemented as there is no known use case. + return false; + } + } + private Lookup createLookup(String lookupClass) throws ReflectiveOperationException { Class<?> clazz = loadFromInternal(lookupClass); Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class); |