Commit 8648c008 authored by ebruneton's avatar ebruneton

Fixed bug #317786.

parent 06058389
......@@ -1079,6 +1079,7 @@ public class ClassReader {
u += 3;
break;
case ClassWriter.LABELW_INSN:
case ClassWriter.ASM_LABELW_INSN:
readLabel(offset + readInt(u + 1), labels);
u += 5;
break;
......@@ -1320,6 +1321,7 @@ public class ClassReader {
// visits the instructions
int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
boolean insertFrame = false;
u = codeStart;
while (u < codeEnd) {
int offset = u - codeStart;
......@@ -1352,6 +1354,9 @@ public class ClassReader {
mv.visitFrame(frame.mode, frame.localDiff, frame.local,
frame.stackCount, frame.stack);
}
// if there is already a frame for this offset, there is no
// need to insert a new one.
insertFrame = false;
}
if (frameCount > 0) {
stackMap = readFrame(stackMap, zip, unzip, frame);
......@@ -1360,6 +1365,13 @@ public class ClassReader {
frame = null;
}
}
// inserts a frame for this offset, if requested by setting
// insertFrame to true during the previous iteration. The actual
// frame content will be computed in MethodWriter.
if (FRAMES && insertFrame) {
mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
insertFrame = false;
}
// visits the instruction at this offset
int opcode = b[u] & 0xFF;
......@@ -1395,31 +1407,36 @@ public class ClassReader {
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
Label target = labels[offset + readUnsignedShort(u + 1)];
// replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
// <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
// <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
// the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
// and where <l'> designates the instruction just after
// and where <L> designates the instruction just after
// the GOTO_W.
if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
mv.visitJumpInsn(opcode + 33, target);
} else {
opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
: opcode ^ 1;
Label endif = new Label();
Label endif = readLabel(offset + 3, labels);
mv.visitJumpInsn(opcode, endif);
mv.visitJumpInsn(200, target); // GOTO_W
mv.visitLabel(endif);
// since we introduced an unconditional jump instruction we
// also need to insert a stack map frame here, unless there
// is already one. The actual frame content will be computed
// in MethodWriter.
if (FRAMES && stackMap != 0
&& (frame == null || frame.offset != offset + 3)) {
mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
}
// endif designates the instruction just after GOTO_W,
// and is visited as part of the next instruction. Since
// it is a jump target, we need to insert a frame here.
insertFrame = true;
}
u += 3;
break;
}
case ClassWriter.ASM_LABELW_INSN: {
// replaces the pseudo GOTO_W instruction with a real one.
mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
// The instruction just after is a jump target (because pseudo
// GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:...,
// see MethodWriter), so we need to insert a frame here.
insertFrame = true;
u += 5;
break;
}
case ClassWriter.WIDE_INSN:
opcode = b[u + 1] & 0xFF;
if (opcode == Opcodes.IINC) {
......
......@@ -173,6 +173,11 @@ public class ClassWriter extends ClassVisitor {
*/
static final int ASM_LABEL_INSN = 18;
/**
* The type of the ASM pseudo instructions with a 4 bytes offset label.
*/
static final int ASM_LABELW_INSN = 19;
/**
* Represents a frame inserted between already existing frames. This kind of
* frame can only be used if the frame content can be computed from the
......@@ -523,11 +528,11 @@ public class ClassWriter extends ClassVisitor {
*/
static {
int i;
byte[] b = new byte[220];
byte[] b = new byte[221];
String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
+ "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSS";
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST";
for (i = 0; i < b.length; ++i) {
b[i] = (byte) (s.charAt(i) - 'A');
}
......@@ -583,6 +588,7 @@ public class ClassWriter extends ClassVisitor {
// for (i = 202; i < 220; ++i) {
// b[i] = ASM_LABEL_INSN;
// }
// b[220] = ASM_LABELW_INSN;
//
// // LDC(_W) instructions
// b[Constants.LDC] = LDC_INSN;
......
......@@ -1050,8 +1050,8 @@ class MethodWriter extends MethodVisitor {
/*
* case of a backward jump with an offset < -32768. In this case we
* automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
* <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
* "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
* <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is the
* "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <L>
* designates the instruction just after the GOTO_W.
*/
if (opcode == Opcodes.GOTO) {
......@@ -1067,7 +1067,11 @@ class MethodWriter extends MethodVisitor {
code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
: opcode ^ 1);
code.putShort(8); // jump offset
code.putByte(200); // GOTO_W
// ASM pseudo GOTO_W insn, see ClassReader. We don't use a real
// GOTO_W because we might need to insert a frame just after (as
// the target of the IFNOTxxx jump instruction).
code.putByte(220);
cw.hasAsmInsns = true;
}
label.put(this, code, code.length - 1, true);
} else if (isWide) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment