From: chibash Date: Fri, 20 Sep 2019 14:20:39 +0000 (+0900) Subject: adds CtBehavior#insertAfter(String,boolean,boolean) for Issue #275 X-Git-Tag: rel_3_26_0_ga~3 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=91086509023cb7cfac0132553ee2871859ad6721;p=javassist.git adds CtBehavior#insertAfter(String,boolean,boolean) for Issue #275 --- diff --git a/Readme.html b/Readme.html index 461c614a..0ce25f57 100644 --- a/Readme.html +++ b/Readme.html @@ -283,7 +283,7 @@ see javassist.Dump.

-version 3.26

-version 3.25 on April 16, 2019 diff --git a/build.xml b/build.xml index da6101fc..f8246c7a 100644 --- a/build.xml +++ b/build.xml @@ -79,8 +79,8 @@ destdir="${build.classes.dir}" debug="on" deprecation="on" - source="1.7" - target="1.7" + source="1.8" + target="1.8" optimize="off" includeantruntime="true" includes="**"> diff --git a/javassist.jar b/javassist.jar index 19969da0..6ca56990 100644 Binary files a/javassist.jar and b/javassist.jar differ diff --git a/pom.xml b/pom.xml index cbc25375..89584133 100644 --- a/pom.xml +++ b/pom.xml @@ -151,8 +151,8 @@ maven-compiler-plugin 3.2 - 1.7 - 1.7 + 1.8 + 1.8 11 11 -parameters diff --git a/src/main/javassist/CtBehavior.java b/src/main/javassist/CtBehavior.java index a0738ec7..fd3dac96 100644 --- a/src/main/javassist/CtBehavior.java +++ b/src/main/javassist/CtBehavior.java @@ -812,7 +812,7 @@ public abstract class CtBehavior extends CtMember { /** * Inserts bytecode at the end of the body. - * The bytecode is inserted just before every return insturction. + * The bytecode is inserted just before every return instruction. * It is not executed when an exception is thrown. * * @param src the source code representing the inserted bytecode. @@ -821,12 +821,12 @@ public abstract class CtBehavior extends CtMember { public void insertAfter(String src) throws CannotCompileException { - insertAfter(src, false); + insertAfter(src, false, false); } /** * Inserts bytecode at the end of the body. - * The bytecode is inserted just before every return insturction. + * The bytecode is inserted just before every return instruction. * * @param src the source code representing the inserted bytecode. * It must be a single statement or block. @@ -838,6 +838,30 @@ public abstract class CtBehavior extends CtMember { */ public void insertAfter(String src, boolean asFinally) throws CannotCompileException + { + insertAfter(src, asFinally, false); + } + + /** + * Inserts bytecode at the end of the body. + * The bytecode is inserted just before every return instruction. + * + * @param src the source code representing the inserted bytecode. + * It must be a single statement or block. + * @param asFinally true if the inserted bytecode is executed + * not only when the control normally returns + * but also when an exception is thrown. + * If this parameter is true, the inserted code cannot + * access local variables. + * @param redundant if true, redundant bytecode will be generated. + * the redundancy is necessary when some compilers (Kotlin?) + * generate the original bytecode. + * The other insertAfter methods calls this method + * with false for this parameter. + * @since 3.26 + */ + public void insertAfter(String src, boolean asFinally, boolean redundant) + throws CannotCompileException { CtClass cc = declaringClass; cc.checkModify(); @@ -878,18 +902,50 @@ 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 (noReturn) { - // finally clause for normal termination - adviceLen = insertAfterAdvice(b, jv, src, pool, rtype, varNo); - handlerPos = iterator.append(b.get()); - iterator.append(b.getExceptionTable(), handlerPos); + if (redundant) { + iterator.setMark2(handlerPos); + Bytecode bcode; + Javac jvc; + int retVarNo; + if (noReturn) { + noReturn = false; + bcode = b; + jvc = jv; + retVarNo = varNo; + } + else { + bcode = new Bytecode(pool, 0, retAddr + 1); + bcode.setStackDepth(ca.getMaxStack() + 1); + jvc = new Javac(bcode, cc); + int nvars2 = jvc.recordParams(getParameterTypes(), + Modifier.isStatic(getModifiers())); + jvc.recordParamNames(ca, nvars2); + retVarNo = jvc.recordReturnType(rtype, true); + jvc.recordLocalVariables(ca, 0); + } + + int adviceLen2 = insertAfterAdvice(bcode, jvc, src, pool, rtype, retVarNo); + int offset = iterator.append(bcode.get()); + iterator.append(bcode.getExceptionTable(), offset); + int advicePos2 = iterator.getCodeLength() - adviceLen2; + insertGoto(iterator, advicePos2, pos); + handlerPos = iterator.getMark2(); + } + else { + if (noReturn) { + // finally clause for normal termination + adviceLen = insertAfterAdvice(b, jv, src, pool, rtype, varNo); + handlerPos = iterator.append(b.get()); + iterator.append(b.getExceptionTable(), handlerPos); + advicePos = iterator.getCodeLength() - adviceLen; + handlerLen = advicePos - handlerPos; + noReturn = false; + } + + insertGoto(iterator, advicePos, pos); advicePos = iterator.getCodeLength() - adviceLen; - handlerLen = advicePos - handlerPos; - noReturn = false; + handlerPos = advicePos - handlerLen; } - insertGoto(iterator, advicePos, pos); - advicePos = iterator.getCodeLength() - adviceLen; - handlerPos = advicePos - handlerLen; } } diff --git a/src/main/javassist/bytecode/CodeIterator.java b/src/main/javassist/bytecode/CodeIterator.java index b9a23c2c..6281ec2d 100644 --- a/src/main/javassist/bytecode/CodeIterator.java +++ b/src/main/javassist/bytecode/CodeIterator.java @@ -52,7 +52,7 @@ public class CodeIterator implements Opcode { protected byte[] bytecode; protected int endPos; protected int currentPos; - protected int mark; + protected int mark, mark2; protected CodeIterator(CodeAttribute ca) { codeAttr = ca; @@ -64,7 +64,7 @@ public class CodeIterator implements Opcode { * Moves to the first instruction. */ public void begin() { - currentPos = mark = 0; + currentPos = mark = mark2 = 0; endPos = getCodeLength(); } @@ -98,6 +98,20 @@ public class CodeIterator implements Opcode { mark = index; } + /** + * Sets a mark to the bytecode at the given index. + * The mark can be used to track the position of that bytecode + * when code blocks are inserted. + * If a code block is inclusively inserted at the position of the + * bytecode, the mark is set to the inserted code block. + * + * @see #getMark2() + * @since 3.26 + */ + public void setMark2(int index) { + mark2 = index; + } + /** * Gets the index of the position of the mark set by * setMark. @@ -108,6 +122,16 @@ public class CodeIterator implements Opcode { */ public int getMark() { return mark; } + /** + * Gets the index of the position of the mark set by + * setMark2. + * + * @return the index of the position. + * @see #setMark2(int) + * @since 3.26 + */ + public int getMark2() { return mark2; } + /** * Returns a Code attribute read with this iterator. */ @@ -646,6 +670,9 @@ public class CodeIterator implements Opcode { if (mark > pos || (mark == pos && exclusive)) mark += length2; + + if (mark2 > pos || (mark2 == pos && exclusive)) + mark2 += length2; } codeAttr.setCode(c); @@ -1012,16 +1039,17 @@ public class CodeIterator implements Opcode { static class Pointers { int cursor; - int mark0, mark; + int mark0, mark, mark2; ExceptionTable etable; LineNumberAttribute line; LocalVariableAttribute vars, types; StackMapTable stack; StackMap stack2; - Pointers(int cur, int m, int m0, ExceptionTable et, CodeAttribute ca) { + Pointers(int cur, int m, int m2, int m0, ExceptionTable et, CodeAttribute ca) { cursor = cur; mark = m; + mark2 = m2; mark0 = m0; etable = et; // non null line = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag); @@ -1038,6 +1066,9 @@ public class CodeIterator implements Opcode { if (where < mark || (where == mark && exclusive)) mark += gapLength; + if (where < mark2 || (where == mark2 && exclusive)) + mark2 += gapLength; + if (where < mark0 || (where == mark0 && exclusive)) mark0 += gapLength; @@ -1074,7 +1105,7 @@ public class CodeIterator implements Opcode { CodeAttribute ca, CodeAttribute.LdcEntry ldcs) throws BadBytecode { - Pointers pointers = new Pointers(0, 0, 0, etable, ca); + Pointers pointers = new Pointers(0, 0, 0, 0, etable, ca); List jumps = makeJumpList(code, code.length, pointers); while (ldcs != null) { addLdcW(ldcs, jumps); @@ -1118,11 +1149,12 @@ public class CodeIterator implements Opcode { if (gapLength <= 0) return code; - Pointers pointers = new Pointers(currentPos, mark, where, etable, ca); + Pointers pointers = new Pointers(currentPos, mark, mark2, where, etable, ca); List jumps = makeJumpList(code, code.length, pointers); byte[] r = insertGap2w(code, where, gapLength, exclusive, jumps, pointers); currentPos = pointers.cursor; mark = pointers.mark; + mark2 = pointers.mark2; int where2 = pointers.mark0; if (where2 == currentPos && !exclusive) currentPos += gapLength; diff --git a/src/test/javassist/JvstTest5.java b/src/test/javassist/JvstTest5.java index 4d4fc719..c2ee9992 100644 --- a/src/test/javassist/JvstTest5.java +++ b/src/test/javassist/JvstTest5.java @@ -546,4 +546,16 @@ public class JvstTest5 extends JvstTestRoot { Object obj = make(cc.getName()); assertEquals(1, invoke(obj, "run")); } + + // Issue #275 + public void testRedundantInsertAfter() throws Exception { + CtClass cc = sloader.get(test5.InsertAfter.class.getName()); + CtMethod m = cc.getDeclaredMethod("foo"); + m.insertAfter("{ $_ += 1; }", false, true); + CtMethod m2 = cc.getDeclaredMethod("bar"); + m2.insertAfter("{ $_ += 1; }", true, true); + cc.writeFile(); + Object obj = make(cc.getName()); + assertEquals(1, invoke(obj, "run")); + } } diff --git a/src/test/test5/InsertAfter.java b/src/test/test5/InsertAfter.java new file mode 100644 index 00000000..6d62c06a --- /dev/null +++ b/src/test/test5/InsertAfter.java @@ -0,0 +1,35 @@ +package test5; + +public class InsertAfter { + public int run() { + return foo(7) + bar(20); + } + + public int foo(int k) { + if (k > 0) + if (k > 10) + return k + 1; + else + return k * 10; + else + return k * 100; + } + + public int bar(int k) { + if (k > 0) + try { + if (k > 10) + return k + 1; + else + return k * 10; + } + catch (Exception e) { + if (k > 0) + return k * 1000; + else + throw e; + } + else + return k * 100; + } +}