]> source.dussan.org Git - javassist.git/commitdiff
adds CtBehavior#insertAfter(String,boolean,boolean) for Issue #275
authorchibash <chiba@javassist.org>
Fri, 20 Sep 2019 14:20:39 +0000 (23:20 +0900)
committerchibash <chiba@javassist.org>
Fri, 20 Sep 2019 14:20:39 +0000 (23:20 +0900)
Readme.html
build.xml
javassist.jar
pom.xml
src/main/javassist/CtBehavior.java
src/main/javassist/bytecode/CodeIterator.java
src/test/javassist/JvstTest5.java
src/test/test5/InsertAfter.java [new file with mode: 0644]

index 461c614a7fb5b47e3260f62693d86e7a4a71a2c2..0ce25f57d4253d17973aba60bf350d52b9b4949b 100644 (file)
@@ -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
index da6101fc439c6b15f65ffe01dc2ee8edbf0d86fd..f8246c7aa9d0aef88aadf03c4c81058d93b8b918 100644 (file)
--- 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="**">
index 19969da060f4eda0e2f653eaa5ee7054a1b49fae..6ca569907b7767a1f9b180d6ae36a45f9dbeb6d2 100644 (file)
Binary files a/javassist.jar and b/javassist.jar differ
diff --git a/pom.xml b/pom.xml
index cbc25375054b0926cd2fd13c76e13b863cf1ea3a..8958413324dd1a25fcd666c85f73f66edfc0f09d 100644 (file)
--- a/pom.xml
+++ b/pom.xml
         <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>
index a0738ec701c480cf5702ba7ab16f3041ee2711e0..fd3dac9604fa59ef80a7e6c5010f03959d9452ff 100644 (file)
@@ -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 <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();
@@ -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;
                 }
             }
 
index b9a23c2cca01a0924baf2614eb678a8fdfc6e471..6281ec2d9a314db9233745dae7cbed7d7d147364 100644 (file)
@@ -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
      * <code>setMark</code>.
@@ -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
+     * <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.
      */
@@ -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;
index 4d4fc719df2e074eca863963c01d37741cd4f09f..c2ee9992775d26331dfeab46c88b198843f0db46 100644 (file)
@@ -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 (file)
index 0000000..6d62c06
--- /dev/null
@@ -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;
+    }
+}