diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java index 71d5ccc79a4..a9096f20826 100644 --- a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java +++ b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java @@ -34,6 +34,7 @@ import java.util.List; import jdk.internal.classfile.impl.StackMapDecoder; +import jdk.internal.classfile.impl.StackMapGenerator; import jdk.internal.classfile.impl.TemporaryConstantPool; /** @@ -101,31 +102,31 @@ public static StackMapFrameInfo of(Label target, sealed interface VerificationTypeInfo { /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#TOP TOP}. */ - int ITEM_TOP = 0; + int ITEM_TOP = StackMapGenerator.ITEM_TOP; /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#INTEGER INTEGER}. */ - int ITEM_INTEGER = 1; + int ITEM_INTEGER = StackMapGenerator.ITEM_INTEGER; /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#FLOAT FLOAT}. */ - int ITEM_FLOAT = 2; + int ITEM_FLOAT = StackMapGenerator.ITEM_FLOAT; /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#DOUBLE DOUBLE}. */ - int ITEM_DOUBLE = 3; + int ITEM_DOUBLE = StackMapGenerator.ITEM_DOUBLE; /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#LONG LONG}. */ - int ITEM_LONG = 4; + int ITEM_LONG = StackMapGenerator.ITEM_LONG; /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#NULL NULL}. */ - int ITEM_NULL = 5; + int ITEM_NULL = StackMapGenerator.ITEM_NULL; /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#UNINITIALIZED_THIS UNINITIALIZED_THIS}. */ - int ITEM_UNINITIALIZED_THIS = 6; + int ITEM_UNINITIALIZED_THIS = StackMapGenerator.ITEM_UNINITIALIZED_THIS; /** The {@link #tag() tag} for verification type info {@link ObjectVerificationTypeInfo OBJECT}. */ - int ITEM_OBJECT = 7; + int ITEM_OBJECT = StackMapGenerator.ITEM_OBJECT; /** The {@link #tag() tag} for verification type info {@link UninitializedVerificationTypeInfo UNINITIALIZED}. */ - int ITEM_UNINITIALIZED = 8; + int ITEM_UNINITIALIZED = StackMapGenerator.ITEM_UNINITIALIZED; /** * {@return the tag of the type info} diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java index c8c6d254650..e4480d740bd 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java @@ -39,6 +39,7 @@ import java.util.Optional; import java.util.function.Consumer; +import static jdk.internal.classfile.impl.StackMapGenerator.*; import static jdk.internal.classfile.impl.RawBytecodeHelper.*; public final class CodeImpl @@ -292,33 +293,33 @@ private void inflateJumpTargets() { for (int i = 0; i < nEntries; ++i) { int frameType = classReader.readU1(p); int offsetDelta; - if (frameType < 64) { + if (frameType <= SAME_FRAME_END) { offsetDelta = frameType; ++p; } - else if (frameType < 128) { + else if (frameType <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) { offsetDelta = frameType & 0x3f; p = adjustForObjectOrUninitialized(p + 1); } else switch (frameType) { - case 247 -> { + case SAME_LOCALS_1_STACK_ITEM_EXTENDED -> { offsetDelta = classReader.readU2(p + 1); p = adjustForObjectOrUninitialized(p + 3); } - case 248, 249, 250, 251 -> { + case CHOP_FRAME_START, CHOP_FRAME_START + 1, CHOP_FRAME_END, SAME_FRAME_EXTENDED -> { offsetDelta = classReader.readU2(p + 1); p += 3; } - case 252, 253, 254 -> { + case APPEND_FRAME_START, APPEND_FRAME_START + 1, APPEND_FRAME_END -> { offsetDelta = classReader.readU2(p + 1); - int k = frameType - 251; + int k = frameType - APPEND_FRAME_START + 1; p += 3; for (int c = 0; c < k; ++c) { p = adjustForObjectOrUninitialized(p); } } - case 255 -> { + case FULL_FRAME -> { offsetDelta = classReader.readU2(p + 1); p += 3; int k = classReader.readU2(p); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapDecoder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapDecoder.java index f8e58ed2242..a19571a1fbb 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapDecoder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapDecoder.java @@ -44,14 +44,11 @@ import java.util.Objects; import static java.lang.classfile.ClassFile.ACC_STATIC; -import static java.lang.classfile.attribute.StackMapFrameInfo.VerificationTypeInfo.*; import static java.util.Objects.requireNonNull; +import static jdk.internal.classfile.impl.StackMapGenerator.*; public class StackMapDecoder { - private static final int - SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247, - SAME_EXTENDED = 251; private static final StackMapFrameInfo[] NO_STACK_FRAME_INFOS = {}; private final ClassReader classReader; @@ -136,25 +133,25 @@ private static void writeFrame(BufWriterImpl out, int offsetDelta, List entries() { var entries = new StackMapFrameInfo[u2()]; for (int ei = 0; ei < entries.length; ei++) { int frameType = classReader.readU1(p++); - if (frameType < 64) { + if (frameType <= SAME_FRAME_END) { bci += frameType + 1; stack = List.of(); - } else if (frameType < 128) { - bci += frameType - 63; + } else if (frameType <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) { + bci += frameType - SAME_LOCALS_1_STACK_ITEM_FRAME_START + 1; stack = List.of(readVerificationTypeInfo()); } else { if (frameType < SAME_LOCALS_1_STACK_ITEM_EXTENDED) @@ -200,14 +197,14 @@ List entries() { bci += u2() + 1; if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { stack = List.of(readVerificationTypeInfo()); - } else if (frameType < SAME_EXTENDED) { - locals = locals.subList(0, locals.size() + frameType - SAME_EXTENDED); + } else if (frameType < SAME_FRAME_EXTENDED) { + locals = locals.subList(0, locals.size() + frameType - SAME_FRAME_EXTENDED); stack = List.of(); - } else if (frameType == SAME_EXTENDED) { + } else if (frameType == SAME_FRAME_EXTENDED) { stack = List.of(); - } else if (frameType < SAME_EXTENDED + 4) { + } else if (frameType <= APPEND_FRAME_END) { int actSize = locals.size(); - var newLocals = locals.toArray(new VerificationTypeInfo[actSize + frameType - SAME_EXTENDED]); + var newLocals = locals.toArray(new VerificationTypeInfo[actSize + frameType - SAME_FRAME_EXTENDED]); for (int i = actSize; i < newLocals.length; i++) newLocals[i] = readVerificationTypeInfo(); locals = List.of(newLocals); 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 eb17e99a94d..0395307262a 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 @@ -166,7 +166,8 @@ static StackMapGenerator of(DirectCodeBuilder dcb, BufWriterImpl buf) { private static final int T_BOOLEAN = 4, T_LONG = 11; private static final Frame[] EMPTY_FRAME_ARRAY = {}; - private static final int ITEM_TOP = 0, + public static final int + ITEM_TOP = 0, ITEM_INTEGER = 1, ITEM_FLOAT = 2, ITEM_DOUBLE = 3, @@ -180,7 +181,22 @@ static StackMapGenerator of(DirectCodeBuilder dcb, BufWriterImpl buf) { ITEM_SHORT = 11, ITEM_CHAR = 12, ITEM_LONG_2ND = 13, - ITEM_DOUBLE_2ND = 14; + ITEM_DOUBLE_2ND = 14, + ITEM_BOGUS = -1; + + // Ranges represented by these constants are inclusive on both ends + public static final int + SAME_FRAME_END = 63, + SAME_LOCALS_1_STACK_ITEM_FRAME_START = 64, + SAME_LOCALS_1_STACK_ITEM_FRAME_END = 127, + RESERVED_END = 246, + SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247, + CHOP_FRAME_START = 248, + CHOP_FRAME_END = 250, + SAME_FRAME_EXTENDED = 251, + APPEND_FRAME_START = 252, + APPEND_FRAME_END = 254, + FULL_FRAME = 255; private static final Type[] ARRAY_FROM_BASIC_TYPE = {null, null, null, null, Type.BOOLEAN_ARRAY_TYPE, Type.CHAR_ARRAY_TYPE, Type.FLOAT_ARRAY_TYPE, Type.DOUBLE_ARRAY_TYPE, @@ -1229,25 +1245,25 @@ void writeTo(BufWriterImpl out, Frame prevFrame, ConstantPoolBuilder cp) { int commonLocalsSize = localsSize > prevFrame.localsSize ? prevFrame.localsSize : localsSize; int diffLocalsSize = localsSize - prevFrame.localsSize; if (-3 <= diffLocalsSize && diffLocalsSize <= 3 && equals(locals, prevFrame.locals, commonLocalsSize)) { - if (diffLocalsSize == 0 && offsetDelta < 64) { //same frame + if (diffLocalsSize == 0 && offsetDelta <= SAME_FRAME_END) { //same frame out.writeU1(offsetDelta); } else { //chop, same extended or append frame - out.writeU1U2(251 + diffLocalsSize, offsetDelta); + out.writeU1U2(SAME_FRAME_EXTENDED + diffLocalsSize, offsetDelta); for (int i=commonLocalsSize; i hashes) { private int stackMapFrameSize(StackMapFrameInfo frame) { int ft = frame.frameType(); - if (ft < 64) return 1; - if (ft < 128) return 1 + verificationTypeSize(frame.stack().getFirst()); - if (ft > 246) { - if (ft == 247) return 3 + verificationTypeSize(frame.stack().getFirst()); - if (ft < 252) return 3; - if (ft < 255) { + if (ft <= SAME_FRAME_END) return 1; + if (ft <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) return 1 + verificationTypeSize(frame.stack().getFirst()); + if (ft > RESERVED_END) { + if (ft == SAME_LOCALS_1_STACK_ITEM_EXTENDED) return 3 + verificationTypeSize(frame.stack().getFirst()); + if (ft <= SAME_FRAME_EXTENDED) return 3; + if (ft <= APPEND_FRAME_END) { var loc = frame.locals(); int l = 3; - for (int i = loc.size() + 251 - ft; i < loc.size(); i++) { + var k = ft - APPEND_FRAME_START + 1; + for (int i = loc.size() - k; i < loc.size(); i++) { l += verificationTypeSize(loc.get(i)); } return l; } - if (ft == 255) { + if (ft == FULL_FRAME) { int l = 7; for (var vt : frame.stack()) { l += verificationTypeSize(vt); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java index 0c4131dd1ba..caa83019f09 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java @@ -24,9 +24,10 @@ */ package jdk.internal.classfile.impl.verifier; -import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_Object; -import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_Uninitialized; -import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_UninitializedThis; +import java.util.ArrayList; +import java.util.List; + +import static jdk.internal.classfile.impl.StackMapGenerator.*; /** * @see hotspot/share/classfile/stackMapTable.hpp @@ -158,11 +159,6 @@ void check_verification_type_array_size(int size, int max_size) { } } - private static final int - SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247, - SAME_EXTENDED = 251, - FULL = 255; - public int get_frame_count() { return _frame_count; } @@ -204,10 +200,10 @@ int chop(VerificationType[] locals, int length, int chops) { VerificationType parse_verification_type(int[] flags) { int tag = _stream.get_u1(); - if (tag < ITEM_UninitializedThis) { + if (tag < ITEM_UNINITIALIZED_THIS) { return VerificationType.from_tag(tag, _verifier); } - if (tag == ITEM_Object) { + if (tag == ITEM_OBJECT) { int class_index = _stream.get_u2(); int nconstants = _cp.entryCount(); if (class_index <= 0 || class_index >= nconstants || _cp.tagAt(class_index) != VerifierImpl.JVM_CONSTANT_Class) { @@ -215,13 +211,13 @@ VerificationType parse_verification_type(int[] flags) { } return VerificationType.reference_type(_cp.classNameAt(class_index)); } - if (tag == ITEM_UninitializedThis) { + if (tag == ITEM_UNINITIALIZED_THIS) { if (flags != null) { flags[0] |= VerificationFrame.FLAG_THIS_UNINIT; } return VerificationType.uninitialized_this_type; } - if (tag == ITEM_Uninitialized) { + if (tag == ITEM_UNINITIALIZED) { int offset = _stream.get_u2(); if (offset >= _code_length || _code_data[offset] != VerifierImpl.NEW_OFFSET) { _verifier.classError("StackMapTable format error: bad offset for Uninitialized"); @@ -237,8 +233,8 @@ public VerificationFrame next(VerificationFrame pre_frame, boolean first, int ma int offset; VerificationType[] locals = null; int frame_type = _stream.get_u1(); - if (frame_type < 64) { - if (first) { + if (frame_type <= SAME_FRAME_END) { + if (_first) { offset = frame_type; if (pre_frame.locals_size() > 0) { locals = new VerificationType[pre_frame.locals_size()]; @@ -253,15 +249,15 @@ public VerificationFrame next(VerificationFrame pre_frame, boolean first, int ma } return frame; } - if (frame_type < 128) { - if (first) { - offset = frame_type - 64; - if (pre_frame.locals_size() > 0) { - locals = new VerificationType[pre_frame.locals_size()]; + if (frame_type <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) { + if (_first) { + offset = frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_START; + if (_prev_frame.locals_size() > 0) { + locals = new VerificationType[_prev_frame.locals_size()]; } } else { - offset = pre_frame.offset() + frame_type - 63; - locals = pre_frame.locals(); + offset = _prev_frame.offset() + frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_START + 1; + locals = _prev_frame.locals(); } VerificationType[] stack = new VerificationType[2]; int stack_size = 1; @@ -305,10 +301,10 @@ public VerificationFrame next(VerificationFrame pre_frame, boolean first, int ma } return frame; } - if (frame_type <= SAME_EXTENDED) { - locals = pre_frame.locals(); - int length = pre_frame.locals_size(); - int chops = SAME_EXTENDED - frame_type; + if (frame_type <= SAME_FRAME_EXTENDED) { + locals = _prev_frame.locals(); + int length = _prev_frame.locals_size(); + int chops = SAME_FRAME_EXTENDED - frame_type; int new_length = length; int flags = pre_frame.flags(); if (chops != 0) { @@ -337,9 +333,9 @@ public VerificationFrame next(VerificationFrame pre_frame, boolean first, int ma frame.copy_locals(pre_frame); } return frame; - } else if (frame_type < SAME_EXTENDED + 4) { - int appends = frame_type - SAME_EXTENDED; - int real_length = pre_frame.locals_size(); + } else if (frame_type <= APPEND_FRAME_END) { + int appends = frame_type - APPEND_FRAME_START + 1; + int real_length = _prev_frame.locals_size(); int new_length = real_length + appends*2; locals = new VerificationType[new_length]; VerificationType[] pre_locals = pre_frame.locals(); @@ -365,7 +361,7 @@ public VerificationFrame next(VerificationFrame pre_frame, boolean first, int ma frame = new VerificationFrame(offset, flags[0], real_length, 0, max_locals, max_stack, locals, null, _verifier); return frame; } - if (frame_type == FULL) { + if (frame_type == FULL_FRAME) { int flags[] = new int[]{0}; int locals_size = _stream.get_u2(); int real_locals_size = 0; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationType.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationType.java index 3fb98195cee..d6f17fb6b12 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationType.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationType.java @@ -33,6 +33,7 @@ import jdk.internal.classfile.impl.ClassHierarchyImpl; import jdk.internal.classfile.impl.Util; +import static jdk.internal.classfile.impl.StackMapGenerator.*; import static jdk.internal.classfile.impl.verifier.VerifierImpl.*; /** @@ -43,18 +44,6 @@ class VerificationType { private static final int BitsPerByte = 8; - static final int - ITEM_Top = 0, - ITEM_Integer = 1, - ITEM_Float = 2, - ITEM_Double = 3, - ITEM_Long = 4, - ITEM_Null = 5, - ITEM_UninitializedThis = 6, - ITEM_Object = 7, - ITEM_Uninitialized = 8, - ITEM_Bogus = -1; - VerificationType(String sym) { _data = 0x100; _sym = sym; @@ -95,9 +84,6 @@ public String toString() { String name() { return _sym; } - private static final int - ITEM_Boolean = 9, ITEM_Byte = 10, ITEM_Short = 11, ITEM_Char = 12, - ITEM_Long_2nd = 13, ITEM_Double_2nd = 14; private static final int TypeMask = 0x00000003, @@ -119,17 +105,17 @@ String name() { Category2_2nd = (Category2_2ndFlag << BitsPerByte) | Primitive, // Primitive values (type discriminator stored in most-significant bytes) // Bogus needs the " | Primitive". Else, isReference(Bogus) returns TRUE. - Bogus = (ITEM_Bogus << 2 * BitsPerByte) | Primitive, - Boolean = (ITEM_Boolean << 2 * BitsPerByte) | Category1, - Byte = (ITEM_Byte << 2 * BitsPerByte) | Category1, - Short = (ITEM_Short << 2 * BitsPerByte) | Category1, - Char = (ITEM_Char << 2 * BitsPerByte) | Category1, - Integer = (ITEM_Integer << 2 * BitsPerByte) | Category1, - Float = (ITEM_Float << 2 * BitsPerByte) | Category1, - Long = (ITEM_Long << 2 * BitsPerByte) | Category2, - Double = (ITEM_Double << 2 * BitsPerByte) | Category2, - Long_2nd = (ITEM_Long_2nd << 2 * BitsPerByte) | Category2_2nd, - Double_2nd = (ITEM_Double_2nd << 2 * BitsPerByte) | Category2_2nd, + Bogus = (ITEM_BOGUS << 2 * BitsPerByte) | Primitive, + Boolean = (ITEM_BOOLEAN << 2 * BitsPerByte) | Category1, + Byte = (ITEM_BYTE << 2 * BitsPerByte) | Category1, + Short = (ITEM_SHORT << 2 * BitsPerByte) | Category1, + Char = (ITEM_CHAR << 2 * BitsPerByte) | Category1, + Integer = (ITEM_INTEGER << 2 * BitsPerByte) | Category1, + Float = (ITEM_FLOAT << 2 * BitsPerByte) | Category1, + Long = (ITEM_LONG << 2 * BitsPerByte) | Category2, + Double = (ITEM_DOUBLE << 2 * BitsPerByte) | Category2, + Long_2nd = (ITEM_LONG_2ND << 2 * BitsPerByte) | Category2_2nd, + Double_2nd = (ITEM_DOUBLE_2ND << 2 * BitsPerByte) | Category2_2nd, // Used by Uninitialized (second and third bytes hold the bci) BciMask = 0xffff << BitsPerByte, // A bci of -1 is an Uninitialized-This @@ -367,12 +353,12 @@ int dimensions(VerifierImpl context) { static VerificationType from_tag(int tag, VerifierImpl context) { switch (tag) { - case ITEM_Top: return bogus_type; - case ITEM_Integer: return integer_type; - case ITEM_Float: return float_type; - case ITEM_Double: return double_type; - case ITEM_Long: return long_type; - case ITEM_Null: return null_type; + case ITEM_TOP: return bogus_type; + case ITEM_INTEGER: return integer_type; + case ITEM_FLOAT: return float_type; + case ITEM_DOUBLE: return double_type; + case ITEM_LONG: return long_type; + case ITEM_NULL: return null_type; default: context.verifyError("Should not reach here"); return bogus_type;