1 /* 2 * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.classfile.attribute; 27 28 import java.lang.classfile.ClassFile; 29 import java.lang.classfile.Label; 30 import java.lang.classfile.Opcode; 31 import java.lang.classfile.constantpool.ClassEntry; 32 import java.lang.classfile.instruction.BranchInstruction; 33 import java.lang.classfile.constantpool.NameAndTypeEntry; 34 import java.lang.constant.ClassDesc; 35 import java.util.List; 36 37 import jdk.internal.classfile.impl.StackMapDecoder; 38 import jdk.internal.classfile.impl.TemporaryConstantPool; 39 40 /** 41 * Models a stack map frame in a {@link StackMapTableAttribute StackMapTable} 42 * attribute (JVMS {@jvms 4.7.4}). A stack map frame must appear at the 43 * beginning of each basic block in a method (JVMS {@jvms 4.10.1}). 44 * 45 * @apiNote 46 * In general, a stack map frame should be defined for each target of a 47 * {@link BranchInstruction}, or unreachable code right after an unconditional 48 * branch instruction like {@link Opcode#GOTO goto}. The automatic stack map 49 * generation cannot handle unreachable code right after an unconditional jump; 50 * The {@link ClassFile.DeadCodeOption} allows substituting such code, or 51 * advanced users can provide their own stack maps for dead code. 52 * 53 * @see StackMapTableAttribute#entries() 54 * @jvms 4.7.4 The {@code StackMapTable} Attribute 55 * @jvms 4.10.1 Verification by Type Checking 56 * @since 24 57 */ 58 public sealed interface StackMapFrameInfo 59 permits StackMapDecoder.StackMapFrameImpl { 60 61 /** 62 * {@return the raw {@code u1 frame_type}} 63 */ 64 int frameType(); 65 66 /** 67 * {@return the frame target label} 68 */ 69 Label target(); 70 71 /** 72 * {@return the expanded local variable types} 73 */ 74 List<VerificationTypeInfo> locals(); 75 76 /** 77 * {@return the expanded operand stack types} 78 */ 79 List<VerificationTypeInfo> stack(); 80 81 /** 82 * {@return the expanded unset fields} 83 * 84 * @see <a href="https://cr.openjdk.org/~dlsmith/jep401/jep401-20250409/specs/strict-fields-jvms.html">Specs</a> 85 */ 86 List<NameAndTypeEntry> unsetFields(); 87 88 /** 89 * {@return a new stack map frame} 90 * 91 * @param target the location of the frame 92 * @param locals the complete list of frame locals 93 * @param stack the complete frame stack 94 */ 95 public static StackMapFrameInfo of(Label target, 96 List<VerificationTypeInfo> locals, 97 List<VerificationTypeInfo> stack) { 98 99 return of(target, locals, stack, List.of()); 100 } 101 102 /** 103 * {@return a new stack map frame} 104 * @param target the location of the frame 105 * @param locals the complete list of frame locals 106 * @param stack the complete frame stack 107 * @param unsetFields the complete list of unset fields 108 * @throws IllegalArgumentException if unset fields has entries but no 109 * {@link SimpleVerificationTypeInfo#UNINITIALIZED_THIS uninitializedThis} 110 * is present in {@code locals} 111 */ 112 public static StackMapFrameInfo of(Label target, 113 List<VerificationTypeInfo> locals, 114 List<VerificationTypeInfo> stack, 115 List<NameAndTypeEntry> unsetFields) { 116 117 return new StackMapDecoder.StackMapFrameImpl(255, target, locals, stack, unsetFields); 118 } 119 120 /** 121 * The type of a stack or local variable value. 122 * 123 * @see #locals() 124 * @see #stack() 125 * @jvms 4.7.4 The {@code StackMapTable} Attribute 126 * @since 24 127 */ 128 sealed interface VerificationTypeInfo { 129 130 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#TOP TOP}. */ 131 int ITEM_TOP = 0; 132 133 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#INTEGER INTEGER}. */ 134 int ITEM_INTEGER = 1; 135 136 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#FLOAT FLOAT}. */ 137 int ITEM_FLOAT = 2; 138 139 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#DOUBLE DOUBLE}. */ 140 int ITEM_DOUBLE = 3; 141 142 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#LONG LONG}. */ 143 int ITEM_LONG = 4; 144 145 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#NULL NULL}. */ 146 int ITEM_NULL = 5; 147 148 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#UNINITIALIZED_THIS UNINITIALIZED_THIS}. */ 149 int ITEM_UNINITIALIZED_THIS = 6; 150 151 /** The {@link #tag() tag} for verification type info {@link ObjectVerificationTypeInfo OBJECT}. */ 152 int ITEM_OBJECT = 7; 153 154 /** The {@link #tag() tag} for verification type info {@link UninitializedVerificationTypeInfo UNINITIALIZED}. */ 155 int ITEM_UNINITIALIZED = 8; 156 157 /** 158 * {@return the tag of the type info} 159 * 160 * @apiNote 161 * {@code ITEM_}-prefixed constants in this class, such as {@link #ITEM_TOP}, describe the 162 * possible return values of this method. 163 */ 164 int tag(); 165 } 166 167 /** 168 * A simple stack value. 169 * 170 * @since 24 171 */ 172 public enum SimpleVerificationTypeInfo implements VerificationTypeInfo { 173 174 /** Verification type top. */ 175 TOP(ITEM_TOP), 176 177 /** Verification type int. */ 178 INTEGER(ITEM_INTEGER), 179 180 /** Verification type float. */ 181 FLOAT(ITEM_FLOAT), 182 183 /** Verification type double. */ 184 DOUBLE(ITEM_DOUBLE), 185 186 /** Verification type long. */ 187 LONG(ITEM_LONG), 188 189 /** Verification type null. */ 190 NULL(ITEM_NULL), 191 192 /** Verification type uninitializedThis. */ 193 UNINITIALIZED_THIS(ITEM_UNINITIALIZED_THIS); 194 195 196 private final int tag; 197 198 SimpleVerificationTypeInfo(int tag) { 199 this.tag = tag; 200 } 201 202 @Override 203 public int tag() { 204 return tag; 205 } 206 } 207 208 /** 209 * A stack value for an object type. Its {@link #tag() tag} is {@value #ITEM_OBJECT}. 210 * 211 * @jvms 4.7.4 The {@code StackMapTable} Attribute 212 * @since 24 213 */ 214 sealed interface ObjectVerificationTypeInfo extends VerificationTypeInfo 215 permits StackMapDecoder.ObjectVerificationTypeInfoImpl { 216 217 /** 218 * {@return a new object verification type info} 219 * @param className the class of the object 220 */ 221 public static ObjectVerificationTypeInfo of(ClassEntry className) { 222 return new StackMapDecoder.ObjectVerificationTypeInfoImpl(className); 223 } 224 225 /** 226 * {@return a new object verification type info} 227 * @param classDesc the class of the object 228 * @throws IllegalArgumentException if {@code classDesc} represents a primitive type 229 */ 230 public static ObjectVerificationTypeInfo of(ClassDesc classDesc) { 231 return of(TemporaryConstantPool.INSTANCE.classEntry(classDesc)); 232 } 233 234 /** 235 * {@return the class of the object} 236 */ 237 ClassEntry className(); 238 239 /** 240 * {@return the class of the object, as a symbolic descriptor} 241 */ 242 default ClassDesc classSymbol() { 243 return className().asSymbol(); 244 } 245 } 246 247 /** 248 * An uninitialized stack value. Its {@link #tag() tag} is {@value #ITEM_UNINITIALIZED}. 249 * 250 * @jvms 4.7.4 The {@code StackMapTable} Attribute 251 * @since 24 252 */ 253 sealed interface UninitializedVerificationTypeInfo extends VerificationTypeInfo 254 permits StackMapDecoder.UninitializedVerificationTypeInfoImpl { 255 256 /** 257 * {@return the label immediately before the {@link Opcode#NEW new} 258 * instruction that creates this uninitialized object} 259 */ 260 Label newTarget(); 261 262 /** 263 * {@return an uninitialized verification type info} 264 * @param newTarget the label immediately before the {@link Opcode#NEW new} 265 * instruction that creates this uninitialized object 266 */ 267 public static UninitializedVerificationTypeInfo of(Label newTarget) { 268 return new StackMapDecoder.UninitializedVerificationTypeInfoImpl(newTarget); 269 } 270 } 271 }