Browse Source

fixed JASSIST-230

tags/rel_3_19_0_ga
chibash 9 years ago
parent
commit
1d3ff9f328
4 changed files with 124 additions and 51 deletions
  1. 1
    1
      Readme.html
  2. 74
    41
      src/main/javassist/compiler/CodeGen.java
  3. 13
    9
      src/test/Test.java
  4. 36
    0
      src/test/javassist/JvstTest4.java

+ 1
- 1
Readme.html View File



<p>-version 3.19 <p>-version 3.19
<ul> <ul>
<li>JIRA JASSIST-158, 205, 206, 207, 211, 212, 216, 220, 223, 224, 227.
<li>JIRA JASSIST-158, 205, 206, 207, 211, 212, 216, 220, 223, 224, 227, 230.
</ul> </ul>
</p> </p>



+ 74
- 41
src/main/javassist/compiler/CodeGen.java View File

ASTree expr = st.head(); ASTree expr = st.head();
Stmnt thenp = (Stmnt)st.tail().head(); Stmnt thenp = (Stmnt)st.tail().head();
Stmnt elsep = (Stmnt)st.tail().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 pc = bytecode.currentPc();
int pc2 = 0; int pc2 = 0;
bytecode.addIndex(0); // correct later bytecode.addIndex(0); // correct later
} }


bytecode.write16bit(pc, bytecode.currentPc() - pc + 1); bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);

if (elsep != null) { if (elsep != null) {
elsep.accept(this); elsep.accept(this);
if (!thenHasReturned) if (!thenHasReturned)
if (notDo) if (notDo)
bytecode.write16bit(pc, pc3 - pc + 1); 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(breakList, bytecode.currentPc());
patchGoto(continueList, pc3); patchGoto(continueList, pc3);
continueList = prevContList; continueList = prevContList;
int pc = bytecode.currentPc(); int pc = bytecode.currentPc();
int pc2 = 0; int pc2 = 0;
if (expr != null) { 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(); pc2 = bytecode.currentPc();
bytecode.addIndex(0); bytecode.addIndex(0);
} }
} }


public void atCondExpr(CondExpr expr) throws CompileError { 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 = { static final int[] binOp = {
else { else {
/* equation: &&, ||, ==, !=, <=, >=, <, > /* 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 bytecode.addIconst(1); // true
} }
} }
} }


/* Produces the opcode to branch if the condition is true. /* 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). * @return true if the compiled code is GOTO (always branch).
* GOTO is not produced.
*/ */
private boolean booleanExpr(boolean branchIf, ASTree expr) private boolean booleanExpr(boolean branchIf, ASTree expr)
throws CompileError throws CompileError
compareExpr(branchIf, bexpr.getOperator(), type1, bexpr); compareExpr(branchIf, bexpr.getOperator(), type1, bexpr);
} }
else if (op == '!') else if (op == '!')
booleanExpr(!branchIf, ((Expr)expr).oprand1());
return booleanExpr(!branchIf, ((Expr)expr).oprand1());
else if ((isAndAnd = (op == ANDAND)) || op == OROR) { else if ((isAndAnd = (op == ANDAND)) || op == OROR) {
BinExpr bexpr = (BinExpr)expr; 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)) { 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 return true; // always branch
} }
else { // others else { // others
return false; return false;
} }



private static boolean isAlwaysBranch(ASTree expr, boolean branchIf) { private static boolean isAlwaysBranch(ASTree expr, boolean branchIf) {
if (expr instanceof Keyword) { if (expr instanceof Keyword) {
int t = ((Keyword)expr).get(); int t = ((Keyword)expr).get();
else if (token == PLUSPLUS || token == MINUSMINUS) else if (token == PLUSPLUS || token == MINUSMINUS)
atPlusPlus(token, oprand, expr, true); atPlusPlus(token, oprand, expr, true);
else if (token == '!') { 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); bytecode.addIconst(0);
} }
else if (token == CALL) // method call else if (token == CALL) // method call

+ 13
- 9
src/test/Test.java View File

public class Test { public class Test {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); 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);
} }
} }

+ 36
- 0
src/test/javassist/JvstTest4.java View File

} }
}); });
} }

// 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);
}
} }

Loading…
Cancel
Save