diff options
Diffstat (limited to 'test/java/com/google/devtools/build/android')
10 files changed, 2107 insertions, 5 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(); + + } +} diff --git a/test/java/com/google/devtools/build/android/desugar/ByteCodeTypePrinter.java b/test/java/com/google/devtools/build/android/desugar/ByteCodeTypePrinter.java new file mode 100644 index 0000000..fefc599 --- /dev/null +++ b/test/java/com/google/devtools/build/android/desugar/ByteCodeTypePrinter.java @@ -0,0 +1,240 @@ +// 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 com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.util.Textifier; + +/** Print the types of the operand stack for each method. */ +public class ByteCodeTypePrinter { + + public static void printClassesWithTypes(Path inputJarFile, PrintWriter printWriter) + throws IOException { + Preconditions.checkState( + Files.exists(inputJarFile), "The input jar file %s does not exist.", inputJarFile); + try (ZipFile jarFile = new ZipFile(inputJarFile.toFile())) { + for (ZipEntry entry : getSortedClassEntriess(jarFile)) { + try (InputStream classStream = jarFile.getInputStream(entry)) { + printWriter.println("\nClass: " + entry.getName()); + ClassReader classReader = new ClassReader(classStream); + ClassVisitor visitor = new ClassWithTypeDumper(printWriter); + classReader.accept(visitor, 0); + } + printWriter.println("\n"); + } + } + } + + private static ImmutableList<ZipEntry> getSortedClassEntriess(ZipFile jar) { + return jar.stream() + .filter(entry -> entry.getName().endsWith(".class")) + .sorted() + .collect(ImmutableList.toImmutableList()); + } + + private static class ClassWithTypeDumper extends ClassVisitor { + + private String internalName; + private final PrintWriter printWriter; + + public ClassWithTypeDumper(PrintWriter printWriter) { + super(Opcodes.ASM5); + this.printWriter = printWriter; + } + + @Override + public void visit( + int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) { + internalName = name; + super.visit(version, access, name, signature, superName, interfaces); + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String desc, String signature, String[] exceptions) { + printWriter.println("Method " + name); + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + BytecodeTypeInference inference = new BytecodeTypeInference(access, internalName, name, desc); + mv = new MethodIrTypeDumper(mv, inference, printWriter); + inference.setDelegateMethodVisitor(mv); + // Let the type inference runs first. + return inference; + } + } + + private static final class TextifierExt extends Textifier { + + public TextifierExt() { + super(Opcodes.ASM5); + } + + public void print(String string) { + text.add(tab2 + string); + } + } + + private static class MethodIrTypeDumper extends MethodVisitor { + + private final BytecodeTypeInference inference; + private final TextifierExt printer = new TextifierExt(); + private final PrintWriter printWriter; + + public MethodIrTypeDumper( + MethodVisitor visitor, BytecodeTypeInference inference, PrintWriter printWriter) { + super(Opcodes.ASM5, visitor); + this.inference = inference; + this.printWriter = printWriter; + } + + private void printTypeOfOperandStackTop() { + printer.print(" |__STACK: " + inference.getOperandStackAsString() + "\n"); + } + + @Override + public void visitIntInsn(int opcode, int operand) { + printer.visitIntInsn(opcode, operand); + printTypeOfOperandStackTop(); + super.visitIntInsn(opcode, operand); + } + + @Override + public void visitInsn(int opcode) { + printer.visitInsn(opcode); + printTypeOfOperandStackTop(); + super.visitInsn(opcode); + } + + @Override + public void visitMultiANewArrayInsn(String desc, int dims) { + printer.visitMultiANewArrayInsn(desc, dims); + printTypeOfOperandStackTop(); + super.visitMultiANewArrayInsn(desc, dims); + } + + @Override + public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { + printer.visitLookupSwitchInsn(dflt, keys, labels); + printTypeOfOperandStackTop(); + super.visitLookupSwitchInsn(dflt, keys, labels); + } + + @Override + public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { + printer.visitTableSwitchInsn(min, max, dflt, labels); + printTypeOfOperandStackTop(); + super.visitTableSwitchInsn(min, max, dflt, labels); + } + + @Override + public void visitIincInsn(int var, int increment) { + printer.visitIincInsn(var, increment); + printTypeOfOperandStackTop(); + super.visitIincInsn(var, increment); + } + + @Override + public void visitLdcInsn(Object cst) { + printer.visitLdcInsn(cst); + printTypeOfOperandStackTop(); + super.visitLdcInsn(cst); + } + + @Override + public void visitJumpInsn(int opcode, Label label) { + printer.visitJumpInsn(opcode, label); + printTypeOfOperandStackTop(); + super.visitJumpInsn(opcode, label); + } + + @Override + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { + printer.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + printTypeOfOperandStackTop(); + super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { + printer.visitMethodInsn(opcode, owner, name, desc, itf); + printTypeOfOperandStackTop(); + super.visitMethodInsn(opcode, owner, name, desc, itf); + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc) { + printer.visitMethodInsn(opcode, owner, name, desc); + printTypeOfOperandStackTop(); + super.visitMethodInsn(opcode, owner, name, desc); + } + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String desc) { + printer.visitFieldInsn(opcode, owner, name, desc); + printTypeOfOperandStackTop(); + super.visitFieldInsn(opcode, owner, name, desc); + } + + @Override + public void visitTypeInsn(int opcode, String type) { + printer.visitTypeInsn(opcode, type); + printTypeOfOperandStackTop(); + super.visitTypeInsn(opcode, type); + } + + @Override + public void visitVarInsn(int opcode, int var) { + printer.visitVarInsn(opcode, var); + printTypeOfOperandStackTop(); + super.visitVarInsn(opcode, var); + } + + @Override + public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { + printer.visitFrame(type, nLocal, local, nStack, stack); + super.visitFrame(type, nLocal, local, nStack, stack); + } + + @Override + public void visitLabel(Label label) { + printer.visitLabel(label); + super.visitLabel(label); + } + + @Override + public void visitEnd() { + printer.print(printWriter); + printWriter.flush(); + super.visitEnd(); + } + } +} diff --git a/test/java/com/google/devtools/build/android/desugar/BytecodeTypeInferenceTest.golden.txt b/test/java/com/google/devtools/build/android/desugar/BytecodeTypeInferenceTest.golden.txt new file mode 100644 index 0000000..722c2ad --- /dev/null +++ b/test/java/com/google/devtools/build/android/desugar/BytecodeTypeInferenceTest.golden.txt @@ -0,0 +1,1170 @@ +Class: testsubjects/TestSubject.class +Method <init> + L0 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject;] + INVOKESPECIAL java/lang/Object.<init> ()V + |__STACK: [] + RETURN + |__STACK: [] +Method catchTest + L0 + ALOAD 0 + |__STACK: [Ljava/lang/Object;] + INSTANCEOF java/lang/String + |__STACK: [I] + IFNE L1 + |__STACK: [] + L2 + GETSTATIC testsubjects/TestSubject.VALUE_ONE : I + |__STACK: [I] + IRETURN + |__STACK: [] + L1 + FRAME SAME + ALOAD 0 + |__STACK: [Ljava/lang/Object;] + CHECKCAST java/lang/String + |__STACK: [Ljava/lang/String;] + INVOKESTATIC java/util/regex/Pattern.compile (Ljava/lang/String;)Ljava/util/regex/Pattern; + |__STACK: [Ljava/util/regex/Pattern;] + POP + |__STACK: [] + L3 + GOTO L4 + |__STACK: [] + L5 + FRAME SAME1 java/util/regex/PatternSyntaxException + ASTORE 2 + |__STACK: [] + L6 + GETSTATIC testsubjects/TestSubject.VALUE_TWO : I + |__STACK: [I] + IRETURN + |__STACK: [] + L4 + FRAME SAME + GETSTATIC testsubjects/TestSubject.VALUE_ONE : I + |__STACK: [I] + IRETURN + |__STACK: [] +Method assertEquals + L0 + DLOAD 1 + |__STACK: [D, TOP] + DLOAD 3 + |__STACK: [D, TOP, D, TOP] + INVOKESTATIC java/lang/Double.compare (DD)I + |__STACK: [I] + IFNE L1 + |__STACK: [] + L2 + RETURN + |__STACK: [] + L1 + FRAME SAME + DLOAD 1 + |__STACK: [D, TOP] + DLOAD 3 + |__STACK: [D, TOP, D, TOP] + DSUB + |__STACK: [D, TOP] + INVOKESTATIC java/lang/Math.abs (D)D + |__STACK: [D, TOP] + DLOAD 5 + |__STACK: [D, TOP, D, TOP] + DCMPG + |__STACK: [I] + IFLE L3 + |__STACK: [] + L4 + NEW java/lang/RuntimeException + |__STACK: [Ljava/lang/RuntimeException;] + DUP + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;] + NEW java/lang/StringBuilder + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;] + DUP + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/StringBuilder;] + INVOKESPECIAL java/lang/StringBuilder.<init> ()V + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;] + ALOAD 0 + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/String;] + INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;] + NEW java/lang/Double + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/Double;] + DUP + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/Double;, Ljava/lang/Double;] + DLOAD 1 + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/Double;, Ljava/lang/Double;, D, TOP] + INVOKESPECIAL java/lang/Double.<init> (D)V + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/Double;] + INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder; + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;] + NEW java/lang/Double + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/Double;] + DUP + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/Double;, Ljava/lang/Double;] + DLOAD 3 + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/Double;, Ljava/lang/Double;, D, TOP] + INVOKESPECIAL java/lang/Double.<init> (D)V + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;, Ljava/lang/Double;] + INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder; + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/StringBuilder;] + INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String; + |__STACK: [Ljava/lang/RuntimeException;, Ljava/lang/RuntimeException;, Ljava/lang/String;] + INVOKESPECIAL java/lang/RuntimeException.<init> (Ljava/lang/String;)V + |__STACK: [Ljava/lang/RuntimeException;] + ATHROW + |__STACK: [] + L3 + FRAME SAME + RETURN + |__STACK: [] +Method simpleTryWithResources + L0 + NEW testsubjects/TestSubject$SimpleResource + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;] + DUP + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;, Ltestsubjects/TestSubject$SimpleResource;] + INVOKESPECIAL testsubjects/TestSubject$SimpleResource.<init> ()V + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;] + ASTORE 0 + |__STACK: [] + ACONST_NULL + |__STACK: [NULL] + ASTORE 1 + |__STACK: [] + L1 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;] + ICONST_1 + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;, I] + INVOKEVIRTUAL testsubjects/TestSubject$SimpleResource.call (Z)V + |__STACK: [] + L2 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;] + IFNULL L3 + |__STACK: [] + ALOAD 1 + |__STACK: [NULL] + IFNULL L4 + |__STACK: [] + L5 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;] + INVOKEVIRTUAL testsubjects/TestSubject$SimpleResource.close ()V + |__STACK: [] + L6 + GOTO L3 + |__STACK: [] + L7 + FRAME FULL [testsubjects/TestSubject$SimpleResource java/lang/Throwable] [java/lang/Throwable] + ASTORE 2 + |__STACK: [] + ALOAD 1 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 2 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Throwable;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + GOTO L3 + |__STACK: [] + L4 + FRAME SAME + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;] + INVOKEVIRTUAL testsubjects/TestSubject$SimpleResource.close ()V + |__STACK: [] + GOTO L3 + |__STACK: [] + L8 + FRAME SAME1 java/lang/Throwable + ASTORE 2 + |__STACK: [] + ALOAD 2 + |__STACK: [Ljava/lang/Throwable;] + ASTORE 1 + |__STACK: [] + ALOAD 2 + |__STACK: [Ljava/lang/Throwable;] + ATHROW + |__STACK: [] + L9 + FRAME SAME1 java/lang/Throwable + ASTORE 3 + |__STACK: [] + L10 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;] + IFNULL L11 + |__STACK: [] + ALOAD 1 + |__STACK: [Ljava/lang/Throwable;] + IFNULL L12 + |__STACK: [] + L13 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;] + INVOKEVIRTUAL testsubjects/TestSubject$SimpleResource.close ()V + |__STACK: [] + L14 + GOTO L11 + |__STACK: [] + L15 + FRAME FULL [testsubjects/TestSubject$SimpleResource java/lang/Throwable T java/lang/Throwable] [java/lang/Throwable] + ASTORE 4 + |__STACK: [] + ALOAD 1 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 4 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Throwable;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + GOTO L11 + |__STACK: [] + L12 + FRAME SAME + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject$SimpleResource;] + INVOKEVIRTUAL testsubjects/TestSubject$SimpleResource.close ()V + |__STACK: [] + L11 + FRAME SAME + ALOAD 3 + |__STACK: [Ljava/lang/Throwable;] + ATHROW + |__STACK: [] + L3 + FRAME FULL [] [] + RETURN + |__STACK: [] +Method internalCompare + L0 + ALOAD 4 + |__STACK: [Ljava/util/function/BinaryOperator;] + LLOAD 0 + |__STACK: [Ljava/util/function/BinaryOperator;, J, TOP] + INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long; + |__STACK: [Ljava/util/function/BinaryOperator;, Ljava/lang/Long;] + LLOAD 2 + |__STACK: [Ljava/util/function/BinaryOperator;, Ljava/lang/Long;, J, TOP] + INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long; + |__STACK: [Ljava/util/function/BinaryOperator;, Ljava/lang/Long;, Ljava/lang/Long;] + INVOKEINTERFACE java/util/function/BinaryOperator.apply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + |__STACK: [Ljava/lang/Object;] + CHECKCAST java/lang/Long + |__STACK: [Ljava/lang/Long;] + INVOKEVIRTUAL java/lang/Long.longValue ()J + |__STACK: [J, TOP] + LRETURN + |__STACK: [] +Method closeResourceArray + L0 + ALOAD 1 + |__STACK: [[Ljava/sql/Statement;] + ASTORE 2 + |__STACK: [] + ALOAD 2 + |__STACK: [[Ljava/sql/Statement;] + ARRAYLENGTH + |__STACK: [I] + ISTORE 3 + |__STACK: [] + ICONST_0 + |__STACK: [I] + ISTORE 4 + |__STACK: [] + L1 + FRAME APPEND [[Ljava/sql/Statement; I I] + ILOAD 4 + |__STACK: [I] + ILOAD 3 + |__STACK: [I, I] + IF_ICMPGE L2 + |__STACK: [] + ALOAD 2 + |__STACK: [[Ljava/sql/Statement;] + ILOAD 4 + |__STACK: [[Ljava/sql/Statement;, I] + AALOAD + |__STACK: [Ljava/sql/Statement;] + ASTORE 5 + |__STACK: [] + L3 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject;] + ALOAD 5 + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;] + ACONST_NULL + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;, NULL] + INVOKEVIRTUAL testsubjects/TestSubject.closeResource (Ljava/lang/AutoCloseable;Ljava/lang/Throwable;)V + |__STACK: [] + L4 + IINC 4 1 + |__STACK: [] + GOTO L1 + |__STACK: [] + L2 + FRAME CHOP 3 + RETURN + |__STACK: [] +Method closeResourceMultiArray + L0 + ALOAD 1 + |__STACK: [[[Ljava/sql/Statement;] + ASTORE 2 + |__STACK: [] + ALOAD 2 + |__STACK: [[[Ljava/sql/Statement;] + ARRAYLENGTH + |__STACK: [I] + ISTORE 3 + |__STACK: [] + ICONST_0 + |__STACK: [I] + ISTORE 4 + |__STACK: [] + L1 + FRAME APPEND [[[Ljava/sql/Statement; I I] + ILOAD 4 + |__STACK: [I] + ILOAD 3 + |__STACK: [I, I] + IF_ICMPGE L2 + |__STACK: [] + ALOAD 2 + |__STACK: [[[Ljava/sql/Statement;] + ILOAD 4 + |__STACK: [[[Ljava/sql/Statement;, I] + AALOAD + |__STACK: [[Ljava/sql/Statement;] + ASTORE 5 + |__STACK: [] + L3 + ALOAD 5 + |__STACK: [[Ljava/sql/Statement;] + ASTORE 6 + |__STACK: [] + ALOAD 6 + |__STACK: [[Ljava/sql/Statement;] + ARRAYLENGTH + |__STACK: [I] + ISTORE 7 + |__STACK: [] + ICONST_0 + |__STACK: [I] + ISTORE 8 + |__STACK: [] + L4 + FRAME FULL [testsubjects/TestSubject [[Ljava/sql/Statement; [[Ljava/sql/Statement; I I [Ljava/sql/Statement; [Ljava/sql/Statement; I I] [] + ILOAD 8 + |__STACK: [I] + ILOAD 7 + |__STACK: [I, I] + IF_ICMPGE L5 + |__STACK: [] + ALOAD 6 + |__STACK: [[Ljava/sql/Statement;] + ILOAD 8 + |__STACK: [[Ljava/sql/Statement;, I] + AALOAD + |__STACK: [Ljava/sql/Statement;] + ASTORE 9 + |__STACK: [] + L6 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject;] + ALOAD 9 + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;] + ACONST_NULL + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;, NULL] + INVOKEVIRTUAL testsubjects/TestSubject.closeResource (Ljava/lang/AutoCloseable;Ljava/lang/Throwable;)V + |__STACK: [] + L7 + IINC 8 1 + |__STACK: [] + GOTO L4 + |__STACK: [] + L5 + FRAME FULL [testsubjects/TestSubject [[Ljava/sql/Statement; [[Ljava/sql/Statement; I I] [] + IINC 4 1 + |__STACK: [] + GOTO L1 + |__STACK: [] + L2 + FRAME CHOP 3 + RETURN + |__STACK: [] +Method closeResourceArrayList + L0 + ALOAD 1 + |__STACK: [Ljava/util/List;] + INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator; + |__STACK: [Ljava/util/Iterator;] + ASTORE 2 + |__STACK: [] + L1 + FRAME APPEND [java/util/Iterator] + ALOAD 2 + |__STACK: [Ljava/util/Iterator;] + INVOKEINTERFACE java/util/Iterator.hasNext ()Z + |__STACK: [I] + IFEQ L2 + |__STACK: [] + ALOAD 2 + |__STACK: [Ljava/util/Iterator;] + INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object; + |__STACK: [Ljava/lang/Object;] + CHECKCAST java/sql/Statement + |__STACK: [Ljava/sql/Statement;] + ASTORE 3 + |__STACK: [] + L3 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject;] + ALOAD 3 + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;] + ACONST_NULL + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;, NULL] + INVOKEVIRTUAL testsubjects/TestSubject.closeResource (Ljava/lang/AutoCloseable;Ljava/lang/Throwable;)V + |__STACK: [] + L4 + GOTO L1 + |__STACK: [] + L2 + FRAME CHOP 1 + RETURN + |__STACK: [] +Method closeSqlStmt + L0 + ACONST_NULL + |__STACK: [NULL] + ASTORE 2 + |__STACK: [] + L1 + ALOAD 1 + |__STACK: [Ljava/sql/Connection;] + INVOKEINTERFACE java/sql/Connection.createStatement ()Ljava/sql/Statement; + |__STACK: [Ljava/sql/Statement;] + ASTORE 2 + |__STACK: [] + L2 + GOTO L3 + |__STACK: [] + L4 + FRAME FULL [testsubjects/TestSubject java/sql/Connection java/sql/Statement] [java/sql/SQLException] + ASTORE 3 + |__STACK: [] + L5 + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject;] + ALOAD 2 + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;] + ALOAD 3 + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;, Ljava/sql/SQLException;] + INVOKEVIRTUAL testsubjects/TestSubject.closeResource (Ljava/lang/AutoCloseable;Ljava/lang/Throwable;)V + |__STACK: [] + L3 + FRAME SAME + ALOAD 0 + |__STACK: [Ltestsubjects/TestSubject;] + ALOAD 2 + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;] + ACONST_NULL + |__STACK: [Ltestsubjects/TestSubject;, Ljava/sql/Statement;, NULL] + INVOKEVIRTUAL testsubjects/TestSubject.closeResource (Ljava/lang/AutoCloseable;Ljava/lang/Throwable;)V + |__STACK: [] + L6 + RETURN + |__STACK: [] +Method closeResource + L0 + ALOAD 1 + |__STACK: [Ljava/lang/AutoCloseable;] + IFNONNULL L1 + |__STACK: [] + L2 + RETURN + |__STACK: [] + L1 + FRAME SAME + ALOAD 1 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L3 + GOTO L4 + |__STACK: [] + L5 + FRAME SAME1 java/lang/Exception + ASTORE 3 + |__STACK: [] + L6 + ALOAD 2 + |__STACK: [Ljava/lang/Throwable;] + IFNULL L7 + |__STACK: [] + L8 + ALOAD 2 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 3 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Exception;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + L7 + FRAME APPEND [java/lang/Exception] + ALOAD 3 + |__STACK: [Ljava/lang/Exception;] + ATHROW + |__STACK: [] + L4 + FRAME CHOP 1 + RETURN + |__STACK: [] +Method intAdd + L0 + ILOAD 0 + |__STACK: [I] + ISTORE 2 + |__STACK: [] + L1 + IINC 2 1 + |__STACK: [] + L2 + IINC 2 1 + |__STACK: [] + L3 + ILOAD 2 + |__STACK: [I] + ILOAD 1 + |__STACK: [I, I] + IADD + |__STACK: [I] + ISTORE 2 + |__STACK: [] + L4 + IINC 2 -1 + |__STACK: [] + L5 + IINC 2 -1 + |__STACK: [] + L6 + ILOAD 2 + |__STACK: [I] + ILOAD 1 + |__STACK: [I, I] + ISUB + |__STACK: [I] + ISTORE 2 + |__STACK: [] + L7 + ILOAD 2 + |__STACK: [I] + ILOAD 1 + |__STACK: [I, I] + IMUL + |__STACK: [I] + ISTORE 2 + |__STACK: [] + L8 + ILOAD 2 + |__STACK: [I] + ILOAD 1 + |__STACK: [I, I] + IDIV + |__STACK: [I] + ISTORE 2 + |__STACK: [] + L9 + ILOAD 2 + |__STACK: [I] + ILOAD 1 + |__STACK: [I, I] + IREM + |__STACK: [I] + ISTORE 2 + |__STACK: [] + L10 + ILOAD 2 + |__STACK: [I] + ICONST_2 + |__STACK: [I, I] + ISHL + |__STACK: [I] + ISTORE 2 + |__STACK: [] + L11 + ILOAD 2 + |__STACK: [I] + ILOAD 1 + |__STACK: [I, I] + ISHR + |__STACK: [I] + ISTORE 2 + |__STACK: [] + L12 + ILOAD 2 + |__STACK: [I] + ICONST_3 + |__STACK: [I, I] + IUSHR + |__STACK: [I] + ISTORE 2 + |__STACK: [] + L13 + ILOAD 2 + |__STACK: [I] + I2L + |__STACK: [J, TOP] + LSTORE 3 + |__STACK: [] + L14 + LLOAD 3 + |__STACK: [J, TOP] + ILOAD 1 + |__STACK: [J, TOP, I] + LSHL + |__STACK: [J, TOP] + LSTORE 3 + |__STACK: [] + L15 + LLOAD 3 + |__STACK: [J, TOP] + L2I + |__STACK: [I] + IRETURN + |__STACK: [] +Method createNumberWithDiamond + L0 + ACONST_NULL + |__STACK: [NULL] + ASTORE 1 + |__STACK: [] + L1 + ILOAD 0 + |__STACK: [I] + IFEQ L2 + |__STACK: [] + L3 + NEW java/lang/Integer + |__STACK: [Ljava/lang/Integer;] + DUP + |__STACK: [Ljava/lang/Integer;, Ljava/lang/Integer;] + ICONST_1 + |__STACK: [Ljava/lang/Integer;, Ljava/lang/Integer;, I] + INVOKESPECIAL java/lang/Integer.<init> (I)V + |__STACK: [Ljava/lang/Integer;] + ASTORE 1 + |__STACK: [] + GOTO L4 + |__STACK: [] + L2 + FRAME APPEND [java/lang/Number] + NEW java/lang/Double + |__STACK: [Ljava/lang/Double;] + DUP + |__STACK: [Ljava/lang/Double;, Ljava/lang/Double;] + DCONST_1 + |__STACK: [Ljava/lang/Double;, Ljava/lang/Double;, D, TOP] + INVOKESPECIAL java/lang/Double.<init> (D)V + |__STACK: [Ljava/lang/Double;] + ASTORE 1 + |__STACK: [] + L4 + FRAME SAME + ALOAD 1 + |__STACK: [Ljava/lang/Number;] + ARETURN + |__STACK: [] +Method createMultiObjectArray + L0 + ICONST_0 + |__STACK: [I] + ICONST_0 + |__STACK: [I, I] + MULTIANEWARRAY [[Ljava/lang/Object; 2 + |__STACK: [[[Ljava/lang/Object;] + ARETURN + |__STACK: [] +Method createObjectArray + L0 + ICONST_0 + |__STACK: [I] + ANEWARRAY java/lang/Object + |__STACK: [[Ljava/lang/Object;] + ARETURN + |__STACK: [] +Method createIntArray + L0 + ICONST_0 + |__STACK: [I] + NEWARRAY T_INT + |__STACK: [[I] + ARETURN + |__STACK: [] +Method staticEmpty1 + L0 + RETURN + |__STACK: [] +Method instanceEmpty1 + L0 + RETURN + |__STACK: [] +Method identity + L0 + ILOAD 0 + |__STACK: [I] + IRETURN + |__STACK: [] +Method identity2 + L0 + ILOAD 0 + |__STACK: [I] + ISTORE 1 + |__STACK: [] + L1 + ILOAD 1 + |__STACK: [I] + IRETURN + |__STACK: [] +Method readFile + L0 + NEW java/io/BufferedReader + |__STACK: [Ljava/io/BufferedReader;] + DUP + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;] + NEW java/io/FileReader + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;] + DUP + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;, Ljava/io/FileReader;] + ALOAD 1 + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;, Ljava/io/FileReader;, Ljava/io/File;] + INVOKESPECIAL java/io/FileReader.<init> (Ljava/io/File;)V + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;] + INVOKESPECIAL java/io/BufferedReader.<init> (Ljava/io/Reader;)V + |__STACK: [Ljava/io/BufferedReader;] + ASTORE 2 + |__STACK: [] + ACONST_NULL + |__STACK: [NULL] + ASTORE 3 + |__STACK: [] + L1 + NEW java/io/BufferedReader + |__STACK: [Ljava/io/BufferedReader;] + DUP + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;] + NEW java/io/FileReader + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;] + DUP + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;, Ljava/io/FileReader;] + ALOAD 1 + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;, Ljava/io/FileReader;, Ljava/io/File;] + INVOKESPECIAL java/io/FileReader.<init> (Ljava/io/File;)V + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;] + INVOKESPECIAL java/io/BufferedReader.<init> (Ljava/io/Reader;)V + |__STACK: [Ljava/io/BufferedReader;] + ASTORE 4 + |__STACK: [] + L2 + ACONST_NULL + |__STACK: [NULL] + ASTORE 5 + |__STACK: [] + L3 + NEW java/io/BufferedReader + |__STACK: [Ljava/io/BufferedReader;] + DUP + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;] + NEW java/io/FileReader + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;] + DUP + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;, Ljava/io/FileReader;] + ALOAD 1 + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;, Ljava/io/FileReader;, Ljava/io/File;] + INVOKESPECIAL java/io/FileReader.<init> (Ljava/io/File;)V + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;] + INVOKESPECIAL java/io/BufferedReader.<init> (Ljava/io/Reader;)V + |__STACK: [Ljava/io/BufferedReader;] + ASTORE 6 + |__STACK: [] + L4 + ACONST_NULL + |__STACK: [NULL] + ASTORE 7 + |__STACK: [] + L5 + NEW java/io/BufferedReader + |__STACK: [Ljava/io/BufferedReader;] + DUP + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;] + NEW java/io/FileReader + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;] + DUP + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;, Ljava/io/FileReader;] + ALOAD 1 + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;, Ljava/io/FileReader;, Ljava/io/File;] + INVOKESPECIAL java/io/FileReader.<init> (Ljava/io/File;)V + |__STACK: [Ljava/io/BufferedReader;, Ljava/io/BufferedReader;, Ljava/io/FileReader;] + INVOKESPECIAL java/io/BufferedReader.<init> (Ljava/io/Reader;)V + |__STACK: [Ljava/io/BufferedReader;] + ASTORE 8 + |__STACK: [] + L6 + ACONST_NULL + |__STACK: [NULL] + ASTORE 9 + |__STACK: [] + L7 + ALOAD 8 + |__STACK: [Ljava/io/BufferedReader;] + IFNULL L8 + |__STACK: [] + ALOAD 9 + |__STACK: [NULL] + IFNULL L9 + |__STACK: [] + L10 + ALOAD 8 + |__STACK: [Ljava/io/BufferedReader;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L11 + GOTO L8 + |__STACK: [] + L12 + FRAME FULL [testsubjects/TestSubject java/io/File java/lang/AutoCloseable java/lang/Throwable java/lang/AutoCloseable java/lang/Throwable java/lang/AutoCloseable java/lang/Throwable java/lang/AutoCloseable java/lang/Throwable] [java/lang/Throwable] + ASTORE 10 + |__STACK: [] + ALOAD 9 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 10 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Throwable;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + GOTO L8 + |__STACK: [] + L9 + FRAME SAME + ALOAD 8 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L8 + FRAME CHOP 2 + ALOAD 6 + |__STACK: [Ljava/lang/AutoCloseable;] + IFNULL L13 + |__STACK: [] + ALOAD 7 + |__STACK: [Ljava/lang/Throwable;] + IFNULL L14 + |__STACK: [] + L15 + ALOAD 6 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L16 + GOTO L13 + |__STACK: [] + L17 + FRAME SAME1 java/lang/Throwable + ASTORE 8 + |__STACK: [] + ALOAD 7 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 8 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Throwable;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + GOTO L13 + |__STACK: [] + L14 + FRAME SAME + ALOAD 6 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + GOTO L13 + |__STACK: [] + L18 + FRAME SAME1 java/lang/Throwable + ASTORE 8 + |__STACK: [] + ALOAD 8 + |__STACK: [Ljava/lang/Throwable;] + ASTORE 7 + |__STACK: [] + ALOAD 8 + |__STACK: [Ljava/lang/Throwable;] + ATHROW + |__STACK: [] + L19 + FRAME SAME1 java/lang/Throwable + ASTORE 11 + |__STACK: [] + L20 + ALOAD 6 + |__STACK: [Ljava/lang/AutoCloseable;] + IFNULL L21 + |__STACK: [] + ALOAD 7 + |__STACK: [Ljava/lang/Throwable;] + IFNULL L22 + |__STACK: [] + L23 + ALOAD 6 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L24 + GOTO L21 + |__STACK: [] + L25 + FRAME FULL [testsubjects/TestSubject java/io/File java/lang/AutoCloseable java/lang/Throwable java/lang/AutoCloseable java/lang/Throwable java/lang/AutoCloseable java/lang/Throwable T T T java/lang/Throwable] [java/lang/Throwable] + ASTORE 12 + |__STACK: [] + ALOAD 7 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 12 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Throwable;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + GOTO L21 + |__STACK: [] + L22 + FRAME SAME + ALOAD 6 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L21 + FRAME SAME + ALOAD 11 + |__STACK: [Ljava/lang/Throwable;] + ATHROW + |__STACK: [] + L13 + FRAME FULL [testsubjects/TestSubject java/io/File java/lang/AutoCloseable java/lang/Throwable java/lang/AutoCloseable java/lang/Throwable] [] + ALOAD 4 + |__STACK: [Ljava/lang/AutoCloseable;] + IFNULL L26 + |__STACK: [] + ALOAD 5 + |__STACK: [Ljava/lang/Throwable;] + IFNULL L27 + |__STACK: [] + L28 + ALOAD 4 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L29 + GOTO L26 + |__STACK: [] + L30 + FRAME SAME1 java/lang/Throwable + ASTORE 6 + |__STACK: [] + ALOAD 5 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 6 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Throwable;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + GOTO L26 + |__STACK: [] + L27 + FRAME SAME + ALOAD 4 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + GOTO L26 + |__STACK: [] + L31 + FRAME SAME1 java/lang/Throwable + ASTORE 6 + |__STACK: [] + ALOAD 6 + |__STACK: [Ljava/lang/Throwable;] + ASTORE 5 + |__STACK: [] + ALOAD 6 + |__STACK: [Ljava/lang/Throwable;] + ATHROW + |__STACK: [] + L32 + FRAME SAME1 java/lang/Throwable + ASTORE 13 + |__STACK: [] + L33 + ALOAD 4 + |__STACK: [Ljava/lang/AutoCloseable;] + IFNULL L34 + |__STACK: [] + ALOAD 5 + |__STACK: [Ljava/lang/Throwable;] + IFNULL L35 + |__STACK: [] + L36 + ALOAD 4 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L37 + GOTO L34 + |__STACK: [] + L38 + FRAME FULL [testsubjects/TestSubject java/io/File java/lang/AutoCloseable java/lang/Throwable java/lang/AutoCloseable java/lang/Throwable T T T T T T T java/lang/Throwable] [java/lang/Throwable] + ASTORE 14 + |__STACK: [] + ALOAD 5 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 14 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Throwable;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + GOTO L34 + |__STACK: [] + L35 + FRAME SAME + ALOAD 4 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L34 + FRAME SAME + ALOAD 13 + |__STACK: [Ljava/lang/Throwable;] + ATHROW + |__STACK: [] + L26 + FRAME FULL [testsubjects/TestSubject java/io/File java/lang/AutoCloseable java/lang/Throwable] [] + ALOAD 2 + |__STACK: [Ljava/lang/AutoCloseable;] + IFNULL L39 + |__STACK: [] + ALOAD 3 + |__STACK: [Ljava/lang/Throwable;] + IFNULL L40 + |__STACK: [] + L41 + ALOAD 2 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L42 + GOTO L39 + |__STACK: [] + L43 + FRAME SAME1 java/lang/Throwable + ASTORE 4 + |__STACK: [] + ALOAD 3 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 4 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Throwable;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + GOTO L39 + |__STACK: [] + L40 + FRAME SAME + ALOAD 2 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + GOTO L39 + |__STACK: [] + L44 + FRAME SAME1 java/lang/Throwable + ASTORE 4 + |__STACK: [] + ALOAD 4 + |__STACK: [Ljava/lang/Throwable;] + ASTORE 3 + |__STACK: [] + ALOAD 4 + |__STACK: [Ljava/lang/Throwable;] + ATHROW + |__STACK: [] + L45 + FRAME SAME1 java/lang/Throwable + ASTORE 15 + |__STACK: [] + L46 + ALOAD 2 + |__STACK: [Ljava/lang/AutoCloseable;] + IFNULL L47 + |__STACK: [] + ALOAD 3 + |__STACK: [Ljava/lang/Throwable;] + IFNULL L48 + |__STACK: [] + L49 + ALOAD 2 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L50 + GOTO L47 + |__STACK: [] + L51 + FRAME FULL [testsubjects/TestSubject java/io/File java/lang/AutoCloseable java/lang/Throwable T T T T T T T T T T T java/lang/Throwable] [java/lang/Throwable] + ASTORE 16 + |__STACK: [] + ALOAD 3 + |__STACK: [Ljava/lang/Throwable;] + ALOAD 16 + |__STACK: [Ljava/lang/Throwable;, Ljava/lang/Throwable;] + INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V + |__STACK: [] + GOTO L47 + |__STACK: [] + L48 + FRAME SAME + ALOAD 2 + |__STACK: [Ljava/lang/AutoCloseable;] + INVOKEINTERFACE java/lang/AutoCloseable.close ()V + |__STACK: [] + L47 + FRAME SAME + ALOAD 15 + |__STACK: [Ljava/lang/Throwable;] + ATHROW + |__STACK: [] + L39 + FRAME FULL [testsubjects/TestSubject java/io/File] [] + GOTO L52 + |__STACK: [] + L53 + FRAME SAME1 java/io/IOException + ASTORE 2 + |__STACK: [] + L54 + ALOAD 2 + |__STACK: [Ljava/io/IOException;] + INVOKEVIRTUAL java/io/IOException.printStackTrace ()V + |__STACK: [] + L52 + FRAME SAME + RETURN + |__STACK: [] +Method <clinit> + L0 + ICONST_1 + |__STACK: [I] + PUTSTATIC testsubjects/TestSubject.VALUE_ONE : I + |__STACK: [] + L1 + ICONST_2 + |__STACK: [I] + PUTSTATIC testsubjects/TestSubject.VALUE_TWO : I + |__STACK: [] + RETURN + |__STACK: []
\ No newline at end of file diff --git a/test/java/com/google/devtools/build/android/desugar/BytecodeTypeInferenceTest.java b/test/java/com/google/devtools/build/android/desugar/BytecodeTypeInferenceTest.java new file mode 100644 index 0000000..2573648 --- /dev/null +++ b/test/java/com/google/devtools/build/android/desugar/BytecodeTypeInferenceTest.java @@ -0,0 +1,46 @@ +// 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 com.google.common.io.Files; +import com.google.common.truth.Truth; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test for {@link BytecodeTypeInference} */ +@RunWith(JUnit4.class) +public class BytecodeTypeInferenceTest { + + private static final Path JAR_PATH = Paths.get(System.getProperty("jar_path")); + private static final Path GOLDEN_PATH = Paths.get(System.getProperty("golden_file")); + + @Test + public void test() throws IOException { + StringWriter stringWriter = new StringWriter(); + try (PrintWriter printWriter = new PrintWriter(stringWriter)) { + ByteCodeTypePrinter.printClassesWithTypes(JAR_PATH, printWriter); + printWriter.close(); + } + String inferenceResult = stringWriter.toString().trim(); + String golden = Files.asCharSource(GOLDEN_PATH.toFile(), StandardCharsets.UTF_8).read().trim(); + Truth.assertThat(inferenceResult).isEqualTo(golden); + } +} diff --git a/test/java/com/google/devtools/build/android/desugar/DesugarLambdaTest.java b/test/java/com/google/devtools/build/android/desugar/DesugarLambdaTest.java new file mode 100644 index 0000000..7c3d7ee --- /dev/null +++ b/test/java/com/google/devtools/build/android/desugar/DesugarLambdaTest.java @@ -0,0 +1,38 @@ +// Copyright 2016 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.truth.Truth.assertThat; + +import com.google.devtools.build.android.desugar.testdata.ConstantArgumentsInLambda; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests uncommon lambda scenarious. + */ +@RunWith(JUnit4.class) +public class DesugarLambdaTest { + + /** + * Test for b/62060793. Verifies constant lambda arguments that were pushed using *CONST_0 + * instructions. + */ + @Test + public void testCallLambdaWithConstants() throws Exception { + assertThat(ConstantArgumentsInLambda.lambdaWithConstantArguments().call("test")) + .isEqualTo("testfalse\00120.00.0049nulltrue"); + } +} diff --git a/test/java/com/google/devtools/build/android/desugar/FrameInfoTest.java b/test/java/com/google/devtools/build/android/desugar/FrameInfoTest.java new file mode 100644 index 0000000..528c78e --- /dev/null +++ b/test/java/com/google/devtools/build/android/desugar/FrameInfoTest.java @@ -0,0 +1,51 @@ +// 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.truth.Truth.assertThat; + +import com.google.common.collect.ImmutableList; +import com.google.devtools.build.android.desugar.BytecodeTypeInference.FrameInfo; +import com.google.devtools.build.android.desugar.BytecodeTypeInference.InferredType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test for {@link BytecodeTypeInference.FrameInfo} */ +@RunWith(JUnit4.class) +public class FrameInfoTest { + + @Test + public void testFieldsAreSetCorrectly() { + { + FrameInfo info = FrameInfo.create(ImmutableList.of(), ImmutableList.of()); + assertThat(info.locals()).isEmpty(); + assertThat(info.stack()).isEmpty(); + } + { + FrameInfo info = + FrameInfo.create(ImmutableList.of(InferredType.INT), ImmutableList.of(InferredType.BYTE)); + assertThat(info.locals()).containsExactly(InferredType.INT).inOrder(); + assertThat(info.stack()).containsExactly(InferredType.BYTE).inOrder(); + } + { + FrameInfo info = + FrameInfo.create( + ImmutableList.of(InferredType.INT, InferredType.BYTE), + ImmutableList.of(InferredType.BOOLEAN, InferredType.LONG)); + assertThat(info.locals()).containsExactly(InferredType.INT, InferredType.BYTE).inOrder(); + assertThat(info.stack()).containsExactly(InferredType.BOOLEAN, InferredType.LONG).inOrder(); + } + } +} diff --git a/test/java/com/google/devtools/build/android/desugar/TryWithResourcesRewriterTest.java b/test/java/com/google/devtools/build/android/desugar/TryWithResourcesRewriterTest.java index 587d4f7..37afae7 100644 --- a/test/java/com/google/devtools/build/android/desugar/TryWithResourcesRewriterTest.java +++ b/test/java/com/google/devtools/build/android/desugar/TryWithResourcesRewriterTest.java @@ -206,16 +206,20 @@ public class TryWithResourcesRewriterTest { .isEqualTo(orig.countExtPrintStackTracePrintWriter()); assertThat(orig.countThrowableGetSuppressed()).isEqualTo(desugared.countExtGetSuppressed()); - // $closeResource is rewritten to ThrowableExtension.closeResource, so addSuppressed() is called - // in the runtime library now. - assertThat(orig.countThrowableAddSuppressed()) - .isAtLeast(desugared.countThrowableAddSuppressed()); + // $closeResource may be specialized into multiple versions. + assertThat(orig.countThrowableAddSuppressed()).isAtMost(desugared.countExtAddSuppressed()); assertThat(orig.countThrowablePrintStackTrace()).isEqualTo(desugared.countExtPrintStackTrace()); assertThat(orig.countThrowablePrintStackTracePrintStream()) .isEqualTo(desugared.countExtPrintStackTracePrintStream()); assertThat(orig.countThrowablePrintStackTracePrintWriter()) .isEqualTo(desugared.countExtPrintStackTracePrintWriter()); + if (orig.getSyntheticCloseResourceCount() > 0) { + // Depending on the specific javac version, $closeResource(Throwable, AutoCloseable) may not + // be there. + assertThat(orig.getSyntheticCloseResourceCount()).isEqualTo(1); + assertThat(desugared.getSyntheticCloseResourceCount()).isAtLeast(1); + } assertThat(desugared.countThrowablePrintStackTracePrintStream()).isEqualTo(0); assertThat(desugared.countThrowablePrintStackTracePrintStream()).isEqualTo(0); assertThat(desugared.countThrowablePrintStackTracePrintWriter()).isEqualTo(0); @@ -270,6 +274,7 @@ public class TryWithResourcesRewriterTest { private static class DesugaredThrowableMethodCallCounter extends ClassVisitor { private final ClassLoader classLoader; private final Map<String, AtomicInteger> counterMap; + private int syntheticCloseResourceCount; public DesugaredThrowableMethodCallCounter(ClassLoader loader) { super(ASM5); @@ -291,6 +296,12 @@ public class TryWithResourcesRewriterTest { @Override public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions) { + if (BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC) + && name.equals("$closeResource") + && Type.getArgumentTypes(desc).length == 2 + && Type.getArgumentTypes(desc)[0].getDescriptor().equals("Ljava/lang/Throwable;")) { + ++syntheticCloseResourceCount; + } return new InvokeCounter(); } @@ -324,6 +335,10 @@ public class TryWithResourcesRewriterTest { } } + public int getSyntheticCloseResourceCount() { + return syntheticCloseResourceCount; + } + public int countThrowableAddSuppressed() { return counterMap.get("addSuppressed(Ljava/lang/Throwable;)V").get(); } @@ -396,13 +411,16 @@ public class TryWithResourcesRewriterTest { private byte[] desugarTryWithResources(String className) { try { ClassReader reader = new ClassReader(className); + CloseResourceMethodScanner scanner = new CloseResourceMethodScanner(); + reader.accept(scanner, ClassReader.SKIP_DEBUG); ClassWriter writer = new ClassWriter(reader, COMPUTE_MAXS); TryWithResourcesRewriter rewriter = new TryWithResourcesRewriter( writer, TryWithResourcesRewriterTest.class.getClassLoader(), visitedExceptionTypes, - numOfTryWithResourcesInvoked); + numOfTryWithResourcesInvoked, + scanner.hasCloseResourceMethod()); reader.accept(rewriter, 0); return writer.toByteArray(); } catch (IOException e) { diff --git a/test/java/com/google/devtools/build/android/desugar/classes_for_testing_type_inference/generate_jar.sh b/test/java/com/google/devtools/build/android/desugar/classes_for_testing_type_inference/generate_jar.sh new file mode 100755 index 0000000..1166620 --- /dev/null +++ b/test/java/com/google/devtools/build/android/desugar/classes_for_testing_type_inference/generate_jar.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# +# Copyright 2016 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. + +# +# I intentionally create this script to create a checked-in jar, because the test cases for +# byte code type inference uses golden files, which consequently relies on the version of javac +# compilers. So instead of creating jar files at build time, we check in a jar file. +# + +javac testsubjects/TestSubject.java + +jar cf test_subjects.jar testsubjects/TestSubject.class
\ No newline at end of file diff --git a/test/java/com/google/devtools/build/android/desugar/classes_for_testing_type_inference/test_subjects.jar b/test/java/com/google/devtools/build/android/desugar/classes_for_testing_type_inference/test_subjects.jar Binary files differnew file mode 100644 index 0000000..efa491b --- /dev/null +++ b/test/java/com/google/devtools/build/android/desugar/classes_for_testing_type_inference/test_subjects.jar diff --git a/test/java/com/google/devtools/build/android/desugar/classes_for_testing_type_inference/testsubjects/TestSubject.java b/test/java/com/google/devtools/build/android/desugar/classes_for_testing_type_inference/testsubjects/TestSubject.java new file mode 100644 index 0000000..b5463a7 --- /dev/null +++ b/test/java/com/google/devtools/build/android/desugar/classes_for_testing_type_inference/testsubjects/TestSubject.java @@ -0,0 +1,196 @@ +// 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 testsubjects; + +import java.io.BufferedReader; +import java.io.Closeable; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.function.BinaryOperator; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * Test subject for testing bytecode type inference {@link + * com.google.devtools.build.android.desugar.BytecodeTypeInference} + */ +public class TestSubject { + + private static int VALUE_ONE = 1; + private static int VALUE_TWO = 2; + + static int catchTest(Object key, Object value) { + if (!(key instanceof String)) { + return VALUE_ONE; + } + try { + Pattern.compile((String) key); + } catch (PatternSyntaxException e) { + return VALUE_TWO; + } + return VALUE_ONE; + } + + public static void assertEquals(String message, double expected, double actual, double delta) { + if (Double.compare(expected, actual) == 0) { + return; + } + if (!(Math.abs(expected - actual) <= delta)) { + throw new RuntimeException(message + new Double(expected) + new Double(actual)); + } + } + + /** + * A simple resource implementation which implements Closeable. + */ + public static class SimpleResource implements Closeable { + + public void call(boolean throwException) { + if (throwException) { + throw new RuntimeException("exception in call()"); + } + } + + @Override + public void close() throws IOException { + throw new IOException("exception in close()."); + } + } + + public static void simpleTryWithResources() throws Exception { + // Throwable.addSuppressed(Throwable) should be called in the following block. + try (SimpleResource resource = new SimpleResource()) { + resource.call(true); + } + } + + private static long internalCompare(long a, long b, BinaryOperator<Long> func) { + return func.apply(a, b); + } + + public void closeResourceArray(Statement[] resources) throws Exception { + for (Statement stmt : resources) { + closeResource(stmt, null); + } + } + + public void closeResourceMultiArray(Statement[][] resources) throws Exception { + for (Statement[] stmts : resources) { + for (Statement stmt : stmts) { + closeResource(stmt, null); + } + } + } + + public void closeResourceArrayList(List<Statement> resources) throws Exception { + for (Statement stmt : resources) { + closeResource(stmt, null); + } + } + + public void closeSqlStmt(Connection connection) throws Exception { + Statement stmt = null; + + try { + stmt = connection.createStatement(); + } catch (SQLException e) { + closeResource(stmt, e); + } + closeResource(stmt, null); + } + + public void closeResource(AutoCloseable resource, Throwable suppressor) throws Exception { + if (resource == null) { + return; + } + try { + resource.close(); + } catch (Exception e) { + if (suppressor != null) { + suppressor.addSuppressed(e); + } + throw e; + } + } + + public static int intAdd(int i, int j) { + int tmp = i; + tmp++; + ++tmp; + tmp += j; + tmp--; + --tmp; + tmp -= j; + tmp *= j; + tmp /= j; + tmp = tmp % j; + tmp = tmp << 2; + tmp = tmp >> j; + tmp = tmp >>> 3; + long longTemp = tmp; + longTemp = longTemp << j; + return (int) longTemp; + } + + public static Number createNumberWithDiamond(boolean flag) { + Number n = null; + if (flag) { + n = new Integer(1); + } else { + n = new Double(1); + } + return n; + } + + public static Object[][] createMultiObjectArray() { + return new Object[0][0]; + } + + public static Object[] createObjectArray() { + return new Object[0]; + } + + public static int[] createIntArray() { + return new int[0]; + } + + public static void staticEmpty1() {} + + public void instanceEmpty1() {} + + public static boolean identity(boolean result) { + return result; + } + + public static boolean identity2(boolean result) { + boolean temp = result; + return temp; + } + + public void readFile(File file) throws Exception { + try (AutoCloseable reader = new BufferedReader(new FileReader(file)); + AutoCloseable reader2 = new BufferedReader(new FileReader(file)); + AutoCloseable reader3 = new BufferedReader(new FileReader(file)); + AutoCloseable reader4 = new BufferedReader(new FileReader(file))) { + + } catch (IOException e) { + e.printStackTrace(); + } + } +} |