Chromium Code Reviews| 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) { |