]> source.dussan.org Git - javassist.git/commitdiff
synchronized statement support.
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Tue, 2 Nov 2004 17:03:26 +0000 (17:03 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Tue, 2 Nov 2004 17:03:26 +0000 (17:03 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@146 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

Readme.html
src/main/javassist/bytecode/ExceptionTable.java
src/main/javassist/compiler/CodeGen.java
tutorial/tutorial2.html

index 8fd543d13dbc43c2db49f40ad1157f7f1fa9888b..615728550aa699367ab438b899df6a2917edbe12 100644 (file)
@@ -255,6 +255,12 @@ see javassist.Dump.
 
 <h2>Changes</h2>
 
+<p>- version 3.0
+
+<ul>
+  <li>The compiler now supports a synchronized statement.
+</ul>
+
 <p>- version 3.0 RC1 in September 13, 2004.
 
 <ul>
index 246b4231391ad8d896d9e0c957adef2334e0469f..e2c20c9217d7bb03f4c7c9fd4df25c8ad345e4ce 100644 (file)
@@ -186,7 +186,8 @@ public class ExceptionTable {
      * @param type      <code>catchType</code>
      */
     public void add(int index, int start, int end, int handler, int type) {
-        entries.add(index,
+        if (start < end)
+            entries.add(index,
                     new ExceptionTableEntry(start, end, handler, type));
     }
 
@@ -199,7 +200,8 @@ public class ExceptionTable {
      * @param type      <code>catchType</code>
      */
     public void add(int start, int end, int handler, int type) {
-        entries.add(new ExceptionTableEntry(start, end, handler, type));
+        if (start < end)
+            entries.add(new ExceptionTableEntry(start, end, handler, type));
     }
 
     /**
index 3308a2420691ce84e258e1df589d862dfdf32492..7dc3d973d18b820e1c7ee0ea8addea7d7e9e1e0d 100644 (file)
@@ -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();
index 778f44eeb579e03d8de019caadb4bbfc3f90c387..7ef1fedb1ff5a6daeb7c21814791cf6f16136182 100644 (file)
@@ -1359,6 +1359,16 @@ value.  This source text can be any Java expression if the result type
 of the expression matches the type of the field.  Note that an expression
 does not end with a semi colon (<code>;</code>).
 
+<p>Furthermore, the above code can be rewritten into the following
+simple code:
+
+<ul><pre>
+CtClass point = ClassPool.getDefault().get("Point");
+CtField f = CtField.make("public int z = 0;", point);
+point.addField(f);
+</pre></ul>
+
+
 <p><br>
 
 <a name="runtime">
@@ -1395,8 +1405,6 @@ supported.
 
 <p><li>Inner classes or anonymous classes are not supported.
 
-<p><li><code>synchronized</code> statements are not supported yet.
-
 <p><li>Labeled <code>continue</code> and <code>break</code> statements
 are not supported.