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-20241108/specs/value-objects-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 */ 109 public static StackMapFrameInfo of(Label target, 110 List<VerificationTypeInfo> locals, 111 List<VerificationTypeInfo> stack, 112 List<NameAndTypeEntry> unsetFields) { 113 114 return new StackMapDecoder.StackMapFrameImpl(255, target, locals, stack, unsetFields); 115 } 116 117 /** 118 * The type of a stack or local variable value. 119 * 120 * @see #locals() 121 * @see #stack() 122 * @jvms 4.7.4 The {@code StackMapTable} Attribute 123 * @since 24 124 */ 125 sealed interface VerificationTypeInfo { 126 127 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#TOP TOP}. */ 128 int ITEM_TOP = 0; 129 130 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#INTEGER INTEGER}. */ 131 int ITEM_INTEGER = 1; 132 133 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#FLOAT FLOAT}. */ 134 int ITEM_FLOAT = 2; 135 136 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#DOUBLE DOUBLE}. */ 137 int ITEM_DOUBLE = 3; 138 139 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#LONG LONG}. */ 140 int ITEM_LONG = 4; 141 142 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#NULL NULL}. */ 143 int ITEM_NULL = 5; 144 145 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#UNINITIALIZED_THIS UNINITIALIZED_THIS}. */ 146 int ITEM_UNINITIALIZED_THIS = 6; 147 148 /** The {@link #tag() tag} for verification type info {@link ObjectVerificationTypeInfo OBJECT}. */ 149 int ITEM_OBJECT = 7; 150 151 /** The {@link #tag() tag} for verification type info {@link UninitializedVerificationTypeInfo UNINITIALIZED}. */ 152 int ITEM_UNINITIALIZED = 8; 153 154 /** 155 * {@return the tag of the type info} 156 * 157 * @apiNote 158 * {@code ITEM_}-prefixed constants in this class, such as {@link #ITEM_TOP}, describe the 159 * possible return values of this method. 160 */ 161 int tag(); 162 } 163 164 /** 165 * A simple stack value. 166 * 167 * @since 24 168 */ 169 public enum SimpleVerificationTypeInfo implements VerificationTypeInfo { 170 171 /** Verification type top. */ 172 TOP(ITEM_TOP), 173 174 /** Verification type int. */ 175 INTEGER(ITEM_INTEGER), 176 177 /** Verification type float. */ 178 FLOAT(ITEM_FLOAT), 179 180 /** Verification type double. */ 181 DOUBLE(ITEM_DOUBLE), 182 183 /** Verification type long. */ 184 LONG(ITEM_LONG), 185 186 /** Verification type null. */ 187 NULL(ITEM_NULL), 188 189 /** Verification type uninitializedThis. */ 190 UNINITIALIZED_THIS(ITEM_UNINITIALIZED_THIS); 191 192 193 private final int tag; 194 195 SimpleVerificationTypeInfo(int tag) { 196 this.tag = tag; 197 } 198 199 @Override 200 public int tag() { 201 return tag; 202 } 203 } 204 205 /** 206 * A stack value for an object type. Its {@link #tag() tag} is {@value #ITEM_OBJECT}. 207 * 208 * @jvms 4.7.4 The {@code StackMapTable} Attribute 209 * @since 24 210 */ 211 sealed interface ObjectVerificationTypeInfo extends VerificationTypeInfo 212 permits StackMapDecoder.ObjectVerificationTypeInfoImpl { 213 214 /** 215 * {@return a new object verification type info} 216 * @param className the class of the object 217 */ 218 public static ObjectVerificationTypeInfo of(ClassEntry className) { 219 return new StackMapDecoder.ObjectVerificationTypeInfoImpl(className); 220 } 221 222 /** 223 * {@return a new object verification type info} 224 * @param classDesc the class of the object 225 * @throws IllegalArgumentException if {@code classDesc} represents a primitive type 226 */ 227 public static ObjectVerificationTypeInfo of(ClassDesc classDesc) { 228 return of(TemporaryConstantPool.INSTANCE.classEntry(classDesc)); 229 } 230 231 /** 232 * {@return the class of the object} 233 */ 234 ClassEntry className(); 235 236 /** 237 * {@return the class of the object, as a symbolic descriptor} 238 */ 239 default ClassDesc classSymbol() { 240 return className().asSymbol(); 241 } 242 } 243 244 /** 245 * An uninitialized stack value. Its {@link #tag() tag} is {@value #ITEM_UNINITIALIZED}. 246 * 247 * @jvms 4.7.4 The {@code StackMapTable} Attribute 248 * @since 24 249 */ 250 sealed interface UninitializedVerificationTypeInfo extends VerificationTypeInfo 251 permits StackMapDecoder.UninitializedVerificationTypeInfoImpl { 252 253 /** 254 * {@return the label immediately before the {@link Opcode#NEW new} 255 * instruction that creates this uninitialized object} 256 */ 257 Label newTarget(); 258 259 /** 260 * {@return an uninitialized verification type info} 261 * @param newTarget the label immediately before the {@link Opcode#NEW new} 262 * instruction that creates this uninitialized object 263 */ 264 public static UninitializedVerificationTypeInfo of(Label newTarget) { 265 return new StackMapDecoder.UninitializedVerificationTypeInfoImpl(newTarget); 266 } 267 } 268 }