Mercurial > hg > graal-jvmci-8
diff agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | 1f2abec69714 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,167 @@ +/* + * Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.tools.jcore; + +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.interpreter.*; +import sun.jvm.hotspot.utilities.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; + +public class ByteCodeRewriter +{ + private Method method; + private ConstantPool cpool; + private ConstantPoolCache cpCache; + private byte[] code; + private Bytes bytes; + + public static final boolean DEBUG = false; + private static final int jintSize = 4; + + protected void debugMessage(String message) { + System.out.println(message); + } + + public ByteCodeRewriter(Method method, ConstantPool cpool, byte[] code) { + this.method = method; + this.cpool = cpool; + this.cpCache = cpool.getCache(); + this.code = code; + this.bytes = VM.getVM().getBytes(); + + } + + protected short getConstantPoolIndex(int bci) { + // get ConstantPool index from ConstantPoolCacheIndex at given bci + short cpCacheIndex = method.getBytecodeShortArg(bci); + if (cpCache == null) { + return cpCacheIndex; + } else { + // change byte-ordering and go via cache + return (short) cpCache.getEntryAt((int) (0xFFFF & bytes.swapShort(cpCacheIndex))).getConstantPoolIndex(); + } + } + + static private void writeShort(byte[] buf, int index, short value) { + buf[index] = (byte) ((value >> 8) & 0x00FF); + buf[index + 1] = (byte) (value & 0x00FF); + } + + public void rewrite() { + int bytecode = Bytecodes._illegal; + int hotspotcode = Bytecodes._illegal; + int len = 0; + + for (int bci = 0; bci < code.length;) { + hotspotcode = Bytecodes.codeAt(method, bci); + bytecode = Bytecodes.javaCode(hotspotcode); + + if (Assert.ASSERTS_ENABLED) { + int code_from_buffer = 0xFF & code[bci]; + Assert.that(code_from_buffer == hotspotcode + || code_from_buffer == Bytecodes._breakpoint, + "Unexpected bytecode found in method bytecode buffer!"); + } + + // update the code buffer hotspot specific bytecode with the jvm bytecode + code[bci] = (byte) (0xFF & bytecode); + + // RewriteFrequentPairs + if(hotspotcode == Bytecodes._fast_iaccess_0 || + hotspotcode == Bytecodes._fast_aaccess_0 || + hotspotcode == Bytecodes._fast_faccess_0) { + // rewrite next bytecode as _getfield + bci++; + code[bci] = (byte) (0xFF & Bytecodes._getfield); + bytecode = Bytecodes._getfield; + hotspotcode = Bytecodes._getfield; + } else if (hotspotcode == Bytecodes._fast_iload2) { + // rewrite next bytecode as _iload + bci++; + code[bci] = (byte) (0xFF & Bytecodes._iload); + bytecode = Bytecodes._iload; + hotspotcode = Bytecodes._iload; + } else if (hotspotcode == Bytecodes._fast_icaload) { + // rewrite next bytecode as _caload + bci++; + code[bci] = (byte) (0xFF & Bytecodes._caload); + bytecode = Bytecodes._caload; + bytecode = Bytecodes._caload; + } + + short cpoolIndex = 0; + switch (bytecode) { + // bytecodes with ConstantPoolCache index + case Bytecodes._getstatic: + case Bytecodes._putstatic: + case Bytecodes._getfield: + case Bytecodes._putfield: + case Bytecodes._invokevirtual: + case Bytecodes._invokespecial: + case Bytecodes._invokestatic: + case Bytecodes._invokeinterface: { + cpoolIndex = getConstantPoolIndex(bci + 1); + writeShort(code, bci + 1, cpoolIndex); + break; + } + } + + len = Bytecodes.lengthFor(bytecode); + if (len <= 0) len = Bytecodes.lengthAt(method, bci); + + if (DEBUG) { + String operand = ""; + switch (len) { + case 2: + operand += code[bci + 1]; + break; + case 3: + operand += (cpoolIndex != 0)? cpoolIndex : + method.getBytecodeShortArg(bci + 1); + break; + case 5: + operand += method.getBytecodeIntArg(bci + 1); + break; + } + + // the operand following # is not quite like javap output. + // in particular, for goto & goto_w, the operand is PC relative + // offset for jump. Javap adds relative offset with current PC + // to give absolute bci to jump to. + + String message = "\t\t" + bci + " " + Bytecodes.name(bytecode); + if (hotspotcode != bytecode) + message += " [" + Bytecodes.name(hotspotcode) + "]"; + if (operand != "") + message += " #" + operand; + + if (DEBUG) debugMessage(message); + } + + bci += len; + } + } +}