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.constant.ClassDesc; 34 import java.util.List; 35 36 import jdk.internal.classfile.impl.StackMapDecoder; 37 import jdk.internal.classfile.impl.TemporaryConstantPool; 38 39 /** 40 * Models a stack map frame in a {@link StackMapTableAttribute StackMapTable} 41 * attribute (JVMS {@jvms 4.7.4}). A stack map frame must appear at the 42 * beginning of each basic block in a method (JVMS {@jvms 4.10.1}). 43 * 44 * @apiNote 45 * In general, a stack map frame should be defined for each target of a 46 * {@link BranchInstruction}, or unreachable code right after an unconditional 47 * branch instruction like {@link Opcode#GOTO goto}. The automatic stack map 48 * generation cannot handle unreachable code right after an unconditional jump; 49 * The {@link ClassFile.DeadCodeOption} allows substituting such code, or 50 * advanced users can provide their own stack maps for dead code. 51 * 52 * @see StackMapTableAttribute#entries() 53 * @jvms 4.7.4 The {@code StackMapTable} Attribute 54 * @jvms 4.10.1 Verification by Type Checking 55 * @since 24 56 */ 57 public sealed interface StackMapFrameInfo 58 permits StackMapDecoder.StackMapFrameImpl { 59 60 /** 61 * {@return the raw {@code u1 frame_type}} 62 */ 63 int frameType(); 64 65 /** 66 * {@return the frame target label} 67 */ 68 Label target(); 69 70 /** 71 * {@return the expanded local variable types} 72 */ 73 List<VerificationTypeInfo> locals(); 74 75 /** 76 * {@return the expanded operand stack types} 77 */ 78 List<VerificationTypeInfo> stack(); 79 80 /** 81 * {@return a new stack map frame} 82 * 83 * @param target the location of the frame 84 * @param locals the complete list of frame locals 85 * @param stack the complete frame stack 86 * @throws IllegalArgumentException if the number of types in {@code locals} 87 * or {@code stack} exceeds the limit of {@link java.lang.classfile##u2 u2} 88 */ 89 public static StackMapFrameInfo of(Label target, 90 List<VerificationTypeInfo> locals, 91 List<VerificationTypeInfo> stack) { 92 return new StackMapDecoder.StackMapFrameImpl(255, target, locals, stack); 93 } 94 95 /** 96 * The type of a stack or local variable value. 97 * 98 * @see #locals() 99 * @see #stack() 100 * @jvms 4.7.4 The {@code StackMapTable} Attribute 101 * @since 24 102 */ 103 sealed interface VerificationTypeInfo { 104 105 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#TOP TOP}. */ 106 int ITEM_TOP = 0; 107 108 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#INTEGER INTEGER}. */ 109 int ITEM_INTEGER = 1; 110 111 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#FLOAT FLOAT}. */ 112 int ITEM_FLOAT = 2; 113 114 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#DOUBLE DOUBLE}. */ 115 int ITEM_DOUBLE = 3; 116 117 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#LONG LONG}. */ 118 int ITEM_LONG = 4; 119 120 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#NULL NULL}. */ 121 int ITEM_NULL = 5; 122 123 /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#UNINITIALIZED_THIS UNINITIALIZED_THIS}. */ 124 int ITEM_UNINITIALIZED_THIS = 6; 125 126 /** The {@link #tag() tag} for verification type info {@link ObjectVerificationTypeInfo OBJECT}. */ 127 int ITEM_OBJECT = 7; 128 129 /** The {@link #tag() tag} for verification type info {@link UninitializedVerificationTypeInfo UNINITIALIZED}. */ 130 int ITEM_UNINITIALIZED = 8; 131 132 /** 133 * {@return the tag of the type info} 134 * 135 * @apiNote 136 * {@code ITEM_}-prefixed constants in this class, such as {@link #ITEM_TOP}, describe the 137 * possible return values of this method. 138 */ 139 int tag(); 140 } 141 142 /** 143 * A simple stack value. 144 * 145 * @since 24 146 */ 147 public enum SimpleVerificationTypeInfo implements VerificationTypeInfo { 148 149 /** Verification type top. */ 150 TOP(ITEM_TOP), 151 152 /** Verification type int. */ 153 INTEGER(ITEM_INTEGER), 154 155 /** Verification type float. */ 156 FLOAT(ITEM_FLOAT), 157 158 /** Verification type double. */ 159 DOUBLE(ITEM_DOUBLE), 160 161 /** Verification type long. */ 162 LONG(ITEM_LONG), 163 164 /** Verification type null. */ 165 NULL(ITEM_NULL), 166 167 /** Verification type uninitializedThis. */ 168 UNINITIALIZED_THIS(ITEM_UNINITIALIZED_THIS); 169 170 171 private final int tag; 172 173 SimpleVerificationTypeInfo(int tag) { 174 this.tag = tag; 175 } 176 177 @Override 178 public int tag() { 179 return tag; 180 } 181 } 182 183 /** 184 * A stack value for an object type. Its {@link #tag() tag} is {@value #ITEM_OBJECT}. 185 * 186 * @jvms 4.7.4 The {@code StackMapTable} Attribute 187 * @since 24 188 */ 189 sealed interface ObjectVerificationTypeInfo extends VerificationTypeInfo 190 permits StackMapDecoder.ObjectVerificationTypeInfoImpl { 191 192 /** 193 * {@return a new object verification type info} 194 * @param className the class of the object 195 */ 196 public static ObjectVerificationTypeInfo of(ClassEntry className) { 197 return new StackMapDecoder.ObjectVerificationTypeInfoImpl(className); 198 } 199 200 /** 201 * {@return a new object verification type info} 202 * @param classDesc the class of the object 203 * @throws IllegalArgumentException if {@code classDesc} represents a primitive type 204 */ 205 public static ObjectVerificationTypeInfo of(ClassDesc classDesc) { 206 return of(TemporaryConstantPool.INSTANCE.classEntry(classDesc)); 207 } 208 209 /** 210 * {@return the class of the object} 211 */ 212 ClassEntry className(); 213 214 /** 215 * {@return the class of the object, as a symbolic descriptor} 216 */ 217 default ClassDesc classSymbol() { 218 return className().asSymbol(); 219 } 220 } 221 222 /** 223 * An uninitialized stack value. Its {@link #tag() tag} is {@value #ITEM_UNINITIALIZED}. 224 * 225 * @jvms 4.7.4 The {@code StackMapTable} Attribute 226 * @since 24 227 */ 228 sealed interface UninitializedVerificationTypeInfo extends VerificationTypeInfo 229 permits StackMapDecoder.UninitializedVerificationTypeInfoImpl { 230 231 /** 232 * {@return the label immediately before the {@link Opcode#NEW new} 233 * instruction that creates this uninitialized object} 234 */ 235 Label newTarget(); 236 237 /** 238 * {@return an uninitialized verification type info} 239 * @param newTarget the label immediately before the {@link Opcode#NEW new} 240 * instruction that creates this uninitialized object 241 */ 242 public static UninitializedVerificationTypeInfo of(Label newTarget) { 243 return new StackMapDecoder.UninitializedVerificationTypeInfoImpl(newTarget); 244 } 245 } 246 }