* @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));
}
* @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));
}
/**
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.
*/
inStaticMethod = false;
breakList = null;
continueList = null;
+ returnHooks = null;
}
public void setTypeChecker(TypeChecker checker) {
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;
}
}
+ for (ReturnHook har = returnHooks; har != null; har = har.next)
+ har.doit(bytecode);
+
bytecode.addOpcode(op);
hasReturned = true;
}
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();
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">
<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.