aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/javassist/compiler/CodeGen.java115
-rw-r--r--src/test/Test.java22
-rw-r--r--src/test/javassist/JvstTest4.java36
3 files changed, 123 insertions, 50 deletions
diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java
index bbcce895..d2bdea9a 100644
--- a/src/main/javassist/compiler/CodeGen.java
+++ b/src/main/javassist/compiler/CodeGen.java
@@ -381,7 +381,14 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
ASTree expr = st.head();
Stmnt thenp = (Stmnt)st.tail().head();
Stmnt elsep = (Stmnt)st.tail().tail().head();
- compileBooleanExpr(false, expr);
+ if (compileBooleanExpr(false, expr)) {
+ hasReturned = false;
+ if (elsep != null)
+ elsep.accept(this);
+
+ return;
+ }
+
int pc = bytecode.currentPc();
int pc2 = 0;
bytecode.addIndex(0); // correct later
@@ -400,7 +407,6 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
}
bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
-
if (elsep != null) {
elsep.accept(this);
if (!thenHasReturned)
@@ -434,9 +440,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
if (notDo)
bytecode.write16bit(pc, pc3 - pc + 1);
- boolean alwaysBranch = compileBooleanExpr(true, expr) && breakList.size() == 0;
- bytecode.addIndex(pc2 - bytecode.currentPc() + 1);
+ boolean alwaysBranch = compileBooleanExpr(true, expr);
+ if (alwaysBranch) {
+ bytecode.addOpcode(Opcode.GOTO);
+ alwaysBranch = breakList.size() == 0;
+ }
+ bytecode.addIndex(pc2 - bytecode.currentPc() + 1);
patchGoto(breakList, bytecode.currentPc());
patchGoto(continueList, pc3);
continueList = prevContList;
@@ -471,7 +481,14 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
int pc = bytecode.currentPc();
int pc2 = 0;
if (expr != null) {
- compileBooleanExpr(false, expr);
+ if (compileBooleanExpr(false, expr)) {
+ // in case of "for (...; false; ...)"
+ continueList = prevContList;
+ breakList = prevBreakList;
+ hasReturned = false;
+ return;
+ }
+
pc2 = bytecode.currentPc();
bytecode.addIndex(0);
}
@@ -915,20 +932,23 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
}
public void atCondExpr(CondExpr expr) throws CompileError {
- booleanExpr(false, expr.condExpr());
- int pc = bytecode.currentPc();
- bytecode.addIndex(0); // correct later
- expr.thenExpr().accept(this);
- int dim1 = arrayDim;
- bytecode.addOpcode(Opcode.GOTO);
- int pc2 = bytecode.currentPc();
- bytecode.addIndex(0);
- bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
- expr.elseExpr().accept(this);
- if (dim1 != arrayDim)
- throw new CompileError("type mismatch in ?:");
+ if (booleanExpr(false, expr.condExpr()))
+ expr.elseExpr().accept(this);
+ else {
+ int pc = bytecode.currentPc();
+ bytecode.addIndex(0); // correct later
+ expr.thenExpr().accept(this);
+ int dim1 = arrayDim;
+ bytecode.addOpcode(Opcode.GOTO);
+ int pc2 = bytecode.currentPc();
+ bytecode.addIndex(0);
+ bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
+ expr.elseExpr().accept(this);
+ if (dim1 != arrayDim)
+ throw new CompileError("type mismatch in ?:");
- bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);
+ bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);
+ }
}
static final int[] binOp = {
@@ -982,11 +1002,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
else {
/* equation: &&, ||, ==, !=, <=, >=, <, >
*/
- booleanExpr(true, expr);
- bytecode.addIndex(7);
- bytecode.addIconst(0); // false
- bytecode.addOpcode(Opcode.GOTO);
- bytecode.addIndex(4);
+ if (!booleanExpr(true, expr)) {
+ bytecode.addIndex(7);
+ bytecode.addIconst(0); // false
+ bytecode.addOpcode(Opcode.GOTO);
+ bytecode.addIndex(4);
+ }
+
bytecode.addIconst(1); // true
}
}
@@ -1088,9 +1110,10 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
}
/* Produces the opcode to branch if the condition is true.
- * The oprand is not produced.
+ * The oprand (branch offset) is not produced.
*
* @return true if the compiled code is GOTO (always branch).
+ * GOTO is not produced.
*/
private boolean booleanExpr(boolean branchIf, ASTree expr)
throws CompileError
@@ -1105,22 +1128,31 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
compareExpr(branchIf, bexpr.getOperator(), type1, bexpr);
}
else if (op == '!')
- booleanExpr(!branchIf, ((Expr)expr).oprand1());
+ return booleanExpr(!branchIf, ((Expr)expr).oprand1());
else if ((isAndAnd = (op == ANDAND)) || op == OROR) {
BinExpr bexpr = (BinExpr)expr;
- booleanExpr(!isAndAnd, bexpr.oprand1());
- int pc = bytecode.currentPc();
- bytecode.addIndex(0); // correct later
-
- booleanExpr(isAndAnd, bexpr.oprand2());
- bytecode.write16bit(pc, bytecode.currentPc() - pc + 3);
- if (branchIf != isAndAnd) {
- bytecode.addIndex(6); // skip GOTO instruction
- bytecode.addOpcode(Opcode.GOTO);
+ if (booleanExpr(!isAndAnd, bexpr.oprand1())) {
+ exprType = BOOLEAN;
+ arrayDim = 0;
+ return true;
+ }
+ else {
+ int pc = bytecode.currentPc();
+ bytecode.addIndex(0); // correct later
+ if (booleanExpr(isAndAnd, bexpr.oprand2()))
+ bytecode.addOpcode(Opcode.GOTO);
+
+ bytecode.write16bit(pc, bytecode.currentPc() - pc + 3);
+ if (branchIf != isAndAnd) {
+ bytecode.addIndex(6); // skip GOTO instruction
+ bytecode.addOpcode(Opcode.GOTO);
+ }
}
}
else if (isAlwaysBranch(expr, branchIf)) {
- bytecode.addOpcode(Opcode.GOTO);
+ // Opcode.GOTO is not added here. The caller must add it.
+ exprType = BOOLEAN;
+ arrayDim = 0;
return true; // always branch
}
else { // others
@@ -1136,7 +1168,6 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
return false;
}
-
private static boolean isAlwaysBranch(ASTree expr, boolean branchIf) {
if (expr instanceof Keyword) {
int t = ((Keyword)expr).get();
@@ -1468,11 +1499,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
else if (token == PLUSPLUS || token == MINUSMINUS)
atPlusPlus(token, oprand, expr, true);
else if (token == '!') {
- booleanExpr(false, expr);
- bytecode.addIndex(7);
- bytecode.addIconst(1);
- bytecode.addOpcode(Opcode.GOTO);
- bytecode.addIndex(4);
+ if (!booleanExpr(false, expr)) {
+ bytecode.addIndex(7);
+ bytecode.addIconst(1);
+ bytecode.addOpcode(Opcode.GOTO);
+ bytecode.addIndex(4);
+ }
+
bytecode.addIconst(0);
}
else if (token == CALL) // method call
diff --git a/src/test/Test.java b/src/test/Test.java
index 51591cf9..044b7d4e 100644
--- a/src/test/Test.java
+++ b/src/test/Test.java
@@ -3,14 +3,18 @@ import javassist.*;
public class Test {
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault();
- // ClassPool cp = new ClassPool();
- cp.insertClassPath("./target/test-classes");
- CtClass cc = cp.get("test4.JIRA207");
- // cc.getClassFile().setMajorVersion(javassist.bytecode.ClassFile.JAVA_4);
- CtMethod cm = cc.getDeclaredMethod("foo");
- cm.insertBefore("throw new Exception();");
- CtMethod cm2 = cc.getDeclaredMethod("run2");
- cm2.insertBefore("throw new Exception();");
- cc.writeFile();
+ CtClass newClass = cp.makeClass("test4.TestDeadcode");
+ addDeadCode(newClass, "public void evaluate5(){ boolean b = !false; b = false && b; b = true && true;"
+ + " b = true || b; b = b || false; }");
+
+ newClass.debugWriteFile();
+ Class<?> cClass = newClass.toClass();
+ Object o = cClass.newInstance();
+ java.lang.reflect.Method m = cClass.getMethod("evaluate5");
+ m.invoke(o);
+ }
+ private static void addDeadCode(CtClass cc, String meth) throws Exception {
+ CtMethod m = CtNewMethod.make(meth, cc);
+ cc.addMethod(m);
}
}
diff --git a/src/test/javassist/JvstTest4.java b/src/test/javassist/JvstTest4.java
index 73a1b08f..b36e9b9f 100644
--- a/src/test/javassist/JvstTest4.java
+++ b/src/test/javassist/JvstTest4.java
@@ -994,4 +994,40 @@ public class JvstTest4 extends JvstTestRoot {
}
});
}
+
+ // JIRA-230
+ public void testDeadcode() throws Exception {
+ CtClass newClass = sloader.makeClass("test4.TestDeadcode");
+ addDeadCode(newClass, "public void evaluate(){if (false) {int i = 0;}}");
+ addDeadCode(newClass, "public void evaluate2(){if (false == true) {int i = 0;}}");
+ addDeadCode(newClass, "public void evaluate3(){if (true) {} else {} int i = 0; if (false) {} else {} i++; }");
+ addDeadCode(newClass, "public void evaluate4(){ for (;false;); int i = false ? 1 : 0; while (true) { return; }}");
+ addDeadCode(newClass, "public void evaluate5(){ boolean b = !false; b = false && b; b = true && true;"
+ + " b = true || b; b = b || false; }");
+ addDeadCode(newClass, "public boolean evaluate6(){ return !false; }");
+ addDeadCode(newClass, "public boolean evaluate7(){ return !true; }");
+
+ newClass.debugWriteFile();
+ Class<?> cClass = newClass.toClass();
+ Object o = cClass.newInstance();
+ java.lang.reflect.Method m = cClass.getMethod("evaluate");
+ m.invoke(o);
+ m = cClass.getMethod("evaluate2");
+ m.invoke(o);
+ m = cClass.getMethod("evaluate3");
+ m.invoke(o);
+ m = cClass.getMethod("evaluate4");
+ m.invoke(o);
+ m = cClass.getMethod("evaluate6");
+ assertTrue((boolean)m.invoke(o));
+ m = cClass.getMethod("evaluate7");
+ assertFalse((boolean)m.invoke(o));
+ m = cClass.getMethod("evaluate5");
+ m.invoke(o);
+ }
+
+ private void addDeadCode(CtClass cc, String meth) throws Exception {
+ CtMethod m = CtNewMethod.make(meth, cc);
+ cc.addMethod(m);
+ }
}