From c8eb33fc60e880e0f8c75d442fa6df7660c87939 Mon Sep 17 00:00:00 2001 From: chiba Date: Wed, 20 Aug 2003 17:49:39 +0000 Subject: [PATCH] made to produce bytecode that HotSpot 1.3 can compile to be efficient native code. (avoiding a bug of HotSpot?) git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@34 30ef5769-5b8d-40dd-aea6-55b5d6557bb3 --- src/main/javassist/CtBehavior.java | 107 +++++++++++++----- src/main/javassist/bytecode/CodeIterator.java | 2 + 2 files changed, 78 insertions(+), 31 deletions(-) diff --git a/src/main/javassist/CtBehavior.java b/src/main/javassist/CtBehavior.java index 35ea4061..e37c81dd 100644 --- a/src/main/javassist/CtBehavior.java +++ b/src/main/javassist/CtBehavior.java @@ -368,13 +368,14 @@ public abstract class CtBehavior extends CtMember { throws CannotCompileException { declaringClass.checkModify(); + ConstPool pool = methodInfo.getConstPool(); CodeAttribute ca = methodInfo.getCodeAttribute(); if (ca == null) throw new CannotCompileException("no method body"); CodeIterator iterator = ca.iterator(); int retAddr = ca.getMaxLocals(); - Bytecode b = new Bytecode(methodInfo.getConstPool(), 0, retAddr + 1); + Bytecode b = new Bytecode(pool, 0, retAddr + 1); b.setStackDepth(ca.getMaxStack() + 1); Javac jv = new Javac(b, declaringClass); try { @@ -382,22 +383,14 @@ public abstract class CtBehavior extends CtMember { Modifier.isStatic(getModifiers())); CtClass rtype = getReturnType0(); int varNo = jv.recordReturnType(rtype, true); - boolean isVoid = rtype == CtClass.voidType; - int handlerLen = insertAfterHandler(asFinally, b, rtype); + int handlerLen = insertAfterHandler(asFinally, b, rtype, varNo); - b.addAstore(retAddr); - if (isVoid) { - b.addOpcode(Opcode.ACONST_NULL); - b.addAstore(varNo); - jv.compileStmnt(src); - } - else { - b.addStore(varNo, rtype); - jv.compileStmnt(src); - b.addLoad(varNo, rtype); - } + byte[] save = makeSaveCode(pool, rtype, varNo); + byte[] restore = makeRestoreCode(b, pool, rtype, varNo); + b.addAstore(retAddr); + jv.compileStmnt(src); b.addRet(retAddr); ca.setMaxStack(b.getMaxStack()); ca.setMaxLocals(b.getMaxLocals()); @@ -420,17 +413,7 @@ public abstract class CtBehavior extends CtMember { if (c == Opcode.ARETURN || c == Opcode.IRETURN || c == Opcode.FRETURN || c == Opcode.LRETURN || c == Opcode.DRETURN || c == Opcode.RETURN) { - if (subr - pos > Short.MAX_VALUE - 5) { - int s = iterator.insertGap(pos, 5); - iterator.writeByte(Opcode.JSR_W, pos); - iterator.write32bit(subr - pos + s, pos + 1); - } - else { - int s = iterator.insertGap(pos, 3); - iterator.writeByte(Opcode.JSR, pos); - iterator.write16bit(subr - pos + s, pos + 1); - } - + insertJSR(iterator, subr, pos, save, restore); subr = iterator.getCodeLength() - gapLen; } } @@ -446,8 +429,60 @@ public abstract class CtBehavior extends CtMember { } } + private byte[] makeSaveCode(ConstPool cp, CtClass rtype, int varNo) { + Bytecode b = new Bytecode(cp, 0, 0); + if (rtype == CtClass.voidType) { + b.addOpcode(Opcode.ACONST_NULL); + b.addAstore(varNo); + return b.get(); + } + else { + b.addStore(varNo, rtype); + return b.get(); + } + } + + private byte[] makeRestoreCode(Bytecode code, ConstPool cp, + CtClass rtype, int varNo) { + if (rtype == CtClass.voidType) { + if (code.getMaxLocals() < 1) + code.setMaxLocals(1); + + return new byte[0]; + } + else { + Bytecode b = new Bytecode(cp, 0, 0); + b.addLoad(varNo, rtype); + return b.get(); + } + } + + private void insertJSR(CodeIterator iterator, int subr, int pos, + byte[] save, byte[] restore) + throws BadBytecode + { + int gapSize = 5 + save.length + restore.length; + boolean wide = subr - pos > Short.MAX_VALUE - gapSize - 4; + gapSize = iterator.insertGap(pos, wide ? gapSize : gapSize - 2); + + iterator.write(save, pos); + pos += save.length; + if (wide) { + iterator.writeByte(Opcode.JSR_W, pos); + iterator.write32bit(subr - pos + gapSize, pos + 1); + pos += 5; + } + else { + iterator.writeByte(Opcode.JSR, pos); + iterator.write16bit(subr - pos + gapSize, pos + 1); + pos += 3; + } + + iterator.write(restore, pos); + } + private int insertAfterHandler(boolean asFinally, Bytecode b, - CtClass rtype) + CtClass rtype, int returnVarNo) { if (!asFinally) return 0; @@ -458,17 +493,27 @@ public abstract class CtBehavior extends CtMember { b.addAstore(var); if (rtype.isPrimitive()) { char c = ((CtPrimitiveType)rtype).getDescriptor(); - if (c == 'D') + if (c == 'D') { b.addDconst(0.0); - else if (c == 'F') + b.addDstore(returnVarNo); + } + else if (c == 'F') { b.addFconst(0); - else if (c == 'J') + b.addFstore(returnVarNo); + } + else if (c == 'J') { b.addLconst(0); - else if (c != 'V') // int, boolean, char, short, ... + b.addLstore(returnVarNo); + } + else if (c != 'V') { // int, boolean, char, short, ... b.addIconst(0); + b.addIstore(returnVarNo); + } } - else + else { b.addOpcode(Opcode.ACONST_NULL); + b.addAstore(returnVarNo); + } b.addOpcode(Opcode.JSR); int pc2 = b.currentPc(); diff --git a/src/main/javassist/bytecode/CodeIterator.java b/src/main/javassist/bytecode/CodeIterator.java index 40eb90d4..03c65da3 100644 --- a/src/main/javassist/bytecode/CodeIterator.java +++ b/src/main/javassist/bytecode/CodeIterator.java @@ -123,6 +123,8 @@ public class CodeIterator implements Opcode { /** * Writes a byte array at the index. + * + * @param code may be a zero-length array. */ public void write(byte[] code, int index) { int len = code.length; -- 2.39.5