--- a/src/share/classes/com/sun/tools/javac/comp/DeClosure.java Sun Jul 13 20:50:18 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/DeClosure.java Sat Jul 26 23:02:31 2008 -0700
@@ -57,6 +57,7 @@ import com.sun.tools.javac.util.ListBuff
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Name;
+import java.lang.ref.Reference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -120,11 +121,6 @@ public class DeClosure {
JCExpression thread; // the field of the current frame that holds the executing thread
JCExpression dead; // the field of the frame that is set to true when the method completes
}
- class ReturnState extends TransferState {
- JCStatement buildReturn(JCExpression value) {
- throw new UnsupportedOperationException();
- }
- }
// We scan each method, identifying the "lambda depth" of each
// variable declaration. Any variable that is accessed at a depth
@@ -138,7 +134,6 @@ public class DeClosure {
// TODO(gafter)7: can we reduce the frequency with which we alloc maps?
Map<VarSymbol,JCTree> variableFrame = new HashMap<VarSymbol,JCTree>();
Map<JCTree,JCTree> blockFrame = new HashMap<JCTree,JCTree>();
- Map<JCMethodDecl,ReturnState> capturedReturns = new HashMap<JCMethodDecl,ReturnState>();
Map<JCTree,TransferState> capturedContinues = new HashMap<JCTree,TransferState>();
Map<JCTree,TransferState> capturedBreaks = new HashMap<JCTree,TransferState>();
Set<JCTree> capturedTransfers = new HashSet<JCTree>();
@@ -150,8 +145,6 @@ public class DeClosure {
@Override
public void visitMethodDef(JCMethodDecl tree) {
Lint oldLint = lint;
- JCMethodDecl oldEnclosingMethod = enclosingMethod;
- enclosingMethod = tree;
frameStack = frameStack.prepend(tree);
blockFrame.put(tree, frameStack.head);
lint = lint.augment(tree.sym.attributes_field, tree.sym.flags());
@@ -161,7 +154,6 @@ public class DeClosure {
lint = oldLint;
frameStack = frameStack.tail;
blockFrame.remove(tree);
- enclosingMethod = oldEnclosingMethod;
}
}
@@ -429,13 +421,13 @@ public class DeClosure {
}
@Override
public void visitReturn(JCReturn tree) {
- if (frameStack.head != enclosingMethod) {
- capturedReturns.put(enclosingMethod, new ReturnState());
+ if (frameStack.head != tree.target) {
capturedTransfers.add(tree);
- if (targetRestricted(enclosingMethod))
+ capturedTransfers.add(tree.target);
+ if (targetRestricted(tree.target))
log.rawError(tree.pos, "'return' not allowed in a restricted closure");
}
- if (tree.expr != null) retype(tree.expr, enclosingMethod.type.getReturnType());
+ if (tree.expr != null) retype(tree.expr, tree.target.type.getReturnType());
super.visitReturn(tree);
}
@@ -529,6 +521,7 @@ public class DeClosure {
// is translated into an idiom using exceptions or exception-like
// transfers.
private class Phase2 extends TreeTranslator {
+ Map<JCMethodDecl,MethodState> methodStates = new HashMap<JCMethodDecl,MethodState>();
Phase1 phase1;
Phase2(Phase1 phase1) {
this.phase1 = phase1;
@@ -606,8 +599,22 @@ public class DeClosure {
frameStack = oldFrame;
}
}
+ JCStatement translateFrameStatement(final JCStatement frameBody) {
+ final JCStatement[] body = { frameBody };
+ final ListBuffer<JCStatement> additionalStatements =
+ doFrame(new Runnable() {
+ public void run() {
+ body[0] = translate(body[0]);
+ }
+ });
+ if (additionalStatements.nonEmpty())
+ body[0] = make.at(frameBody.pos).Block(0, additionalStatements.append(body[0]).toList());
+ return body[0];
+ }
ListBuffer<JCStatement> doFrame(Runnable body) {
- FrameState state = new FrameState();
+ return doFrame(new FrameState(), body);
+ }
+ ListBuffer<JCStatement> doFrame(FrameState state, Runnable body) {
state.open();
try {
body.run();
@@ -632,14 +639,24 @@ public class DeClosure {
return replacementExpression;
}
+ class MethodState extends FrameState {
+ JCStatement rewriteReturn(JCReturn tree) {
+ log.rawError(tree.pos, "'return' out of a closure not implemented");
+ return tree;
+ }
+ }
+
@Override
public void visitMethodDef(final JCMethodDecl tree) {
+ final MethodState frameState = new MethodState();
+ methodStates.put(tree, frameState); // TODO(gafter)2: can we use the frame stack instead?
Symbol oldOwner = currentOwner;
try {
currentOwner = tree.sym;
final ListBuffer<JCStatement> assign = ListBuffer.<JCStatement>lb();
- final ListBuffer<JCStatement> additionalStatements =
+ final ListBuffer<JCStatement> prelude =
doFrame(
+ frameState,
new Runnable() {
public void run() {
for (JCVariableDecl param : tree.params) {
@@ -649,9 +666,8 @@ public class DeClosure {
assign.add(make.at(param.pos).Exec(make.Assign(replacementExpression, make.Ident(param.sym)).setType(param.sym.type)));
}
}
- if ((tree.mods.flags & Flags.CAPTURED) != 0) {
- TransferState returnState = phase1.capturedReturns.get(tree);
- System.out.println("need to implement support state for nonlocal return");
+ if (phase1.capturedTransfers.remove(tree)) {
+ System.err.println("need to implement support state for nonlocal return");
// TODO(gafter)1: implement support state for nonlocal return.
return;
}
@@ -659,9 +675,10 @@ public class DeClosure {
}
});
if (tree.body != null)
- tree.body.stats = additionalStatements.appendList(assign).appendList(tree.body.stats).toList();
+ tree.body.stats = prelude.appendList(assign).appendList(tree.body.stats).toList();
} finally {
currentOwner = oldOwner;
+ methodStates.remove(tree);
}
}
@@ -698,20 +715,14 @@ public class DeClosure {
}
tree.body = translate(tree.body);
if (assign != null) tree.body.stats = tree.body.stats.prepend(assign);
+ // TODO(gafter)1: implement transparent transfers using java.lang.Jump
result = tree;
}
public void visitDoLoop(final JCDoWhileLoop tree) {
// TODO(gafter)1: capture do loop break transfer target
// TODO(gafter)1: capture do continue transfer target
- final ListBuffer<JCStatement> additionalStatements =
- doFrame(new Runnable() {
- public void run() {
- tree.body = translate(tree.body);
- }
- });
- if (additionalStatements.nonEmpty())
- tree.body = make.Block(0, additionalStatements.append(tree.body).toList());
+ tree.body = translateFrameStatement(tree.body);
tree.cond = translate(tree.cond);
result = tree;
}
@@ -720,14 +731,7 @@ public class DeClosure {
// TODO(gafter)1: capture while loop break transfer target
// TODO(gafter)1: capture while continue transfer target
tree.cond = translate(tree.cond);
- final ListBuffer<JCStatement> additionalStatements =
- doFrame(new Runnable() {
- public void run() {
- tree.body = translate(tree.body);
- }
- });
- if (additionalStatements.nonEmpty())
- tree.body = make.Block(0, additionalStatements.append(tree.body).toList());
+ tree.body = translateFrameStatement(tree.body);
result = tree;
}
@@ -737,14 +741,7 @@ public class DeClosure {
tree.init = translate(tree.init);
tree.cond = translate(tree.cond);
tree.step = translate(tree.step);
- final ListBuffer<JCStatement> additionalStatements =
- doFrame(new Runnable() {
- public void run() {
- tree.body = translate(tree.body);
- }
- });
- if (additionalStatements.nonEmpty())
- tree.body = make.Block(0, additionalStatements.append(tree.body).toList());
+ tree.body = translateFrameStatement(tree.body);
result = tree;
}
@@ -769,7 +766,7 @@ public class DeClosure {
}
});
if (additionalStatements.nonEmpty())
- tree.body = make.Block(0, additionalStatements.appendList(assign).append(tree.body).toList());
+ tree.body = make.at(tree.pos).Block(0, additionalStatements.appendList(assign).append(tree.body).toList());
tree.var.sym.flags_field &= ~Flags.PARAMETER;
result = tree;
}
@@ -804,10 +801,12 @@ public class DeClosure {
@Override
public void visitReturn(JCReturn tree) {
+ super.visitReturn(tree);
// TODO(gafter)1: implement nonlocal return
- if (phase1.capturedTransfers.remove(tree))
- log.rawError(tree.pos, "'return' out of a closure not implemented");
- super.visitReturn(tree);
+ if (phase1.capturedTransfers.remove(tree)) {
+ MethodState state = methodStates.get(tree.target);
+ result = state.rewriteReturn(tree);
+ }
}
<T extends JCTree> T copy(T tree) {
@@ -880,7 +879,7 @@ public class DeClosure {
tree.fromInvocation() ? "control.invocation.restricted"
: "unrestricted.to.restricted.conversion");
if ((tree.flags & Flags.CAPTURED) == 0) tree.flags |= Flags.STATIC | Flags.NOOUTERTHIS;
- JCClassDecl body = make.ClassDef(
+ JCClassDecl body = make.at(tree.pos).ClassDef(
/*mods*/make.Modifiers(Flags.FINAL|Flags.SYNTHETIC|tree.flags),
/*name*/names.empty,
/*typarams*/emptyTypeParameters,
@@ -1123,14 +1122,7 @@ public class DeClosure {
Symbol oldOwner = currentOwner;
currentOwner = new MethodSymbol(tree.flags, names.empty, null, currentOwner);
try {
- final ListBuffer<JCStatement> additionalStatements =
- doFrame(new Runnable() {
- public void run() {
- Phase2.super.visitBlock(tree);
- }
- });
- if (additionalStatements.nonEmpty())
- tree.stats = additionalStatements.appendList(tree.stats).toList();
+ result = translateFrameStatement(tree);
} finally {
currentOwner = oldOwner;
}