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.IOException; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Map; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>LineNumberTable_attribute</code>. 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class LineNumberAttribute extends AttributeInfo { 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The name of this attribute <code>"LineNumberTable"</code>. 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String tag = "LineNumberTable"; 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal LineNumberAttribute(ConstPool cp, int n, DataInputStream in) 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(cp, n, in); 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private LineNumberAttribute(ConstPool cp, byte[] i) { 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(cp, tag, i); 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns <code>line_number_table_length</code>. 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This represents the number of entries in the table. 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int tableLength() { 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return ByteArray.readU16bit(info, 0); 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns <code>line_number_table[i].start_pc</code>. 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This represents the index into the code array at which the code 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for a new line in the original source file begins. 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param i the i-th entry. 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int startPc(int i) { 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return ByteArray.readU16bit(info, i * 4 + 2); 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns <code>line_number_table[i].line_number</code>. 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This represents the corresponding line number in the original 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * source file. 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param i the i-th entry. 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int lineNumber(int i) { 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return ByteArray.readU16bit(info, i * 4 + 4); 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the line number corresponding to the specified bytecode. 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param pc the index into the code array. 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int toLineNumber(int pc) { 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = tableLength(); 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = 0; 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (; i < n; ++i) 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (pc < startPc(i)) 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i == 0) 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return lineNumber(0); 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return lineNumber(i - 1); 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the index into the code array at which the code for 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the specified line begins. 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param line the line number. 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return -1 if the specified line is not found. 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int toStartPc(int line) { 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = tableLength(); 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (line == lineNumber(i)) 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return startPc(i); 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return -1; 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Used as a return type of <code>toNearPc()</code>. 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static public class Pc { 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The index into the code array. 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int index; 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The line number. 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int line; 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the index into the code array at which the code for 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the specified line (or the nearest line after the specified one) 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * begins. 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param line the line number. 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return a pair of the index and the line number of the 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * bytecode at that index. 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Pc toNearPc(int line) { 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = tableLength(); 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int nearPc = 0; 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int distance = 0; 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (n > 0) { 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal distance = lineNumber(0) - line; 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal nearPc = startPc(0); 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 1; i < n; ++i) { 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int d = lineNumber(i) - line; 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if ((d < 0 && d > distance) 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || (d >= 0 && (d < distance || distance < 0))) { 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal distance = d; 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal nearPc = startPc(i); 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Pc res = new Pc(); 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal res.index = nearPc; 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal res.line = line + distance; 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return res; 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Makes a copy. 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param newCp the constant pool table used by the new copy. 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param classnames should be null. 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public AttributeInfo copy(ConstPool newCp, Map classnames) { 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] src = info; 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int num = src.length; 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] dest = new byte[num]; 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < num; ++i) 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dest[i] = src[i]; 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal LineNumberAttribute attr = new LineNumberAttribute(newCp, dest); 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return attr; 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Adjusts start_pc if bytecode is inserted in a method body. 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal void shiftPc(int where, int gapLength, boolean exclusive) { 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = tableLength(); 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) { 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int pos = i * 4 + 2; 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int pc = ByteArray.readU16bit(info, pos); 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (pc > where || (exclusive && pc == where)) 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ByteArray.write16bit(pc + gapLength, info, pos); 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 182