Chromium Code Reviews| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart |
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart |
| index 5c8313bdace0c090f944f4babfe2479ebc0ff5b5..a793078991269c5b02bf50b5ca4556141750a1ee 100644 |
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart |
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart |
| @@ -453,8 +453,7 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive> |
| return null; |
| } |
| - ir.Primitive visitTryStatement(ast.TryStatement node) { |
| - assert(this.irBuilder.isOpen); |
| + visitTryStatement(ast.TryStatement node) { |
| // Try/catch is not yet implemented in the JS backend. |
| if (this.irBuilder.tryStatements == null) { |
| return giveup(node, 'try/catch in the JS backend'); |
| @@ -473,130 +472,25 @@ abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive> |
| return giveup(node, 'try/finally'); |
| } |
| - // Catch handlers are in scope for their body. The CPS translation of |
| - // [[try tryBlock catch (e) catchBlock; successor]] is: |
| - // |
| - // let cont join(v0, v1, ...) = [[successor]] in |
| - // let mutable m0 = x0 in |
| - // let mutable m1 = x1 in |
| - // ... |
| - // let handler catch_(e) = |
| - // let prim p0 = GetMutable(m0) in |
| - // let prim p1 = GetMutable(m1) in |
| - // ... |
| - // [[catchBlock]] |
| - // join(p0, p1, ...) |
| - // in |
| - // [[tryBlock]] |
| - // let prim p0' = GetMutable(m0) in |
| - // let prim p1' = GetMutable(m1) in |
| - // ... |
| - // join(p0', p1', ...) |
| - // |
| - // In other words, both the try and catch block are in the scope of the |
| - // join-point continuation, and they are both in the scope of a sequence |
| - // of mutable bindings for the variables assigned in the try. The join- |
| - // point continuation is not in the scope of these mutable bindings. |
| - // The tryBlock is in the scope of a binding for the catch handler. Each |
| - // instruction (specifically, each call) in the tryBlock is in the dynamic |
| - // scope of the handler. The mutable bindings are dereferenced at the end |
| - // of the try block and at the beginning of the catch block, so the |
| - // variables are unboxed in the catch block and at the join point. |
| - |
| - IrBuilder tryCatchBuilder = irBuilder.makeDelimitedBuilder(); |
| - TryStatementInfo tryInfo = tryCatchBuilder.tryStatements[node]; |
| - // Variables that are boxed due to being captured in a closure are boxed |
| - // for their entire lifetime, and so they do not need to be boxed on |
| - // entry to any try block. We check for them here because we can not |
| - // identify all of them in the same pass where we identify the variables |
| - // assigned in the try (the may be captured by a closure after the try |
| - // statement). |
| - Iterable<LocalVariableElement> boxedOnEntry = |
| - tryInfo.boxedOnEntry.where((LocalVariableElement variable) { |
| - return !tryCatchBuilder.mutableCapturedVariables.contains(variable); |
| - }); |
| - for (LocalVariableElement variable in boxedOnEntry) { |
| - assert(!tryCatchBuilder.isInMutableVariable(variable)); |
| - ir.Primitive value = tryCatchBuilder.buildLocalGet(variable); |
| - tryCatchBuilder.makeMutableVariable(variable); |
| - tryCatchBuilder.declareLocalVariable(variable, initialValue: value); |
| - } |
| - |
| - IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| - IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| - List<ir.Parameter> joinParameters = |
| - new List<ir.Parameter>.generate(irBuilder.environment.length, (i) { |
| - return new ir.Parameter(irBuilder.environment.index2variable[i]); |
| - }); |
| - ir.Continuation joinContinuation = new ir.Continuation(joinParameters); |
| - |
| - void interceptJumps(JumpCollector collector) { |
| - collector.enterTry(boxedOnEntry); |
| - } |
| - void restoreJumps(JumpCollector collector) { |
| - collector.leaveTry(); |
| - } |
| - tryBuilder.state.breakCollectors.forEach(interceptJumps); |
| - tryBuilder.state.continueCollectors.forEach(interceptJumps); |
| - withBuilder(tryBuilder, () { |
| - visit(node.tryBlock); |
| - }); |
| - tryBuilder.state.breakCollectors.forEach(restoreJumps); |
| - tryBuilder.state.continueCollectors.forEach(restoreJumps); |
| - if (tryBuilder.isOpen) { |
| - for (LocalVariableElement variable in boxedOnEntry) { |
| - assert(tryBuilder.isInMutableVariable(variable)); |
| - ir.Primitive value = tryBuilder.buildLocalGet(variable); |
| - tryBuilder.environment.update(variable, value); |
| + List<CatchClauseInfo> catchClauseInfos = <CatchClauseInfo>[]; |
| + for (Link link = node.catchBlocks.nodes; !link.isEmpty; link = link.tail) { |
|
Kevin Millikin (Google)
2015/03/04 14:45:54
There is a .iterator on Link, so you should be abl
Johnni Winther
2015/03/05 09:10:27
Done.
|
| + ast.CatchBlock catchClause = link.head; |
| + assert(catchClause.exception != null); |
| + LocalVariableElement exceptionVariable = elements[catchClause.exception]; |
| + LocalVariableElement stackTraceVariable; |
| + if (catchClause.trace != null) { |
| + stackTraceVariable = elements[catchClause.trace]; |
| } |
| - tryBuilder.jumpTo(joinContinuation); |
| + catchClauseInfos.add(new CatchClauseInfo( |
| + exceptionVariable: exceptionVariable, |
| + stackTraceVariable: stackTraceVariable, |
| + buildCatchBlock: subbuild(catchClause.block))); |
| } |
| - for (LocalVariableElement variable in boxedOnEntry) { |
| - assert(catchBuilder.isInMutableVariable(variable)); |
| - ir.Primitive value = catchBuilder.buildLocalGet(variable); |
| - // Note that we remove the variable from the set of mutable variables |
| - // here (and not above for the try body). This is because the set of |
| - // mutable variables is global for the whole function and not local to |
| - // a delimited builder. |
| - catchBuilder.removeMutableVariable(variable); |
| - catchBuilder.environment.update(variable, value); |
| - } |
| - ast.CatchBlock catchClause = node.catchBlocks.nodes.head; |
| - assert(catchClause.exception != null); |
| - LocalVariableElement exceptionElement = elements[catchClause.exception]; |
| - ir.Parameter exceptionParameter = new ir.Parameter(exceptionElement); |
| - catchBuilder.environment.extend(exceptionElement, exceptionParameter); |
| - ir.Parameter traceParameter; |
| - if (catchClause.trace != null) { |
| - LocalVariableElement traceElement = elements[catchClause.trace]; |
| - traceParameter = new ir.Parameter(traceElement); |
| - catchBuilder.environment.extend(traceElement, traceParameter); |
| - } else { |
| - // Use a dummy continuation parameter for the stack trace parameter. |
| - // This will ensure that all handlers have two parameters and so they |
| - // can be treated uniformly. |
| - traceParameter = new ir.Parameter(null); |
| - } |
| - withBuilder(catchBuilder, () { |
| - visit(catchClause.block); |
| - }); |
| - if (catchBuilder.isOpen) { |
| - catchBuilder.jumpTo(joinContinuation); |
| - } |
| - List<ir.Parameter> catchParameters = |
| - <ir.Parameter>[exceptionParameter, traceParameter]; |
| - ir.Continuation catchContinuation = new ir.Continuation(catchParameters); |
| - catchContinuation.body = catchBuilder._root; |
| - |
| - tryCatchBuilder.add(new ir.LetHandler(catchContinuation, tryBuilder._root)); |
| - tryCatchBuilder._current = null; |
| - |
| - irBuilder.add(new ir.LetCont(joinContinuation, tryCatchBuilder._root)); |
| - for (int i = 0; i < irBuilder.environment.length; ++i) { |
| - irBuilder.environment.index2value[i] = joinParameters[i]; |
| - } |
| - return null; |
| + irBuilder.buildTry( |
| + tryStatementInfo: irBuilder.tryStatements[node], |
| + buildTryBlock: subbuild(node.tryBlock), |
| + catchClauseInfos: catchClauseInfos); |
| } |
| // ==== Expressions ==== |