diff options
author | chibash <chiba@javassist.org> | 2019-09-20 23:20:39 +0900 |
---|---|---|
committer | chibash <chiba@javassist.org> | 2019-09-20 23:20:39 +0900 |
commit | 91086509023cb7cfac0132553ee2871859ad6721 (patch) | |
tree | c3ca739488cd20a2668caf0b9d330324fa4ed340 | |
parent | f7ef31ce8b723e425a66aafb8c0beddeabfe9a66 (diff) | |
download | javassist-91086509023cb7cfac0132553ee2871859ad6721.tar.gz javassist-91086509023cb7cfac0132553ee2871859ad6721.zip |
adds CtBehavior#insertAfter(String,boolean,boolean) for Issue #275
-rw-r--r-- | Readme.html | 2 | ||||
-rw-r--r-- | build.xml | 4 | ||||
-rw-r--r-- | javassist.jar | bin | 774695 -> 771168 bytes | |||
-rw-r--r-- | pom.xml | 4 | ||||
-rw-r--r-- | src/main/javassist/CtBehavior.java | 82 | ||||
-rw-r--r-- | src/main/javassist/bytecode/CodeIterator.java | 44 | ||||
-rw-r--r-- | src/test/javassist/JvstTest5.java | 12 | ||||
-rw-r--r-- | src/test/test5/InsertAfter.java | 35 |
8 files changed, 159 insertions, 24 deletions
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. <p>-version 3.26 <ul> - <li>GitHub Issue #270 (PR #272), Issue #265 (PR #267), Issue #271 and #222. + <li>GitHub Issue #270 (PR #272), #265 (PR #267), #271, #222, and #275. </ul> <p>-version 3.25 on April 16, 2019 @@ -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 Binary files differindex 19969da0..6ca56990 100644 --- a/javassist.jar +++ b/javassist.jar @@ -151,8 +151,8 @@ <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> - <source>1.7</source> - <target>1.7</target> + <source>1.8</source> + <target>1.8</target> <testSource>11</testSource> <testTarget>11</testTarget> <testCompilerArgument>-parameters</testCompilerArgument> 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. @@ -839,6 +839,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 <code>insertAfter</code> methods calls this method + * with <code>false</code> for this parameter. + * @since 3.26 + */ + public void insertAfter(String src, boolean asFinally, boolean redundant) + throws CannotCompileException + { CtClass cc = declaringClass; cc.checkModify(); ConstPool pool = methodInfo.getConstPool(); @@ -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(); } @@ -99,6 +99,20 @@ public class CodeIterator implements Opcode { } /** + * 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 * <code>setMark</code>. * @@ -109,6 +123,16 @@ public class CodeIterator implements Opcode { public int getMark() { return mark; } /** + * Gets the index of the position of the mark set by + * <code>setMark2</code>. + * + * @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. */ public CodeAttribute get() { @@ -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<Branch> 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<Branch> 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; + } +} |