Wed, 21 Nov 2012 18:40:45 +0000
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
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 +}