aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android/desugar
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-11-28 05:54:07 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2017-11-28 05:56:02 -0800
commitaf10f2a83bdda8406a8c0a012db6d38e19d022b0 (patch)
treed384623998a0096577b5c747d3bc9a97e135efcc /src/tools/android/java/com/google/devtools/build/android/desugar
parent683bdc7a069a8328676740798d2fb6abc2119a2f (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.java66
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);