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

8007297: [pack200] allow opcodes with InterfaceMethodRefs

Reviewed-by: jrose
上级 a693e4dc
......@@ -564,7 +564,7 @@ class ClassReader {
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++) {
......
......@@ -207,6 +207,10 @@ class ConstantPool {
return tag;
}
public final boolean tagEquals(int tag) {
return getTag() == tag;
}
public Entry getRef(int i) {
return null;
}
......
......@@ -479,4 +479,10 @@ class Constants {
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;
}
......@@ -446,12 +446,14 @@ class Instruction {
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 @@ 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);
while (i != null) {
int opcode = i.getBC();
......@@ -658,10 +661,17 @@ class Instruction {
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);
}
}
......
......@@ -2256,6 +2256,12 @@ class PackageReader extends BandStructure {
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:
......
......@@ -1409,6 +1409,10 @@ class PackageWriter extends BandStructure {
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 @@ class PackageWriter extends BandStructure {
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:
......
......@@ -505,5 +505,9 @@ enum {
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
};
......@@ -2942,6 +2942,9 @@ band* unpacker::ref_band_for_op(int bc) {
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 @@ void unpacker::write_bc_ops() {
}
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:
......
......@@ -67,17 +67,7 @@ public class AttributeTests {
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
......
......@@ -26,11 +26,10 @@ import java.nio.file.Files;
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 @@ public class InstructionTests {
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());
}
}
......@@ -314,6 +314,20 @@ class Utils {
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<>();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册