--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Sun Mar 03 20:52:04 2013 -0800
@@ -564,7 +564,7 @@
code.bytes = new byte[readInt()];
in.readFully(code.bytes);
Entry[] cpMap = cls.getCPMap();
- Instruction.opcodeChecker(code.bytes, cpMap);
+ Instruction.opcodeChecker(code.bytes, cpMap, this.cls.version);
int nh = readUnsignedShort();
code.setHandlerCount(nh);
for (int i = 0; i < nh; i++) {
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Sun Mar 03 20:52:04 2013 -0800
@@ -207,6 +207,10 @@
return tag;
}
+ public final boolean tagEquals(int tag) {
+ return getTag() == tag;
+ }
+
public Entry getRef(int i) {
return null;
}
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Sun Mar 03 20:52:04 2013 -0800
@@ -479,4 +479,10 @@
public final static int _qldc = _xldc_op+7;
public final static int _qldc_w = _xldc_op+8;
public final static int _xldc_limit = _xldc_op+9;
+
+ // handling of InterfaceMethodRef
+ public final static int _invoke_int_op = _xldc_limit;
+ public final static int _invokespecial_int = _invoke_int_op+0;
+ public final static int _invokestatic_int = _invoke_int_op+1;
+ public final static int _invoke_int_limit = _invoke_int_op+2;
}
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Sun Mar 03 20:52:04 2013 -0800
@@ -446,12 +446,14 @@
public static boolean isCPRefOp(int bc) {
if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return true;
if (bc >= _xldc_op && bc < _xldc_limit) return true;
+ if (bc == _invokespecial_int || bc == _invokestatic_int) return true;
return false;
}
public static byte getCPRefOpTag(int bc) {
if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return BC_TAG[0][bc];
if (bc >= _xldc_op && bc < _xldc_limit) return CONSTANT_LoadableValue;
+ if (bc == _invokestatic_int || bc == _invokespecial_int) return CONSTANT_InterfaceMethodref;
return CONSTANT_None;
}
@@ -647,7 +649,8 @@
}
}
- public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap) throws FormatException {
+ public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap,
+ Package.Version clsVersion) throws FormatException {
Instruction i = at(code, 0);
while (i != null) {
int opcode = i.getBC();
@@ -658,10 +661,17 @@
ConstantPool.Entry e = i.getCPRef(cpMap);
if (e != null) {
byte tag = i.getCPTag();
- if (!e.tagMatches(tag)) {
- String message = "illegal reference, expected type=" +
- ConstantPool.tagName(tag) + ": " +
- i.toString(cpMap);
+ boolean match = e.tagMatches(tag);
+ if (!match &&
+ (i.bc == _invokespecial || i.bc == _invokestatic) &&
+ e.tagMatches(CONSTANT_InterfaceMethodref) &&
+ clsVersion.greaterThan(Constants.JAVA7_MAX_CLASS_VERSION)) {
+ match = true;
+ }
+ if (!match) {
+ String message = "illegal reference, expected type="
+ + ConstantPool.tagName(tag) + ": "
+ + i.toString(cpMap);
throw new FormatException(message);
}
}
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Sun Mar 03 20:52:04 2013 -0800
@@ -2256,6 +2256,12 @@
int origBC = bc;
int size = 2;
switch (bc) {
+ case _invokestatic_int:
+ origBC = _invokestatic;
+ break;
+ case _invokespecial_int:
+ origBC = _invokespecial;
+ break;
case _ildc:
case _cldc:
case _fldc:
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Sun Mar 03 20:52:04 2013 -0800
@@ -1409,6 +1409,10 @@
int bc = i.getBC();
if (!(bc >= _first_linker_op && bc <= _last_linker_op)) return -1;
MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap);
+ // do not optimize this case, simply fall back to regular coding
+ if ((bc == _invokespecial || bc == _invokestatic) &&
+ ref.tagEquals(CONSTANT_InterfaceMethodref))
+ return -1;
ClassEntry refClass = ref.classRef;
int self_bc = _self_linker_op + (bc - _first_linker_op);
if (refClass == curClass.thisClass)
@@ -1609,7 +1613,16 @@
case CONSTANT_Fieldref:
bc_which = bc_fieldref; break;
case CONSTANT_Methodref:
- bc_which = bc_methodref; break;
+ if (ref.tagEquals(CONSTANT_InterfaceMethodref)) {
+ if (bc == _invokespecial)
+ vbc = _invokespecial_int;
+ if (bc == _invokestatic)
+ vbc = _invokestatic_int;
+ bc_which = bc_imethodref;
+ } else {
+ bc_which = bc_methodref;
+ }
+ break;
case CONSTANT_InterfaceMethodref:
bc_which = bc_imethodref; break;
case CONSTANT_InvokeDynamic:
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h Sun Mar 03 20:52:04 2013 -0800
@@ -505,5 +505,9 @@
bc_qldc = _xldc_op+7,
bc_qldc_w = _xldc_op+8,
_xldc_limit = _xldc_op+9,
+ _invoke_int_op = _xldc_limit,
+ _invokespecial_int = _invoke_int_op+0,
+ _invokestatic_int = _invoke_int_op+1,
+ _invoke_int_limit = _invoke_int_op+2,
_xxx_3_end
};
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Sun Mar 03 20:52:04 2013 -0800
@@ -2942,6 +2942,9 @@
case bc_putfield:
return &bc_fieldref;
+ case _invokespecial_int:
+ case _invokestatic_int:
+ return &bc_imethodref;
case bc_invokevirtual:
case bc_invokespecial:
case bc_invokestatic:
@@ -4177,6 +4180,12 @@
}
origBC = bc;
switch (bc) {
+ case _invokestatic_int:
+ origBC = bc_invokestatic;
+ break;
+ case _invokespecial_int:
+ origBC = bc_invokespecial;
+ break;
case bc_ildc:
case bc_cldc:
case bc_fldc:
--- a/jdk/test/tools/pack200/AttributeTests.java Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/test/tools/pack200/AttributeTests.java Sun Mar 03 20:52:04 2013 -0800
@@ -67,17 +67,7 @@
File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT);
Utils.jar("cvf", testjarFile.getName(), javaClassName);
- // pack using native --repack
- File nativejarFile = new File(cwd, "out-n" + Utils.JAR_FILE_EXT);
- Utils.repack(testjarFile, nativejarFile, false,
- "--unknown-attribute=error");
- Utils.doCompareVerify(testjarFile, nativejarFile);
-
- // pack using java --repack
- File javajarFile = new File(cwd, "out-j" + Utils.JAR_FILE_EXT);
- Utils.repack(testjarFile, javajarFile, true,
- "--unknown-attribute=error");
- Utils.doCompareBitWise(nativejarFile, javajarFile);
+ Utils.testWithRepack(testjarFile, "--unknown-attribute=error");
}
/*
* this test checks to see if we get the expected strings for output
--- a/jdk/test/tools/pack200/InstructionTests.java Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/test/tools/pack200/InstructionTests.java Sun Mar 03 20:52:04 2013 -0800
@@ -26,11 +26,10 @@
import java.util.ArrayList;
import java.util.List;
import static java.nio.file.StandardOpenOption.*;
-import java.util.regex.Pattern;
/*
* @test
- * @bug 8003549
+ * @bug 8003549 8007297
* @summary tests class files instruction formats introduced in JSR-335
* @compile -XDignore.symbol.file Utils.java InstructionTests.java
* @run main InstructionTests
@@ -48,52 +47,34 @@
List<String> scratch = new ArrayList<>();
final String fname = "A";
String javaFileName = fname + Utils.JAVA_FILE_EXT;
- scratch.add("interface IntIterator {");
+ scratch.add("interface I {");
scratch.add(" default void forEach(){}");
scratch.add(" static void next() {}");
scratch.add("}");
- scratch.add("class A implements IntIterator {");
- scratch.add("public void forEach(Object o){");
- scratch.add("IntIterator.super.forEach();");
- scratch.add("IntIterator.next();");
- scratch.add("}");
+ scratch.add("class A implements I {");
+ scratch.add(" public void forEach(Object o){");
+ scratch.add(" I.super.forEach();");
+ scratch.add(" I.next();");
+ scratch.add(" }");
scratch.add("}");
File cwd = new File(".");
File javaFile = new File(cwd, javaFileName);
Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(),
CREATE, TRUNCATE_EXISTING);
- // make sure we have -g so that we compare LVT and LNT entries
+ // -g to compare LVT and LNT entries
Utils.compiler("-g", javaFile.getName());
+ File propsFile = new File("pack.props");
+ scratch.clear();
+ scratch.add("com.sun.java.util.jar.pack.class.format.error=error");
+ scratch.add("pack.unknown.attribute=error");
+ Files.write(propsFile.toPath(), scratch, Charset.defaultCharset(),
+ CREATE, TRUNCATE_EXISTING);
// jar the file up
File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT);
Utils.jar("cvf", testjarFile.getName(), ".");
- // pack using --repack
- File outjarFile = new File(cwd, "out" + Utils.JAR_FILE_EXT);
- scratch.clear();
- scratch.add(Utils.getPack200Cmd());
- scratch.add("-J-ea");
- scratch.add("-J-esa");
- scratch.add("--repack");
- scratch.add(outjarFile.getName());
- scratch.add(testjarFile.getName());
- List<String> output = Utils.runExec(scratch);
- // TODO remove this when we get bc escapes working correctly
- // this test anyhow would fail at that time
- findString("WARNING: Passing.*" + fname + Utils.CLASS_FILE_EXT,
- output);
-
- Utils.doCompareVerify(testjarFile, outjarFile);
- }
-
- static boolean findString(String str, List<String> list) {
- Pattern p = Pattern.compile(str);
- for (String x : list) {
- if (p.matcher(x).matches())
- return true;
- }
- throw new RuntimeException("Error: " + str + " not found in output");
+ Utils.testWithRepack(testjarFile, "--config-file=" + propsFile.getName());
}
}
--- a/jdk/test/tools/pack200/Utils.java Sat Mar 02 08:54:37 2013 +0000
+++ b/jdk/test/tools/pack200/Utils.java Sun Mar 03 20:52:04 2013 -0800
@@ -314,6 +314,20 @@
throw new RuntimeException("jar command failed");
}
}
+
+ static void testWithRepack(File inFile, String... repackOpts) throws IOException {
+ File cwd = new File(".");
+ // pack using --repack in native mode
+ File nativejarFile = new File(cwd, "out-n" + Utils.JAR_FILE_EXT);
+ repack(inFile, nativejarFile, false, repackOpts);
+ doCompareVerify(inFile, nativejarFile);
+
+ // ensure bit compatibility between the unpacker variants
+ File javajarFile = new File(cwd, "out-j" + Utils.JAR_FILE_EXT);
+ repack(inFile, javajarFile, true, repackOpts);
+ doCompareBitWise(javajarFile, nativejarFile);
+ }
+
static List<String> repack(File inFile, File outFile,
boolean disableNative, String... extraOpts) {
List<String> cmdList = new ArrayList<>();