8343436: Regression in StackMapGenerator after JDK-8339205

Reviewed-by: liach
This commit is contained in:
Adam Sotona 2024-11-04 07:19:23 +00:00
parent 2432c4f862
commit f9e1c62dcd
2 changed files with 131 additions and 302 deletions

View File

@ -349,7 +349,6 @@ public final class StackMapGenerator {
var it = handlers.listIterator();
while (it.hasNext()) {
var e = it.next();
var labelContext = this.labelContext;
int handlerStart = labelContext.labelToBci(e.tryStart());
int handlerEnd = labelContext.labelToBci(e.tryEnd());
if (rangeStart >= handlerEnd || rangeEnd <= handlerStart) {
@ -391,15 +390,14 @@ public final class StackMapGenerator {
return framesCount == 0 ? null : new UnboundAttribute.AdHocAttribute<>(Attributes.stackMapTable()) {
@Override
public void writeBody(BufWriterImpl b) {
var gen = StackMapGenerator.this;
b.writeU2(gen.framesCount);
Frame prevFrame = gen.new Frame(gen.classHierarchy);
prevFrame.setLocalsFromArg(gen.methodName, gen.methodDesc, gen.isStatic, gen.thisType);
b.writeU2(framesCount);
Frame prevFrame = new Frame(classHierarchy);
prevFrame.setLocalsFromArg(methodName, methodDesc, isStatic, thisType);
prevFrame.trimAndCompress();
for (int i = 0; i < gen.framesCount; i++) {
var fr = gen.frames[i];
for (int i = 0; i < framesCount; i++) {
var fr = frames[i];
fr.trimAndCompress();
fr.writeTo(b, prevFrame, gen.cp);
fr.writeTo(b, prevFrame, cp);
prevFrame = fr;
}
}
@ -462,7 +460,6 @@ public final class StackMapGenerator {
processExceptionHandlerTargets(bci, this_uninit);
verified_exc_handlers = true;
}
var currentFrame = this.currentFrame;
switch (opcode) {
case NOP -> {}
case RETURN -> {
@ -503,27 +500,27 @@ public final class StackMapGenerator {
case ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3 ->
currentFrame.pushStack(currentFrame.getLocal(opcode - ALOAD_0));
case IALOAD, BALOAD, CALOAD, SALOAD ->
currentFrame.decStack2PushStack(Type.INTEGER_TYPE);
currentFrame.decStack(2).pushStack(Type.INTEGER_TYPE);
case LALOAD ->
currentFrame.decStack2PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
currentFrame.decStack(2).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
case FALOAD ->
currentFrame.decStack2PushStack(Type.FLOAT_TYPE);
currentFrame.decStack(2).pushStack(Type.FLOAT_TYPE);
case DALOAD ->
currentFrame.decStack2PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
currentFrame.decStack(2).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
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 ->
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 ->
currentFrame.decStack().setLocal(opcode - ISTORE_0, Type.INTEGER_TYPE);
currentFrame.decStack(1).setLocal(opcode - ISTORE_0, Type.INTEGER_TYPE);
case LSTORE ->
currentFrame.decStack(2).setLocal2(bcs.getIndex(), Type.LONG_TYPE, Type.LONG2_TYPE);
case LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3 ->
currentFrame.decStack(2).setLocal2(opcode - LSTORE_0, Type.LONG_TYPE, Type.LONG2_TYPE);
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 ->
currentFrame.decStack().setLocal(opcode - FSTORE_0, Type.FLOAT_TYPE);
currentFrame.decStack(1).setLocal(opcode - FSTORE_0, Type.FLOAT_TYPE);
case DSTORE ->
currentFrame.decStack(2).setLocal2(bcs.getIndex(), Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
case DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3 ->
@ -537,75 +534,98 @@ public final class StackMapGenerator {
case IASTORE, BASTORE, CASTORE, SASTORE, FASTORE, AASTORE ->
currentFrame.decStack(3);
case POP, MONITORENTER, MONITOREXIT ->
currentFrame.decStack();
currentFrame.decStack(1);
case POP2 ->
currentFrame.decStack(2);
case DUP ->
currentFrame.dup();
case DUP_X1 ->
currentFrame.dup_x1();
case DUP_X2 ->
currentFrame.dup_x2();
case DUP2 ->
currentFrame.dup2();
case DUP2_X1 ->
currentFrame.dup2_x1();
case DUP2_X2 ->
currentFrame.dup2_x2();
case SWAP ->
currentFrame.swap();
currentFrame.pushStack(type1 = currentFrame.popStack()).pushStack(type1);
case DUP_X1 -> {
type1 = currentFrame.popStack();
type2 = currentFrame.popStack();
currentFrame.pushStack(type1).pushStack(type2).pushStack(type1);
}
case DUP_X2 -> {
type1 = currentFrame.popStack();
type2 = currentFrame.popStack();
type3 = currentFrame.popStack();
currentFrame.pushStack(type1).pushStack(type3).pushStack(type2).pushStack(type1);
}
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 ->
currentFrame.decStack2PushStack(Type.INTEGER_TYPE);
currentFrame.decStack(2).pushStack(Type.INTEGER_TYPE);
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 ->
currentFrame.decStack4PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
currentFrame.decStack(4).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
case LNEG ->
currentFrame.decStack2PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
currentFrame.decStack(2).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
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 ->
currentFrame.decStack2PushStack(Type.FLOAT_TYPE);
currentFrame.decStack(2).pushStack(Type.FLOAT_TYPE);
case FNEG ->
currentFrame.decStack1PushStack(Type.FLOAT_TYPE);
currentFrame.decStack(1).pushStack(Type.FLOAT_TYPE);
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 ->
currentFrame.decStack2PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
currentFrame.decStack(2).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
case IINC ->
currentFrame.checkLocal(bcs.getIndex());
case I2L ->
currentFrame.decStack1PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
currentFrame.decStack(1).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
case L2I ->
currentFrame.decStack2PushStack(Type.INTEGER_TYPE);
currentFrame.decStack(2).pushStack(Type.INTEGER_TYPE);
case I2F ->
currentFrame.decStack1PushStack(Type.FLOAT_TYPE);
currentFrame.decStack(1).pushStack(Type.FLOAT_TYPE);
case I2D ->
currentFrame.decStack1PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
currentFrame.decStack(1).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
case L2F ->
currentFrame.decStack2PushStack(Type.FLOAT_TYPE);
currentFrame.decStack(2).pushStack(Type.FLOAT_TYPE);
case L2D ->
currentFrame.decStack2PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
currentFrame.decStack(2).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
case F2I ->
currentFrame.decStack1PushStack(Type.INTEGER_TYPE);
currentFrame.decStack(1).pushStack(Type.INTEGER_TYPE);
case F2L ->
currentFrame.decStack1PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
currentFrame.decStack(1).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
case F2D ->
currentFrame.decStack1PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
currentFrame.decStack(1).pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
case D2L ->
currentFrame.decStack2PushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
currentFrame.decStack(2).pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
case D2F ->
currentFrame.decStack2PushStack(Type.FLOAT_TYPE);
currentFrame.decStack(2).pushStack(Type.FLOAT_TYPE);
case I2B, I2C, I2S ->
currentFrame.decStack1PushStack(Type.INTEGER_TYPE);
currentFrame.decStack(1).pushStack(Type.INTEGER_TYPE);
case LCMP, DCMPL, DCMPG ->
currentFrame.decStack4PushStack(Type.INTEGER_TYPE);
currentFrame.decStack(4).pushStack(Type.INTEGER_TYPE);
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 ->
checkJumpTarget(currentFrame.decStack(2), bcs.dest());
case IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IFNULL, IFNONNULL ->
checkJumpTarget(currentFrame.decStack(), bcs.dest());
checkJumpTarget(currentFrame.decStack(1), bcs.dest());
case GOTO -> {
checkJumpTarget(currentFrame, bcs.dest());
ncf = true;
@ -623,7 +643,7 @@ public final class StackMapGenerator {
ncf = true;
}
case IRETURN, FRETURN, ARETURN, ATHROW -> {
currentFrame.decStack();
currentFrame.decStack(1);
ncf = true;
}
case GETSTATIC, PUTSTATIC, GETFIELD, PUTFIELD ->
@ -633,16 +653,17 @@ public final class StackMapGenerator {
case NEW ->
currentFrame.pushStack(Type.uninitializedType(bci));
case NEWARRAY ->
currentFrame.decStack1PushStack(getNewarrayType(bcs.getIndex()));
currentFrame.decStack(1).pushStack(getNewarrayType(bcs.getIndex()));
case ANEWARRAY ->
processAnewarray(bcs.getIndexU2());
case CHECKCAST ->
currentFrame.decStack1PushStack(cpIndexToType(bcs.getIndexU2(), cp));
currentFrame.decStack(1).pushStack(cpIndexToType(bcs.getIndexU2(), cp));
case MULTIANEWARRAY -> {
type1 = cpIndexToType(bcs.getIndexU2(), cp);
currentFrame.decStack(
bcs.getU1Unchecked(bcs.bci() + 3) /* dim */
);
int dim = bcs.getU1Unchecked(bcs.bci() + 3);
for (int i = 0; i < dim; i++) {
currentFrame.popStack();
}
currentFrame.pushStack(type1);
}
case JSR, JSR_W, RET ->
@ -657,7 +678,6 @@ public final class StackMapGenerator {
}
private void processExceptionHandlerTargets(int bci, boolean this_uninit) {
var currentFrame = this.currentFrame;
for (var ex : rawHandlers) {
if (bci == ex.start || (currentFrame.localsChanged && bci > ex.start && bci < ex.end)) {
int flags = currentFrame.flags;
@ -670,10 +690,7 @@ public final class StackMapGenerator {
}
private void processLdc(int index) {
var e = cp.entryByIndex(index);
byte tag = e.tag();
var currentFrame = this.currentFrame;
switch (tag) {
switch (cp.entryByIndex(index).tag()) {
case TAG_UTF8 ->
currentFrame.pushStack(Type.OBJECT_TYPE);
case TAG_STRING ->
@ -693,9 +710,9 @@ public final class StackMapGenerator {
case TAG_METHOD_TYPE ->
currentFrame.pushStack(Type.METHOD_TYPE);
case TAG_DYNAMIC ->
currentFrame.pushStack(ClassReaderImpl.checkType(e, index, ConstantDynamicEntry.class).asSymbol().constantType());
currentFrame.pushStack(cp.entryByIndex(index, ConstantDynamicEntry.class).asSymbol().constantType());
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 defaultOffset = bcs.getIntUnchecked(alignedBci);
int keys, delta;
currentFrame.decStack();
currentFrame.popStack();
if (bcs.opcode() == TABLESWITCH) {
int low = bcs.getIntUnchecked(alignedBci + 4);
int high = bcs.getIntUnchecked(alignedBci + 2 * 4);
@ -748,7 +765,8 @@ public final class StackMapGenerator {
currentFrame.decStack(Util.isDoubleSlot(desc) ? 2 : 1);
}
case GETFIELD -> {
currentFrame.dec1PushStack(desc);
currentFrame.decStack(1);
currentFrame.pushStack(desc);
}
case PUTFIELD -> {
currentFrame.decStack(Util.isDoubleSlot(desc) ? 3 : 2);
@ -786,7 +804,7 @@ public final class StackMapGenerator {
throw generatorError("Bad operand type when invoking <init>");
}
} else {
currentFrame.decStack();
currentFrame.decStack(1);
}
}
currentFrame.pushStack(mDesc.returnType());
@ -799,17 +817,10 @@ public final class StackMapGenerator {
}
private void processAnewarray(int index) {
currentFrame.decStack();
currentFrame.popStack();
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}
* @param msg error message
@ -889,7 +900,6 @@ public final class StackMapGenerator {
} catch (IllegalArgumentException iae) {
throw generatorError("Detected branch target out of bytecode range", bci);
}
for (int i = 0; i < rawHandlers.size(); i++) try {
addFrame(rawHandlers.get(i).handler());
} 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));
}
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) {
if (desc == CD_long) return pushStack(Type.LONG_TYPE, Type.LONG2_TYPE);
if (desc == CD_double) return pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
@ -1063,109 +978,27 @@ public final class StackMapGenerator {
: 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) {
int stackSize = this.stackSize;
checkStack(stackSize);
stack[stackSize] = type;
this.stackSize = stackSize + 1;
stack[stackSize++] = type;
return this;
}
Frame pushStack(Type type1, Type type2) {
int stackSize = this.stackSize;
checkStack(stackSize + 1);
stack[stackSize] = type1;
stack[stackSize + 1] = type2;
this.stackSize = stackSize + 2;
stack[stackSize++] = type1;
stack[stackSize++] = type2;
return this;
}
Type popStack() {
int stackSize = this.stackSize - 1;
if (stackSize < 0) throw stackUnderflow();
this.stackSize = stackSize;
return stack[stackSize];
}
Frame decStack() {
if (--stackSize < 0) throw stackUnderflow();
return this;
if (stackSize < 1) throw generatorError("Operand stack underflow");
return stack[--stackSize];
}
Frame decStack(int size) {
stackSize -= size;
if (stackSize < 0) throw stackUnderflow();
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;
if (stackSize < 0) throw generatorError("Operand stack underflow");
return this;
}
@ -1194,59 +1027,34 @@ public final class StackMapGenerator {
Frame checkLocal(int index) {
if (index >= frameMaxLocals) frameMaxLocals = index + 1;
if (locals == null) {
initLocals(index);
locals = new Type[index + FRAME_DEFAULT_CAPACITY];
Arrays.fill(locals, Type.TOP_TYPE);
} else if (index >= locals.length) {
growLocals(index);
int current = locals.length;
locals = Arrays.copyOf(locals, index + FRAME_DEFAULT_CAPACITY);
Arrays.fill(locals, current, locals.length, Type.TOP_TYPE);
}
return this;
}
private void initLocals(int index) {
locals = new Type[index + FRAME_DEFAULT_CAPACITY];
Arrays.fill(locals, Type.TOP_TYPE);
}
private void growLocals(int index) {
int current = locals.length;
locals = Arrays.copyOf(locals, index + FRAME_DEFAULT_CAPACITY);
Arrays.fill(locals, current, locals.length, Type.TOP_TYPE);
}
private void checkStack(int index) {
if (index >= frameMaxStack) frameMaxStack = index + 1;
if (stack == null) {
initStack(index);
stack = new Type[index + FRAME_DEFAULT_CAPACITY];
Arrays.fill(stack, Type.TOP_TYPE);
} else if (index >= stack.length) {
growStack(index);
int current = stack.length;
stack = Arrays.copyOf(stack, index + FRAME_DEFAULT_CAPACITY);
Arrays.fill(stack, current, stack.length, Type.TOP_TYPE);
}
}
private void initStack(int index) {
stack = new Type[index + FRAME_DEFAULT_CAPACITY];
Arrays.fill(stack, Type.TOP_TYPE);
}
private void growStack(int index) {
int current = stack.length;
stack = Arrays.copyOf(stack, index + FRAME_DEFAULT_CAPACITY);
Arrays.fill(stack, current, stack.length, Type.TOP_TYPE);
}
private void setLocalRawInternal(int index, Type type) {
checkLocal(index);
var locals = this.locals;
localsChanged |= !type.equals(locals[index]);
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) {
int localsSize = 0;
// Pre-emptively create a locals array that encompass all parameter slots
@ -1347,7 +1155,8 @@ public final class StackMapGenerator {
Type old = getLocalRawInternal(index);
if (old == Type.DOUBLE_TYPE || old == Type.LONG_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, type);
@ -1365,7 +1174,8 @@ public final class StackMapGenerator {
if (old == Type.DOUBLE2_TYPE || old == Type.LONG2_TYPE) {
setLocalRawInternal(index - 1, Type.TOP_TYPE);
}
setLocalRawInternal(index, type1, type2);
setLocalRawInternal(index, type1);
setLocalRawInternal(index + 1, type2);
if (index >= localsSize - 1) {
localsSize = index + 2;
}

View File

@ -24,7 +24,7 @@
/*
* @test
* @summary Testing Classfile stack maps generator.
* @bug 8305990 8320222 8320618 8335475 8338623 8338661
* @bug 8305990 8320222 8320618 8335475 8338623 8338661 8343436
* @build testdata.*
* @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_String = MethodTypeDesc.of(CD_int, CD_String);
private static final MethodTypeDesc MTD_long_int = MethodTypeDesc.of(CD_long, CD_int);
@ParameterizedTest
@EnumSource(ClassFile.StackMapsOption.class)