aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/compiler/CodeGen.java
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2004-11-02 17:03:26 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2004-11-02 17:03:26 +0000
commit30ea2357da95ebda1d7b28fb3027bb8694b55614 (patch)
treeefa84d27594fbc4eaf2f928f4496da96fb0d1137 /src/main/javassist/compiler/CodeGen.java
parent6dfecfeff49e85ccb241243b5132ea9af718ce02 (diff)
downloadjavassist-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.java83
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();