diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java
index ba51474c131..31e1a7f2533 100644
--- a/src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java
+++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java
@@ -53,6 +53,14 @@ public class AttributeHolder {
Util.writeAttributes(buf, attributes);
}
+ @SuppressWarnings("unchecked")
+ A get(AttributeMapper am) {
+ for (Attribute> a : attributes)
+ if (a.attributeMapper() == am)
+ return (A)a;
+ return null;
+ }
+
boolean isPresent(AttributeMapper> am) {
for (Attribute> a : attributes)
if (a.attributeMapper() == am)
diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/StackCounter.java b/src/java.base/share/classes/jdk/internal/classfile/impl/StackCounter.java
index 24a27ad5af6..861bb509420 100644
--- a/src/java.base/share/classes/jdk/internal/classfile/impl/StackCounter.java
+++ b/src/java.base/share/classes/jdk/internal/classfile/impl/StackCounter.java
@@ -25,20 +25,23 @@
*/
package jdk.internal.classfile.impl;
+import java.lang.classfile.Attributes;
import java.lang.classfile.TypeKind;
+import java.lang.classfile.attribute.StackMapFrameInfo;
+import java.lang.classfile.attribute.StackMapTableAttribute;
import java.lang.classfile.constantpool.ConstantDynamicEntry;
import java.lang.classfile.constantpool.DynamicConstantPoolEntry;
import java.lang.classfile.constantpool.MemberRefEntry;
+import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.BitSet;
import java.util.List;
import java.util.Queue;
+import java.util.stream.Collectors;
import static java.lang.classfile.ClassFile.*;
-import java.lang.constant.ClassDesc;
-import java.util.stream.Collectors;
public final class StackCounter {
@@ -47,6 +50,7 @@ public final class StackCounter {
static StackCounter of(DirectCodeBuilder dcb, BufWriterImpl buf) {
return new StackCounter(
dcb,
+ dcb.attributes.get(Attributes.stackMapTable()),
buf.thisClass().asSymbol(),
dcb.methodInfo.methodName().stringValue(),
dcb.methodInfo.methodTypeSymbol(),
@@ -97,6 +101,7 @@ public final class StackCounter {
}
public StackCounter(LabelContext labelContext,
+ StackMapTableAttribute smta,
ClassDesc thisClass,
String methodName,
MethodTypeDesc methodDesc,
@@ -111,8 +116,20 @@ public final class StackCounter {
this.bytecode = bytecode;
this.cp = cp;
targets = new ArrayDeque<>();
- maxStack = stack = rets = 0;
+ stack = rets = 0;
+ maxStack = handlers.isEmpty() ? 0 : 1;
for (var h : handlers) targets.add(new Target(labelContext.labelToBci(h.handler), 1));
+ if (smta != null) {
+ for (var smfi : smta.entries()) {
+ int frameStack = smfi.stack().size();
+ for (var vti : smfi.stack()) {
+ if (vti == StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_LONG
+ || vti == StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_DOUBLE) frameStack++;
+ }
+ if (maxStack < frameStack) maxStack = frameStack;
+ targets.add(new Target(labelContext.labelToBci(smfi.target()), frameStack));
+ }
+ }
maxLocals = isStatic ? 0 : 1;
maxLocals += Util.parameterSlots(methodDesc);
bcs = new RawBytecodeHelper(bytecode);
diff --git a/test/jdk/jdk/classfile/StackMapsTest.java b/test/jdk/jdk/classfile/StackMapsTest.java
index 3ee8eaf51ee..09be56f0de2 100644
--- a/test/jdk/jdk/classfile/StackMapsTest.java
+++ b/test/jdk/jdk/classfile/StackMapsTest.java
@@ -24,18 +24,25 @@
/*
* @test
* @summary Testing Classfile stack maps generator.
- * @bug 8305990 8320222 8320618 8335475 8338623
+ * @bug 8305990 8320222 8320618 8335475 8338623 8338661
* @build testdata.*
* @run junit StackMapsTest
*/
import java.lang.classfile.*;
import java.lang.classfile.attribute.CodeAttribute;
+import java.lang.classfile.attribute.StackMapFrameInfo;
+import java.lang.classfile.attribute.StackMapTableAttribute;
import java.lang.classfile.components.ClassPrinter;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.ConstantDescs;
+import java.lang.constant.MethodTypeDesc;
+import java.lang.reflect.AccessFlag;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
+import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
@@ -45,11 +52,6 @@ import static helpers.TestUtil.assertEmpty;
import static java.lang.classfile.ClassFile.ACC_STATIC;
import static java.lang.constant.ConstantDescs.*;
-import java.lang.constant.ClassDesc;
-import java.lang.constant.ConstantDescs;
-import java.lang.constant.MethodTypeDesc;
-import java.lang.reflect.AccessFlag;
-
/**
* StackMapsTest
*/
@@ -368,4 +370,30 @@ class StackMapsTest {
assertEquals(1, code.maxStack());
}
}
+
+ @Test
+ void testDeadCodeCountersWithCustomSMTA() {
+ ClassDesc bar = ClassDesc.of("Bar");
+ byte[] bytes = ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS).build(bar, clb -> clb
+ .withMethodBody(
+ "foo", MethodTypeDesc.of(ConstantDescs.CD_long), ACC_STATIC, cob -> {
+ cob.lconst_0().lreturn();
+ Label f2 = cob.newBoundLabel();
+ cob.lstore(0);
+ Label f3 = cob.newBoundLabel();
+ cob.lload(0).lreturn().with(
+ StackMapTableAttribute.of(List.of(
+ StackMapFrameInfo.of(f2,
+ List.of(),
+ List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_LONG)),
+ StackMapFrameInfo.of(f3,
+ List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_LONG),
+ List.of()))));
+ }
+ ));
+ assertEmpty(ClassFile.of().verify(bytes));
+ var code = (CodeAttribute) ClassFile.of().parse(bytes).methods().getFirst().code().orElseThrow();
+ assertEquals(2, code.maxLocals());
+ assertEquals(2, code.maxStack());
+ }
}
diff --git a/test/micro/org/openjdk/bench/jdk/classfile/CodeAttributeTools.java b/test/micro/org/openjdk/bench/jdk/classfile/CodeAttributeTools.java
index d2defd6c5ef..4cf578889d1 100644
--- a/test/micro/org/openjdk/bench/jdk/classfile/CodeAttributeTools.java
+++ b/test/micro/org/openjdk/bench/jdk/classfile/CodeAttributeTools.java
@@ -122,6 +122,7 @@ public class CodeAttributeTools {
public void benchmarkStackCounter(Blackhole bh) {
for (var d : data) bh.consume(new StackCounter(
d.labelContext(),
+ null,
d.thisClass(),
d.methodName(),
d.methodDesc(),