From 2f60d3684843e42c2c4c3bf628ac6d62dcdfcadb Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Mon, 8 Jul 2024 11:01:53 +0000 Subject: [PATCH] 8335475: ClassBuilder incorrectly calculates max_locals in some cases Reviewed-by: asotona Backport-of: 1ef34c183315b70ddc27c177a2867e30132609f5 --- .../classfile/impl/StackMapGenerator.java | 2 +- test/jdk/jdk/classfile/StackMapsTest.java | 34 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java index ba032c7b0c2..dd4d7d42070 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java @@ -1047,7 +1047,7 @@ private void setLocalRawInternal(int index, Type type) { void setLocalsFromArg(String name, MethodTypeDesc methodDesc, boolean isStatic, Type thisKlass) { int localsSize = 0; // Pre-emptively create a locals array that encompass all parameter slots - checkLocal(methodDesc.parameterCount() + (isStatic ? 0 : -1)); + checkLocal(methodDesc.parameterCount() + (isStatic ? -1 : 0)); if (!isStatic) { localsSize++; if (OBJECT_INITIALIZER_NAME.equals(name) && !CD_Object.equals(thisKlass.sym)) { diff --git a/test/jdk/jdk/classfile/StackMapsTest.java b/test/jdk/jdk/classfile/StackMapsTest.java index b3df31291bc..f72c237aa8f 100644 --- a/test/jdk/jdk/classfile/StackMapsTest.java +++ b/test/jdk/jdk/classfile/StackMapsTest.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @summary Testing Classfile stack maps generator. - * @bug 8305990 8320222 8320618 + * @bug 8305990 8320222 8320618 8335475 * @build testdata.* * @run junit StackMapsTest */ @@ -36,6 +36,10 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import static java.lang.constant.ConstantDescs.MTD_void; import static org.junit.jupiter.api.Assertions.*; import static helpers.TestUtil.assertEmpty; import static java.lang.classfile.ClassFile.ACC_STATIC; @@ -238,7 +242,7 @@ void testClassVersions() throws Exception { @Test void testInvalidAALOADStack() { ClassFile.of().build(ClassDesc.of("Test"), clb - -> clb.withMethodBody("test", ConstantDescs.MTD_void, 0, cob + -> clb.withMethodBody("test", MTD_void, 0, cob -> cob.bipush(10) .anewarray(ConstantDescs.CD_Object) .lconst_1() //long on stack caused NPE, see 8320618 @@ -312,4 +316,28 @@ void testInvalidStack() throws Exception { cb.pop(); }))); } + + @ParameterizedTest + @EnumSource(ClassFile.StackMapsOption.class) + void testEmptyCounters(ClassFile.StackMapsOption option) { + var cf = ClassFile.of(option); + var bytes = cf.build(ClassDesc.of("Test"), clb -> clb + .withMethodBody("a", MTD_void, ACC_STATIC, CodeBuilder::return_) + .withMethodBody("b", MTD_void, 0, CodeBuilder::return_) + ); + + var cm = ClassFile.of().parse(bytes); + for (var method : cm.methods()) { + var name = method.methodName(); + var code = method.code().orElseThrow(); + if (name.equalsString("a")) { + assertEquals(0, code.maxLocals()); // static method + assertEquals(0, code.maxStack()); + } else { + assertTrue(name.equalsString("b")); + assertEquals(1, code.maxLocals()); // instance method + assertEquals(0, code.maxStack()); + } + } + } }