Skip to content

Commit e88a3b0

Browse files
committed
8338661: StackMapTable is invalid if frames appear in dead code
Reviewed-by: liach
1 parent 5981697 commit e88a3b0

File tree

4 files changed

+63
-9
lines changed

4 files changed

+63
-9
lines changed

src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ public void writeTo(BufWriterImpl buf) {
5353
Util.writeAttributes(buf, attributes);
5454
}
5555

56+
@SuppressWarnings("unchecked")
57+
<A> A get(AttributeMapper<A> am) {
58+
for (Attribute<?> a : attributes)
59+
if (a.attributeMapper() == am)
60+
return (A)a;
61+
return null;
62+
}
63+
5664
boolean isPresent(AttributeMapper<?> am) {
5765
for (Attribute<?> a : attributes)
5866
if (a.attributeMapper() == am)

src/java.base/share/classes/jdk/internal/classfile/impl/StackCounter.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,23 @@
2525
*/
2626
package jdk.internal.classfile.impl;
2727

28+
import java.lang.classfile.Attributes;
2829
import java.lang.classfile.TypeKind;
30+
import java.lang.classfile.attribute.StackMapFrameInfo;
31+
import java.lang.classfile.attribute.StackMapTableAttribute;
2932
import java.lang.classfile.constantpool.ConstantDynamicEntry;
3033
import java.lang.classfile.constantpool.DynamicConstantPoolEntry;
3134
import java.lang.classfile.constantpool.MemberRefEntry;
35+
import java.lang.constant.ClassDesc;
3236
import java.lang.constant.MethodTypeDesc;
3337
import java.nio.ByteBuffer;
3438
import java.util.ArrayDeque;
3539
import java.util.BitSet;
3640
import java.util.List;
3741
import java.util.Queue;
42+
import java.util.stream.Collectors;
3843

3944
import static java.lang.classfile.ClassFile.*;
40-
import java.lang.constant.ClassDesc;
41-
import java.util.stream.Collectors;
4245

4346
public final class StackCounter {
4447

@@ -47,6 +50,7 @@ private record Target(int bci, int stack) {}
4750
static StackCounter of(DirectCodeBuilder dcb, BufWriterImpl buf) {
4851
return new StackCounter(
4952
dcb,
53+
dcb.attributes.get(Attributes.stackMapTable()),
5054
buf.thisClass().asSymbol(),
5155
dcb.methodInfo.methodName().stringValue(),
5256
dcb.methodInfo.methodTypeSymbol(),
@@ -97,6 +101,7 @@ private boolean next() {
97101
}
98102

99103
public StackCounter(LabelContext labelContext,
104+
StackMapTableAttribute smta,
100105
ClassDesc thisClass,
101106
String methodName,
102107
MethodTypeDesc methodDesc,
@@ -111,8 +116,20 @@ public StackCounter(LabelContext labelContext,
111116
this.bytecode = bytecode;
112117
this.cp = cp;
113118
targets = new ArrayDeque<>();
114-
maxStack = stack = rets = 0;
119+
stack = rets = 0;
120+
maxStack = handlers.isEmpty() ? 0 : 1;
115121
for (var h : handlers) targets.add(new Target(labelContext.labelToBci(h.handler), 1));
122+
if (smta != null) {
123+
for (var smfi : smta.entries()) {
124+
int frameStack = smfi.stack().size();
125+
for (var vti : smfi.stack()) {
126+
if (vti == StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_LONG
127+
|| vti == StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_DOUBLE) frameStack++;
128+
}
129+
if (maxStack < frameStack) maxStack = frameStack;
130+
targets.add(new Target(labelContext.labelToBci(smfi.target()), frameStack));
131+
}
132+
}
116133
maxLocals = isStatic ? 0 : 1;
117134
maxLocals += Util.parameterSlots(methodDesc);
118135
bcs = new RawBytecodeHelper(bytecode);

test/jdk/jdk/classfile/StackMapsTest.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,25 @@
2424
/*
2525
* @test
2626
* @summary Testing Classfile stack maps generator.
27-
* @bug 8305990 8320222 8320618 8335475 8338623
27+
* @bug 8305990 8320222 8320618 8335475 8338623 8338661
2828
* @build testdata.*
2929
* @run junit StackMapsTest
3030
*/
3131

3232
import java.lang.classfile.*;
3333
import java.lang.classfile.attribute.CodeAttribute;
34+
import java.lang.classfile.attribute.StackMapFrameInfo;
35+
import java.lang.classfile.attribute.StackMapTableAttribute;
3436
import java.lang.classfile.components.ClassPrinter;
37+
import java.lang.constant.ClassDesc;
38+
import java.lang.constant.ConstantDescs;
39+
import java.lang.constant.MethodTypeDesc;
40+
import java.lang.reflect.AccessFlag;
3541
import java.net.URI;
3642
import java.nio.file.FileSystem;
3743
import java.nio.file.FileSystems;
3844
import java.nio.file.Files;
45+
import java.util.List;
3946
import org.junit.jupiter.api.Test;
4047
import org.junit.jupiter.params.ParameterizedTest;
4148
import org.junit.jupiter.params.provider.EnumSource;
@@ -45,11 +52,6 @@
4552
import static java.lang.classfile.ClassFile.ACC_STATIC;
4653
import static java.lang.constant.ConstantDescs.*;
4754

48-
import java.lang.constant.ClassDesc;
49-
import java.lang.constant.ConstantDescs;
50-
import java.lang.constant.MethodTypeDesc;
51-
import java.lang.reflect.AccessFlag;
52-
5355
/**
5456
* StackMapsTest
5557
*/
@@ -368,4 +370,30 @@ void testInvocationCounters(ClassFile.StackMapsOption option) {
368370
assertEquals(1, code.maxStack());
369371
}
370372
}
373+
374+
@Test
375+
void testDeadCodeCountersWithCustomSMTA() {
376+
ClassDesc bar = ClassDesc.of("Bar");
377+
byte[] bytes = ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS).build(bar, clb -> clb
378+
.withMethodBody(
379+
"foo", MethodTypeDesc.of(ConstantDescs.CD_long), ACC_STATIC, cob -> {
380+
cob.lconst_0().lreturn();
381+
Label f2 = cob.newBoundLabel();
382+
cob.lstore(0);
383+
Label f3 = cob.newBoundLabel();
384+
cob.lload(0).lreturn().with(
385+
StackMapTableAttribute.of(List.of(
386+
StackMapFrameInfo.of(f2,
387+
List.of(),
388+
List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_LONG)),
389+
StackMapFrameInfo.of(f3,
390+
List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_LONG),
391+
List.of()))));
392+
}
393+
));
394+
assertEmpty(ClassFile.of().verify(bytes));
395+
var code = (CodeAttribute) ClassFile.of().parse(bytes).methods().getFirst().code().orElseThrow();
396+
assertEquals(2, code.maxLocals());
397+
assertEquals(2, code.maxStack());
398+
}
371399
}

test/micro/org/openjdk/bench/jdk/classfile/CodeAttributeTools.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ public void benchmarkStackMapsGenerator(Blackhole bh) {
122122
public void benchmarkStackCounter(Blackhole bh) {
123123
for (var d : data) bh.consume(new StackCounter(
124124
d.labelContext(),
125+
null,
125126
d.thisClass(),
126127
d.methodName(),
127128
d.methodDesc(),

0 commit comments

Comments
 (0)