summaryrefslogtreecommitdiff
path: root/test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java
diff options
context:
space:
mode:
Diffstat (limited to 'test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java')
-rw-r--r--test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java318
1 files changed, 318 insertions, 0 deletions
diff --git a/test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java b/test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java
new file mode 100644
index 0000000..f6c3c99
--- /dev/null
+++ b/test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java
@@ -0,0 +1,318 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.android.desugar;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
+import static org.objectweb.asm.Opcodes.ACC_FINAL;
+import static org.objectweb.asm.Opcodes.ACC_INTERFACE;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+import static org.objectweb.asm.Opcodes.ACC_SUPER;
+import static org.objectweb.asm.Opcodes.ACONST_NULL;
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.ARETURN;
+import static org.objectweb.asm.Opcodes.ASTORE;
+import static org.objectweb.asm.Opcodes.BIPUSH;
+import static org.objectweb.asm.Opcodes.DCONST_0;
+import static org.objectweb.asm.Opcodes.DLOAD;
+import static org.objectweb.asm.Opcodes.DUP_X1;
+import static org.objectweb.asm.Opcodes.FCONST_0;
+import static org.objectweb.asm.Opcodes.FLOAD;
+import static org.objectweb.asm.Opcodes.GOTO;
+import static org.objectweb.asm.Opcodes.IADD;
+import static org.objectweb.asm.Opcodes.ICONST_0;
+import static org.objectweb.asm.Opcodes.ICONST_1;
+import static org.objectweb.asm.Opcodes.ICONST_2;
+import static org.objectweb.asm.Opcodes.ICONST_4;
+import static org.objectweb.asm.Opcodes.IFNONNULL;
+import static org.objectweb.asm.Opcodes.ILOAD;
+import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.ISTORE;
+import static org.objectweb.asm.Opcodes.LCONST_0;
+import static org.objectweb.asm.Opcodes.LLOAD;
+import static org.objectweb.asm.Opcodes.NEW;
+import static org.objectweb.asm.Opcodes.RETURN;
+import static org.objectweb.asm.Opcodes.SIPUSH;
+import static org.objectweb.asm.Opcodes.SWAP;
+import static org.objectweb.asm.Opcodes.V1_8;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+/**
+ * Test data generator for b/62060793. This class creates a special labmda invocation that
+ * contains *CONST_0 values on stack, which are passed as lambda arguments.
+ */
+public class Bug62060793TestDataGenerator {
+
+ private static final String CLASS_NAME =
+ "com/google/devtools/build/android/desugar/testdata/ConstantArgumentsInLambda";
+
+ private static final String INTERFACE_TYPE_NAME = CLASS_NAME + "$Interface";
+
+ public static void main(String[] args) throws IOException {
+ checkArgument(
+ args.length == 1,
+ "Usage: %s <output-jar>",
+ Bug62060793TestDataGenerator.class.getName());
+ Path outputJar = Paths.get(args[0]);
+
+ try (ZipOutputStream outZip =
+ new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(outputJar)))) {
+ String className = CLASS_NAME + ".class";
+ writeToZipFile(outZip, className, createClass());
+ String interfaceName = INTERFACE_TYPE_NAME + ".class";
+ writeToZipFile(outZip, interfaceName, createInterface());
+ }
+ }
+
+ private static void writeToZipFile(ZipOutputStream outZip, String entryName, byte[] content)
+ throws IOException {
+ ZipEntry result = new ZipEntry(entryName);
+ result.setTime(0L);
+ outZip.putNextEntry(result);
+ outZip.write(content);
+ outZip.closeEntry();
+ }
+
+ private static byte[] createClass() {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ MethodVisitor mv;
+ cw.visit(
+ V1_8, ACC_PUBLIC | ACC_SUPER,
+ CLASS_NAME,
+ null, "java/lang/Object", null);
+
+ cw.visitInnerClass(
+ INTERFACE_TYPE_NAME,
+ CLASS_NAME,
+ "Interface",
+ ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
+
+ cw.visitInnerClass(
+ "java/lang/invoke/MethodHandles$Lookup",
+ "java/lang/invoke/MethodHandles",
+ "Lookup",
+ ACC_PUBLIC | ACC_FINAL | ACC_STATIC);
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(
+ ACC_PRIVATE | ACC_STATIC,
+ "method",
+ "(Ljava/lang/String;)Ljava/lang/String;",
+ null,
+ null);
+ mv.visitParameter("str", 0);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(ARETURN);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(
+ ACC_PRIVATE | ACC_STATIC,
+ "method",
+ "(ZCBFDJISLjava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;",
+ null,
+ null);
+ mv.visitParameter("bool", 0);
+ mv.visitParameter("c", 0);
+ mv.visitParameter("b", 0);
+ mv.visitParameter("f", 0);
+ mv.visitParameter("d", 0);
+ mv.visitParameter("l", 0);
+ mv.visitParameter("i", 0);
+ mv.visitParameter("s", 0);
+ mv.visitParameter("o", 0);
+ mv.visitParameter("array", 0);
+ mv.visitParameter("str", 0);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 10);
+ mv.visitMethodInsn(
+ INVOKESTATIC,
+ "java/lang/String",
+ "valueOf",
+ "(Ljava/lang/Object;)Ljava/lang/String;", false);
+ mv.visitVarInsn(ASTORE, 13);
+ mv.visitVarInsn(ALOAD, 11);
+ Label l0 = new Label();
+ mv.visitJumpInsn(IFNONNULL, l0);
+ mv.visitInsn(ICONST_1);
+ Label l1 = new Label();
+ mv.visitJumpInsn(GOTO, l1);
+ mv.visitLabel(l0);
+ mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {"java/lang/String"}, 0, null);
+ mv.visitInsn(ICONST_0);
+ mv.visitLabel(l1);
+ mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
+ mv.visitVarInsn(ISTORE, 14);
+ mv.visitIntInsn(BIPUSH, 91);
+ mv.visitVarInsn(ALOAD, 12);
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/String",
+ "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;", false);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String",
+ "length", "()I", false);
+ mv.visitInsn(IADD);
+ mv.visitVarInsn(ALOAD, 13);
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/String",
+ "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;", false);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String",
+ "length", "()I", false);
+ mv.visitInsn(IADD);
+ mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
+ mv.visitInsn(DUP_X1);
+ mv.visitInsn(SWAP);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder",
+ "<init>", "(I)V", false);
+ mv.visitVarInsn(ALOAD, 12);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(Z)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 1);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(C)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(I)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(FLOAD, 3);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(F)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(DLOAD, 4);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(D)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(LLOAD, 6);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(J)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 8);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(I)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 9);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(I)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ALOAD, 13);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 14);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(Z)Ljava/lang/StringBuilder;", false);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "toString", "()Ljava/lang/String;", false);
+ mv.visitInsn(ARETURN);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(
+ ACC_PUBLIC | ACC_STATIC,
+ "lambdaWithConstantArguments",
+ "()L" + INTERFACE_TYPE_NAME + ";",
+ null, null);
+ mv.visitCode();
+ mv.visitInsn(ICONST_0);
+ mv.visitInsn(ICONST_1);
+ mv.visitInsn(ICONST_2);
+ mv.visitInsn(FCONST_0);
+ mv.visitInsn(DCONST_0);
+ mv.visitInsn(LCONST_0);
+ mv.visitInsn(ICONST_4);
+ mv.visitIntInsn(SIPUSH, 9);
+ mv.visitInsn(ACONST_NULL);
+ mv.visitInsn(ACONST_NULL);
+ mv.visitInvokeDynamicInsn(
+ "call",
+ "(ZCBFDJISLjava/lang/Object;[Ljava/lang/Object;)L" + INTERFACE_TYPE_NAME + ";",
+ new Handle(
+ Opcodes.H_INVOKESTATIC,
+ "java/lang/invoke/LambdaMetafactory",
+ "metafactory",
+ "(Ljava/lang/invoke/MethodHandles$Lookup;"
+ + "Ljava/lang/String;Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodHandle;"
+ + "Ljava/lang/invoke/MethodType;"
+ + ")Ljava/lang/invoke/CallSite;",
+ false),
+ new Object[] {
+ Type.getType("(Ljava/lang/String;)Ljava/lang/String;"),
+ new Handle(
+ Opcodes.H_INVOKESTATIC,
+ CLASS_NAME,
+ "method",
+ "(ZCBFDJISLjava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;"
+ + ")Ljava/lang/String;",
+ false),
+ Type.getType("(Ljava/lang/String;)Ljava/lang/String;")});
+ mv.visitInsn(ARETURN);
+ mv.visitEnd();
+ }
+
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ private static byte[] createInterface() {
+ ClassWriter cw = new ClassWriter(0);
+ MethodVisitor mv;
+
+ cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE,
+ INTERFACE_TYPE_NAME,
+ null, "java/lang/Object", null);
+
+ cw.visitInnerClass(
+ INTERFACE_TYPE_NAME,
+ CLASS_NAME,
+ "Interface",
+ ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
+
+ {
+ mv = cw.visitMethod(
+ ACC_PUBLIC | ACC_ABSTRACT,
+ "call",
+ "(Ljava/lang/String;)Ljava/lang/String;",
+ null,
+ null);
+ mv.visitParameter("input", 0);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+
+ return cw.toByteArray();
+
+ }
+}