7190862: javap shows an incorrect type for operands if the 'wide' prefix is used

Wed, 21 Nov 2012 18:40:45 +0000

author
vromero
date
Wed, 21 Nov 2012 18:40:45 +0000
changeset 1428
d9fe1f80515d
parent 1422
d898d9ee352f
child 1429
3746b071d75b

7190862: javap shows an incorrect type for operands if the 'wide' prefix is used
7109747: (javap) classfile not treating iinc_w correctly.
Reviewed-by: jjg, mcimadamore

src/share/classes/com/sun/tools/classfile/Instruction.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/classfile/Opcode.java file | annotate | diff | comparison | revisions
test/tools/javap/T7190862.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/classfile/Instruction.java	Tue Nov 20 09:58:55 2012 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/classfile/Instruction.java	Wed Nov 21 18:40:45 2012 +0000
     1.3 @@ -71,11 +71,16 @@
     1.4          SHORT(3),
     1.5          /** Wide opcode is not followed by any operands. */
     1.6          WIDE_NO_OPERANDS(2),
     1.7 +        /** Wide opcode is followed by a 2-byte index into the local variables array. */
     1.8 +        WIDE_LOCAL(4),
     1.9          /** Wide opcode is followed by a 2-byte index into the constant pool. */
    1.10          WIDE_CPREF_W(4),
    1.11          /** Wide opcode is followed by a 2-byte index into the constant pool,
    1.12           *  and a signed short value. */
    1.13          WIDE_CPREF_W_SHORT(6),
    1.14 +        /** Wide opcode is followed by a 2-byte reference to a local variable,
    1.15 +         *  and a signed short value. */
    1.16 +        WIDE_LOCAL_SHORT(6),
    1.17          /** Opcode was not recognized. */
    1.18          UNKNOWN(1);
    1.19  
    1.20 @@ -101,7 +106,7 @@
    1.21          R visitConstantPoolRef(Instruction instr, int index, P p);
    1.22          /** See {@link Kind#CPREF_W_UBYTE}, {@link Kind#CPREF_W_UBYTE_ZERO}, {@link Kind#WIDE_CPREF_W_SHORT}. */
    1.23          R visitConstantPoolRefAndValue(Instruction instr, int index, int value, P p);
    1.24 -        /** See {@link Kind#LOCAL}. */
    1.25 +        /** See {@link Kind#LOCAL}, {@link Kind#WIDE_LOCAL}. */
    1.26          R visitLocal(Instruction instr, int index, P p);
    1.27          /** See {@link Kind#LOCAL_BYTE}. */
    1.28          R visitLocalAndValue(Instruction instr, int index, int value, P p);
    1.29 @@ -315,6 +320,9 @@
    1.30              case WIDE_NO_OPERANDS:
    1.31                  return visitor.visitNoOperands(this, p);
    1.32  
    1.33 +            case WIDE_LOCAL:
    1.34 +                return visitor.visitLocal(this, getUnsignedShort(2), p);
    1.35 +
    1.36              case WIDE_CPREF_W:
    1.37                  return visitor.visitConstantPoolRef(this, getUnsignedShort(2), p);
    1.38  
    1.39 @@ -322,6 +330,10 @@
    1.40                  return visitor.visitConstantPoolRefAndValue(
    1.41                          this, getUnsignedShort(2), getUnsignedByte(4), p);
    1.42  
    1.43 +            case WIDE_LOCAL_SHORT:
    1.44 +                return visitor.visitLocalAndValue(
    1.45 +                        this, getUnsignedShort(2), getShort(4), p);
    1.46 +
    1.47              case UNKNOWN:
    1.48                  return visitor.visitUnknown(this, p);
    1.49  
     2.1 --- a/src/share/classes/com/sun/tools/classfile/Opcode.java	Tue Nov 20 09:58:55 2012 -0800
     2.2 +++ b/src/share/classes/com/sun/tools/classfile/Opcode.java	Wed Nov 21 18:40:45 2012 +0000
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -246,18 +246,18 @@
    2.11      // impdep 0xff: Picojava priv
    2.12  
    2.13      // wide opcodes
    2.14 -    ILOAD_W(0xc415, WIDE_CPREF_W),
    2.15 -    LLOAD_W(0xc416, WIDE_CPREF_W),
    2.16 -    FLOAD_W(0xc417, WIDE_CPREF_W),
    2.17 -    DLOAD_W(0xc418, WIDE_CPREF_W),
    2.18 -    ALOAD_W(0xc419, WIDE_CPREF_W),
    2.19 -    ISTORE_W(0xc436, WIDE_CPREF_W),
    2.20 -    LSTORE_W(0xc437, WIDE_CPREF_W),
    2.21 -    FSTORE_W(0xc438, WIDE_CPREF_W),
    2.22 -    DSTORE_W(0xc439, WIDE_CPREF_W),
    2.23 -    ASTORE_W(0xc43a, WIDE_CPREF_W),
    2.24 -    IINC_W(0xc484, WIDE_CPREF_W_SHORT),
    2.25 -    RET_W(0xc4a9, WIDE_CPREF_W),
    2.26 +    ILOAD_W(0xc415, WIDE_LOCAL),
    2.27 +    LLOAD_W(0xc416, WIDE_LOCAL),
    2.28 +    FLOAD_W(0xc417, WIDE_LOCAL),
    2.29 +    DLOAD_W(0xc418, WIDE_LOCAL),
    2.30 +    ALOAD_W(0xc419, WIDE_LOCAL),
    2.31 +    ISTORE_W(0xc436, WIDE_LOCAL),
    2.32 +    LSTORE_W(0xc437, WIDE_LOCAL),
    2.33 +    FSTORE_W(0xc438, WIDE_LOCAL),
    2.34 +    DSTORE_W(0xc439, WIDE_LOCAL),
    2.35 +    ASTORE_W(0xc43a, WIDE_LOCAL),
    2.36 +    IINC_W(0xc484, WIDE_LOCAL_SHORT),
    2.37 +    RET_W(0xc4a9, WIDE_LOCAL),
    2.38  
    2.39      // PicoJava nonpriv instructions
    2.40      LOAD_UBYTE(PICOJAVA, 0xfe00),
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/tools/javap/T7190862.java	Wed Nov 21 18:40:45 2012 +0000
     3.3 @@ -0,0 +1,157 @@
     3.4 +
     3.5 +/*
     3.6 + * @test /nodynamiccopyright/
     3.7 + * @bug 7190862 7109747
     3.8 + * @summary javap shows an incorrect type for operands if the 'wide' prefix is used
     3.9 + */
    3.10 +
    3.11 +import com.sun.source.util.JavacTask;
    3.12 +import com.sun.tools.javap.JavapFileManager;
    3.13 +import com.sun.tools.javap.JavapTask;
    3.14 +import java.io.PrintWriter;
    3.15 +import java.io.StringWriter;
    3.16 +import java.net.URI;
    3.17 +import java.util.Arrays;
    3.18 +import java.util.List;
    3.19 +import java.util.Locale;
    3.20 +import javax.tools.Diagnostic;
    3.21 +import javax.tools.DiagnosticCollector;
    3.22 +import javax.tools.JavaCompiler;
    3.23 +import javax.tools.JavaFileManager;
    3.24 +import javax.tools.JavaFileObject;
    3.25 +import javax.tools.SimpleJavaFileObject;
    3.26 +import javax.tools.ToolProvider;
    3.27 +
    3.28 +public class T7190862 {
    3.29 +
    3.30 +    enum TypeWideInstructionMap {
    3.31 +        INT("int", new String[]{"istore_w", "iload_w"}),
    3.32 +        LONG("long", new String[]{"lstore_w", "lload_w"}),
    3.33 +        FLOAT("float", new String[]{"fstore_w", "fload_w"}),
    3.34 +        DOUBLE("double", new String[]{"dstore_w", "dload_w"}),
    3.35 +        OBJECT("Object", new String[]{"astore_w", "aload_w"});
    3.36 +
    3.37 +        String type;
    3.38 +        String[] instructions;
    3.39 +
    3.40 +        TypeWideInstructionMap(String type, String[] instructions) {
    3.41 +            this.type = type;
    3.42 +            this.instructions = instructions;
    3.43 +        }
    3.44 +    }
    3.45 +
    3.46 +    JavaSource source;
    3.47 +
    3.48 +    public static void main(String[] args) {
    3.49 +        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
    3.50 +        new T7190862().run(comp);
    3.51 +    }
    3.52 +
    3.53 +    private void run(JavaCompiler comp) {
    3.54 +        String code;
    3.55 +        for (TypeWideInstructionMap typeInstructionMap: TypeWideInstructionMap.values()) {
    3.56 +            if (typeInstructionMap != TypeWideInstructionMap.OBJECT) {
    3.57 +                code = createWideLocalSource(typeInstructionMap.type, 300);
    3.58 +            } else {
    3.59 +                code = createWideLocalSourceForObject(300);
    3.60 +            }
    3.61 +            source = new JavaSource(code);
    3.62 +            compile(comp);
    3.63 +            check(typeInstructionMap.instructions);
    3.64 +        }
    3.65 +
    3.66 +        //an extra test for the iinc instruction
    3.67 +        code = createIincSource();
    3.68 +        source = new JavaSource(code);
    3.69 +        compile(comp);
    3.70 +        check(new String[]{"iinc_w"});
    3.71 +    }
    3.72 +
    3.73 +    private void compile(JavaCompiler comp) {
    3.74 +        JavacTask ct = (JavacTask)comp.getTask(null, null, null, null, null, Arrays.asList(source));
    3.75 +        try {
    3.76 +            if (!ct.call()) {
    3.77 +                throw new AssertionError("Error thrown when compiling the following source:\n" + source.getCharContent(true));
    3.78 +            }
    3.79 +        } catch (Throwable ex) {
    3.80 +            throw new AssertionError("Error thrown when compiling the following source:\n" + source.getCharContent(true));
    3.81 +        }
    3.82 +    }
    3.83 +
    3.84 +    private void check(String[] instructions) {
    3.85 +        String out = javap(Arrays.asList("-c"), Arrays.asList("Test.class"));
    3.86 +        for (String line: out.split(System.getProperty("line.separator"))) {
    3.87 +            line = line.trim();
    3.88 +            for (String instruction: instructions) {
    3.89 +                if (line.contains(instruction) && line.contains("#")) {
    3.90 +                    throw new Error("incorrect type for operands for instruction " + instruction);
    3.91 +                }
    3.92 +            }
    3.93 +        }
    3.94 +    }
    3.95 +
    3.96 +    private String javap(List<String> args, List<String> classes) {
    3.97 +        DiagnosticCollector<JavaFileObject> dc = new DiagnosticCollector<JavaFileObject>();
    3.98 +        StringWriter sw = new StringWriter();
    3.99 +        PrintWriter pw = new PrintWriter(sw);
   3.100 +        JavaFileManager fm = JavapFileManager.create(dc, pw);
   3.101 +        JavapTask t = new JavapTask(pw, fm, dc, args, classes);
   3.102 +        boolean ok = t.run();
   3.103 +        if (!ok)
   3.104 +            throw new Error("javap failed unexpectedly");
   3.105 +
   3.106 +        List<Diagnostic<? extends JavaFileObject>> diags = dc.getDiagnostics();
   3.107 +        for (Diagnostic<? extends JavaFileObject> d: diags) {
   3.108 +            if (d.getKind() == Diagnostic.Kind.ERROR)
   3.109 +                throw new Error(d.getMessage(Locale.ENGLISH));
   3.110 +        }
   3.111 +        return sw.toString();
   3.112 +
   3.113 +    }
   3.114 +
   3.115 +    private String createWideLocalSource(String type, int numberOfVars) {
   3.116 +        String result = "    " + type + " x0 = 0;\n";
   3.117 +        for (int i = 1; i < numberOfVars; i++) {
   3.118 +            result += "        " + type + " x" + i + " = x" + (i - 1) + " + 1;\n";
   3.119 +        }
   3.120 +        return result;
   3.121 +    }
   3.122 +
   3.123 +    private String createWideLocalSourceForObject(int numberOfVars) {
   3.124 +        String result = "    Object x0 = new Object();\n";
   3.125 +        for (int i = 1; i < numberOfVars; i++) {
   3.126 +            result += "        Object x" + i + " = x0;\n";
   3.127 +        }
   3.128 +        return result;
   3.129 +    }
   3.130 +
   3.131 +    private String createIincSource() {
   3.132 +        return "    int i = 0;\n"
   3.133 +                + "        i += 1;\n"
   3.134 +                + "        i += 51;\n"
   3.135 +                + "        i += 101;\n"
   3.136 +                + "        i += 151;\n";
   3.137 +    }
   3.138 +
   3.139 +    class JavaSource extends SimpleJavaFileObject {
   3.140 +
   3.141 +        String template = "class Test {\n" +
   3.142 +                          "    public static void main(String[] args)\n" +
   3.143 +                          "    {\n" +
   3.144 +                          "        #C" +
   3.145 +                          "    }\n" +
   3.146 +                          "}";
   3.147 +
   3.148 +        String source;
   3.149 +
   3.150 +        public JavaSource(String code) {
   3.151 +            super(URI.create("Test.java"), JavaFileObject.Kind.SOURCE);
   3.152 +            source = template.replaceAll("#C", code);
   3.153 +        }
   3.154 +
   3.155 +        @Override
   3.156 +        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   3.157 +            return source;
   3.158 +        }
   3.159 +    }
   3.160 +}

mercurial