mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8343436: Regression in StackMapGenerator after JDK-8339205
Reviewed-by: liach
This commit is contained in:
parent
2432c4f862
commit
f9e1c62dcd
2 changed files with 131 additions and 302 deletions
|
@ -349,7 +349,6 @@ public final class StackMapGenerator {
|
||||||
var it = handlers.listIterator();
|
var it = handlers.listIterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
var e = it.next();
|
var e = it.next();
|
||||||
var labelContext = this.labelContext;
|
|
||||||
int handlerStart = labelContext.labelToBci(e.tryStart());
|
int handlerStart = labelContext.labelToBci(e.tryStart());
|
||||||
int handlerEnd = labelContext.labelToBci(e.tryEnd());
|
int handlerEnd = labelContext.labelToBci(e.tryEnd());
|
||||||
if (rangeStart >= handlerEnd || rangeEnd <= handlerStart) {
|
if (rangeStart >= handlerEnd || rangeEnd <= handlerStart) {
|
||||||
|
@ -391,15 +390,14 @@ public final class StackMapGenerator {
|
||||||
return framesCount == 0 ? null : new UnboundAttribute.AdHocAttribute<>(Attributes.stackMapTable()) {
|
return framesCount == 0 ? null : new UnboundAttribute.AdHocAttribute<>(Attributes.stackMapTable()) {
|
||||||
@Override
|
@Override
|
||||||
public void writeBody(BufWriterImpl b) {
|
public void writeBody(BufWriterImpl b) {
|
||||||
var gen = StackMapGenerator.this;
|
b.writeU2(framesCount);
|
||||||
b.writeU2(gen.framesCount);
|
Frame prevFrame = new Frame(classHierarchy);
|
||||||
Frame prevFrame = gen.new Frame(gen.classHierarchy);
|
prevFrame.setLocalsFromArg(methodName, methodDesc, isStatic, thisType);
|
||||||
prevFrame.setLocalsFromArg(gen.methodName, gen.methodDesc, gen.isStatic, gen.thisType);
|
|
||||||
prevFrame.trimAndCompress();
|
prevFrame.trimAndCompress();
|
||||||
for (int i = 0; i < gen.framesCount; i++) {
|
for (int i = 0; i < framesCount; i++) {
|
||||||
var fr = gen.frames[i];
|
var fr = frames[i];
|
||||||
fr.trimAndCompress();
|
fr.trimAndCompress();
|
||||||
fr.writeTo(b, prevFrame, gen.cp);
|
fr.writeTo(b, prevFrame, cp);
|
||||||
prevFrame = fr;
|
prevFrame = fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,7 +460,6 @@ public final class StackMapGenerator {
|
||||||
processExceptionHandlerTargets(bci, this_uninit);
|
processExceptionHandlerTargets(bci, this_uninit);
|
||||||
verified_exc_handlers = true;
|
verified_exc_handlers = true;
|
||||||
}
|
}
|
||||||
var currentFrame = this.currentFrame;
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case NOP -> {}
|
case NOP -> {}
|
||||||
case RETURN -> {
|
case RETURN -> {
|
||||||
|
@ -503,27 +500,27 @@ public final class StackMapGenerator {
|
||||||
case ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3 ->
|
case ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3 ->
|
||||||
currentFrame.pushStack(currentFrame.getLocal(opcode - ALOAD_0));
|
currentFrame.pushStack(currentFrame.getLocal(opcode - ALOAD_0));
|
||||||
case IALOAD, BALOAD, CALOAD, SALOAD ->
|
case IALOAD, BALOAD, CALOAD, SALOAD ->
|
||||||
currentFrame.decStack2PushStack(Type.INTEGER_TYPE);
|
currentFrame.decStack(2).pushStack(Type.INTEGER_TYPE);
|
||||||
case LALOAD ->
|
case LALOAD ->
|
||||||
currentFrame.decStack2PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
currentFrame.decStack(2).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
case FALOAD ->
|
case FALOAD ->
|
||||||
currentFrame.decStack2PushStack(Type.FLOAT_TYPE);
|
currentFrame.decStack(2).pushStack(Type.FLOAT_TYPE);
|
||||||
case DALOAD ->
|
case DALOAD ->
|
||||||
currentFrame.decStack2PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
currentFrame.decStack(2).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||||
case AALOAD ->
|
case AALOAD ->
|
||||||
currentFrame.pushStack((type1 = currentFrame.decStack().popStack()) == Type.NULL_TYPE ? Type.NULL_TYPE : type1.getComponent());
|
currentFrame.pushStack((type1 = currentFrame.decStack(1).popStack()) == Type.NULL_TYPE ? Type.NULL_TYPE : type1.getComponent());
|
||||||
case ISTORE ->
|
case ISTORE ->
|
||||||
currentFrame.decStack().setLocal(bcs.getIndex(), Type.INTEGER_TYPE);
|
currentFrame.decStack(1).setLocal(bcs.getIndex(), Type.INTEGER_TYPE);
|
||||||
case ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3 ->
|
case ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3 ->
|
||||||
currentFrame.decStack().setLocal(opcode - ISTORE_0, Type.INTEGER_TYPE);
|
currentFrame.decStack(1).setLocal(opcode - ISTORE_0, Type.INTEGER_TYPE);
|
||||||
case LSTORE ->
|
case LSTORE ->
|
||||||
currentFrame.decStack(2).setLocal2(bcs.getIndex(), Type.LONG_TYPE, Type.LONG2_TYPE);
|
currentFrame.decStack(2).setLocal2(bcs.getIndex(), Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
case LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3 ->
|
case LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3 ->
|
||||||
currentFrame.decStack(2).setLocal2(opcode - LSTORE_0, Type.LONG_TYPE, Type.LONG2_TYPE);
|
currentFrame.decStack(2).setLocal2(opcode - LSTORE_0, Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
case FSTORE ->
|
case FSTORE ->
|
||||||
currentFrame.decStack().setLocal(bcs.getIndex(), Type.FLOAT_TYPE);
|
currentFrame.decStack(1).setLocal(bcs.getIndex(), Type.FLOAT_TYPE);
|
||||||
case FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3 ->
|
case FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3 ->
|
||||||
currentFrame.decStack().setLocal(opcode - FSTORE_0, Type.FLOAT_TYPE);
|
currentFrame.decStack(1).setLocal(opcode - FSTORE_0, Type.FLOAT_TYPE);
|
||||||
case DSTORE ->
|
case DSTORE ->
|
||||||
currentFrame.decStack(2).setLocal2(bcs.getIndex(), Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
currentFrame.decStack(2).setLocal2(bcs.getIndex(), Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||||
case DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3 ->
|
case DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3 ->
|
||||||
|
@ -537,75 +534,98 @@ public final class StackMapGenerator {
|
||||||
case IASTORE, BASTORE, CASTORE, SASTORE, FASTORE, AASTORE ->
|
case IASTORE, BASTORE, CASTORE, SASTORE, FASTORE, AASTORE ->
|
||||||
currentFrame.decStack(3);
|
currentFrame.decStack(3);
|
||||||
case POP, MONITORENTER, MONITOREXIT ->
|
case POP, MONITORENTER, MONITOREXIT ->
|
||||||
currentFrame.decStack();
|
currentFrame.decStack(1);
|
||||||
case POP2 ->
|
case POP2 ->
|
||||||
currentFrame.decStack(2);
|
currentFrame.decStack(2);
|
||||||
case DUP ->
|
case DUP ->
|
||||||
currentFrame.dup();
|
currentFrame.pushStack(type1 = currentFrame.popStack()).pushStack(type1);
|
||||||
case DUP_X1 ->
|
case DUP_X1 -> {
|
||||||
currentFrame.dup_x1();
|
type1 = currentFrame.popStack();
|
||||||
case DUP_X2 ->
|
type2 = currentFrame.popStack();
|
||||||
currentFrame.dup_x2();
|
currentFrame.pushStack(type1).pushStack(type2).pushStack(type1);
|
||||||
case DUP2 ->
|
}
|
||||||
currentFrame.dup2();
|
case DUP_X2 -> {
|
||||||
case DUP2_X1 ->
|
type1 = currentFrame.popStack();
|
||||||
currentFrame.dup2_x1();
|
type2 = currentFrame.popStack();
|
||||||
case DUP2_X2 ->
|
type3 = currentFrame.popStack();
|
||||||
currentFrame.dup2_x2();
|
currentFrame.pushStack(type1).pushStack(type3).pushStack(type2).pushStack(type1);
|
||||||
case SWAP ->
|
}
|
||||||
currentFrame.swap();
|
case DUP2 -> {
|
||||||
|
type1 = currentFrame.popStack();
|
||||||
|
type2 = currentFrame.popStack();
|
||||||
|
currentFrame.pushStack(type2).pushStack(type1).pushStack(type2).pushStack(type1);
|
||||||
|
}
|
||||||
|
case DUP2_X1 -> {
|
||||||
|
type1 = currentFrame.popStack();
|
||||||
|
type2 = currentFrame.popStack();
|
||||||
|
type3 = currentFrame.popStack();
|
||||||
|
currentFrame.pushStack(type2).pushStack(type1).pushStack(type3).pushStack(type2).pushStack(type1);
|
||||||
|
}
|
||||||
|
case DUP2_X2 -> {
|
||||||
|
type1 = currentFrame.popStack();
|
||||||
|
type2 = currentFrame.popStack();
|
||||||
|
type3 = currentFrame.popStack();
|
||||||
|
type4 = currentFrame.popStack();
|
||||||
|
currentFrame.pushStack(type2).pushStack(type1).pushStack(type4).pushStack(type3).pushStack(type2).pushStack(type1);
|
||||||
|
}
|
||||||
|
case SWAP -> {
|
||||||
|
type1 = currentFrame.popStack();
|
||||||
|
type2 = currentFrame.popStack();
|
||||||
|
currentFrame.pushStack(type1);
|
||||||
|
currentFrame.pushStack(type2);
|
||||||
|
}
|
||||||
case IADD, ISUB, IMUL, IDIV, IREM, ISHL, ISHR, IUSHR, IOR, IXOR, IAND ->
|
case IADD, ISUB, IMUL, IDIV, IREM, ISHL, ISHR, IUSHR, IOR, IXOR, IAND ->
|
||||||
currentFrame.decStack2PushStack(Type.INTEGER_TYPE);
|
currentFrame.decStack(2).pushStack(Type.INTEGER_TYPE);
|
||||||
case INEG, ARRAYLENGTH, INSTANCEOF ->
|
case INEG, ARRAYLENGTH, INSTANCEOF ->
|
||||||
currentFrame.decStack1PushStack(Type.INTEGER_TYPE);
|
currentFrame.decStack(1).pushStack(Type.INTEGER_TYPE);
|
||||||
case LADD, LSUB, LMUL, LDIV, LREM, LAND, LOR, LXOR ->
|
case LADD, LSUB, LMUL, LDIV, LREM, LAND, LOR, LXOR ->
|
||||||
currentFrame.decStack4PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
currentFrame.decStack(4).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
case LNEG ->
|
case LNEG ->
|
||||||
currentFrame.decStack2PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
currentFrame.decStack(2).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
case LSHL, LSHR, LUSHR ->
|
case LSHL, LSHR, LUSHR ->
|
||||||
currentFrame.decStack3PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
currentFrame.decStack(3).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
case FADD, FSUB, FMUL, FDIV, FREM ->
|
case FADD, FSUB, FMUL, FDIV, FREM ->
|
||||||
currentFrame.decStack2PushStack(Type.FLOAT_TYPE);
|
currentFrame.decStack(2).pushStack(Type.FLOAT_TYPE);
|
||||||
case FNEG ->
|
case FNEG ->
|
||||||
currentFrame.decStack1PushStack(Type.FLOAT_TYPE);
|
currentFrame.decStack(1).pushStack(Type.FLOAT_TYPE);
|
||||||
case DADD, DSUB, DMUL, DDIV, DREM ->
|
case DADD, DSUB, DMUL, DDIV, DREM ->
|
||||||
currentFrame.decStack4PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
currentFrame.decStack(4).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||||
case DNEG ->
|
case DNEG ->
|
||||||
currentFrame.decStack2PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
currentFrame.decStack(2).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||||
case IINC ->
|
case IINC ->
|
||||||
currentFrame.checkLocal(bcs.getIndex());
|
currentFrame.checkLocal(bcs.getIndex());
|
||||||
case I2L ->
|
case I2L ->
|
||||||
currentFrame.decStack1PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
currentFrame.decStack(1).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
case L2I ->
|
case L2I ->
|
||||||
currentFrame.decStack2PushStack(Type.INTEGER_TYPE);
|
currentFrame.decStack(2).pushStack(Type.INTEGER_TYPE);
|
||||||
case I2F ->
|
case I2F ->
|
||||||
currentFrame.decStack1PushStack(Type.FLOAT_TYPE);
|
currentFrame.decStack(1).pushStack(Type.FLOAT_TYPE);
|
||||||
case I2D ->
|
case I2D ->
|
||||||
currentFrame.decStack1PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
currentFrame.decStack(1).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||||
case L2F ->
|
case L2F ->
|
||||||
currentFrame.decStack2PushStack(Type.FLOAT_TYPE);
|
currentFrame.decStack(2).pushStack(Type.FLOAT_TYPE);
|
||||||
case L2D ->
|
case L2D ->
|
||||||
currentFrame.decStack2PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
currentFrame.decStack(2).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||||
case F2I ->
|
case F2I ->
|
||||||
currentFrame.decStack1PushStack(Type.INTEGER_TYPE);
|
currentFrame.decStack(1).pushStack(Type.INTEGER_TYPE);
|
||||||
case F2L ->
|
case F2L ->
|
||||||
currentFrame.decStack1PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
currentFrame.decStack(1).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
case F2D ->
|
case F2D ->
|
||||||
currentFrame.decStack1PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
currentFrame.decStack(1).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||||
case D2L ->
|
case D2L ->
|
||||||
currentFrame.decStack2PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
currentFrame.decStack(2).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
case D2F ->
|
case D2F ->
|
||||||
currentFrame.decStack2PushStack(Type.FLOAT_TYPE);
|
currentFrame.decStack(2).pushStack(Type.FLOAT_TYPE);
|
||||||
case I2B, I2C, I2S ->
|
case I2B, I2C, I2S ->
|
||||||
currentFrame.decStack1PushStack(Type.INTEGER_TYPE);
|
currentFrame.decStack(1).pushStack(Type.INTEGER_TYPE);
|
||||||
case LCMP, DCMPL, DCMPG ->
|
case LCMP, DCMPL, DCMPG ->
|
||||||
currentFrame.decStack4PushStack(Type.INTEGER_TYPE);
|
currentFrame.decStack(4).pushStack(Type.INTEGER_TYPE);
|
||||||
case FCMPL, FCMPG, D2I ->
|
case FCMPL, FCMPG, D2I ->
|
||||||
currentFrame.decStack2PushStack(Type.INTEGER_TYPE);
|
currentFrame.decStack(2).pushStack(Type.INTEGER_TYPE);
|
||||||
case IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE ->
|
case IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE ->
|
||||||
checkJumpTarget(currentFrame.decStack(2), bcs.dest());
|
checkJumpTarget(currentFrame.decStack(2), bcs.dest());
|
||||||
case IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IFNULL, IFNONNULL ->
|
case IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IFNULL, IFNONNULL ->
|
||||||
checkJumpTarget(currentFrame.decStack(), bcs.dest());
|
checkJumpTarget(currentFrame.decStack(1), bcs.dest());
|
||||||
case GOTO -> {
|
case GOTO -> {
|
||||||
checkJumpTarget(currentFrame, bcs.dest());
|
checkJumpTarget(currentFrame, bcs.dest());
|
||||||
ncf = true;
|
ncf = true;
|
||||||
|
@ -623,7 +643,7 @@ public final class StackMapGenerator {
|
||||||
ncf = true;
|
ncf = true;
|
||||||
}
|
}
|
||||||
case IRETURN, FRETURN, ARETURN, ATHROW -> {
|
case IRETURN, FRETURN, ARETURN, ATHROW -> {
|
||||||
currentFrame.decStack();
|
currentFrame.decStack(1);
|
||||||
ncf = true;
|
ncf = true;
|
||||||
}
|
}
|
||||||
case GETSTATIC, PUTSTATIC, GETFIELD, PUTFIELD ->
|
case GETSTATIC, PUTSTATIC, GETFIELD, PUTFIELD ->
|
||||||
|
@ -633,16 +653,17 @@ public final class StackMapGenerator {
|
||||||
case NEW ->
|
case NEW ->
|
||||||
currentFrame.pushStack(Type.uninitializedType(bci));
|
currentFrame.pushStack(Type.uninitializedType(bci));
|
||||||
case NEWARRAY ->
|
case NEWARRAY ->
|
||||||
currentFrame.decStack1PushStack(getNewarrayType(bcs.getIndex()));
|
currentFrame.decStack(1).pushStack(getNewarrayType(bcs.getIndex()));
|
||||||
case ANEWARRAY ->
|
case ANEWARRAY ->
|
||||||
processAnewarray(bcs.getIndexU2());
|
processAnewarray(bcs.getIndexU2());
|
||||||
case CHECKCAST ->
|
case CHECKCAST ->
|
||||||
currentFrame.decStack1PushStack(cpIndexToType(bcs.getIndexU2(), cp));
|
currentFrame.decStack(1).pushStack(cpIndexToType(bcs.getIndexU2(), cp));
|
||||||
case MULTIANEWARRAY -> {
|
case MULTIANEWARRAY -> {
|
||||||
type1 = cpIndexToType(bcs.getIndexU2(), cp);
|
type1 = cpIndexToType(bcs.getIndexU2(), cp);
|
||||||
currentFrame.decStack(
|
int dim = bcs.getU1Unchecked(bcs.bci() + 3);
|
||||||
bcs.getU1Unchecked(bcs.bci() + 3) /* dim */
|
for (int i = 0; i < dim; i++) {
|
||||||
);
|
currentFrame.popStack();
|
||||||
|
}
|
||||||
currentFrame.pushStack(type1);
|
currentFrame.pushStack(type1);
|
||||||
}
|
}
|
||||||
case JSR, JSR_W, RET ->
|
case JSR, JSR_W, RET ->
|
||||||
|
@ -657,7 +678,6 @@ public final class StackMapGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processExceptionHandlerTargets(int bci, boolean this_uninit) {
|
private void processExceptionHandlerTargets(int bci, boolean this_uninit) {
|
||||||
var currentFrame = this.currentFrame;
|
|
||||||
for (var ex : rawHandlers) {
|
for (var ex : rawHandlers) {
|
||||||
if (bci == ex.start || (currentFrame.localsChanged && bci > ex.start && bci < ex.end)) {
|
if (bci == ex.start || (currentFrame.localsChanged && bci > ex.start && bci < ex.end)) {
|
||||||
int flags = currentFrame.flags;
|
int flags = currentFrame.flags;
|
||||||
|
@ -670,10 +690,7 @@ public final class StackMapGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processLdc(int index) {
|
private void processLdc(int index) {
|
||||||
var e = cp.entryByIndex(index);
|
switch (cp.entryByIndex(index).tag()) {
|
||||||
byte tag = e.tag();
|
|
||||||
var currentFrame = this.currentFrame;
|
|
||||||
switch (tag) {
|
|
||||||
case TAG_UTF8 ->
|
case TAG_UTF8 ->
|
||||||
currentFrame.pushStack(Type.OBJECT_TYPE);
|
currentFrame.pushStack(Type.OBJECT_TYPE);
|
||||||
case TAG_STRING ->
|
case TAG_STRING ->
|
||||||
|
@ -693,9 +710,9 @@ public final class StackMapGenerator {
|
||||||
case TAG_METHOD_TYPE ->
|
case TAG_METHOD_TYPE ->
|
||||||
currentFrame.pushStack(Type.METHOD_TYPE);
|
currentFrame.pushStack(Type.METHOD_TYPE);
|
||||||
case TAG_DYNAMIC ->
|
case TAG_DYNAMIC ->
|
||||||
currentFrame.pushStack(ClassReaderImpl.checkType(e, index, ConstantDynamicEntry.class).asSymbol().constantType());
|
currentFrame.pushStack(cp.entryByIndex(index, ConstantDynamicEntry.class).asSymbol().constantType());
|
||||||
default ->
|
default ->
|
||||||
throw generatorError("CP entry #%d %s is not loadable constant".formatted(index, tag));
|
throw generatorError("CP entry #%d %s is not loadable constant".formatted(index, cp.entryByIndex(index).tag()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,7 +721,7 @@ public final class StackMapGenerator {
|
||||||
int alignedBci = RawBytecodeHelper.align(bci + 1);
|
int alignedBci = RawBytecodeHelper.align(bci + 1);
|
||||||
int defaultOffset = bcs.getIntUnchecked(alignedBci);
|
int defaultOffset = bcs.getIntUnchecked(alignedBci);
|
||||||
int keys, delta;
|
int keys, delta;
|
||||||
currentFrame.decStack();
|
currentFrame.popStack();
|
||||||
if (bcs.opcode() == TABLESWITCH) {
|
if (bcs.opcode() == TABLESWITCH) {
|
||||||
int low = bcs.getIntUnchecked(alignedBci + 4);
|
int low = bcs.getIntUnchecked(alignedBci + 4);
|
||||||
int high = bcs.getIntUnchecked(alignedBci + 2 * 4);
|
int high = bcs.getIntUnchecked(alignedBci + 2 * 4);
|
||||||
|
@ -748,7 +765,8 @@ public final class StackMapGenerator {
|
||||||
currentFrame.decStack(Util.isDoubleSlot(desc) ? 2 : 1);
|
currentFrame.decStack(Util.isDoubleSlot(desc) ? 2 : 1);
|
||||||
}
|
}
|
||||||
case GETFIELD -> {
|
case GETFIELD -> {
|
||||||
currentFrame.dec1PushStack(desc);
|
currentFrame.decStack(1);
|
||||||
|
currentFrame.pushStack(desc);
|
||||||
}
|
}
|
||||||
case PUTFIELD -> {
|
case PUTFIELD -> {
|
||||||
currentFrame.decStack(Util.isDoubleSlot(desc) ? 3 : 2);
|
currentFrame.decStack(Util.isDoubleSlot(desc) ? 3 : 2);
|
||||||
|
@ -786,7 +804,7 @@ public final class StackMapGenerator {
|
||||||
throw generatorError("Bad operand type when invoking <init>");
|
throw generatorError("Bad operand type when invoking <init>");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentFrame.decStack();
|
currentFrame.decStack(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentFrame.pushStack(mDesc.returnType());
|
currentFrame.pushStack(mDesc.returnType());
|
||||||
|
@ -799,17 +817,10 @@ public final class StackMapGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processAnewarray(int index) {
|
private void processAnewarray(int index) {
|
||||||
currentFrame.decStack();
|
currentFrame.popStack();
|
||||||
currentFrame.pushStack(cpIndexToType(index, cp).toArray());
|
currentFrame.pushStack(cpIndexToType(index, cp).toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@return the generator error with stack underflow}
|
|
||||||
*/
|
|
||||||
private IllegalArgumentException stackUnderflow() {
|
|
||||||
return generatorError("Operand stack underflow");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@return the generator error with attached details}
|
* {@return the generator error with attached details}
|
||||||
* @param msg error message
|
* @param msg error message
|
||||||
|
@ -889,7 +900,6 @@ public final class StackMapGenerator {
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
throw generatorError("Detected branch target out of bytecode range", bci);
|
throw generatorError("Detected branch target out of bytecode range", bci);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < rawHandlers.size(); i++) try {
|
for (int i = 0; i < rawHandlers.size(); i++) try {
|
||||||
addFrame(rawHandlers.get(i).handler());
|
addFrame(rawHandlers.get(i).handler());
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
|
@ -958,101 +968,6 @@ public final class StackMapGenerator {
|
||||||
return (dirty ? "frame* @" : "frame @") + offset + " with locals " + (locals == null ? "[]" : Arrays.asList(locals).subList(0, localsSize)) + " and stack " + (stack == null ? "[]" : Arrays.asList(stack).subList(0, stackSize));
|
return (dirty ? "frame* @" : "frame @") + offset + " with locals " + (locals == null ? "[]" : Arrays.asList(locals).subList(0, localsSize)) + " and stack " + (stack == null ? "[]" : Arrays.asList(stack).subList(0, stackSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame dup() {
|
|
||||||
int stackSize = this.stackSize;
|
|
||||||
if (stackSize < 1) throw stackUnderflow();
|
|
||||||
checkStack(stackSize + 1);
|
|
||||||
stack[stackSize] = stack[stackSize - 1];
|
|
||||||
this.stackSize = stackSize + 1;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame dup_x1() {
|
|
||||||
int stackSize = this.stackSize;
|
|
||||||
if (stackSize < 2) throw stackUnderflow();
|
|
||||||
checkStack(stackSize + 1);
|
|
||||||
var stack = this.stack;
|
|
||||||
Type type0 = stack[stackSize - 2];
|
|
||||||
Type type1 = stack[stackSize - 1];
|
|
||||||
stack[stackSize - 2] = type1;
|
|
||||||
stack[stackSize - 1] = type0;
|
|
||||||
stack[stackSize ] = type1;
|
|
||||||
this.stackSize = stackSize + 1;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame dup_x2() {
|
|
||||||
int stackSize = this.stackSize;
|
|
||||||
if (stackSize < 3) throw stackUnderflow();
|
|
||||||
checkStack(stackSize + 1);
|
|
||||||
var stack = this.stack;
|
|
||||||
Type type0 = stack[stackSize - 3];
|
|
||||||
Type type1 = stack[stackSize - 2];
|
|
||||||
Type type2 = stack[stackSize - 1];
|
|
||||||
stack[stackSize - 3] = type2;
|
|
||||||
stack[stackSize - 2] = type0;
|
|
||||||
stack[stackSize - 1] = type1;
|
|
||||||
stack[stackSize ] = type2;
|
|
||||||
this.stackSize = stackSize + 1;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame dup2() {
|
|
||||||
int stackSize = this.stackSize;
|
|
||||||
if (stackSize < 2) throw stackUnderflow();
|
|
||||||
checkStack(stackSize + 2);
|
|
||||||
stack[stackSize ] = stack[stackSize - 2];
|
|
||||||
stack[stackSize + 1] = stack[stackSize - 1];
|
|
||||||
this.stackSize = stackSize + 2;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame dup2_x1() {
|
|
||||||
int stackSize = this.stackSize;
|
|
||||||
if (stackSize < 3) throw stackUnderflow();
|
|
||||||
checkStack(stackSize + 2);
|
|
||||||
var stack = this.stack;
|
|
||||||
Type type0 = stack[stackSize - 3];
|
|
||||||
Type type1 = stack[stackSize - 2];
|
|
||||||
Type type2 = stack[stackSize - 1];
|
|
||||||
stack[stackSize - 3] = type1;
|
|
||||||
stack[stackSize - 2] = type2;
|
|
||||||
stack[stackSize - 1] = type0;
|
|
||||||
stack[stackSize ] = type1;
|
|
||||||
stack[stackSize + 1] = type2;
|
|
||||||
this.stackSize = stackSize + 2;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame dup2_x2() {
|
|
||||||
int stackSize = this.stackSize;
|
|
||||||
if (stackSize < 4) throw stackUnderflow();
|
|
||||||
checkStack(stackSize + 2);
|
|
||||||
var stack = this.stack;
|
|
||||||
Type type0 = stack[stackSize - 4];
|
|
||||||
Type type1 = stack[stackSize - 3];
|
|
||||||
Type type2 = stack[stackSize - 2];
|
|
||||||
Type type3 = stack[stackSize - 1];
|
|
||||||
stack[stackSize - 4] = type2;
|
|
||||||
stack[stackSize - 3] = type3;
|
|
||||||
stack[stackSize - 2] = type0;
|
|
||||||
stack[stackSize - 1] = type1;
|
|
||||||
stack[stackSize ] = type2;
|
|
||||||
stack[stackSize + 1] = type3;
|
|
||||||
this.stackSize = stackSize + 4;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame swap() {
|
|
||||||
int stackSize = this.stackSize - 2;
|
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
|
||||||
var stack = this.stack;
|
|
||||||
Type type = stack[stackSize];
|
|
||||||
stack[stackSize] = stack[stackSize + 1];
|
|
||||||
stack[stackSize + 1] = type;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame pushStack(ClassDesc desc) {
|
Frame pushStack(ClassDesc desc) {
|
||||||
if (desc == CD_long) return pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
if (desc == CD_long) return pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
||||||
if (desc == CD_double) return pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
if (desc == CD_double) return pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||||
|
@ -1063,109 +978,27 @@ public final class StackMapGenerator {
|
||||||
: Type.referenceType(desc));
|
: Type.referenceType(desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame dec1PushStack(ClassDesc desc) {
|
|
||||||
if (desc == CD_long) return decStack1PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
|
|
||||||
if (desc == CD_double) return decStack1PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
|
||||||
return desc == CD_void ? this
|
|
||||||
: decStack1PushStack(
|
|
||||||
desc.isPrimitive()
|
|
||||||
? (desc == CD_float ? Type.FLOAT_TYPE : Type.INTEGER_TYPE)
|
|
||||||
: Type.referenceType(desc));
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame pushStack(Type type) {
|
Frame pushStack(Type type) {
|
||||||
int stackSize = this.stackSize;
|
|
||||||
checkStack(stackSize);
|
checkStack(stackSize);
|
||||||
stack[stackSize] = type;
|
stack[stackSize++] = type;
|
||||||
this.stackSize = stackSize + 1;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame pushStack(Type type1, Type type2) {
|
Frame pushStack(Type type1, Type type2) {
|
||||||
int stackSize = this.stackSize;
|
|
||||||
checkStack(stackSize + 1);
|
checkStack(stackSize + 1);
|
||||||
stack[stackSize] = type1;
|
stack[stackSize++] = type1;
|
||||||
stack[stackSize + 1] = type2;
|
stack[stackSize++] = type2;
|
||||||
this.stackSize = stackSize + 2;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type popStack() {
|
Type popStack() {
|
||||||
int stackSize = this.stackSize - 1;
|
if (stackSize < 1) throw generatorError("Operand stack underflow");
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
return stack[--stackSize];
|
||||||
this.stackSize = stackSize;
|
|
||||||
return stack[stackSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame decStack() {
|
|
||||||
if (--stackSize < 0) throw stackUnderflow();
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame decStack(int size) {
|
Frame decStack(int size) {
|
||||||
stackSize -= size;
|
stackSize -= size;
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
if (stackSize < 0) throw generatorError("Operand stack underflow");
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame decStack1PushStack(Type type1, Type type2) {
|
|
||||||
int stackSize = this.stackSize - 1;
|
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
|
||||||
checkStack(stackSize + 2);
|
|
||||||
stack[stackSize ] = type1;
|
|
||||||
stack[stackSize + 1] = type2;
|
|
||||||
this.stackSize = stackSize + 2;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame decStack1PushStack(Type type) {
|
|
||||||
int stackSize = this.stackSize - 1;
|
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
|
||||||
stack[stackSize] = type;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame decStack2PushStack(Type type) {
|
|
||||||
int stackSize = this.stackSize - 2;
|
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
|
||||||
stack[stackSize] = type;
|
|
||||||
this.stackSize = stackSize + 1;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame decStack2PushStack(Type type1, Type type2) {
|
|
||||||
int stackSize = this.stackSize - 2;
|
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
|
||||||
var stack = this.stack;
|
|
||||||
stack[stackSize ] = type1;
|
|
||||||
stack[stackSize + 1] = type2;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame decStack3PushStack(Type type1, Type type2) {
|
|
||||||
int stackSize = this.stackSize - 3;
|
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
|
||||||
stack[stackSize ] = type1;
|
|
||||||
stack[stackSize + 1] = type2;
|
|
||||||
this.stackSize = stackSize + 2;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame decStack4PushStack(Type type) {
|
|
||||||
int stackSize = this.stackSize - 4;
|
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
|
||||||
stack[stackSize] = type;
|
|
||||||
this.stackSize = stackSize + 1;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame decStack4PushStack(Type type1, Type type2) {
|
|
||||||
int stackSize = this.stackSize - 4;
|
|
||||||
if (stackSize < 0) throw stackUnderflow();
|
|
||||||
var stack = this.stack;
|
|
||||||
stack[stackSize ] = type1;
|
|
||||||
stack[stackSize + 1] = type2;
|
|
||||||
this.stackSize = stackSize + 2;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1194,59 +1027,34 @@ public final class StackMapGenerator {
|
||||||
Frame checkLocal(int index) {
|
Frame checkLocal(int index) {
|
||||||
if (index >= frameMaxLocals) frameMaxLocals = index + 1;
|
if (index >= frameMaxLocals) frameMaxLocals = index + 1;
|
||||||
if (locals == null) {
|
if (locals == null) {
|
||||||
initLocals(index);
|
|
||||||
} else if (index >= locals.length) {
|
|
||||||
growLocals(index);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initLocals(int index) {
|
|
||||||
locals = new Type[index + FRAME_DEFAULT_CAPACITY];
|
locals = new Type[index + FRAME_DEFAULT_CAPACITY];
|
||||||
Arrays.fill(locals, Type.TOP_TYPE);
|
Arrays.fill(locals, Type.TOP_TYPE);
|
||||||
}
|
} else if (index >= locals.length) {
|
||||||
|
|
||||||
private void growLocals(int index) {
|
|
||||||
int current = locals.length;
|
int current = locals.length;
|
||||||
locals = Arrays.copyOf(locals, index + FRAME_DEFAULT_CAPACITY);
|
locals = Arrays.copyOf(locals, index + FRAME_DEFAULT_CAPACITY);
|
||||||
Arrays.fill(locals, current, locals.length, Type.TOP_TYPE);
|
Arrays.fill(locals, current, locals.length, Type.TOP_TYPE);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private void checkStack(int index) {
|
private void checkStack(int index) {
|
||||||
if (index >= frameMaxStack) frameMaxStack = index + 1;
|
if (index >= frameMaxStack) frameMaxStack = index + 1;
|
||||||
if (stack == null) {
|
if (stack == null) {
|
||||||
initStack(index);
|
|
||||||
} else if (index >= stack.length) {
|
|
||||||
growStack(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initStack(int index) {
|
|
||||||
stack = new Type[index + FRAME_DEFAULT_CAPACITY];
|
stack = new Type[index + FRAME_DEFAULT_CAPACITY];
|
||||||
Arrays.fill(stack, Type.TOP_TYPE);
|
Arrays.fill(stack, Type.TOP_TYPE);
|
||||||
}
|
} else if (index >= stack.length) {
|
||||||
|
|
||||||
private void growStack(int index) {
|
|
||||||
int current = stack.length;
|
int current = stack.length;
|
||||||
stack = Arrays.copyOf(stack, index + FRAME_DEFAULT_CAPACITY);
|
stack = Arrays.copyOf(stack, index + FRAME_DEFAULT_CAPACITY);
|
||||||
Arrays.fill(stack, current, stack.length, Type.TOP_TYPE);
|
Arrays.fill(stack, current, stack.length, Type.TOP_TYPE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setLocalRawInternal(int index, Type type) {
|
private void setLocalRawInternal(int index, Type type) {
|
||||||
checkLocal(index);
|
checkLocal(index);
|
||||||
var locals = this.locals;
|
|
||||||
localsChanged |= !type.equals(locals[index]);
|
localsChanged |= !type.equals(locals[index]);
|
||||||
locals[index] = type;
|
locals[index] = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLocalRawInternal(int index, Type type1, Type type2) {
|
|
||||||
checkLocal(index + 1);
|
|
||||||
var locals = this.locals;
|
|
||||||
localsChanged |= !type1.equals(locals[index]) || !type2.equals(locals[index + 1]);
|
|
||||||
locals[index ] = type1;
|
|
||||||
locals[index + 1] = type2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLocalsFromArg(String name, MethodTypeDesc methodDesc, boolean isStatic, Type thisKlass) {
|
void setLocalsFromArg(String name, MethodTypeDesc methodDesc, boolean isStatic, Type thisKlass) {
|
||||||
int localsSize = 0;
|
int localsSize = 0;
|
||||||
// Pre-emptively create a locals array that encompass all parameter slots
|
// Pre-emptively create a locals array that encompass all parameter slots
|
||||||
|
@ -1347,7 +1155,8 @@ public final class StackMapGenerator {
|
||||||
Type old = getLocalRawInternal(index);
|
Type old = getLocalRawInternal(index);
|
||||||
if (old == Type.DOUBLE_TYPE || old == Type.LONG_TYPE) {
|
if (old == Type.DOUBLE_TYPE || old == Type.LONG_TYPE) {
|
||||||
setLocalRawInternal(index + 1, Type.TOP_TYPE);
|
setLocalRawInternal(index + 1, Type.TOP_TYPE);
|
||||||
} else if (old == Type.DOUBLE2_TYPE || old == Type.LONG2_TYPE) {
|
}
|
||||||
|
if (old == Type.DOUBLE2_TYPE || old == Type.LONG2_TYPE) {
|
||||||
setLocalRawInternal(index - 1, Type.TOP_TYPE);
|
setLocalRawInternal(index - 1, Type.TOP_TYPE);
|
||||||
}
|
}
|
||||||
setLocalRawInternal(index, type);
|
setLocalRawInternal(index, type);
|
||||||
|
@ -1365,7 +1174,8 @@ public final class StackMapGenerator {
|
||||||
if (old == Type.DOUBLE2_TYPE || old == Type.LONG2_TYPE) {
|
if (old == Type.DOUBLE2_TYPE || old == Type.LONG2_TYPE) {
|
||||||
setLocalRawInternal(index - 1, Type.TOP_TYPE);
|
setLocalRawInternal(index - 1, Type.TOP_TYPE);
|
||||||
}
|
}
|
||||||
setLocalRawInternal(index, type1, type2);
|
setLocalRawInternal(index, type1);
|
||||||
|
setLocalRawInternal(index + 1, type2);
|
||||||
if (index >= localsSize - 1) {
|
if (index >= localsSize - 1) {
|
||||||
localsSize = index + 2;
|
localsSize = index + 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @summary Testing Classfile stack maps generator.
|
* @summary Testing Classfile stack maps generator.
|
||||||
* @bug 8305990 8320222 8320618 8335475 8338623 8338661
|
* @bug 8305990 8320222 8320618 8335475 8338623 8338661 8343436
|
||||||
* @build testdata.*
|
* @build testdata.*
|
||||||
* @run junit StackMapsTest
|
* @run junit StackMapsTest
|
||||||
*/
|
*/
|
||||||
|
@ -344,8 +344,27 @@ class StackMapsTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(ClassFile.StackMapsOption.class)
|
||||||
|
void testI2LCounters(ClassFile.StackMapsOption option) {
|
||||||
|
var cf = ClassFile.of(option);
|
||||||
|
var bytes = cf.build(ClassDesc.of("Test"), clb -> clb
|
||||||
|
.withMethodBody("a", MTD_long_int, ACC_STATIC, cob ->
|
||||||
|
cob.iload(0)
|
||||||
|
.i2l()
|
||||||
|
.lreturn()));
|
||||||
|
|
||||||
|
var cm = ClassFile.of().parse(bytes);
|
||||||
|
for (var method : cm.methods()) {
|
||||||
|
var code = (CodeAttribute) method.code().orElseThrow();
|
||||||
|
assertEquals(1, code.maxLocals());
|
||||||
|
assertEquals(2, code.maxStack());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final MethodTypeDesc MTD_int = MethodTypeDesc.of(CD_int);
|
private static final MethodTypeDesc MTD_int = MethodTypeDesc.of(CD_int);
|
||||||
private static final MethodTypeDesc MTD_int_String = MethodTypeDesc.of(CD_int, CD_String);
|
private static final MethodTypeDesc MTD_int_String = MethodTypeDesc.of(CD_int, CD_String);
|
||||||
|
private static final MethodTypeDesc MTD_long_int = MethodTypeDesc.of(CD_long, CD_int);
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@EnumSource(ClassFile.StackMapsOption.class)
|
@EnumSource(ClassFile.StackMapsOption.class)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue