Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart

Issue 1207703002: dart2js CPS: Support try/catch/finally. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Merge, and fix a test expectation. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | pkg/pkg.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.ir_builder_task; 5 library dart2js.ir_builder_task;
6 6
7 import '../closure.dart' as closurelib; 7 import '../closure.dart' as closurelib;
8 import '../closure.dart' hide ClosureScope; 8 import '../closure.dart' hide ClosureScope;
9 import '../constants/expressions.dart'; 9 import '../constants/expressions.dart';
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 final TreeElements elements; 104 final TreeElements elements;
105 final Compiler compiler; 105 final Compiler compiler;
106 final SourceInformationBuilder sourceInformationBuilder; 106 final SourceInformationBuilder sourceInformationBuilder;
107 107
108 /// A map from try statements in the source to analysis information about 108 /// A map from try statements in the source to analysis information about
109 /// them. 109 /// them.
110 /// 110 ///
111 /// The analysis information includes the set of variables that must be 111 /// The analysis information includes the set of variables that must be
112 /// copied into [ir.MutableVariable]s on entry to the try and copied out on 112 /// copied into [ir.MutableVariable]s on entry to the try and copied out on
113 /// exit. 113 /// exit.
114 Map<ast.TryStatement, TryStatementInfo> tryStatements = null; 114 Map<ast.Node, TryStatementInfo> tryStatements = null;
115 115
116 // In SSA terms, join-point continuation parameters are the phis and the 116 // In SSA terms, join-point continuation parameters are the phis and the
117 // continuation invocation arguments are the corresponding phi inputs. To 117 // continuation invocation arguments are the corresponding phi inputs. To
118 // support name introduction and renaming for source level variables, we use 118 // support name introduction and renaming for source level variables, we use
119 // nested (delimited) visitors for constructing subparts of the IR that will 119 // nested (delimited) visitors for constructing subparts of the IR that will
120 // need renaming. Each source variable is assigned an index. 120 // need renaming. Each source variable is assigned an index.
121 // 121 //
122 // Each nested visitor maintains a list of free variable uses in the body. 122 // Each nested visitor maintains a list of free variable uses in the body.
123 // These are implemented as a list of parameters, each with their own use 123 // These are implemented as a list of parameters, each with their own use
124 // list of references. When the delimited subexpression is plugged into the 124 // list of references. When the delimited subexpression is plugged into the
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 } 424 }
425 ir.Primitive value = visit(node.expression); 425 ir.Primitive value = visit(node.expression);
426 JumpTarget target = elements.getTargetDefinition(node); 426 JumpTarget target = elements.getTargetDefinition(node);
427 Element error = 427 Element error =
428 (compiler.backend as JavaScriptBackend).getFallThroughError(); 428 (compiler.backend as JavaScriptBackend).getFallThroughError();
429 irBuilder.buildSimpleSwitch(target, value, cases, defaultCase, error, 429 irBuilder.buildSimpleSwitch(target, value, cases, defaultCase, error,
430 sourceInformationBuilder.buildGeneric(node)); 430 sourceInformationBuilder.buildGeneric(node));
431 } 431 }
432 432
433 visitTryStatement(ast.TryStatement node) { 433 visitTryStatement(ast.TryStatement node) {
434 // Try/catch/finally is not yet implemented.
435 if (!node.catchBlocks.isEmpty && node.finallyBlock != null) {
436 return giveup(node, 'try/catch/finally');
437 }
438
439 List<CatchClauseInfo> catchClauseInfos = <CatchClauseInfo>[]; 434 List<CatchClauseInfo> catchClauseInfos = <CatchClauseInfo>[];
440 for (ast.CatchBlock catchClause in node.catchBlocks.nodes) { 435 for (ast.CatchBlock catchClause in node.catchBlocks.nodes) {
441 assert(catchClause.exception != null); 436 assert(catchClause.exception != null);
442 LocalVariableElement exceptionVariable = elements[catchClause.exception]; 437 LocalVariableElement exceptionVariable = elements[catchClause.exception];
443 LocalVariableElement stackTraceVariable; 438 LocalVariableElement stackTraceVariable;
444 if (catchClause.trace != null) { 439 if (catchClause.trace != null) {
445 stackTraceVariable = elements[catchClause.trace]; 440 stackTraceVariable = elements[catchClause.trace];
446 } 441 }
447 DartType type; 442 DartType type;
448 if (catchClause.onKeyword != null) { 443 if (catchClause.onKeyword != null) {
449 type = elements.getType(catchClause.type); 444 type = elements.getType(catchClause.type);
450 } 445 }
451 catchClauseInfos.add(new CatchClauseInfo( 446 catchClauseInfos.add(new CatchClauseInfo(
452 type: type, 447 type: type,
453 exceptionVariable: exceptionVariable, 448 exceptionVariable: exceptionVariable,
454 stackTraceVariable: stackTraceVariable, 449 stackTraceVariable: stackTraceVariable,
455 buildCatchBlock: subbuild(catchClause.block))); 450 buildCatchBlock: subbuild(catchClause.block)));
456 } 451 }
457 452
458 SubbuildFunction buildFinallyBlock = 453 assert(!node.catchBlocks.isEmpty || node.finallyBlock != null);
459 node.finallyBlock == null ? null : subbuild(node.finallyBlock); 454 if (!node.catchBlocks.isEmpty && node.finallyBlock != null) {
460 irBuilder.buildTry( 455 // Try/catch/finally is encoded in terms of try/catch and try/finally:
461 tryStatementInfo: tryStatements[node], 456 //
462 buildTryBlock: subbuild(node.tryBlock), 457 // try tryBlock catch (ex, st) catchBlock finally finallyBlock
463 catchClauseInfos: catchClauseInfos, 458 // ==>
464 buildFinallyBlock: buildFinallyBlock, 459 // try { try tryBlock catch (ex, st) catchBlock } finally finallyBlock
465 closureClassMap: closureClassMap); 460 irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
461 (IrBuilder inner) {
462 inner.buildTryCatch(tryStatements[node.catchBlocks],
463 subbuild(node.tryBlock),
464 catchClauseInfos);
465 },
466 subbuild(node.finallyBlock));
467 } else if (!node.catchBlocks.isEmpty) {
468 irBuilder.buildTryCatch(tryStatements[node.catchBlocks],
469 subbuild(node.tryBlock),
470 catchClauseInfos);
471 } else {
472 irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
473 subbuild(node.tryBlock),
474 subbuild(node.finallyBlock));
475 }
466 } 476 }
467 477
468 // ## Expressions ## 478 // ## Expressions ##
469 ir.Primitive visitConditional(ast.Conditional node) { 479 ir.Primitive visitConditional(ast.Conditional node) {
470 return irBuilder.buildConditional( 480 return irBuilder.buildConditional(
471 build(node.condition), 481 build(node.condition),
472 subbuild(node.thenExpression), 482 subbuild(node.thenExpression),
473 subbuild(node.elseExpression)); 483 subbuild(node.elseExpression));
474 } 484 }
475 485
(...skipping 1478 matching lines...) Expand 10 before | Expand all | Expand 10 after
1954 /// loop variables captured in a for-loop initializer, condition, or update 1964 /// loop variables captured in a for-loop initializer, condition, or update
1955 /// expression are unsupported. 1965 /// expression are unsupported.
1956 class DartCapturedVariables extends ast.Visitor { 1966 class DartCapturedVariables extends ast.Visitor {
1957 final TreeElements elements; 1967 final TreeElements elements;
1958 DartCapturedVariables(this.elements); 1968 DartCapturedVariables(this.elements);
1959 1969
1960 FunctionElement currentFunction; 1970 FunctionElement currentFunction;
1961 bool insideInitializer = false; 1971 bool insideInitializer = false;
1962 Set<Local> capturedVariables = new Set<Local>(); 1972 Set<Local> capturedVariables = new Set<Local>();
1963 1973
1964 Map<ast.TryStatement, TryStatementInfo> tryStatements = 1974 /// A map containing variables boxed inside try blocks.
1965 <ast.TryStatement, TryStatementInfo>{}; 1975 ///
1976 /// The map is keyed by the [NodeList] of catch clauses for try/catch and
1977 /// by the finally block for try/finally. try/catch/finally is treated
1978 /// as a try/catch nested in the try block of a try/finally.
1979 Map<ast.Node, TryStatementInfo> tryStatements =
1980 <ast.Node, TryStatementInfo>{};
1966 1981
1967 List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[]; 1982 List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[];
1968 bool get inTryStatement => tryNestingStack.isNotEmpty; 1983 bool get inTryStatement => tryNestingStack.isNotEmpty;
1969 1984
1970 String bailoutMessage = null; 1985 String bailoutMessage = null;
1971 1986
1972 giveup(ast.Node node, [String reason]) { 1987 giveup(ast.Node node, [String reason]) {
1973 bailoutMessage = '($node): $reason'; 1988 bailoutMessage = '($node): $reason';
1974 throw ABORT_IRNODE_BUILDER; 1989 throw ABORT_IRNODE_BUILDER;
1975 } 1990 }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2072 if (node.initializers != null) { 2087 if (node.initializers != null) {
2073 insideInitializer = true; 2088 insideInitializer = true;
2074 visit(node.initializers); 2089 visit(node.initializers);
2075 insideInitializer = false; 2090 insideInitializer = false;
2076 } 2091 }
2077 visit(node.body); 2092 visit(node.body);
2078 currentFunction = oldFunction; 2093 currentFunction = oldFunction;
2079 } 2094 }
2080 2095
2081 visitTryStatement(ast.TryStatement node) { 2096 visitTryStatement(ast.TryStatement node) {
2082 TryStatementInfo info = new TryStatementInfo(); 2097 // Try/catch/finally is treated as two simpler constructs: try/catch and
2083 tryStatements[node] = info; 2098 // try/finally. The encoding is:
2084 tryNestingStack.add(info); 2099 //
2100 // try S0 catch (ex, st) S1 finally S2
2101 // ==>
2102 // try { try S0 catch (ex, st) S1 } finally S2
2103 //
2104 // The analysis associates variables assigned in S0 with the catch clauses
2105 // and variables assigned in S0 and S1 with the finally block.
2106 TryStatementInfo enterTryFor(ast.Node node) {
2107 TryStatementInfo info = new TryStatementInfo();
2108 tryStatements[node] = info;
2109 tryNestingStack.add(info);
2110 return info;
2111 }
2112 void leaveTryFor(TryStatementInfo info) {
2113 assert(tryNestingStack.last == info);
2114 tryNestingStack.removeLast();
2115 }
2116 bool hasCatch = !node.catchBlocks.isEmpty;
2117 bool hasFinally = node.finallyBlock != null;
2118 TryStatementInfo catchInfo, finallyInfo;
2119 // There is a nesting stack of try blocks, so the outer try/finally block
2120 // is added first.
2121 if (hasFinally) finallyInfo = enterTryFor(node.finallyBlock);
2122 if (hasCatch) catchInfo = enterTryFor(node.catchBlocks);
2085 visit(node.tryBlock); 2123 visit(node.tryBlock);
2086 assert(tryNestingStack.last == info);
2087 tryNestingStack.removeLast();
2088 2124
2089 visit(node.catchBlocks); 2125 if (hasCatch) {
2090 if (node.finallyBlock != null) visit(node.finallyBlock); 2126 leaveTryFor(catchInfo);
2127 visit(node.catchBlocks);
2128 }
2129 if (hasFinally) {
2130 leaveTryFor(finallyInfo);
2131 visit(node.finallyBlock);
2132 }
2091 } 2133 }
2092 2134
2093 visitVariableDefinitions(ast.VariableDefinitions node) { 2135 visitVariableDefinitions(ast.VariableDefinitions node) {
2094 if (inTryStatement) { 2136 if (inTryStatement) {
2095 for (ast.Node definition in node.definitions.nodes) { 2137 for (ast.Node definition in node.definitions.nodes) {
2096 LocalVariableElement local = elements[definition]; 2138 LocalVariableElement local = elements[definition];
2097 assert(local != null); 2139 assert(local != null);
2098 // In the closure conversion pass we check for isInitializingFormal, 2140 // In the closure conversion pass we check for isInitializingFormal,
2099 // but I'm not sure it can arise. 2141 // but I'm not sure it can arise.
2100 assert(!local.isInitializingFormal); 2142 assert(!local.isInitializingFormal);
(...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after
3186 } 3228 }
3187 3229
3188 processSetStatic(ir.SetStatic node) { 3230 processSetStatic(ir.SetStatic node) {
3189 node.body = replacementFor(node.body); 3231 node.body = replacementFor(node.body);
3190 } 3232 }
3191 3233
3192 processContinuation(ir.Continuation node) { 3234 processContinuation(ir.Continuation node) {
3193 node.body = replacementFor(node.body); 3235 node.body = replacementFor(node.body);
3194 } 3236 }
3195 } 3237 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | pkg/pkg.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698