/* * Copyright (c) 2023, 2025, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.lang.classfile.instruction; import java.lang.classfile.*; import java.lang.classfile.attribute.StackMapTableAttribute; import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; import jdk.internal.classfile.impl.Util; /** * Marker interface for instruction discontinued from the {@code code} array of * a {@code Code} attribute. Delivered as a {@link CodeElement} when traversing * the elements of a {@link CodeModel}. * * @apiNote * While most instructions have convenience factory methods in {@link * CodeBuilder}, discontinued instructions can only be supplied to code builders * explicitly with {@link CodeBuilder#with CodeBuilder::with} to discourage * their use. * * @jvms 4.9.1 Static Constraints * @sealedGraph * @since 24 */ public sealed interface DiscontinuedInstruction extends Instruction { /** * Models jump subroutine instructions discontinued from the {@code code} * array of a {@code Code} attribute since class file major version {@value * ClassFile#JAVA_7_VERSION} (JVMS {@jvms 4.9.1}). Corresponding opcodes * have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#DISCONTINUED_JSR}. * Delivered as a {@link CodeElement} when traversing the elements of a * {@link CodeModel}. *

* A jump subroutine instruction is composite: * {@snippet lang=text : * // @link substring="JsrInstruction" target="#of(Label)" : * JsrInstruction(Label target) // @link substring="target" target="#target()" * } *

* Due to physical restrictions, {@link Opcode#JSR jsr} instructions cannot * encode labels too far away in the list of code elements. In such cases, * the {@link ClassFile.ShortJumpsOption} controls how an invalid {@code jsr} * instruction model is written by a {@link CodeBuilder}. *

* Jump subroutine instructions push a {@link TypeKind##returnAddress * returnAddress} value to the operand stack, and {@link StoreInstruction * astore} series of instructions can then store this value to a local * variable slot. * * @apiNote * Jump subroutine instructions are discontinued to enforce verification by * type checking (JVMS {@jvms 4.10.1}) using the {@link StackMapTableAttribute * StackMapTable} attribute. * * @see Opcode.Kind#DISCONTINUED_JSR * @see StackMapTableAttribute * @since 24 */ sealed interface JsrInstruction extends DiscontinuedInstruction permits AbstractInstruction.BoundJsrInstruction, AbstractInstruction.UnboundJsrInstruction { /** * {@return the target of the jump subroutine instruction} */ Label target(); /** * {@return a jump subroutine instruction} * * @apiNote * The explicit {@code op} argument allows creating {@link Opcode#JSR_W * jsr_w} instructions to avoid short jumps. * * @param op the opcode for the specific type of jump subroutine instruction, * which must be of kind {@link Opcode.Kind#DISCONTINUED_JSR} * @param target target label of the subroutine * @throws IllegalArgumentException if the opcode kind is not * {@link Opcode.Kind#DISCONTINUED_JSR}. */ static JsrInstruction of(Opcode op, Label target) { Util.checkKind(op, Opcode.Kind.DISCONTINUED_JSR); return new AbstractInstruction.UnboundJsrInstruction(op, target); } /** * {@return a jump subroutine instruction} * * @param target target label of the subroutine */ static JsrInstruction of(Label target) { return of(Opcode.JSR, target); } } /** * Models return from subroutine instructions discontinued from the {@code * code} array of a {@code Code} attribute since class file major version * {@value ClassFile#JAVA_7_VERSION} (JVMS {@jvms 4.9.1}). * Corresponding opcodes have a {@linkplain Opcode#kind() kind} of * {@link Opcode.Kind#DISCONTINUED_RET}. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. *

* A return from subroutine instruction is composite: * {@snippet lang=text : * // @link substring="RetInstruction" target="#of(int)" : * RetInstruction(int slot) // @link substring="slot" target="#slot()" * } * where {@code slot} must be within {@code [0, 65535]}. *

* {@link StoreInstruction astore} series of instructions store a {@link * TypeKind##returnAddress returnAddress} value to a local variable slot, * making the slot usable by a return from subroutine instruction. * * @apiNote * Return from subroutine instructions are discontinued to enforce * verification by type checking (JVMS {@jvms 4.10.1}) using the {@link * StackMapTableAttribute StackMapTable} attribute. * * @jvms 6.5.ret ret * @see Opcode.Kind#DISCONTINUED_RET * @see StackMapTableAttribute * @since 24 */ sealed interface RetInstruction extends DiscontinuedInstruction permits AbstractInstruction.BoundRetInstruction, AbstractInstruction.UnboundRetInstruction { /** * {@return the local variable slot with return address} * The value is within {@code [0, 65535]}. */ int slot(); /** * {@return a return from subroutine instruction} *

* {@code slot} must be in the closed range of {@code [0, 255]} for * {@link Opcode#RET ret}, or within {@code [0, 65535]} for {@link * Opcode#RET_W wide ret}. * * @apiNote * The explicit {@code op} argument allows creating {@code wide ret} * instructions with {@code slot} in the range of regular {@code ret} * instructions. * * @param op the opcode for the specific type of return from subroutine instruction, * which must be of kind {@link Opcode.Kind#DISCONTINUED_RET} * @param slot the local variable slot to load return address from * @throws IllegalArgumentException if the opcode kind is not * {@link Opcode.Kind#DISCONTINUED_RET} or if {@code slot} is out of range */ static RetInstruction of(Opcode op, int slot) { BytecodeHelpers.validateRet(op, slot); return new AbstractInstruction.UnboundRetInstruction(op, slot); } /** * {@return a return from subroutine instruction} *

* {@code slot} must be within {@code [0, 65535]}. * * @param slot the local variable slot to load return address from * @throws IllegalArgumentException if {@code slot} is out of range */ static RetInstruction of(int slot) { return of(slot < 256 ? Opcode.RET : Opcode.RET_W, slot); } } }