8337225: Demote maxStack and maxLocals from CodeModel to CodeAttribute

Reviewed-by: asotona
This commit is contained in:
Chen Liang 2024-07-29 21:58:08 +00:00
parent bd36b6ae5d
commit ab27090aa0
13 changed files with 166 additions and 88 deletions

View file

@ -43,17 +43,7 @@ import jdk.internal.javac.PreviewFeature;
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface CodeModel
extends CompoundElement<CodeElement>, AttributedElement, MethodElement
permits CodeAttribute, BufferedCodeBuilder.Model, CodeImpl {
/**
* {@return the maximum size of the local variable table}
*/
int maxLocals();
/**
* {@return the maximum size of the operand stack}
*/
int maxStack();
permits CodeAttribute, BufferedCodeBuilder.Model {
/**
* {@return the enclosing method, if known}

View file

@ -47,6 +47,16 @@ import jdk.internal.javac.PreviewFeature;
public sealed interface CodeAttribute extends Attribute<CodeAttribute>, CodeModel
permits BoundAttribute.BoundCodeAttribute {
/**
* {@return the maximum size of the local variable table}
*/
int maxLocals();
/**
* {@return the maximum size of the operand stack}
*/
int maxStack();
/**
* {@return The length of the code array in bytes}
*/

View file

@ -35,7 +35,7 @@ import java.lang.classfile.CompoundElement;
public abstract sealed class AbstractUnboundModel<E extends ClassFileElement>
extends AbstractElement
implements CompoundElement<E>, AttributedElement, Util.Writable
implements CompoundElement<E>, AttributedElement
permits BufferedCodeBuilder.Model, BufferedFieldBuilder.Model, BufferedMethodBuilder.Model {
private final List<E> elements;
private List<Attribute<?>> attributes;
@ -63,8 +63,11 @@ public abstract sealed class AbstractUnboundModel<E extends ClassFileElement>
public List<Attribute<?>> attributes() {
if (attributes == null)
attributes = elements.stream()
.filter(e -> e instanceof Attribute)
.<Attribute<?>>map(e -> (Attribute<?>) e)
.<Attribute<?>>mapMulti((e, sink) -> {
if (e instanceof Attribute<?> attr) {
sink.accept(attr);
}
})
.toList();
return attributes;
}

View file

@ -32,9 +32,6 @@ import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.Label;
import java.lang.classfile.MethodModel;
import java.lang.classfile.instruction.ExceptionCatch;
import java.lang.classfile.instruction.IncrementInstruction;
import java.lang.classfile.instruction.LoadInstruction;
import java.lang.classfile.instruction.StoreInstruction;
import java.util.ArrayList;
import java.util.List;
@ -47,7 +44,6 @@ public final class BufferedCodeBuilder
private final ClassFileImpl context;
private final List<CodeElement> elements = new ArrayList<>();
private final LabelImpl startLabel, endLabel;
private final CodeModel original;
private final MethodInfo methodInfo;
private boolean finished;
private int maxLocals;
@ -60,12 +56,8 @@ public final class BufferedCodeBuilder
this.context = context;
this.startLabel = new LabelImpl(this, -1);
this.endLabel = new LabelImpl(this, -1);
this.original = original;
this.methodInfo = methodInfo;
this.maxLocals = Util.maxLocals(methodInfo.methodFlags(), methodInfo.methodTypeSymbol());
if (original != null)
this.maxLocals = Math.max(this.maxLocals, original.maxLocals());
this.maxLocals = TerminalCodeBuilder.setupTopLocal(methodInfo, original);
elements.add(startLabel);
}
@ -162,27 +154,16 @@ public final class BufferedCodeBuilder
@Override
public List<ExceptionCatch> exceptionHandlers() {
return elements.stream()
.filter(x -> x instanceof ExceptionCatch)
.map(x -> (ExceptionCatch) x)
.<ExceptionCatch>mapMulti((x, sink) -> {
if (x instanceof ExceptionCatch ec) {
sink.accept(ec);
}
})
.toList();
}
@Override
public int maxLocals() {
for (CodeElement element : elements) {
if (element instanceof LoadInstruction i)
maxLocals = Math.max(maxLocals, i.slot() + i.typeKind().slotSize());
else if (element instanceof StoreInstruction i)
maxLocals = Math.max(maxLocals, i.slot() + i.typeKind().slotSize());
else if (element instanceof IncrementInstruction i)
maxLocals = Math.max(maxLocals, i.slot() + 1);
}
return maxLocals;
}
@Override
public int maxStack() {
throw new UnsupportedOperationException("nyi");
int curTopLocal() {
return BufferedCodeBuilder.this.curTopLocal();
}
@Override
@ -200,11 +181,6 @@ public final class BufferedCodeBuilder
});
}
@Override
public void writeTo(BufWriterImpl buf) {
DirectCodeBuilder.build(methodInfo, cb -> elements.forEach(cb), constantPool, context, null).writeTo(buf);
}
@Override
public String toString() {
return String.format("CodeModel[id=%s]", Integer.toHexString(System.identityHashCode(this)));

View file

@ -103,7 +103,7 @@ public final class BufferedFieldBuilder
@Override
public void writeTo(DirectClassBuilder builder) {
builder.withField(name, desc, new Consumer<FieldBuilder>() {
builder.withField(name, desc, new Consumer<>() {
@Override
public void accept(FieldBuilder fieldBuilder) {
elements.forEach(fieldBuilder);
@ -111,13 +111,6 @@ public final class BufferedFieldBuilder
});
}
@Override
public void writeTo(BufWriterImpl buf) {
DirectFieldBuilder fb = new DirectFieldBuilder(constantPool, context, name, desc, null);
elements.forEach(fb);
fb.writeTo(buf);
}
@Override
public String toString() {
return String.format("FieldModel[fieldName=%s, fieldType=%s, flags=%d]", name.stringValue(), desc.stringValue(), flags.flagsMask());

View file

@ -196,7 +196,11 @@ public final class BufferedMethodBuilder
@Override
public Optional<CodeModel> code() {
throw new UnsupportedOperationException("nyi");
return elements.stream().<CodeModel>mapMulti((e, sink) -> {
if (e instanceof CodeModel cm) {
sink.accept(cm);
}
}).findFirst();
}
@Override
@ -209,13 +213,6 @@ public final class BufferedMethodBuilder
});
}
@Override
public void writeTo(BufWriterImpl buf) {
DirectMethodBuilder mb = new DirectMethodBuilder(constantPool, context, name, desc, methodFlags(), null);
elements.forEach(mb);
mb.writeTo(buf);
}
@Override
public String toString() {
return String.format("MethodModel[methodName=%s, methodType=%s, flags=%d]",

View file

@ -43,7 +43,7 @@ import static java.lang.classfile.ClassFile.*;
public final class CodeImpl
extends BoundAttribute.BoundCodeAttribute
implements CodeModel, LabelContext {
implements LabelContext {
static final Instruction[] SINGLETON_INSTRUCTIONS = new Instruction[256];

View file

@ -127,12 +127,10 @@ public final class DirectCodeBuilder
this.transformFwdJumps = transformFwdJumps;
this.transformBackJumps = context.shortJumpsOption() == ClassFile.ShortJumpsOption.FIX_SHORT_JUMPS;
bytecodesBufWriter = (original instanceof CodeImpl cai) ? new BufWriterImpl(constantPool, context, cai.codeLength())
: new BufWriterImpl(constantPool, context);
: new BufWriterImpl(constantPool, context);
this.startLabel = new LabelImpl(this, 0);
this.endLabel = new LabelImpl(this, -1);
this.topLocal = Util.maxLocals(methodInfo.methodFlags(), methodInfo.methodTypeSymbol());
if (original != null)
this.topLocal = Math.max(this.topLocal, original.maxLocals());
this.topLocal = TerminalCodeBuilder.setupTopLocal(methodInfo, original);
}
@Override
@ -312,8 +310,9 @@ public final class DirectCodeBuilder
private void writeCounters(boolean codeMatch, BufWriterImpl buf) {
if (codeMatch) {
buf.writeU2(original.maxStack());
buf.writeU2(original.maxLocals());
var originalAttribute = (CodeImpl) original;
buf.writeU2(originalAttribute.maxStack());
buf.writeU2(originalAttribute.maxLocals());
} else {
StackCounter cntr = StackCounter.of(DirectCodeBuilder.this, buf);
buf.writeU2(cntr.maxStack());

View file

@ -25,8 +25,24 @@
package jdk.internal.classfile.impl;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeModel;
import java.lang.classfile.attribute.CodeAttribute;
public sealed interface TerminalCodeBuilder extends CodeBuilder, LabelContext
permits DirectCodeBuilder, BufferedCodeBuilder {
int curTopLocal();
static int setupTopLocal(MethodInfo methodInfo, CodeModel original) {
int paramSlots = Util.maxLocals(methodInfo.methodFlags(), methodInfo.methodTypeSymbol());
if (original == null) {
return paramSlots;
}
if (original instanceof CodeAttribute attr) {
return Math.max(paramSlots, attr.maxLocals());
}
if (original instanceof BufferedCodeBuilder.Model buffered) {
return Math.max(paramSlots, buffered.curTopLocal());
}
throw new InternalError("Unknown code model " + original);
}
}