169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.DataInputStream; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.DataOutputStream; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.ByteArrayOutputStream; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.PrintWriter; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException; 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Map; 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException; 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>stack_map</code> attribute. 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This is an entry in the attributes table of a Code attribute. 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It was introduced by J2SE 6 for the process of verification by 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * typechecking. 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see StackMap 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @since 3.4 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class StackMapTable extends AttributeInfo { 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The name of this attribute <code>"StackMapTable"</code>. 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String tag = "StackMapTable"; 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a <code>stack_map</code> attribute. 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StackMapTable(ConstPool cp, byte[] newInfo) { 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(cp, tag, newInfo); 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StackMapTable(ConstPool cp, int name_id, DataInputStream in) 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(cp, name_id, in); 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Makes a copy. 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @exception RuntimeCopyException if a <code>BadBytecode</code> 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * exception is thrown while copying, 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * it is converted into 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>RuntimeCopyException</code>. 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public AttributeInfo copy(ConstPool newCp, Map classnames) 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws RuntimeCopyException 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new StackMapTable(newCp, 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Copier(this.constPool, info, newCp).doit()); 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (BadBytecode e) { 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeCopyException("bad bytecode. fatal?"); 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * An exception that may be thrown by <code>copy()</code> 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * in <code>StackMapTable</code>. 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static class RuntimeCopyException extends RuntimeException { 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs an exception. 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public RuntimeCopyException(String s) { 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(s); 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal void write(DataOutputStream out) throws IOException { 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.write(out); 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Top_variable_info.tag</code>. 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int TOP = 0; 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Integer_variable_info.tag</code>. 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int INTEGER = 1; 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Float_variable_info.tag</code>. 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int FLOAT = 2; 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Double_variable_info.tag</code>. 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int DOUBLE = 3; 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Long_variable_info.tag</code>. 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int LONG = 4; 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Null_variable_info.tag</code>. 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int NULL = 5; 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>UninitializedThis_variable_info.tag</code>. 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int THIS = 6; 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Object_variable_info.tag</code>. 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int OBJECT = 7; 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Uninitialized_variable_info.tag</code>. 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int UNINIT = 8; 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A code walker for a StackMapTable attribute. 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static class Walker { 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] info; 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int numOfEntries; 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a walker. 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param smt the StackMapTable that this walker 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * walks around. 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Walker(StackMapTable smt) { 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this(smt.get()); 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a walker. 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param data the <code>info</code> field of the 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>attribute_info</code> structure. 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It can be obtained by <code>get()</code> 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * in the <code>AttributeInfo</code> class. 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Walker(byte[] data) { 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal info = data; 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal numOfEntries = ByteArray.readU16bit(data, 0); 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the number of the entries. 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public final int size() { return numOfEntries; } 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Visits each entry of the stack map frames. 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void parse() throws BadBytecode { 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = numOfEntries; 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int pos = 2; 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos = stackMapFrames(pos, i); 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Invoked when the next entry of the stack map frames is visited. 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param pos the position of the frame in the <code>info</code> 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * field of <code>attribute_info</code> structure. 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param nth the frame is the N-th 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * (0, 1st, 2nd, 3rd, 4th, ...) entry. 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the position of the next frame. 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int stackMapFrames(int pos, int nth) throws BadBytecode { 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int type = info[pos] & 0xff; 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (type < 64) { 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sameFrame(pos, type); 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos++; 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (type < 128) 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos = sameLocals(pos, type); 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (type < 247) 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new BadBytecode("bad frame_type in StackMapTable"); 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (type == 247) // SAME_LOCALS_1_STACK_ITEM_EXTENDED 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos = sameLocals(pos, type); 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (type < 251) { 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int offset = ByteArray.readU16bit(info, pos + 1); 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal chopFrame(pos, offset, 251 - type); 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos += 3; 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (type == 251) { // SAME_FRAME_EXTENDED 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int offset = ByteArray.readU16bit(info, pos + 1); 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sameFrame(pos, offset); 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos += 3; 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (type < 255) 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos = appendFrame(pos, type); 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else // FULL_FRAME 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos = fullFrame(pos); 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return pos; 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Invoked if the visited frame is a <code>same_frame</code> or 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a <code>same_frame_extended</code>. 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param pos the position of this frame in the <code>info</code> 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * field of <code>attribute_info</code> structure. 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param offsetDelta 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameFrame(int pos, int offsetDelta) throws BadBytecode {} 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int sameLocals(int pos, int type) throws BadBytecode { 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int top = pos; 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int offset; 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (type < 128) 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offset = type - 64; 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { // type == 247 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offset = ByteArray.readU16bit(info, pos + 1); 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos += 2; 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int tag = info[pos + 1] & 0xff; 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int data = 0; 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (tag == OBJECT || tag == UNINIT) { 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal data = ByteArray.readU16bit(info, pos + 2); 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos += 2; 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sameLocals(top, offset, tag, data); 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return pos + 2; 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Invoked if the visited frame is a <code>same_locals_1_stack_item_frame</code> 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or a <code>same_locals_1_stack_item_frame_extended</code>. 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param pos the position. 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param offsetDelta 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param stackTag <code>stack[0].tag</code>. 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param stackData <code>stack[0].cpool_index</code> 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>OBJECT</code>, 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or <code>stack[0].offset</code> 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>UNINIT</code>. 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode {} 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Invoked if the visited frame is a <code>chop_frame</code>. 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param pos the position. 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param offsetDelta 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param k the <cod>k</code> last locals are absent. 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void chopFrame(int pos, int offsetDelta, int k) throws BadBytecode {} 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int appendFrame(int pos, int type) throws BadBytecode { 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int k = type - 251; 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int offset = ByteArray.readU16bit(info, pos + 1); 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] tags = new int[k]; 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] data = new int[k]; 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int p = pos + 3; 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < k; i++) { 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int tag = info[p] & 0xff; 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tags[i] = tag; 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (tag == OBJECT || tag == UNINIT) { 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal data[i] = ByteArray.readU16bit(info, p + 1); 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal p += 3; 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal data[i] = 0; 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal p++; 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal appendFrame(pos, offset, tags, data); 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return p; 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Invoked if the visited frame is a <code>append_frame</code>. 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param pos the position. 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param offsetDelta 30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param tags <code>locals[i].tag</code>. 30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param data <code>locals[i].cpool_index</code> 30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or <cod>locals[i].offset</code>. 30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) 31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode {} 31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int fullFrame(int pos) throws BadBytecode { 31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int offset = ByteArray.readU16bit(info, pos + 1); 31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int numOfLocals = ByteArray.readU16bit(info, pos + 3); 31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] localsTags = new int[numOfLocals]; 31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] localsData = new int[numOfLocals]; 31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int p = verifyTypeInfo(pos + 5, numOfLocals, localsTags, localsData); 31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int numOfItems = ByteArray.readU16bit(info, p); 31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] itemsTags = new int[numOfItems]; 32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] itemsData = new int[numOfItems]; 32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal p = verifyTypeInfo(p + 2, numOfItems, itemsTags, itemsData); 32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fullFrame(pos, offset, localsTags, localsData, itemsTags, itemsData); 32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return p; 32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Invoked if the visited frame is <code>full_frame</code>. 32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param pos the position. 33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param offsetDelta 33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param localTags <code>locals[i].tag</code> 33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param localData <code>locals[i].cpool_index</code> 33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or <code>locals[i].offset</code> 33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param stackTags <code>stack[i].tag</code> 33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param stackData <code>stack[i].cpool_index</code> 33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or <code>stack[i].offset</code> 33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, 33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stackTags, int[] stackData) 34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode {} 34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int verifyTypeInfo(int pos, int n, int[] tags, int[] data) { 34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) { 34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int tag = info[pos++] & 0xff; 34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tags[i] = tag; 34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (tag == OBJECT || tag == UNINIT) { 34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal data[i] = ByteArray.readU16bit(info, pos); 34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos += 2; 34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return pos; 35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static class SimpleCopy extends Walker { 35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Writer writer; 35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public SimpleCopy(byte[] data) { 36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(data); 36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer = new Writer(data.length); 36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public byte[] doit() throws BadBytecode { 36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal parse(); 36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return writer.toByteArray(); 36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameFrame(int pos, int offsetDelta) { 37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.sameFrame(offsetDelta); 37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) { 37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.sameLocals(offsetDelta, stackTag, copyData(stackTag, stackData)); 37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void chopFrame(int pos, int offsetDelta, int k) { 37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.chopFrame(offsetDelta, k); 37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) { 38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.appendFrame(offsetDelta, tags, copyData(tags, data)); 38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, 38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stackTags, int[] stackData) { 38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.fullFrame(offsetDelta, localTags, copyData(localTags, localData), 38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal stackTags, copyData(stackTags, stackData)); 38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected int copyData(int tag, int data) { 39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return data; 39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected int[] copyData(int[] tags, int[] data) { 39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return data; 39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static class Copier extends SimpleCopy { 40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ConstPool srcPool, destPool; 40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Copier(ConstPool src, byte[] data, ConstPool dest) { 40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(data); 40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal srcPool = src; 40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal destPool = dest; 40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected int copyData(int tag, int data) { 41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (tag == OBJECT) 41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return srcPool.copy(data, destPool, null); 41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return data; 41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected int[] copyData(int[] tags, int[] data) { 41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] newData = new int[data.length]; 41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < data.length; i++) 41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (tags[i] == OBJECT) 42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newData[i] = srcPool.copy(data[i], destPool, null); 42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newData[i] = data[i]; 42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return newData; 42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Updates this stack map table when a new local variable is inserted 43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for a new parameter. 43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param index the index of the added local variable. 43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param tag the type tag of that local variable. 43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param classInfo the index of the <code>CONSTANT_Class_info</code> structure 43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * in a constant pool table. This should be zero unless the tag 43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is <code>ITEM_Object</code>. 43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.CtBehavior#addParameter(javassist.CtClass) 43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see #typeTagOf(char) 44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see ConstPool 44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void insertLocal(int index, int tag, int classInfo) 44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] data = new InsertLocal(this.get(), index, tag, classInfo).doit(); 44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.set(data); 44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the tag of the type specified by the 45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * descriptor. This method returns <code>INTEGER</code> 45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * unless the descriptor is either D (double), F (float), 45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * J (long), L (class type), or [ (array). 45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param descriptor the type descriptor. 45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see Descriptor 45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static int typeTagOf(char descriptor) { 45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (descriptor) { 46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'D' : 46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return DOUBLE; 46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'F' : 46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return FLOAT; 46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'J' : 46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return LONG; 46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'L' : 46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '[' : 46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return OBJECT; 46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // case 'V' : 47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal default : 47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return INTEGER; 47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* This implementation assumes that a local variable initially 47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * holding a parameter value is never changed to be a different 47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * type. 47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static class InsertLocal extends SimpleCopy { 48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int varIndex; 48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int varTag, varData; 48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public InsertLocal(byte[] data, int varIndex, int varTag, int varData) { 48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(data); 48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.varIndex = varIndex; 48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.varTag = varTag; 48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.varData = varData; 48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, 49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stackTags, int[] stackData) { 49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len = localTags.length; 49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (len < varIndex) { 49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.fullFrame(pos, offsetDelta, localTags, localData, stackTags, stackData); 49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int typeSize = (varTag == LONG || varTag == DOUBLE) ? 2 : 1; 50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] localTags2 = new int[len + typeSize]; 50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] localData2 = new int[len + typeSize]; 50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int index = varIndex; 50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int j = 0; 50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < len; i++) { 50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (j == index) 50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal j += typeSize; 50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal localTags2[j] = localTags[i]; 50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal localData2[j++] = localData[i]; 51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal localTags2[index] = varTag; 51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal localData2[index] = varData; 51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (typeSize > 1) { 51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal localTags2[index + 1] = TOP; 51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal localData2[index + 1] = 0; 51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.fullFrame(pos, offsetDelta, localTags2, localData2, stackTags, stackData); 52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A writer of stack map tables. 52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static class Writer { 52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ByteArrayOutputStream output; 52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int numOfEntries; 52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a writer. 53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param size the initial buffer size. 53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Writer(int size) { 53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output = new ByteArrayOutputStream(size); 53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal numOfEntries = 0; 53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(0); // u2 number_of_entries 53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(0); 53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the stack map table written out. 54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public byte[] toByteArray() { 54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] b = output.toByteArray(); 54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ByteArray.write16bit(numOfEntries, b, 0); 54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return b; 54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs and a return a stack map table containing 55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the written stack map entries. 55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param cp the constant pool used to write 55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the stack map entries. 55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public StackMapTable toStackMapTable(ConstPool cp) { 55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new StackMapTable(cp, toByteArray()); 55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Writes a <code>same_frame</code> or a <code>same_frame_extended</code>. 56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameFrame(int offsetDelta) { 56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal numOfEntries++; 56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (offsetDelta < 64) 56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(offsetDelta); 56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(251); // SAME_FRAME_EXTENDED 57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal write16(offsetDelta); 57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Writes a <code>same_locals_1_stack_item</code> 57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or a <code>same_locals_1_stack_item_extended</code>. 57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param tag <code>stack[0].tag</code>. 57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param data <code>stack[0].cpool_index</code> 58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>OBJECT</code>, 58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or <cod>stack[0].offset</code> 58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>UNINIT</code>. 58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Otherwise, this parameter is not used. 58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameLocals(int offsetDelta, int tag, int data) { 58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal numOfEntries++; 58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (offsetDelta < 64) 58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(offsetDelta + 64); 58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(247); // SAME_LOCALS_1_STACK_ITEM_EXTENDED 59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal write16(offsetDelta); 59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeTypeInfo(tag, data); 59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Writes a <code>chop_frame</code>. 59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param k the number of absent locals. 1, 2, or 3. 60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void chopFrame(int offsetDelta, int k) { 60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal numOfEntries++; 60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(251 - k); 60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal write16(offsetDelta); 60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Writes a <code>append_frame</code>. The number of the appended 61069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * locals is specified by the length of <code>tags</code>. 61169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 61269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param tags <code>locals[].tag</code>. 61369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The length of this array must be 61469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * either 1, 2, or 3. 61569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param data <code>locals[].cpool_index</code> 61669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>OBJECT</code>, 61769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or <cod>locals[].offset</code> 61869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>UNINIT</code>. 61969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Otherwise, this parameter is not used. 62069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 62169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void appendFrame(int offsetDelta, int[] tags, int[] data) { 62269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal numOfEntries++; 62369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int k = tags.length; // k is 1, 2, or 3 62469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(k + 251); 62569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal write16(offsetDelta); 62669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < k; i++) 62769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeTypeInfo(tags[i], data[i]); 62869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 62969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 63069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 63169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Writes a <code>full_frame</code>. 63269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>number_of_locals</code> and <code>number_of_stack_items</code> 63369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * are specified by the the length of <code>localTags</code> and 63469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>stackTags</code>. 63569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 63669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param localTags <code>locals[].tag</code>. 63769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param localData <code>locals[].cpool_index</code> 63869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>OBJECT</code>, 63969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or <cod>locals[].offset</code> 64069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>UNINIT</code>. 64169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Otherwise, this parameter is not used. 64269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param stackTags <code>stack[].tag</code>. 64369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param stackData <code>stack[].cpool_index</code> 64469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>OBJECT</code>, 64569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or <cod>stack[].offset</code> 64669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the tag is <code>UNINIT</code>. 64769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Otherwise, this parameter is not used. 64869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 64969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void fullFrame(int offsetDelta, int[] localTags, int[] localData, 65069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stackTags, int[] stackData) { 65169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal numOfEntries++; 65269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(255); // FULL_FRAME 65369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal write16(offsetDelta); 65469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = localTags.length; 65569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal write16(n); 65669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 65769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeTypeInfo(localTags[i], localData[i]); 65869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 65969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal n = stackTags.length; 66069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal write16(n); 66169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 66269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeTypeInfo(stackTags[i], stackData[i]); 66369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 66469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 66569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void writeTypeInfo(int tag, int data) { 66669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(tag); 66769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (tag == OBJECT || tag == UNINIT) 66869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal write16(data); 66969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 67069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 67169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void write16(int value) { 67269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write((value >>> 8) & 0xff); 67369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal output.write(value & 0xff); 67469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 67569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 67669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 67769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 67869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Prints the stack table map. 67969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 68069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void println(PrintWriter w) { 68169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Printer.print(this, w); 68269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 68369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 68469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 68569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Prints the stack table map. 68669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 68769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param ps a print stream such as <code>System.out</code>. 68869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 68969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void println(java.io.PrintStream ps) { 69069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Printer.print(this, new java.io.PrintWriter(ps, true)); 69169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 69269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 69369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static class Printer extends Walker { 69469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private PrintWriter writer; 69569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int offset; 69669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 69769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 69869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Prints the stack table map. 69969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 70069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static void print(StackMapTable smt, PrintWriter writer) { 70169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 70269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Printer(smt.get(), writer).parse(); 70369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 70469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (BadBytecode e) { 70569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.println(e.getMessage()); 70669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 70769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 70869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 70969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Printer(byte[] data, PrintWriter pw) { 71069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(data); 71169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer = pw; 71269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offset = -1; 71369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 71469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 71569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameFrame(int pos, int offsetDelta) { 71669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offset += offsetDelta + 1; 71769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.println(offset + " same frame: " + offsetDelta); 71869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 71969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 72069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) { 72169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offset += offsetDelta + 1; 72269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.println(offset + " same locals: " + offsetDelta); 72369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal printTypeInfo(stackTag, stackData); 72469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 72569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 72669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void chopFrame(int pos, int offsetDelta, int k) { 72769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offset += offsetDelta + 1; 72869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.println(offset + " chop frame: " + offsetDelta + ", " + k + " last locals"); 72969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 73069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 73169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) { 73269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offset += offsetDelta + 1; 73369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.println(offset + " append frame: " + offsetDelta); 73469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < tags.length; i++) 73569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal printTypeInfo(tags[i], data[i]); 73669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 73769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 73869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, 73969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stackTags, int[] stackData) { 74069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal offset += offsetDelta + 1; 74169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.println(offset + " full frame: " + offsetDelta); 74269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.println("[locals]"); 74369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < localTags.length; i++) 74469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal printTypeInfo(localTags[i], localData[i]); 74569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 74669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.println("[stack]"); 74769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < stackTags.length; i++) 74869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal printTypeInfo(stackTags[i], stackData[i]); 74969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 75069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 75169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void printTypeInfo(int tag, int data) { 75269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String msg = null; 75369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (tag) { 75469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case TOP : 75569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal msg = "top"; 75669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 75769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case INTEGER : 75869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal msg = "integer"; 75969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 76069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case FLOAT : 76169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal msg = "float"; 76269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 76369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case DOUBLE : 76469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal msg = "double"; 76569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 76669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case LONG : 76769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal msg = "long"; 76869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 76969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case NULL : 77069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal msg = "null"; 77169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 77269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case THIS : 77369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal msg = "this"; 77469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 77569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case OBJECT : 77669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal msg = "object (cpool_index " + data + ")"; 77769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 77869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case UNINIT : 77969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal msg = "uninitialized (offset " + data + ")"; 78069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 78169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 78269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 78369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.print(" "); 78469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writer.println(msg); 78569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 78669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 78769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 78869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal void shiftPc(int where, int gapSize, boolean exclusive) 78969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadBytecode 79069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 79169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Shifter(this, where, gapSize, exclusive).doit(); 79269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 79369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 79469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static class Shifter extends Walker { 79569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private StackMapTable stackMap; 79669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int where, gap; 79769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int position; 79869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private byte[] updatedInfo; 79969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean exclusive; 80069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 80169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Shifter(StackMapTable smt, int where, int gap, boolean exclusive) { 80269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(smt); 80369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal stackMap = smt; 80469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.where = where; 80569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.gap = gap; 80669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.position = 0; 80769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.updatedInfo = null; 80869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.exclusive = exclusive; 80969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 81069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 81169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void doit() throws BadBytecode { 81269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal parse(); 81369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (updatedInfo != null) 81469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal stackMap.set(updatedInfo); 81569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 81669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 81769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameFrame(int pos, int offsetDelta) { 81869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal update(pos, offsetDelta, 0, 251); 81969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 82069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 82169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) { 82269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal update(pos, offsetDelta, 64, 247); 82369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 82469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 82569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void update(int pos, int offsetDelta, int base, int entry) { 82669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int oldPos = position; 82769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1); 82869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean match; 82969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (exclusive) 83069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal match = oldPos < where && where <= position; 83169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 83269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal match = oldPos <= where && where < position; 83369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 83469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (match) { 83569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int newDelta = offsetDelta + gap; 83669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal position += gap; 83769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (newDelta < 64) 83869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal info[pos] = (byte)(newDelta + base); 83969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (offsetDelta < 64) { 84069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] newinfo = insertGap(info, pos, 2); 84169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newinfo[pos] = (byte)entry; 84269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ByteArray.write16bit(newDelta, newinfo, pos + 1); 84369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal updatedInfo = newinfo; 84469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 84569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 84669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ByteArray.write16bit(newDelta, info, pos + 1); 84769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 84869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 84969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 85069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static byte[] insertGap(byte[] info, int where, int gap) { 85169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len = info.length; 85269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] newinfo = new byte[len + gap]; 85369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < len; i++) 85469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newinfo[i + (i < where ? 0 : gap)] = info[i]; 85569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 85669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return newinfo; 85769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 85869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 85969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void chopFrame(int pos, int offsetDelta, int k) { 86069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal update(pos, offsetDelta); 86169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 86269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 86369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) { 86469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal update(pos, offsetDelta); 86569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 86669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 86769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, 86869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stackTags, int[] stackData) { 86969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal update(pos, offsetDelta); 87069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 87169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 87269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void update(int pos, int offsetDelta) { 87369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int oldPos = position; 87469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1); 87569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean match; 87669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (exclusive) 87769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal match = oldPos < where && where <= position; 87869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 87969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal match = oldPos <= where && where < position; 88069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 88169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (match) { 88269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int newDelta = offsetDelta + gap; 88369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ByteArray.write16bit(newDelta, info, pos + 1); 88469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal position += gap; 88569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 88669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 88769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 88869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 88969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 89069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Undocumented method. Do not use; internal-use only. 89169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 89269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This method is for javassist.convert.TransformNew. 89369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It is called to update the stack map table when 89469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the NEW opcode (and the following DUP) is removed. 89569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 89669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param where the position of the removed NEW opcode. 89769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 89869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void removeNew(int where) throws CannotCompileException { 89969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 90069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] data = new NewRemover(this.get(), where).doit(); 90169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.set(data); 90269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 90369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (BadBytecode e) { 90469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException("bad stack map table", e); 90569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 90669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 90769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 90869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static class NewRemover extends SimpleCopy { 90969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int posOfNew; 91069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 91169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public NewRemover(byte[] data, int pos) { 91269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(data); 91369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal posOfNew = pos; 91469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 91569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 91669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) { 91769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (stackTag == UNINIT && stackData == posOfNew) 91869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.sameFrame(pos, offsetDelta); 91969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 92069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.sameLocals(pos, offsetDelta, stackTag, stackData); 92169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 92269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 92369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, 92469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stackTags, int[] stackData) { 92569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = stackTags.length - 1; 92669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 92769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (stackTags[i] == UNINIT && stackData[i] == posOfNew 92869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && stackTags[i + 1] == UNINIT && stackData[i + 1] == posOfNew) { 92969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal n++; 93069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stackTags2 = new int[n - 2]; 93169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] stackData2 = new int[n - 2]; 93269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int k = 0; 93369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int j = 0; j < n; j++) 93469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (j == i) 93569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal j++; 93669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 93769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal stackTags2[k] = stackTags[j]; 93869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal stackData2[k++] = stackData[j]; 93969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 94069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 94169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal stackTags = stackTags2; 94269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal stackData = stackData2; 94369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 94469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 94569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 94669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.fullFrame(pos, offsetDelta, localTags, localData, stackTags, stackData); 94769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 94869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 94969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 950