mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-26 21:38:10 +00:00
8007297: [pack200] allow opcodes with InterfaceMethodRefs
Reviewed-by: jrose
This commit is contained in:
parent
3a216a7fdc
commit
bffaa53287
@ -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<>();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user