mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-15 08:34:30 +02:00
8337225: Demote maxStack and maxLocals from CodeModel to CodeAttribute
Reviewed-by: asotona
This commit is contained in:
parent
bd36b6ae5d
commit
ab27090aa0
13 changed files with 166 additions and 88 deletions
|
@ -43,17 +43,7 @@ import jdk.internal.javac.PreviewFeature;
|
||||||
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
|
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
|
||||||
public sealed interface CodeModel
|
public sealed interface CodeModel
|
||||||
extends CompoundElement<CodeElement>, AttributedElement, MethodElement
|
extends CompoundElement<CodeElement>, AttributedElement, MethodElement
|
||||||
permits CodeAttribute, BufferedCodeBuilder.Model, CodeImpl {
|
permits CodeAttribute, BufferedCodeBuilder.Model {
|
||||||
|
|
||||||
/**
|
|
||||||
* {@return the maximum size of the local variable table}
|
|
||||||
*/
|
|
||||||
int maxLocals();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@return the maximum size of the operand stack}
|
|
||||||
*/
|
|
||||||
int maxStack();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@return the enclosing method, if known}
|
* {@return the enclosing method, if known}
|
||||||
|
|
|
@ -47,6 +47,16 @@ import jdk.internal.javac.PreviewFeature;
|
||||||
public sealed interface CodeAttribute extends Attribute<CodeAttribute>, CodeModel
|
public sealed interface CodeAttribute extends Attribute<CodeAttribute>, CodeModel
|
||||||
permits BoundAttribute.BoundCodeAttribute {
|
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}
|
* {@return The length of the code array in bytes}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -35,7 +35,7 @@ import java.lang.classfile.CompoundElement;
|
||||||
|
|
||||||
public abstract sealed class AbstractUnboundModel<E extends ClassFileElement>
|
public abstract sealed class AbstractUnboundModel<E extends ClassFileElement>
|
||||||
extends AbstractElement
|
extends AbstractElement
|
||||||
implements CompoundElement<E>, AttributedElement, Util.Writable
|
implements CompoundElement<E>, AttributedElement
|
||||||
permits BufferedCodeBuilder.Model, BufferedFieldBuilder.Model, BufferedMethodBuilder.Model {
|
permits BufferedCodeBuilder.Model, BufferedFieldBuilder.Model, BufferedMethodBuilder.Model {
|
||||||
private final List<E> elements;
|
private final List<E> elements;
|
||||||
private List<Attribute<?>> attributes;
|
private List<Attribute<?>> attributes;
|
||||||
|
@ -63,8 +63,11 @@ public abstract sealed class AbstractUnboundModel<E extends ClassFileElement>
|
||||||
public List<Attribute<?>> attributes() {
|
public List<Attribute<?>> attributes() {
|
||||||
if (attributes == null)
|
if (attributes == null)
|
||||||
attributes = elements.stream()
|
attributes = elements.stream()
|
||||||
.filter(e -> e instanceof Attribute)
|
.<Attribute<?>>mapMulti((e, sink) -> {
|
||||||
.<Attribute<?>>map(e -> (Attribute<?>) e)
|
if (e instanceof Attribute<?> attr) {
|
||||||
|
sink.accept(attr);
|
||||||
|
}
|
||||||
|
})
|
||||||
.toList();
|
.toList();
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,6 @@ import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||||
import java.lang.classfile.Label;
|
import java.lang.classfile.Label;
|
||||||
import java.lang.classfile.MethodModel;
|
import java.lang.classfile.MethodModel;
|
||||||
import java.lang.classfile.instruction.ExceptionCatch;
|
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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -47,7 +44,6 @@ public final class BufferedCodeBuilder
|
||||||
private final ClassFileImpl context;
|
private final ClassFileImpl context;
|
||||||
private final List<CodeElement> elements = new ArrayList<>();
|
private final List<CodeElement> elements = new ArrayList<>();
|
||||||
private final LabelImpl startLabel, endLabel;
|
private final LabelImpl startLabel, endLabel;
|
||||||
private final CodeModel original;
|
|
||||||
private final MethodInfo methodInfo;
|
private final MethodInfo methodInfo;
|
||||||
private boolean finished;
|
private boolean finished;
|
||||||
private int maxLocals;
|
private int maxLocals;
|
||||||
|
@ -60,12 +56,8 @@ public final class BufferedCodeBuilder
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.startLabel = new LabelImpl(this, -1);
|
this.startLabel = new LabelImpl(this, -1);
|
||||||
this.endLabel = new LabelImpl(this, -1);
|
this.endLabel = new LabelImpl(this, -1);
|
||||||
this.original = original;
|
|
||||||
this.methodInfo = methodInfo;
|
this.methodInfo = methodInfo;
|
||||||
this.maxLocals = Util.maxLocals(methodInfo.methodFlags(), methodInfo.methodTypeSymbol());
|
this.maxLocals = TerminalCodeBuilder.setupTopLocal(methodInfo, original);
|
||||||
if (original != null)
|
|
||||||
this.maxLocals = Math.max(this.maxLocals, original.maxLocals());
|
|
||||||
|
|
||||||
elements.add(startLabel);
|
elements.add(startLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,27 +154,16 @@ public final class BufferedCodeBuilder
|
||||||
@Override
|
@Override
|
||||||
public List<ExceptionCatch> exceptionHandlers() {
|
public List<ExceptionCatch> exceptionHandlers() {
|
||||||
return elements.stream()
|
return elements.stream()
|
||||||
.filter(x -> x instanceof ExceptionCatch)
|
.<ExceptionCatch>mapMulti((x, sink) -> {
|
||||||
.map(x -> (ExceptionCatch) x)
|
if (x instanceof ExceptionCatch ec) {
|
||||||
|
sink.accept(ec);
|
||||||
|
}
|
||||||
|
})
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
int curTopLocal() {
|
||||||
public int maxLocals() {
|
return BufferedCodeBuilder.this.curTopLocal();
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("CodeModel[id=%s]", Integer.toHexString(System.identityHashCode(this)));
|
return String.format("CodeModel[id=%s]", Integer.toHexString(System.identityHashCode(this)));
|
||||||
|
|
|
@ -103,7 +103,7 @@ public final class BufferedFieldBuilder
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(DirectClassBuilder builder) {
|
public void writeTo(DirectClassBuilder builder) {
|
||||||
builder.withField(name, desc, new Consumer<FieldBuilder>() {
|
builder.withField(name, desc, new Consumer<>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(FieldBuilder fieldBuilder) {
|
public void accept(FieldBuilder fieldBuilder) {
|
||||||
elements.forEach(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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("FieldModel[fieldName=%s, fieldType=%s, flags=%d]", name.stringValue(), desc.stringValue(), flags.flagsMask());
|
return String.format("FieldModel[fieldName=%s, fieldType=%s, flags=%d]", name.stringValue(), desc.stringValue(), flags.flagsMask());
|
||||||
|
|
|
@ -196,7 +196,11 @@ public final class BufferedMethodBuilder
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<CodeModel> code() {
|
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
|
@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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("MethodModel[methodName=%s, methodType=%s, flags=%d]",
|
return String.format("MethodModel[methodName=%s, methodType=%s, flags=%d]",
|
||||||
|
|
|
@ -43,7 +43,7 @@ import static java.lang.classfile.ClassFile.*;
|
||||||
|
|
||||||
public final class CodeImpl
|
public final class CodeImpl
|
||||||
extends BoundAttribute.BoundCodeAttribute
|
extends BoundAttribute.BoundCodeAttribute
|
||||||
implements CodeModel, LabelContext {
|
implements LabelContext {
|
||||||
|
|
||||||
static final Instruction[] SINGLETON_INSTRUCTIONS = new Instruction[256];
|
static final Instruction[] SINGLETON_INSTRUCTIONS = new Instruction[256];
|
||||||
|
|
||||||
|
|
|
@ -127,12 +127,10 @@ public final class DirectCodeBuilder
|
||||||
this.transformFwdJumps = transformFwdJumps;
|
this.transformFwdJumps = transformFwdJumps;
|
||||||
this.transformBackJumps = context.shortJumpsOption() == ClassFile.ShortJumpsOption.FIX_SHORT_JUMPS;
|
this.transformBackJumps = context.shortJumpsOption() == ClassFile.ShortJumpsOption.FIX_SHORT_JUMPS;
|
||||||
bytecodesBufWriter = (original instanceof CodeImpl cai) ? new BufWriterImpl(constantPool, context, cai.codeLength())
|
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.startLabel = new LabelImpl(this, 0);
|
||||||
this.endLabel = new LabelImpl(this, -1);
|
this.endLabel = new LabelImpl(this, -1);
|
||||||
this.topLocal = Util.maxLocals(methodInfo.methodFlags(), methodInfo.methodTypeSymbol());
|
this.topLocal = TerminalCodeBuilder.setupTopLocal(methodInfo, original);
|
||||||
if (original != null)
|
|
||||||
this.topLocal = Math.max(this.topLocal, original.maxLocals());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -312,8 +310,9 @@ public final class DirectCodeBuilder
|
||||||
|
|
||||||
private void writeCounters(boolean codeMatch, BufWriterImpl buf) {
|
private void writeCounters(boolean codeMatch, BufWriterImpl buf) {
|
||||||
if (codeMatch) {
|
if (codeMatch) {
|
||||||
buf.writeU2(original.maxStack());
|
var originalAttribute = (CodeImpl) original;
|
||||||
buf.writeU2(original.maxLocals());
|
buf.writeU2(originalAttribute.maxStack());
|
||||||
|
buf.writeU2(originalAttribute.maxLocals());
|
||||||
} else {
|
} else {
|
||||||
StackCounter cntr = StackCounter.of(DirectCodeBuilder.this, buf);
|
StackCounter cntr = StackCounter.of(DirectCodeBuilder.this, buf);
|
||||||
buf.writeU2(cntr.maxStack());
|
buf.writeU2(cntr.maxStack());
|
||||||
|
|
|
@ -25,8 +25,24 @@
|
||||||
package jdk.internal.classfile.impl;
|
package jdk.internal.classfile.impl;
|
||||||
|
|
||||||
import java.lang.classfile.CodeBuilder;
|
import java.lang.classfile.CodeBuilder;
|
||||||
|
import java.lang.classfile.CodeModel;
|
||||||
|
import java.lang.classfile.attribute.CodeAttribute;
|
||||||
|
|
||||||
public sealed interface TerminalCodeBuilder extends CodeBuilder, LabelContext
|
public sealed interface TerminalCodeBuilder extends CodeBuilder, LabelContext
|
||||||
permits DirectCodeBuilder, BufferedCodeBuilder {
|
permits DirectCodeBuilder, BufferedCodeBuilder {
|
||||||
int curTopLocal();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -23,36 +23,48 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
|
* @bug 8337225
|
||||||
* @summary Testing ClassFile builder blocks.
|
* @summary Testing ClassFile builder blocks.
|
||||||
* @run junit BuilderBlockTest
|
* @run junit BuilderBlockTest
|
||||||
*/
|
*/
|
||||||
import java.lang.constant.ClassDesc;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static java.lang.constant.ConstantDescs.*;
|
|
||||||
|
|
||||||
import java.lang.constant.MethodTypeDesc;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
import helpers.ByteArrayClassLoader;
|
|
||||||
import java.lang.classfile.AccessFlags;
|
import java.lang.classfile.AccessFlags;
|
||||||
import java.lang.reflect.AccessFlag;
|
import java.lang.classfile.Attributes;
|
||||||
import java.lang.classfile.ClassFile;
|
import java.lang.classfile.ClassFile;
|
||||||
|
import java.lang.classfile.ClassTransform;
|
||||||
|
import java.lang.classfile.CodeBuilder;
|
||||||
|
import java.lang.classfile.CodeElement;
|
||||||
|
import java.lang.classfile.CodeTransform;
|
||||||
import java.lang.classfile.Label;
|
import java.lang.classfile.Label;
|
||||||
|
import java.lang.classfile.MethodModel;
|
||||||
|
import java.lang.classfile.MethodTransform;
|
||||||
import java.lang.classfile.Opcode;
|
import java.lang.classfile.Opcode;
|
||||||
import java.lang.classfile.TypeKind;
|
import java.lang.classfile.TypeKind;
|
||||||
|
import java.lang.classfile.constantpool.StringEntry;
|
||||||
|
import java.lang.classfile.instruction.ConstantInstruction;
|
||||||
|
import java.lang.constant.ClassDesc;
|
||||||
|
import java.lang.constant.MethodTypeDesc;
|
||||||
|
import java.lang.reflect.AccessFlag;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import helpers.ByteArrayClassLoader;
|
||||||
import jdk.internal.classfile.impl.LabelImpl;
|
import jdk.internal.classfile.impl.LabelImpl;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static java.lang.constant.ConstantDescs.CD_int;
|
||||||
|
import static java.lang.constant.ConstantDescs.CD_void;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BuilderBlockTest
|
* BuilderBlockTest
|
||||||
*/
|
*/
|
||||||
class BuilderBlockTest {
|
class BuilderBlockTest {
|
||||||
|
|
||||||
static final String testClassName = "AdaptCodeTest$TestClass";
|
static final String testClassName = "BuilderBlockTest$TestClass";
|
||||||
static final Path testClassPath = Paths.get("target/test-classes/" + testClassName + ".class");
|
static final Path testClassPath = Path.of(URI.create(BuilderBlockTest.class.getResource(testClassName + ".class").toString()));
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testStartEnd() throws Exception {
|
void testStartEnd() throws Exception {
|
||||||
|
@ -305,4 +317,81 @@ class BuilderBlockTest {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final CodeTransform ALLOCATE_LOCAL_EXAMINER = CodeTransform.ofStateful(() -> new CodeTransform() {
|
||||||
|
boolean foundItem = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void atStart(CodeBuilder builder) {
|
||||||
|
foundItem = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(CodeBuilder cob, CodeElement coe) {
|
||||||
|
cob.with(coe);
|
||||||
|
if (coe instanceof ConstantInstruction.LoadConstantInstruction ldc
|
||||||
|
&& ldc.constantEntry() instanceof StringEntry se
|
||||||
|
&& se.utf8().equalsString("Output")) {
|
||||||
|
assertFalse(foundItem);
|
||||||
|
foundItem = true;
|
||||||
|
var i = cob.allocateLocal(TypeKind.IntType);
|
||||||
|
assertEquals(7, i, "Allocated new int slot");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void atEnd(CodeBuilder builder) {
|
||||||
|
assertTrue(foundItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test updating local variable slot management from
|
||||||
|
// source code models in transformingCode;
|
||||||
|
// CodeBuilder.transform(CodeModel, CodeTransform) is
|
||||||
|
// not managed for now
|
||||||
|
@Test
|
||||||
|
void testAllocateLocalTransformingCodeAttribute() throws IOException {
|
||||||
|
var cf = ClassFile.of();
|
||||||
|
var code = cf.parse(testClassPath)
|
||||||
|
.methods()
|
||||||
|
.stream()
|
||||||
|
.filter(f -> f.methodName().equalsString("work"))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow()
|
||||||
|
.findAttribute(Attributes.code())
|
||||||
|
.orElseThrow();
|
||||||
|
ClassFile.of().build(ClassDesc.of("Foo"), cb -> cb
|
||||||
|
.withMethod("foo", MethodTypeDesc.ofDescriptor("(IJI)V"), 0, mb -> mb
|
||||||
|
.transformCode(code, ALLOCATE_LOCAL_EXAMINER)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAllocateLocalTransformingBufferedCode() throws IOException {
|
||||||
|
var cf = ClassFile.of();
|
||||||
|
var testClass = cf.parse(testClassPath);
|
||||||
|
ClassTransform bufferingTransform = (clb, cle) -> {
|
||||||
|
if (cle instanceof MethodModel mm && mm.methodName().equalsString("work")) {
|
||||||
|
clb.withMethodBody(mm.methodName(), mm.methodType(), mm.flags().flagsMask(), cob -> {
|
||||||
|
int d = cob.allocateLocal(TypeKind.IntType);
|
||||||
|
int e = cob.allocateLocal(TypeKind.IntType);
|
||||||
|
|
||||||
|
assertEquals(5, d);
|
||||||
|
assertEquals(6, e);
|
||||||
|
|
||||||
|
mm.code().ifPresent(code -> code.forEach(cob));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cf.transformClass(testClass, bufferingTransform.andThen(ClassTransform.transformingMethods(MethodTransform.transformingCode(ALLOCATE_LOCAL_EXAMINER))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TestClass {
|
||||||
|
public void work(int a, long b, int c) {
|
||||||
|
int d = Math.addExact(a, 25);
|
||||||
|
int e = Math.multiplyExact(d, c);
|
||||||
|
System.out.println("Output");
|
||||||
|
System.out.println(e + b);
|
||||||
|
throw new IllegalArgumentException("foo");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.junit.jupiter.api.parallel.Execution;
|
||||||
import org.junit.jupiter.api.parallel.ExecutionMode;
|
import org.junit.jupiter.api.parallel.ExecutionMode;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.lang.classfile.attribute.CodeAttribute;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static helpers.ClassRecord.assertEqualsDeep;
|
import static helpers.ClassRecord.assertEqualsDeep;
|
||||||
|
@ -222,9 +223,11 @@ class CorpusTest {
|
||||||
var m1 = itStack.next();
|
var m1 = itStack.next();
|
||||||
var m2 = itNoStack.next();
|
var m2 = itNoStack.next();
|
||||||
var text1 = m1.methodName().stringValue() + m1.methodType().stringValue() + ": "
|
var text1 = m1.methodName().stringValue() + m1.methodType().stringValue() + ": "
|
||||||
+ m1.code().map(c -> c.maxLocals() + " / " + c.maxStack()).orElse("-");
|
+ m1.code().map(CodeAttribute.class::cast)
|
||||||
|
.map(c -> c.maxLocals() + " / " + c.maxStack()).orElse("-");
|
||||||
var text2 = m2.methodName().stringValue() + m2.methodType().stringValue() + ": "
|
var text2 = m2.methodName().stringValue() + m2.methodType().stringValue() + ": "
|
||||||
+ m2.code().map(c -> c.maxLocals() + " / " + c.maxStack()).orElse("-");
|
+ m2.code().map(CodeAttribute.class::cast)
|
||||||
|
.map(c -> c.maxLocals() + " / " + c.maxStack()).orElse("-");
|
||||||
assertEquals(text1, text2);
|
assertEquals(text1, text2);
|
||||||
}
|
}
|
||||||
assertFalse(itNoStack.hasNext());
|
assertFalse(itNoStack.hasNext());
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
* @summary Testing ClassFile handling JSR and RET instructions.
|
* @summary Testing ClassFile handling JSR and RET instructions.
|
||||||
* @run junit DiscontinuedInstructionsTest
|
* @run junit DiscontinuedInstructionsTest
|
||||||
*/
|
*/
|
||||||
|
import java.lang.classfile.attribute.CodeAttribute;
|
||||||
import java.lang.constant.ClassDesc;
|
import java.lang.constant.ClassDesc;
|
||||||
import java.lang.constant.MethodTypeDesc;
|
import java.lang.constant.MethodTypeDesc;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -63,7 +64,7 @@ class DiscontinuedInstructionsTest {
|
||||||
.pop()
|
.pop()
|
||||||
.with(DiscontinuedInstruction.RetInstruction.of(355))));
|
.with(DiscontinuedInstruction.RetInstruction.of(355))));
|
||||||
|
|
||||||
var c = cc.parse(bytes).methods().get(0).code().get();
|
var c = (CodeAttribute) cc.parse(bytes).methods().get(0).code().get();
|
||||||
assertEquals(356, c.maxLocals());
|
assertEquals(356, c.maxLocals());
|
||||||
assertEquals(6, c.maxStack());
|
assertEquals(6, c.maxStack());
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.classfile.*;
|
import java.lang.classfile.*;
|
||||||
|
import java.lang.classfile.attribute.CodeAttribute;
|
||||||
import java.lang.classfile.components.ClassPrinter;
|
import java.lang.classfile.components.ClassPrinter;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
|
@ -329,7 +330,7 @@ class StackMapsTest {
|
||||||
var cm = ClassFile.of().parse(bytes);
|
var cm = ClassFile.of().parse(bytes);
|
||||||
for (var method : cm.methods()) {
|
for (var method : cm.methods()) {
|
||||||
var name = method.methodName();
|
var name = method.methodName();
|
||||||
var code = method.code().orElseThrow();
|
var code = (CodeAttribute) method.code().orElseThrow();
|
||||||
if (name.equalsString("a")) {
|
if (name.equalsString("a")) {
|
||||||
assertEquals(0, code.maxLocals()); // static method
|
assertEquals(0, code.maxLocals()); // static method
|
||||||
assertEquals(0, code.maxStack());
|
assertEquals(0, code.maxStack());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue