All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.dev.assembler.StackMapTableAttribute Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */
package com.tangosol.dev.assembler;

import com.oracle.coherence.common.collections.ChainedIterator;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
* Represents a Java Virtual Machine "StackMapTable" attribute.
*
* 

* The StackMapTable Attribute was defined by JDK 1.6 under bytecode * version 50.0. The structure is defined as: *

*

* StackMapTable_attribute
*     {
*     u2              attribute_name_index;
*     u4              attribute_length;
*     u2              number_of_entries;
*     stack_map_frame entries[number_of_entries];
*     }
* 
* * @author hr 2012.08.06 */ public class StackMapTableAttribute extends Attribute implements Constants { // ----- constructors --------------------------------------------------- /** * Construct a StackMapTableAttribute under the provided context. * * @param context a related VMStructure object */ protected StackMapTableAttribute(VMStructure context) { super(context, ATTR_STACKMAPTABLE); } // ----- Attribute methods ---------------------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { stream.readInt(); int cFrames = stream.readUnsignedShort(); List listFrames = m_listFrames = new LinkedList(); for (int i = 0; i < cFrames; ++i) { listFrames.add(loadFrame(this, stream, pool)); } } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { stream.writeShort(pool.findConstant(super.getNameConstant())); List listFrames = m_listFrames; int cLength = 2; for (StackMapFrame frame : listFrames) { cLength += frame.size(); } stream.writeInt(cLength); stream.writeShort(listFrames.size()); for (StackMapFrame frame : listFrames) { frame.assemble(stream, pool); } } // ----- accessors ------------------------------------------------------ /** * Return a List of {@link StackMapFrame}'s allowing the list to be * mutated. * * @return a List of StackMapFrame's */ public List getFrames() { return m_listFrames; } // ----- constants ------------------------------------------------------ /** * Create and disassembles a StackMapFrame or return null. * * @param context the StackMapTable attribute this frame belongs to * @param stream DataInput stream to disassemble * @param pool the ConstantPool allowing access to constants * * @return an appropriate StackMapFrame or null * * @throws IOException iff an error occurred during disassembly */ protected static StackMapFrame loadFrame(StackMapTableAttribute context, DataInput stream, ConstantPool pool) throws IOException { StackMapFrame frame = null; int nTag = stream.readUnsignedByte(); if ((nTag & 0xC0) == 0) // same_frame { frame = context.new SameFrame(nTag); } else if ((nTag & 0x80) == 0) // same_locals_1_stack_item_frame { frame = context.new SameLocalsOneStackItemFrame(nTag); } else { switch (nTag) { case 247: // same_locals_1_stack_item_frame_extended frame = context.new SameLocalsOneStackItemFrameExtended(); break; case 248: // chop_frame case 249: case 250: frame = context.new ChopFrame(nTag); break; case 251: //same_frame_extended frame = context.new SameFrameExtended(); break; case 252: // append_frame case 253: case 254: frame = context.new AppendFrame(nTag); break; case 255: // full_frame frame = context.new FullFrame(); break; } } if (frame != null) { frame.disassemble(stream, pool); } return frame; } /** * Creates and disassembles a "verification_type_info" structure into * an instance of {@link StackMapFrame.VariableInfo} or null. * * @param context the StackMapTable attribute this frame belongs to * @param stream DataInput stream to disassemble * @param pool the ConstantPool allowing access to constants * * @return a VariableInfo object or subclass or null * * @throws IOException iff an error occurred during disassembly */ protected static StackMapFrame.VariableInfo loadVariableInfo(StackMapFrame context, DataInput stream, ConstantPool pool) throws IOException { int nTag = stream.readByte(); StackMapFrame.VariableInfo var = null; switch (nTag) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: var = context.new VariableInfo(nTag); break; case 7: var = context.new ObjectVariableInfo(); break; case 8: var = context.new UninitializedVariableInfo(); break; } if (var != null) { var.disassemble(stream, pool); } return var; } // ----- inner class: StackMapFrame ------------------------------------- /** * Represents a Java Virtual Machine "stack_map_frame" structure within * the "StackMapTable" attribute. * *

* The stack_map_frame structure was defined by JDK 1.6 under bytecode * version 50.0. The structure is defined as: *

*

    * union stack_map_frame
    *     {
    *     same_frame;
    *     same_locals_1_stack_item_frame;
    *     same_locals_1_stack_item_frame_extended;
    *     chop_frame;
    *     same_frame_extended;
    *     append_frame;
    *     full_frame;
    *     }
    * 
* * @see SameFrame * @see SameLocalsOneStackItemFrame * @see SameLocalsOneStackItemFrameExtended * @see ChopFrame * @see SameFrameExtended * @see AppendFrame * @see FullFrame */ public abstract class StackMapFrame extends VMStructure implements Constants { // ----- constructors ----------------------------------------------- /** * Construct a StackMapFrame with the provided {@code nTag}. * * @param nTag byte tag representing the type of the stack frame */ public StackMapFrame(int nTag) { m_nTag = nTag; } // ----- VMStructure methods ---------------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { } /** * {@inheritDoc} */ @Override protected void preassemble(ConstantPool pool) { } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { stream.writeByte(m_nTag); } // ----- abstract methods ------------------------------------------- /** * The Code attribute offset this frame refers to. * * @return the Code attribute offset this frame refers to */ public abstract int getOffset(); /** * Returns the size of this frame in bytes. * * @return the size of this frame in bytes */ protected abstract int size(); // ----- inner class: VariableInfo ---------------------------------- /** * A VariableInfo represents an instance of a verification_type_info * structure as specified in 50.0 bytecode specification. The * verification_type_info has the following structure: *
        * union verification_type_info
        *     {
        *     Top_variable_info;
        *     Integer_variable_info;
        *     Float_variable_info;
        *     Long_variable_info;
        *     Double_variable_info;
        *     Null_variable_info;
        *     UninitializedThis_variable_info;
        *     Object_variable_info;
        *     Uninitialized_variable_info;
        *     }
        * 
* This class represents all of the above structures except the final * two that are represented by {@link ObjectVariableInfo} and * {@link UninitializedVariableInfo} respectively. The underlying * types can be distinguished via {@link #getType()}. * * @see VariableInfoType */ public class VariableInfo extends VMStructure implements Constants { // ----- constructors ------------------------------------------- /** * Create a VariableInfo object with the provided byte tag. * * @param nTag a byte tag representing the type of VariableInfo */ public VariableInfo(int nTag) { m_type = VariableInfoType.values()[nTag]; } // ----- accessors ---------------------------------------------- /** * Returns a {@link VariableInfoType} enum representation of the * type of this VariableInfo object. * * @return enum representation of the type of this VariableInfo * object */ public VariableInfoType getType() { return m_type; } // ----- VMStructure methods ------------------------------------ /** * {@inheritDoc} */ protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { } /** * {@inheritDoc} */ protected void preassemble(ConstantPool pool) { } /** * {@inheritDoc} */ protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { stream.writeByte(m_type.ordinal()); } /** * Returns the size of this VariableInfo instance in bytes. * * @return the size of this VariableInfo instance in bytes */ protected int size() { return 1; } // ----- data members ------------------------------------------- /** * Enum representation of the type of this VariableInfo. */ private VariableInfoType m_type; } // ----- inner class: ObjectVariableInfo ---------------------------- /** * A ObjectVariableInfo represents an instance of a VariableInfo * such that the type is {@link VariableInfoType#Object}. The * structure varies from all other types and is defined below: *
        * Object_variable_info
        *     {
        *     u1 tag = ITEM_Object;
        *     u2 cpool_index;
        *     }
        * 
* Opposed to providing the constant pool index this class provides * the constant value. */ public class ObjectVariableInfo extends VariableInfo { // ----- constructors ------------------------------------------- /** * Creates an instance of ObjectVariableInfo. */ public ObjectVariableInfo() { super(VariableInfoType.Object.ordinal()); } // ----- accessors ---------------------------------------------- /** * Returns the constant pool value this object refers to. * * @return the constant pool value this object refers to */ public Constant getName() { return m_objectName; } // ----- VariableInfo methods ----------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { super.disassemble(stream, pool); m_objectName = pool.getConstant(stream.readUnsignedShort()); } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { super.assemble(stream, pool); stream.writeShort(pool.findConstant(m_objectName)); } /** * {@inheritDoc} */ protected int size() { return 3; } // ----- data members ------------------------------------------- /** * The object name this variable info refers to. */ private Constant m_objectName; } // ----- inner class: UninitializedVariableInfo --------------------- /** * A UninitializedVariableInfo represents an instance of a VariableInfo * such that the type is {@link VariableInfoType#Uninitialized}. The * structure varies from all other types and is defined below: *
        * Uninitialized_variable_info
        *     {
        *     u1 tag = ITEM_Uninitialized;
        *     u2 offset;
        *     }
        * 
*/ public class UninitializedVariableInfo extends VariableInfo { // ----- constructors ------------------------------------------- /** * Creates an UninitializedVariableInfo object. */ public UninitializedVariableInfo() { super(VariableInfoType.Uninitialized.ordinal()); } // ----- accessors ---------------------------------------------- /** * Returns the offset of the location in the Code attribute that * this variable info refers to, i.e. the associated new * instruction. * * @return the offset of the location in the Code attribute that * this variable info refers to */ public int getOffset() { return m_nOffset; } // ----- VariableInfo methods ----------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { super.disassemble(stream, pool); m_nOffset = stream.readUnsignedShort(); } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { super.assemble(stream, pool); stream.writeShort(m_nOffset); } /** * {@inheritDoc} */ protected int size() { return 3; } // ----- data members ------------------------------------------- /** * The offset of the location in the Code attribute that * this variable info refers to, i.e. the associated new * instruction. */ private int m_nOffset; } // ----- data members ----------------------------------------------- /** * The byte tag of this stack map frame. */ int m_nTag; /** * The length of this frame in bytes. */ int m_nLength; } // ----- inner class: SameFrame ----------------------------------------- /** * A specialization of the StackMapFrame with the following definition: *
    * SameFrame means the frame has exactly the same locals as the previous
    * stack map frame and that the number of stack items is zero.
    * 
*/ public class SameFrame extends StackMapFrame { // ----- constructors ----------------------------------------------- /** * Constructs a SameFrame instance with the provided byte tag * (0 - 63). * * @param nTag the byte tag within the region for a same_frame */ public SameFrame(int nTag) { super(nTag); } /** * {@inheritDoc} */ public int getOffset() { return m_nTag; } /** * {@inheritDoc} */ protected int size() { return 1; } } // ----- inner class: SameFrame ----------------------------------------- /** * A specialization of the StackMapFrame with the following definition: *
    * SameFrameExtended means the frame has exactly the same locals as the
    * previous stack map frame and that the number of stack items is zero.
    * 
*/ public class SameFrameExtended extends StackMapFrame { // ----- constructors ----------------------------------------------- /** * Constructs a SameFrameExtended instance with the provided byte tag * (251). */ public SameFrameExtended() { super(251); } // ----- accessors -------------------------------------------------- /** * {@inheritDoc} */ public int getOffset() { return m_nOffset; } /** * Set the Code attribute offset this frame refers to. * * @param nOffset */ public void setOffset(int nOffset) { m_nOffset = nOffset; } /** * {@inheritDoc} */ protected int size() { return 3; } // ----- StackMapFrame methods -------------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { super.disassemble(stream, pool); m_nOffset = stream.readUnsignedShort(); } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { super.assemble(stream, pool); stream.writeShort(m_nOffset); } // ----- data members ----------------------------------------------- /** * The Code attribute offset this frame refers to. */ private int m_nOffset; } // ----- inner class: SameLocalsOneStackItemFrame ----------------------- /** * A specialization of the StackMapFrame with the following definition: *
    * SameLocalsOneStackItemFrame means the frame has exactly the same locals
    * as the previous stack map frame and that the number of stack items is 1.
    * 
* The offset can be discovered via {@link #getOffset()}. */ public class SameLocalsOneStackItemFrame extends StackMapFrame { // ----- constructors ----------------------------------------------- /** * Creates a SameLocalsOneStackItemFrame instance. * * @param nTag the byte tag within the region for a * same_locals_1_stack_item_frame */ public SameLocalsOneStackItemFrame(int nTag) { super(nTag); } // ----- accessors -------------------------------------------------- /** * {@inheritDoc} */ public int getOffset() { return m_nTag - 64; } /** * Returns the stack item ({@link VariableInfo}) for this frame. * * @return the stack item for this frame */ public VariableInfo getStack() { return m_stack; } /** * Sets the stack item ({@link VariableInfo}) for this frame. * * @param varInfo the stack item for this frame */ public void setStack(VariableInfo varInfo) { m_stack = varInfo; } /** * {@inheritDoc} */ protected int size() { return 1 + m_stack.size(); } // ----- StackMapFrame methods -------------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { super.disassemble(stream, pool); // verification_type_info tag m_stack = loadVariableInfo(this, stream, pool); } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { super.assemble(stream, pool); if (m_stack != null) { m_stack.assemble(stream, pool); } } // ----- data members ----------------------------------------------- /** * The stack item ({@link VariableInfo}) for this frame. */ VariableInfo m_stack; } // ----- inner class: SameLocalsOneStackItemFrameExtended --------------- /** * A specialization of the StackMapFrame with the following definition: *
    * SameLocalsOneStackItemFrameExtended means the frame has exactly the
    * same locals as the previous stack map frame and that the number of
    * stack items is 1.
    * 
* The explicitly defined offset can be discovered via {@link #getOffset()}. */ public class SameLocalsOneStackItemFrameExtended extends SameLocalsOneStackItemFrame { // ----- constructors ----------------------------------------------- /** * Creates a SameLocalsOneStackItemFrameExtended instance. */ public SameLocalsOneStackItemFrameExtended() { super(247); } // ----- accessors -------------------------------------------------- /** * {@inheritDoc} */ public int getOffset() { return m_nOffset; } /** * Set the Code attribute offset this frame refers to. * * @param nOffset */ public void setOffset(int nOffset) { m_nOffset = nOffset; } /** * {@inheritDoc} */ protected int size() { return 3 + m_stack.size(); } // ----- StackMapFrame methods -------------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { m_nOffset = stream.readUnsignedShort(); // verification_type_info tag super.disassemble(stream, pool); } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { stream.writeByte(m_nTag); stream.writeShort(m_nOffset); if (m_stack != null) { m_stack.assemble(stream, pool); } } // ----- data members ----------------------------------------------- /** * The Code attribute offset this frame refers to. */ private int m_nOffset; } // ----- inner class: ChopFrame ----------------------------------------- /** * A specialization of the StackMapFrame with the following definition: *
    * ChopFrame means that the operand stack is empty and the current locals
    * are the same as the locals in the previous frame, except that the k
    * last locals are absent.
    * 
* The value of {@code k}, mentioned above, can be determined by * {@link #getAbsentLocals()}. The explicitly defined offset can be * discovered via {@link #getOffset()}. */ public class ChopFrame extends StackMapFrame { // ----- constructors ----------------------------------------------- /** * Constructs a ChopFrame instance. * * @param nTag the byte tag within the region for a chop_frame */ public ChopFrame(int nTag) { super(nTag); } // ----- accessors -------------------------------------------------- /** * The number of absent locals in the previous frame. * * @return the number of absent locals in the previous frame */ public int getAbsentLocals() { return 251 - m_nTag; } /** * {@inheritDoc} */ public int getOffset() { return m_nOffset; } /** * Set the Code attribute offset this frame refers to. * * @param nOffset */ public void setOffset(int nOffset) { m_nOffset = nOffset; } /** * {@inheritDoc} */ protected int size() { return 3; } // ----- StackMapFrame methods -------------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { super.disassemble(stream, pool); m_nOffset = stream.readUnsignedShort(); } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { super.assemble(stream, pool); stream.writeShort(m_nOffset); } // ----- data members ----------------------------------------------- /** * The Code attribute offset this frame refers to. */ private int m_nOffset; } // ----- inner class: AppendFrame --------------------------------------- /** * A specialization of the StackMapFrame with the following definition: *
    * AppendFrame means that the operand stack is empty and the current
    * locals are the same as the locals in the previous frame, except that k
    * additional locals are defined.
    * 
* The value of {@code k}, mentioned above, can be determined by * {@link #getAppendedLocals()}. The explicitly defined offset can be * discovered via {@link #getOffset()}. */ public class AppendFrame extends StackMapFrame { // ----- constructors ----------------------------------------------- /** * Constructs a AppendFrame instance. * * @param nTag the byte tag within the region for a append_frame */ public AppendFrame(int nTag) { super(nTag); } // ----- accessors -------------------------------------------------- /** * Returns the number of additional locals. * * @return the number of additional locals */ public int getAppendedLocals() { return m_nTag - 251; } /** * {@inheritDoc} */ public int getOffset() { return m_nOffset; } /** * Set the Code attribute offset this frame refers to. * * @param nOffset */ public void setOffset(int nOffset) { m_nOffset = nOffset; } /** * {@inheritDoc} */ protected int size() { int cSize = 3; for (VariableInfo var : m_listLocals) { cSize += var.size(); } return cSize; } /** * Returns an Enumeration of {@link VariableInfo} objects. * * @return an Enumeration of VariableInfo objects */ public Enumeration getLocals() { return Collections.enumeration(m_listLocals); } /** * Adds a VariableInfo to the append_frame ensuring it is permitted * under the constraints of the byte tag. * * @param i index position to add the VariableInfo * @param var the VariableInfo to add * * @return whether the VariableInfo was added */ public boolean add(int i, VariableInfo var) { List listVars = m_listLocals; if (getAppendedLocals() >= listVars.size()) { return false; } listVars.add(i, var); return true; } /** * Adds a VariableInfo to the append_frame ensuring it is permitted * under the constraints of the byte tag. * * @param var the VariableInfo to add * * @return whether the VariableInfo was added */ public boolean add(VariableInfo var) { List listVars = m_listLocals; if (getAppendedLocals() >= listVars.size()) { return false; } return listVars.add(var); } /** * Removes a VariableInfo from the append_frame. * * @param i index position to remove the VariableInfo * * @return the removed VariableInfo object */ public VariableInfo remove(int i) { VariableInfo var = m_listLocals.remove(i); return var; } /** * Removes the given VariableInfo from the append_frame. * * @return whenther the VariableInfo was removed */ public boolean remove(VariableInfo var) { return m_listLocals.remove(var); } // ----- StackMapFrame methods -------------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { super.disassemble(stream, pool); m_nOffset = stream.readUnsignedShort(); int cLocals = getAppendedLocals(); List listLocals = m_listLocals = new LinkedList(); for (int i = 0; i < cLocals; ++i) { listLocals.add(loadVariableInfo(this, stream, pool)); } } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { super.assemble(stream, pool); stream.writeShort(m_nOffset); for (VariableInfo var : m_listLocals) { var.assemble(stream, pool); } } // ----- data members ----------------------------------------------- /** * The Code attribute offset this frame refers to. */ private int m_nOffset; /** * The local ({@link VariableInfo}) variables to append. */ private List m_listLocals; } // ----- inner class: AppendFrame --------------------------------------- /** * A specialization of the StackMapFrame with the following definition: *
    * FullFrame encompasses all the required values for a frame; an offset,
    * an array of local and an array or stack variable info objects.
    * 
*/ public class FullFrame extends StackMapFrame { // ----- constructors ----------------------------------------------- /** * Construct a FullFrame instance. */ public FullFrame() { super(255); } // ----- accessors -------------------------------------------------- /** * {@inheritDoc} */ public int getOffset() { return m_nOffset; } /** * Returns a List of {@link VariableInfo} objects * representing local variables. * * @return a List of {@link VariableInfo} objects representing * local variables */ public List getLocals() { return m_listLocals; } /** * Returns a List of {@link VariableInfo} objects * representing stack variables. * * @return a List of {@link VariableInfo} objects representing * stack variables */ public List getStack() { return m_listStack; } /** * Set the Code attribute offset this frame refers to. * * @param nOffset */ public void setOffset(int nOffset) { m_nOffset = nOffset; } /** * {@inheritDoc} */ protected int size() { int cSize = 7; for (Iterator iter = new ChainedIterator(m_listLocals.iterator(), m_listStack.iterator()); iter.hasNext(); ) { cSize += iter.next().size(); } return cSize; } // ----- StackMapTable methods -------------------------------------- /** * {@inheritDoc} */ @Override protected void disassemble(DataInput stream, ConstantPool pool) throws IOException { super.disassemble(stream, pool); m_nOffset = stream.readUnsignedShort(); int cItems = stream.readUnsignedShort(); List listLocals = m_listLocals = new LinkedList(); for (int i = 0; i < cItems; ++i) { listLocals.add(loadVariableInfo(this, stream, pool)); } cItems = stream.readUnsignedShort(); List listStack = m_listStack = new LinkedList(); for (int i = 0; i < cItems; ++i) { listStack.add(loadVariableInfo(this, stream, pool)); } } /** * {@inheritDoc} */ @Override protected void assemble(DataOutput stream, ConstantPool pool) throws IOException { super.assemble(stream, pool); stream.writeShort(m_nOffset); List listLocals = m_listLocals; stream.writeShort(listLocals.size()); for (VariableInfo var : listLocals) { var.assemble(stream, pool); } List listStack = m_listStack; stream.writeShort(listStack.size()); for (VariableInfo var : listStack) { var.assemble(stream, pool); } } // ----- data members ----------------------------------------------- /** * The Code attribute offset this frame refers to. */ private int m_nOffset; /** * The local ({@link VariableInfo}) variables in this frame. */ private List m_listLocals = new LinkedList(); /** * The stack items ({@link VariableInfo}). */ private List m_listStack = new LinkedList(); } // ----- inner enum: VariableInfoType ----------------------------------- /** * An enum representing the various types of * {@link StackMapFrame.VariableInfo} objects. */ public enum VariableInfoType { Top, Integer, Float, Long, Double, Null, UninitializedThis, Object, Uninitialized } // ----- data members --------------------------------------------------- /** * The frames encapsulated by the StackMapTable. */ private List m_listFrames; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy