diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-11-02 17:03:26 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-11-02 17:03:26 +0000 |
commit | 30ea2357da95ebda1d7b28fb3027bb8694b55614 (patch) | |
tree | efa84d27594fbc4eaf2f928f4496da96fb0d1137 /src/main/javassist/compiler/CodeGen.java | |
parent | 6dfecfeff49e85ccb241243b5132ea9af718ce02 (diff) | |
download | javassist-30ea2357da95ebda1d7b28fb3027bb8694b55614.tar.gz javassist-30ea2357da95ebda1d7b28fb3027bb8694b55614.zip |
synchronized statement support.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@146 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist/compiler/CodeGen.java')
-rw-r--r-- | src/main/javassist/compiler/CodeGen.java | 83 |
1 files changed, 79 insertions, 4 deletions
diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java index 3308a242..7dc3d973 100644 --- a/src/main/javassist/compiler/CodeGen.java +++ b/src/main/javassist/compiler/CodeGen.java @@ -48,6 +48,24 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { protected ArrayList breakList, continueList; + /** + * doit() in ReturnHook is called from atReturn(). + */ + protected static abstract class ReturnHook { + ReturnHook next; + protected abstract void doit(Bytecode b); + protected ReturnHook(CodeGen gen) { + next = gen.returnHooks; + gen.returnHooks = this; + } + + protected void remove(CodeGen gen) { + gen.returnHooks = next; + } + } + + protected ReturnHook returnHooks; + /* The following fields are used by atXXX() methods * for returning the type of the compiled expression. */ @@ -63,6 +81,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { inStaticMethod = false; breakList = null; continueList = null; + returnHooks = null; } public void setTypeChecker(TypeChecker checker) { @@ -341,10 +360,8 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { atTryStmnt(st); else if (op == SWITCH) atSwitchStmnt(st); - else if (op == SYNCHRONIZED) { - hasReturned = false; - throw new CompileError("sorry, synchronized is not supported"); - } + else if (op == SYNCHRONIZED) + atSyncStmnt(st); else { // LABEL, SWITCH label stament might be null?. hasReturned = false; @@ -589,6 +606,9 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { } } + for (ReturnHook har = returnHooks; har != null; har = har.next) + har.doit(bytecode); + bytecode.addOpcode(op); hasReturned = true; } @@ -607,6 +627,61 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { hasReturned = false; } + private void atSyncStmnt(Stmnt st) throws CompileError { + int nbreaks = getListSize(breakList); + int ncontinues = getListSize(continueList); + + compileExpr(st.head()); + if (exprType != CLASS && arrayDim == 0) + throw new CompileError("bad type expr for synchronized block"); + + Bytecode bc = bytecode; + final int var = bc.getMaxLocals(); + bc.incMaxLocals(1); + bc.addOpcode(DUP); + bc.addAstore(var); + bc.addOpcode(MONITORENTER); + + ReturnHook rh = new ReturnHook(this) { + protected void doit(Bytecode b) { + b.addAload(var); + b.addOpcode(MONITOREXIT); + } + }; + + int pc = bc.currentPc(); + Stmnt body = (Stmnt)st.tail(); + if (body != null) + body.accept(this); + + int pc2 = bc.currentPc(); + int pc3 = 0; + if (!hasReturned) { + rh.doit(bc); + bc.addOpcode(Opcode.GOTO); + pc3 = bc.currentPc(); + bc.addIndex(0); + } + + int pc4 = bc.currentPc(); + rh.doit(bc); + bc.addOpcode(ATHROW); + bc.addExceptionHandler(pc, pc2, pc4, 0); + if (!hasReturned) + bc.write16bit(pc3, bc.currentPc() - pc3 + 1); + + rh.remove(this); + + if (getListSize(breakList) != nbreaks + || getListSize(continueList) != ncontinues) + throw new CompileError( + "sorry, cannot break/continue in synchronized block"); + } + + private static int getListSize(ArrayList list) { + return list == null ? 0 : list.size(); + } + private static boolean isPlusPlusExpr(ASTree expr) { if (expr instanceof Expr) { int op = ((Expr)expr).getOperator(); |