diff options
author | chibash <chiba@javassist.org> | 2014-08-10 18:23:09 +0900 |
---|---|---|
committer | chibash <chiba@javassist.org> | 2014-08-10 18:23:09 +0900 |
commit | 1d3ff9f328f1f90be71799857fc0ce9814eea4df (patch) | |
tree | 3a800f38d65d1895345630c09e8136dd9210cf32 /src/main/javassist/compiler | |
parent | 7497ae88e9644826568aa3b927f314804e4fc021 (diff) | |
download | javassist-1d3ff9f328f1f90be71799857fc0ce9814eea4df.tar.gz javassist-1d3ff9f328f1f90be71799857fc0ce9814eea4df.zip |
fixed JASSIST-230
Diffstat (limited to 'src/main/javassist/compiler')
-rw-r--r-- | src/main/javassist/compiler/CodeGen.java | 115 |
1 files changed, 74 insertions, 41 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 |