提交 05f1d1ac 编写于 作者: K ksrini

8007297: [pack200] allow opcodes with InterfaceMethodRefs

Reviewed-by: jrose
上级 a693e4dc
...@@ -564,7 +564,7 @@ class ClassReader { ...@@ -564,7 +564,7 @@ class ClassReader {
code.bytes = new byte[readInt()]; code.bytes = new byte[readInt()];
in.readFully(code.bytes); in.readFully(code.bytes);
Entry[] cpMap = cls.getCPMap(); Entry[] cpMap = cls.getCPMap();
Instruction.opcodeChecker(code.bytes, cpMap); Instruction.opcodeChecker(code.bytes, cpMap, this.cls.version);
int nh = readUnsignedShort(); int nh = readUnsignedShort();
code.setHandlerCount(nh); code.setHandlerCount(nh);
for (int i = 0; i < nh; i++) { for (int i = 0; i < nh; i++) {
......
...@@ -207,6 +207,10 @@ class ConstantPool { ...@@ -207,6 +207,10 @@ class ConstantPool {
return tag; return tag;
} }
public final boolean tagEquals(int tag) {
return getTag() == tag;
}
public Entry getRef(int i) { public Entry getRef(int i) {
return null; return null;
} }
......
...@@ -479,4 +479,10 @@ class Constants { ...@@ -479,4 +479,10 @@ class Constants {
public final static int _qldc = _xldc_op+7; public final static int _qldc = _xldc_op+7;
public final static int _qldc_w = _xldc_op+8; public final static int _qldc_w = _xldc_op+8;
public final static int _xldc_limit = _xldc_op+9; 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;
} }
...@@ -446,12 +446,14 @@ class Instruction { ...@@ -446,12 +446,14 @@ class Instruction {
public static boolean isCPRefOp(int bc) { public static boolean isCPRefOp(int bc) {
if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return true; if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return true;
if (bc >= _xldc_op && bc < _xldc_limit) return true; if (bc >= _xldc_op && bc < _xldc_limit) return true;
if (bc == _invokespecial_int || bc == _invokestatic_int) return true;
return false; return false;
} }
public static byte getCPRefOpTag(int bc) { public static byte getCPRefOpTag(int bc) {
if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return BC_TAG[0][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 >= _xldc_op && bc < _xldc_limit) return CONSTANT_LoadableValue;
if (bc == _invokestatic_int || bc == _invokespecial_int) return CONSTANT_InterfaceMethodref;
return CONSTANT_None; return CONSTANT_None;
} }
...@@ -647,7 +649,8 @@ class Instruction { ...@@ -647,7 +649,8 @@ class Instruction {
} }
} }
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); Instruction i = at(code, 0);
while (i != null) { while (i != null) {
int opcode = i.getBC(); int opcode = i.getBC();
...@@ -658,10 +661,17 @@ class Instruction { ...@@ -658,10 +661,17 @@ class Instruction {
ConstantPool.Entry e = i.getCPRef(cpMap); ConstantPool.Entry e = i.getCPRef(cpMap);
if (e != null) { if (e != null) {
byte tag = i.getCPTag(); byte tag = i.getCPTag();
if (!e.tagMatches(tag)) { boolean match = e.tagMatches(tag);
String message = "illegal reference, expected type=" + if (!match &&
ConstantPool.tagName(tag) + ": " + (i.bc == _invokespecial || i.bc == _invokestatic) &&
i.toString(cpMap); 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); throw new FormatException(message);
} }
} }
......
...@@ -2256,6 +2256,12 @@ class PackageReader extends BandStructure { ...@@ -2256,6 +2256,12 @@ class PackageReader extends BandStructure {
int origBC = bc; int origBC = bc;
int size = 2; int size = 2;
switch (bc) { switch (bc) {
case _invokestatic_int:
origBC = _invokestatic;
break;
case _invokespecial_int:
origBC = _invokespecial;
break;
case _ildc: case _ildc:
case _cldc: case _cldc:
case _fldc: case _fldc:
......
...@@ -1409,6 +1409,10 @@ class PackageWriter extends BandStructure { ...@@ -1409,6 +1409,10 @@ class PackageWriter extends BandStructure {
int bc = i.getBC(); int bc = i.getBC();
if (!(bc >= _first_linker_op && bc <= _last_linker_op)) return -1; if (!(bc >= _first_linker_op && bc <= _last_linker_op)) return -1;
MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap); 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; ClassEntry refClass = ref.classRef;
int self_bc = _self_linker_op + (bc - _first_linker_op); int self_bc = _self_linker_op + (bc - _first_linker_op);
if (refClass == curClass.thisClass) if (refClass == curClass.thisClass)
...@@ -1609,7 +1613,16 @@ class PackageWriter extends BandStructure { ...@@ -1609,7 +1613,16 @@ class PackageWriter extends BandStructure {
case CONSTANT_Fieldref: case CONSTANT_Fieldref:
bc_which = bc_fieldref; break; bc_which = bc_fieldref; break;
case CONSTANT_Methodref: 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: case CONSTANT_InterfaceMethodref:
bc_which = bc_imethodref; break; bc_which = bc_imethodref; break;
case CONSTANT_InvokeDynamic: case CONSTANT_InvokeDynamic:
......
...@@ -505,5 +505,9 @@ enum { ...@@ -505,5 +505,9 @@ enum {
bc_qldc = _xldc_op+7, bc_qldc = _xldc_op+7,
bc_qldc_w = _xldc_op+8, bc_qldc_w = _xldc_op+8,
_xldc_limit = _xldc_op+9, _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 _xxx_3_end
}; };
...@@ -2942,6 +2942,9 @@ band* unpacker::ref_band_for_op(int bc) { ...@@ -2942,6 +2942,9 @@ band* unpacker::ref_band_for_op(int bc) {
case bc_putfield: case bc_putfield:
return &bc_fieldref; return &bc_fieldref;
case _invokespecial_int:
case _invokestatic_int:
return &bc_imethodref;
case bc_invokevirtual: case bc_invokevirtual:
case bc_invokespecial: case bc_invokespecial:
case bc_invokestatic: case bc_invokestatic:
...@@ -4177,6 +4180,12 @@ void unpacker::write_bc_ops() { ...@@ -4177,6 +4180,12 @@ void unpacker::write_bc_ops() {
} }
origBC = bc; origBC = bc;
switch (bc) { switch (bc) {
case _invokestatic_int:
origBC = bc_invokestatic;
break;
case _invokespecial_int:
origBC = bc_invokespecial;
break;
case bc_ildc: case bc_ildc:
case bc_cldc: case bc_cldc:
case bc_fldc: case bc_fldc:
......
...@@ -67,17 +67,7 @@ public class AttributeTests { ...@@ -67,17 +67,7 @@ public class AttributeTests {
File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT);
Utils.jar("cvf", testjarFile.getName(), javaClassName); Utils.jar("cvf", testjarFile.getName(), javaClassName);
// pack using native --repack Utils.testWithRepack(testjarFile, "--unknown-attribute=error");
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);
} }
/* /*
* this test checks to see if we get the expected strings for output * this test checks to see if we get the expected strings for output
......
...@@ -26,11 +26,10 @@ import java.nio.file.Files; ...@@ -26,11 +26,10 @@ import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static java.nio.file.StandardOpenOption.*; import static java.nio.file.StandardOpenOption.*;
import java.util.regex.Pattern;
/* /*
* @test * @test
* @bug 8003549 * @bug 8003549 8007297
* @summary tests class files instruction formats introduced in JSR-335 * @summary tests class files instruction formats introduced in JSR-335
* @compile -XDignore.symbol.file Utils.java InstructionTests.java * @compile -XDignore.symbol.file Utils.java InstructionTests.java
* @run main InstructionTests * @run main InstructionTests
...@@ -48,52 +47,34 @@ public class InstructionTests { ...@@ -48,52 +47,34 @@ public class InstructionTests {
List<String> scratch = new ArrayList<>(); List<String> scratch = new ArrayList<>();
final String fname = "A"; final String fname = "A";
String javaFileName = fname + Utils.JAVA_FILE_EXT; String javaFileName = fname + Utils.JAVA_FILE_EXT;
scratch.add("interface IntIterator {"); scratch.add("interface I {");
scratch.add(" default void forEach(){}"); scratch.add(" default void forEach(){}");
scratch.add(" static void next() {}"); scratch.add(" static void next() {}");
scratch.add("}"); scratch.add("}");
scratch.add("class A implements IntIterator {"); scratch.add("class A implements I {");
scratch.add("public void forEach(Object o){"); scratch.add(" public void forEach(Object o){");
scratch.add("IntIterator.super.forEach();"); scratch.add(" I.super.forEach();");
scratch.add("IntIterator.next();"); scratch.add(" I.next();");
scratch.add("}"); scratch.add(" }");
scratch.add("}"); scratch.add("}");
File cwd = new File("."); File cwd = new File(".");
File javaFile = new File(cwd, javaFileName); File javaFile = new File(cwd, javaFileName);
Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(), Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(),
CREATE, TRUNCATE_EXISTING); 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()); 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 // jar the file up
File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT);
Utils.jar("cvf", testjarFile.getName(), "."); Utils.jar("cvf", testjarFile.getName(), ".");
// pack using --repack Utils.testWithRepack(testjarFile, "--config-file=" + propsFile.getName());
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");
} }
} }
...@@ -314,6 +314,20 @@ class Utils { ...@@ -314,6 +314,20 @@ class Utils {
throw new RuntimeException("jar command failed"); 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, static List<String> repack(File inFile, File outFile,
boolean disableNative, String... extraOpts) { boolean disableNative, String... extraOpts) {
List<String> cmdList = new ArrayList<>(); List<String> cmdList = new ArrayList<>();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册