1 
   2 /*
   3  * @test /nodynamiccopyright/
   4  * @bug 7190862 7109747
   5  * @summary javap shows an incorrect type for operands if the 'wide' prefix is used
   6  * @modules jdk.jdeps
   7  */
   8 
   9 import com.sun.source.util.JavacTask;
  10 import com.sun.tools.javap.JavapFileManager;
  11 import com.sun.tools.javap.JavapTask;
  12 import java.io.PrintWriter;
  13 import java.io.StringWriter;
  14 import java.net.URI;
  15 import java.util.Arrays;
  16 import java.util.List;
  17 import java.util.Locale;
  18 import javax.tools.Diagnostic;
  19 import javax.tools.DiagnosticCollector;
  20 import javax.tools.JavaCompiler;
  21 import javax.tools.JavaFileManager;
  22 import javax.tools.JavaFileObject;
  23 import javax.tools.SimpleJavaFileObject;
  24 import javax.tools.ToolProvider;
  25 
  26 public class T7190862 {
  27 
  28     enum TypeWideInstructionMap {
  29         INT("int", new String[]{"istore_w", "iload_w"}),
  30         LONG("long", new String[]{"lstore_w", "lload_w"}),
  31         FLOAT("float", new String[]{"fstore_w", "fload_w"}),
  32         DOUBLE("double", new String[]{"dstore_w", "dload_w"}),
  33         OBJECT("Object", new String[]{"astore_w", "aload_w"});
  34 
  35         String type;
  36         String[] instructions;
  37 
  38         TypeWideInstructionMap(String type, String[] instructions) {
  39             this.type = type;
  40             this.instructions = instructions;
  41         }
  42     }
  43 
  44     JavaSource source;
  45 
  46     public static void main(String[] args) {
  47         JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
  48         new T7190862().run(comp);
  49     }
  50 
  51     private void run(JavaCompiler comp) {
  52         String code;
  53         for (TypeWideInstructionMap typeInstructionMap: TypeWideInstructionMap.values()) {
  54             if (typeInstructionMap != TypeWideInstructionMap.OBJECT) {
  55                 code = createWideLocalSource(typeInstructionMap.type, 300);
  56             } else {
  57                 code = createWideLocalSourceForObject(300);
  58             }
  59             source = new JavaSource(code);
  60             compile(comp);
  61             check(typeInstructionMap.instructions);
  62         }
  63 
  64         //an extra test for the iinc instruction
  65         code = createIincSource();
  66         source = new JavaSource(code);
  67         compile(comp);
  68         check(new String[]{"iinc_w"});
  69     }
  70 
  71     private void compile(JavaCompiler comp) {
  72         JavacTask ct = (JavacTask)comp.getTask(null, null, null, null, null, Arrays.asList(source));
  73         try {
  74             if (!ct.call()) {
  75                 throw new AssertionError("Error thrown when compiling the following source:\n" + source.getCharContent(true));
  76             }
  77         } catch (Throwable ex) {
  78             throw new AssertionError("Error thrown when compiling the following source:\n" + source.getCharContent(true));
  79         }
  80     }
  81 
  82     private void check(String[] instructions) {
  83         String out = javap(Arrays.asList("-c"), Arrays.asList("Test.class"));
  84         for (String line: out.split(System.getProperty("line.separator"))) {
  85             line = line.trim();
  86             for (String instruction: instructions) {
  87                 if (line.contains(instruction) && line.contains("#")) {
  88                     throw new Error("incorrect type for operands for instruction " + instruction);
  89                 }
  90             }
  91         }
  92     }
  93 
  94     private String javap(List<String> args, List<String> classes) {
  95         DiagnosticCollector<JavaFileObject> dc = new DiagnosticCollector<JavaFileObject>();
  96         StringWriter sw = new StringWriter();
  97         PrintWriter pw = new PrintWriter(sw);
  98         JavaFileManager fm = JavapFileManager.create(dc, pw);
  99         JavapTask t = new JavapTask(pw, fm, dc, args, classes);
 100         if (t.run() != 0)
 101             throw new Error("javap failed unexpectedly");
 102 
 103         List<Diagnostic<? extends JavaFileObject>> diags = dc.getDiagnostics();
 104         for (Diagnostic<? extends JavaFileObject> d: diags) {
 105             if (d.getKind() == Diagnostic.Kind.ERROR)
 106                 throw new Error(d.getMessage(Locale.ENGLISH));
 107         }
 108         return sw.toString();
 109 
 110     }
 111 
 112     private String createWideLocalSource(String type, int numberOfVars) {
 113         String result = "    " + type + " x0 = 0;\n";
 114         for (int i = 1; i < numberOfVars; i++) {
 115             result += "        " + type + " x" + i + " = x" + (i - 1) + " + 1;\n";
 116         }
 117         return result;
 118     }
 119 
 120     private String createWideLocalSourceForObject(int numberOfVars) {
 121         String result = "    Object x0 = new Object();\n";
 122         for (int i = 1; i < numberOfVars; i++) {
 123             result += "        Object x" + i + " = x0;\n";
 124         }
 125         return result;
 126     }
 127 
 128     private String createIincSource() {
 129         return "    int i = 0;\n"
 130                 + "        i += 1;\n"
 131                 + "        i += 51;\n"
 132                 + "        i += 101;\n"
 133                 + "        i += 151;\n";
 134     }
 135 
 136     class JavaSource extends SimpleJavaFileObject {
 137 
 138         String template = "class Test {\n" +
 139                           "    public static void main(String[] args)\n" +
 140                           "    {\n" +
 141                           "        #C" +
 142                           "    }\n" +
 143                           "}";
 144 
 145         String source;
 146 
 147         public JavaSource(String code) {
 148             super(URI.create("Test.java"), JavaFileObject.Kind.SOURCE);
 149             source = template.replaceAll("#C", code);
 150         }
 151 
 152         @Override
 153         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
 154             return source;
 155         }
 156     }
 157 }