Index: frog/leg/ssa/builder.dart |
=================================================================== |
--- frog/leg/ssa/builder.dart (revision 3986) |
+++ frog/leg/ssa/builder.dart (working copy) |
@@ -267,13 +267,15 @@ |
*/ |
bool isAccessedDirectly(Element element) { |
assert(element !== null); |
- return redirectionMapping[element] === null; |
+ return redirectionMapping[element] === null |
+ && !closureData.usedVariablesInTry.contains(element); |
} |
bool isStoredInClosureField(Element element) { |
assert(element !== null); |
if (isAccessedDirectly(element)) return false; |
Element redirectElement = redirectionMapping[element]; |
+ if (redirectElement == null) return false; |
if (redirectElement.enclosingElement.kind == ElementKind.CLASS) { |
assert(redirectElement is ClosureFieldElement); |
return true; |
@@ -284,10 +286,13 @@ |
bool isBoxed(Element element) { |
if (isAccessedDirectly(element)) return false; |
if (isStoredInClosureField(element)) return false; |
- // TODO(floitsch): add some asserts that we really have a boxed element. |
- return true; |
+ return redirectionMapping[element] !== null; |
} |
+ bool isUsedInTry(Element element) { |
+ return closureData.usedVariablesInTry.contains(element); |
+ } |
+ |
/** |
* Returns an [HInstruction] for the given element. If the element is |
* boxed or stored in a closure then the method generates code to retrieve |
@@ -310,8 +315,7 @@ |
HInstruction fieldGet = new HFieldGet(redirect, receiver); |
builder.add(fieldGet); |
return fieldGet; |
- } else { |
- assert(isBoxed(element)); |
+ } else if (isBoxed(element)) { |
Element redirect = redirectionMapping[element]; |
// In the function that declares the captured variable the box is |
// accessed as direct local. Inside the nested closure the box is |
@@ -323,6 +327,11 @@ |
HInstruction lookup = new HFieldGet(redirect, box); |
builder.add(lookup); |
return lookup; |
+ } else { |
+ assert(isUsedInTry(element)); |
+ HInstruction variable = new HFieldGet.fromActivation(element); |
+ builder.add(variable); |
+ return variable; |
} |
} |
@@ -347,8 +356,7 @@ |
HInstruction receiver = new HThis(); |
builder.add(receiver); |
builder.add(new HFieldSet(redirect, receiver, value)); |
- } else { |
- assert(isBoxed(element)); |
+ } else if (isBoxed(element)) { |
Element redirect = redirectionMapping[element]; |
// The box itself could be captured, or be local. A local variable that |
// is captured will be boxed, but the box itself will be a local. |
@@ -357,6 +365,9 @@ |
assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); |
HInstruction box = readLocal(redirect.enclosingElement); |
builder.add(new HFieldSet(redirect, box, value)); |
+ } else { |
+ assert(isUsedInTry(element)); |
+ builder.add(new HFieldSet.fromActivation(element,value)); |
} |
} |
@@ -1703,7 +1714,53 @@ |
} |
visitTryStatement(TryStatement node) { |
- compiler.unimplemented('SsaBuilder.visitTryStatement', node: node); |
+ HBasicBlock enterBlock = graph.addNewBlock(); |
+ close(new HGoto()).addSuccessor(enterBlock); |
+ open(enterBlock); |
+ close(new HTry()); |
+ |
+ HBasicBlock tryBody = graph.addNewBlock(); |
+ enterBlock.addSuccessor(tryBody); |
+ open(tryBody); |
+ visit(node.tryBlock); |
+ HBasicBlock endTryBlock; |
+ if (!isAborted()) endTryBlock = close(new HGoto()); |
floitsch
2012/02/07 17:40:00
We usually just update the variable:
tryBlock = cl
ngeoffray
2012/02/08 09:52:23
As discussed, renamed the variable to endTryBody.
|
+ |
+ List<HBasicBlock> catchBlocks = <HBasicBlock>[]; |
+ int catchBlocksCount = 0; |
+ for (CatchBlock catchBlock in node.catchBlocks.nodes) { |
+ if (++catchBlocksCount != 1) { |
+ compiler.unimplemented('SsaBuilder multiple catch blocks', node: node); |
+ } |
+ HBasicBlock block = graph.addNewBlock(); |
+ enterBlock.addSuccessor(block); |
+ open(block); |
+ visit(catchBlock); |
+ if (!isAborted()) { |
+ close(new HGoto()); |
+ catchBlocks.add(block); |
+ } |
+ } |
+ |
+ HBasicBlock exitBlock = graph.addNewBlock(); |
+ |
+ if (endTryBlock != null) { |
+ endTryBlock.addSuccessor(exitBlock); |
+ } |
+ |
+ for (HBasicBlock block in catchBlocks) { |
+ block.addSuccessor(exitBlock); |
+ } |
+ |
+ if (node.finallyBlock != null) { |
+ compiler.unimplemented('SsaBuilder finally block', node: node); |
+ } |
+ |
+ HBasicBlock joinBlock = graph.addNewBlock(); |
floitsch
2012/02/07 17:40:00
now that I think about it, I'm not sure we need th
ngeoffray
2012/02/08 09:52:23
Done.
|
+ open(exitBlock); |
+ close(new HGoto()).addSuccessor(joinBlock); |
+ |
+ open(joinBlock); |
} |
visitScriptTag(ScriptTag node) { |
@@ -1711,7 +1768,12 @@ |
} |
visitCatchBlock(CatchBlock node) { |
- compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node); |
+ NodeList formals = node.formals; |
+ VariableDefinitions exception = formals.nodes.head; |
+ if (exception.type != null) { |
+ compiler.unimplemented('SsaBuilder catch with type', node: node); |
+ } |
+ visit(node.block); |
} |
visitTypedef(Typedef node) { |