001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.instrumentation;
042:
043: import org.netbeans.lib.profiler.classfile.ClassInfo;
044:
045: /**
046: * Base class, containing functionality to scan bytecodes in a single method.
047: *
048: * @author Misha Dmitriev
049: */
050: public class SingleMethodScaner implements JavaClassConstants {
051: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
052:
053: // The following array is re-used,to avoid excessive object allocations - which means that THIS CLASS IS NOT MULTITHREAD-SAFE!
054: private static byte[] reusableBytecodes = new byte[100];
055:
056: //~ Instance fields ----------------------------------------------------------------------------------------------------------
057:
058: protected ClassInfo clazz;
059: protected byte[] bytecodes; // Current updateable copy of bytecodes (what is in MethodInfo Code attribute between the code_length and the exception_table_length fields)
060: protected byte[] origMethodInfo;
061: protected int bytecodesLength;
062: protected int bytecodesStartIdx;
063: protected int methodIdx;
064:
065: //~ Constructors -------------------------------------------------------------------------------------------------------------
066:
067: public SingleMethodScaner() {
068: }
069:
070: public SingleMethodScaner(ClassInfo clazz, int methodIdx) {
071: setClassAndMethod(clazz, methodIdx);
072: }
073:
074: //~ Methods ------------------------------------------------------------------------------------------------------------------
075:
076: public void setClassAndMethod(ClassInfo clazz, int methodIdx) {
077: this .clazz = clazz;
078: this .methodIdx = methodIdx;
079: origMethodInfo = clazz.getMethodInfo(methodIdx);
080: bytecodesStartIdx = clazz
081: .getMethodBytecodeOffsetInMethodInfo(methodIdx);
082: bytecodesLength = clazz.getMethodBytecodesLength(methodIdx);
083: initBytecodesArray();
084: }
085:
086: protected static int getU2(byte[] buf, int pos) {
087: return ((buf[pos] & 0xFF) << 8) + (buf[pos + 1] & 0xFF);
088: }
089:
090: protected static int getU4(byte[] buf, int pos) {
091: return ((buf[pos] & 0xFF) << 24)
092: + ((buf[pos + 1] & 0xFF) << 16)
093: + ((buf[pos + 2] & 0xFF) << 8) + (buf[pos + 3] & 0xFF);
094: }
095:
096: protected static int align(int n) {
097: return (n + 3) & ~3;
098: }
099:
100: protected int opcodeLength(int bci) {
101: int ret;
102: int opcode = bytecodes[bci] & 0xFF;
103:
104: try {
105: ret = opc_length[opcode];
106: } catch (ArrayIndexOutOfBoundsException ex) {
107: System.err.println("*** JFluid warning: unknown opcode: "
108: + opcode
109: + " detected at offset "
110: + bci // NOI18N
111: + "in class/method " + clazz.getName() + "."
112: + clazz.getMethodName(methodIdx)
113: + clazz.getMethodSignature(methodIdx)); // NOI18N
114:
115: ClassRewriter.saveToDisk(clazz.getName(), bytecodes);
116:
117: return 1;
118: }
119:
120: if (ret != 0) {
121: return ret;
122: }
123:
124: if (opcode == opc_wide) {
125: opcode = bytecodes[bci + 1] & 0xFF;
126:
127: if (((opcode >= opc_iload) && (opcode <= opc_aload))
128: || ((opcode >= opc_istore) && (opcode <= opc_astore))
129: || (opcode == opc_ret)) {
130: return 4;
131: } else if (opcode == opc_iinc) {
132: return 6;
133: } else {
134: return 2;
135: }
136: } else {
137: int pad = align(bci + 1) - (bci + 1);
138:
139: switch (opcode) {
140: case opc_tableswitch: {
141: int lo = getInt(bci + 1 + pad + (4 * 1));
142: int hi = getInt(bci + 1 + pad + (4 * 2));
143: int n = hi - lo + 1;
144:
145: return 1 + pad + (4 * (3 + n));
146: }
147: case opc_lookupswitch: {
148: int npairs = getInt(bci + 1 + pad + (4 * 1));
149:
150: return 1 + pad + (4 * (2 + (2 * npairs)));
151: }
152: }
153: }
154:
155: System.err
156: .println("*** Profiler Engine: error - should not reach here in opcodeLength()"); // NOI18N
157:
158: return 0;
159: }
160:
161: protected static void putByte(byte[] buf, int pos, int value) {
162: buf[pos] = (byte) (value & 0xFF);
163: }
164:
165: protected static void putU2(byte[] buf, int pos, int value) {
166: buf[pos] = (byte) ((value >> 8) & 0xFF);
167: buf[pos + 1] = (byte) (value & 0xFF);
168: }
169:
170: protected static void putU4(byte[] buf, int pos, int value) {
171: buf[pos] = (byte) ((value >> 24) & 0xFF);
172: buf[pos + 1] = (byte) ((value >> 16) & 0xFF);
173: buf[pos + 2] = (byte) ((value >> 8) & 0xFF);
174: buf[pos + 3] = (byte) (value & 0xFF);
175: }
176:
177: protected int getByte(int pos) {
178: return (bytecodes[pos] & 0xFF);
179: }
180:
181: protected int getInt(int pos) {
182: return getU4(pos);
183: }
184:
185: protected short getShort(int pos) {
186: return (short) (((bytecodes[pos] & 0xFF) << 8) + (bytecodes[pos + 1] & 0xFF));
187: }
188:
189: protected int getU2(int pos) {
190: return ((bytecodes[pos] & 0xFF) << 8)
191: + (bytecodes[pos + 1] & 0xFF);
192: }
193:
194: protected int getU4(int pos) {
195: return ((bytecodes[pos] & 0xFF) << 24)
196: + ((bytecodes[pos + 1] & 0xFF) << 16)
197: + ((bytecodes[pos + 2] & 0xFF) << 8)
198: + (bytecodes[pos + 3] & 0xFF);
199: }
200:
201: protected void initBytecodesArray() {
202: if (reusableBytecodes.length < (bytecodesLength * 8)) {
203: reusableBytecodes = new byte[bytecodesLength * 8];
204: }
205:
206: System.arraycopy(origMethodInfo, bytecodesStartIdx,
207: reusableBytecodes, 0, bytecodesLength);
208: bytecodes = reusableBytecodes;
209: }
210:
211: protected void putInt(int pos, int value) {
212: putU4(pos, value);
213: }
214:
215: protected void putShort(int pos, short value) {
216: bytecodes[pos] = (byte) ((value >> 8) & 0xFF);
217: bytecodes[pos + 1] = (byte) (value & 0xFF);
218: }
219:
220: protected void putU4(int pos, int value) {
221: bytecodes[pos] = (byte) ((value >> 24) & 0xFF);
222: bytecodes[pos + 1] = (byte) ((value >> 16) & 0xFF);
223: bytecodes[pos + 2] = (byte) ((value >> 8) & 0xFF);
224: bytecodes[pos + 3] = (byte) (value & 0xFF);
225: }
226: }
|