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

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

Issue 955543004: Pass SourceInformation through the CPS IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update comments Created 5 years, 10 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 | Annotate | Revision Log
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 part of dart2js.ir_builder; 5 part of dart2js.ir_builder;
6 6
7 /** 7 /**
8 * This task iterates through all resolved elements and builds [ir.Node]s. The 8 * This task iterates through all resolved elements and builds [ir.Node]s. The
9 * nodes are stored in the [nodes] map and accessible through [hasIr] and 9 * nodes are stored in the [nodes] map and accessible through [hasIr] and
10 * [getIr]. 10 * [getIr].
11 * 11 *
12 * The functionality of the IrNodes is added gradually, therefore elements might 12 * The functionality of the IrNodes is added gradually, therefore elements might
13 * have an IR or not, depending on the language features that are used. For 13 * have an IR or not, depending on the language features that are used. For
14 * elements that do have an IR, the tree [ast.Node]s and the [Token]s are not 14 * elements that do have an IR, the tree [ast.Node]s and the [Token]s are not
15 * used in the rest of the compilation. This is ensured by setting the element's 15 * used in the rest of the compilation. This is ensured by setting the element's
16 * cached tree to `null` and also breaking the token stream to crash future 16 * cached tree to `null` and also breaking the token stream to crash future
17 * attempts to parse. 17 * attempts to parse.
18 * 18 *
19 * The type inferrer works on either IR nodes or tree nodes. The IR nodes are 19 * The type inferrer works on either IR nodes or tree nodes. The IR nodes are
20 * then translated into the SSA form for optimizations and code generation. 20 * then translated into the SSA form for optimizations and code generation.
21 * Long-term, once the IR supports the full language, the backend can be 21 * Long-term, once the IR supports the full language, the backend can be
22 * re-implemented to work directly on the IR. 22 * re-implemented to work directly on the IR.
23 */ 23 */
24 class IrBuilderTask extends CompilerTask { 24 class IrBuilderTask extends CompilerTask {
25 final Map<Element, ir.ExecutableDefinition> nodes = 25 final Map<Element, ir.ExecutableDefinition> nodes =
26 <Element, ir.ExecutableDefinition>{}; 26 <Element, ir.ExecutableDefinition>{};
27 final bool generateSourceMap;
27 28
28 IrBuilderTask(Compiler compiler) : super(compiler); 29 IrBuilderTask(Compiler compiler, {this.generateSourceMap: true})
30 : super(compiler);
29 31
30 String get name => 'IR builder'; 32 String get name => 'IR builder';
31 33
32 bool hasIr(Element element) => nodes.containsKey(element.implementation); 34 bool hasIr(Element element) => nodes.containsKey(element.implementation);
33 35
34 ir.ExecutableDefinition getIr(ExecutableElement element) { 36 ir.ExecutableDefinition getIr(ExecutableElement element) {
35 return nodes[element.implementation]; 37 return nodes[element.implementation];
36 } 38 }
37 39
38 ir.ExecutableDefinition buildNode(AstElement element) { 40 ir.ExecutableDefinition buildNode(AstElement element) {
39 if (!canBuild(element)) return null; 41 if (!canBuild(element)) return null;
42
40 TreeElements elementsMapping = element.resolvedAst.elements; 43 TreeElements elementsMapping = element.resolvedAst.elements;
41 element = element.implementation; 44 element = element.implementation;
42 return compiler.withCurrentElement(element, () { 45 return compiler.withCurrentElement(element, () {
43 SourceFile sourceFile = elementSourceFile(element); 46 SourceInformationBuilder sourceInformationBuilder = generateSourceMap
47 ? new PositionSourceInformationBuilder(element)
48 : const SourceInformationBuilder();
49
44 IrBuilderVisitor builder = 50 IrBuilderVisitor builder =
45 compiler.backend is JavaScriptBackend 51 compiler.backend is JavaScriptBackend
46 ? new JsIrBuilderVisitor(elementsMapping, compiler, sourceFile) 52 ? new JsIrBuilderVisitor(
47 : new DartIrBuilderVisitor(elementsMapping, compiler, sourceFile); 53 elementsMapping, compiler, sourceInformationBuilder)
48 return builder.buildExecutable(element); 54 : new DartIrBuilderVisitor(
55 elementsMapping, compiler, sourceInformationBuilder);
56 ir.ExecutableDefinition definition =
57 builder.buildExecutable(element);
58 if (definition != null) {
59 nodes[element] = definition;
60 }
61 return definition;
49 }); 62 });
50 } 63 }
51 64
52 void buildNodes() { 65 void buildNodes() {
53 measure(() { 66 measure(() {
54 Set<Element> resolved = compiler.enqueuer.resolution.resolvedElements; 67 Set<Element> resolved = compiler.enqueuer.resolution.resolvedElements;
55 resolved.forEach((AstElement element) { 68 resolved.forEach(buildNode);
56 ir.ExecutableDefinition definition = buildNode(element);
57 if (definition != null) {
58 nodes[element] = definition;
59 }
60 });
61 }); 69 });
62 } 70 }
63 71
64 bool canBuild(Element element) { 72 bool canBuild(Element element) {
65 if (element is TypedefElement) return false; 73 if (element is TypedefElement) return false;
66 if (element is FunctionElement) { 74 if (element is FunctionElement) {
67 // TODO(sigurdm): Support native functions for dart2js. 75 // TODO(sigurdm): Support native functions for dart2js.
68 assert(invariant(element, !element.isNative)); 76 assert(invariant(element, !element.isNative));
69 77
70 if (element is ConstructorElement) { 78 if (element is ConstructorElement) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 } 116 }
109 117
110 /** 118 /**
111 * A tree visitor that builds [IrNodes]. The visit methods add statements using 119 * A tree visitor that builds [IrNodes]. The visit methods add statements using
112 * to the [builder] and return the last added statement for trees that represent 120 * to the [builder] and return the last added statement for trees that represent
113 * an expression. 121 * an expression.
114 */ 122 */
115 abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive> 123 abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
116 with IrBuilderMixin<ast.Node> { 124 with IrBuilderMixin<ast.Node> {
117 final Compiler compiler; 125 final Compiler compiler;
118 final SourceFile sourceFile; 126 final SourceInformationBuilder sourceInformationBuilder;
119 127
120 // In SSA terms, join-point continuation parameters are the phis and the 128 // In SSA terms, join-point continuation parameters are the phis and the
121 // continuation invocation arguments are the corresponding phi inputs. To 129 // continuation invocation arguments are the corresponding phi inputs. To
122 // support name introduction and renaming for source level variables, we use 130 // support name introduction and renaming for source level variables, we use
123 // nested (delimited) visitors for constructing subparts of the IR that will 131 // nested (delimited) visitors for constructing subparts of the IR that will
124 // need renaming. Each source variable is assigned an index. 132 // need renaming. Each source variable is assigned an index.
125 // 133 //
126 // Each nested visitor maintains a list of free variable uses in the body. 134 // Each nested visitor maintains a list of free variable uses in the body.
127 // These are implemented as a list of parameters, each with their own use 135 // These are implemented as a list of parameters, each with their own use
128 // list of references. When the delimited subexpression is plugged into the 136 // list of references. When the delimited subexpression is plugged into the
129 // surrounding context, the free occurrences can be captured or become free 137 // surrounding context, the free occurrences can be captured or become free
130 // occurrences in the next outer delimited subexpression. 138 // occurrences in the next outer delimited subexpression.
131 // 139 //
132 // Each nested visitor maintains a list that maps indexes of variables 140 // Each nested visitor maintains a list that maps indexes of variables
133 // assigned in the delimited subexpression to their reaching definition --- 141 // assigned in the delimited subexpression to their reaching definition ---
134 // that is, the definition in effect at the hole in 'current'. These are 142 // that is, the definition in effect at the hole in 'current'. These are
135 // used to determine if a join-point continuation needs to be passed 143 // used to determine if a join-point continuation needs to be passed
136 // arguments, and what the arguments are. 144 // arguments, and what the arguments are.
137 145
138 /// Construct a top-level visitor. 146 /// Construct a top-level visitor.
139 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile) 147 IrBuilderVisitor(TreeElements elements,
148 this.compiler,
149 this.sourceInformationBuilder)
140 : super(elements); 150 : super(elements);
141 151
142 /** 152 /**
143 * Builds the [ir.ExecutableDefinition] for an executable element. In case the 153 * Builds the [ir.ExecutableDefinition] for an executable element. In case the
144 * function uses features that cannot be expressed in the IR, this element 154 * function uses features that cannot be expressed in the IR, this element
145 * returns `null`. 155 * returns `null`.
146 */ 156 */
147 ir.ExecutableDefinition buildExecutable(ExecutableElement element); 157 ir.ExecutableDefinition buildExecutable(ExecutableElement element);
148 158
149 ClosureScope getClosureScopeForNode(ast.Node node); 159 ClosureScope getClosureScopeForNode(ast.Node node);
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 irBuilder.buildDynamicInvocation(receiver, selector, arguments); 656 irBuilder.buildDynamicInvocation(receiver, selector, arguments);
647 } 657 }
648 } else if (element.isField || element.isGetter || element.isErroneous || 658 } else if (element.isField || element.isGetter || element.isErroneous ||
649 element.isSetter) { 659 element.isSetter) {
650 // TODO(johnniwinther): Change handling of setter selectors. 660 // TODO(johnniwinther): Change handling of setter selectors.
651 // Access to a static field or getter (non-static case handled above). 661 // Access to a static field or getter (non-static case handled above).
652 // Even if there is only a setter, we compile as if it was a getter, 662 // Even if there is only a setter, we compile as if it was a getter,
653 // so the vm can fail at runtime. 663 // so the vm can fail at runtime.
654 assert(selector.kind == SelectorKind.GETTER || 664 assert(selector.kind == SelectorKind.GETTER ||
655 selector.kind == SelectorKind.SETTER); 665 selector.kind == SelectorKind.SETTER);
656 result = irBuilder.buildStaticGet(element, selector); 666 result = irBuilder.buildStaticGet(element, selector,
667 sourceInformation: sourceInformationBuilder.buildGet(node));
657 } else if (Elements.isStaticOrTopLevelFunction(element)) { 668 } else if (Elements.isStaticOrTopLevelFunction(element)) {
658 // Convert a top-level or static function to a function object. 669 // Convert a top-level or static function to a function object.
659 result = translateConstant(node); 670 result = translateConstant(node);
660 } else { 671 } else {
661 throw "Unexpected SendSet getter: $node, $element"; 672 throw "Unexpected SendSet getter: $node, $element";
662 } 673 }
663 return new _GetterElements( 674 return new _GetterElements(
664 result: result,index: index, receiver: receiver); 675 result: result,index: index, receiver: receiver);
665 } 676 }
666 677
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 return irBuilder.buildCallInvocation(receiver, call, arguments); 756 return irBuilder.buildCallInvocation(receiver, call, arguments);
746 } else if (selector.isGetter) { 757 } else if (selector.isGetter) {
747 // We are reading a static field or invoking a static getter. 758 // We are reading a static field or invoking a static getter.
748 return irBuilder.buildStaticGet(element, selector); 759 return irBuilder.buildStaticGet(element, selector);
749 } else { 760 } else {
750 // We are invoking a static method. 761 // We are invoking a static method.
751 assert(selector.isCall); 762 assert(selector.isCall);
752 assert(element is FunctionElement); 763 assert(element is FunctionElement);
753 List<ir.Primitive> arguments = node.arguments.mapToList(visit); 764 List<ir.Primitive> arguments = node.arguments.mapToList(visit);
754 arguments = normalizeStaticArguments(selector, element, arguments); 765 arguments = normalizeStaticArguments(selector, element, arguments);
755 return irBuilder.buildStaticInvocation(element, selector, arguments); 766 return irBuilder.buildStaticInvocation(element, selector, arguments,
767 sourceInformation: sourceInformationBuilder.buildCall(node));
756 } 768 }
757 } 769 }
758 770
759 ir.Primitive visitSuperSend(ast.Send node) { 771 ir.Primitive visitSuperSend(ast.Send node) {
760 assert(irBuilder.isOpen); 772 assert(irBuilder.isOpen);
761 Selector selector = elements.getSelector(node); 773 Selector selector = elements.getSelector(node);
762 Element target = elements[node]; 774 Element target = elements[node];
763 775
764 if (selector.isCall && (target.isGetter || target.isField)) { 776 if (selector.isCall && (target.isGetter || target.isField)) {
765 // We are invoking a field or getter as if it was a method, e.g: 777 // We are invoking a field or getter as if it was a method, e.g:
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
1071 currentFunction = oldFunction; 1083 currentFunction = oldFunction;
1072 } 1084 }
1073 } 1085 }
1074 1086
1075 /// IR builder specific to the Dart backend, coupled to the [DartIrBuilder]. 1087 /// IR builder specific to the Dart backend, coupled to the [DartIrBuilder].
1076 class DartIrBuilderVisitor extends IrBuilderVisitor { 1088 class DartIrBuilderVisitor extends IrBuilderVisitor {
1077 /// Promote the type of [irBuilder] to [DartIrBuilder]. 1089 /// Promote the type of [irBuilder] to [DartIrBuilder].
1078 DartIrBuilder get irBuilder => super.irBuilder; 1090 DartIrBuilder get irBuilder => super.irBuilder;
1079 1091
1080 DartIrBuilderVisitor(TreeElements elements, 1092 DartIrBuilderVisitor(TreeElements elements,
1081 Compiler compiler, 1093 Compiler compiler,
1082 SourceFile sourceFile) 1094 SourceInformationBuilder sourceInformationBuilder)
1083 : super(elements, compiler, sourceFile); 1095 : super(elements, compiler, sourceInformationBuilder);
1084 1096
1085 DartIrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) { 1097 DartIrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) {
1086 DartCapturedVariables closures = new DartCapturedVariables(elements); 1098 DartCapturedVariables closures = new DartCapturedVariables(elements);
1087 if (!element.isSynthesized) { 1099 if (!element.isSynthesized) {
1088 closures.visit(node); 1100 closures.visit(node);
1089 } 1101 }
1090 return new DartIrBuilder(compiler.backend.constantSystem, 1102 return new DartIrBuilder(compiler.backend.constantSystem,
1091 element, 1103 element,
1092 closures); 1104 closures);
1093 } 1105 }
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 /// Will be initialized upon entering the body of a function. 1210 /// Will be initialized upon entering the body of a function.
1199 /// It is computed by the [ClosureTranslator]. 1211 /// It is computed by the [ClosureTranslator].
1200 ClosureClassMap closureMap; 1212 ClosureClassMap closureMap;
1201 1213
1202 /// During construction of a constructor factory, [fieldValues] maps fields 1214 /// During construction of a constructor factory, [fieldValues] maps fields
1203 /// to the primitive containing their initial value. 1215 /// to the primitive containing their initial value.
1204 Map<FieldElement, ir.Primitive> fieldValues = <FieldElement, ir.Primitive>{}; 1216 Map<FieldElement, ir.Primitive> fieldValues = <FieldElement, ir.Primitive>{};
1205 1217
1206 JsIrBuilderVisitor(TreeElements elements, 1218 JsIrBuilderVisitor(TreeElements elements,
1207 Compiler compiler, 1219 Compiler compiler,
1208 SourceFile sourceFile) 1220 SourceInformationBuilder sourceInformationBuilder)
1209 : super(elements, compiler, sourceFile); 1221 : super(elements, compiler, sourceInformationBuilder);
1210 1222
1211 /// Builds the IR for creating an instance of the closure class corresponding 1223 /// Builds the IR for creating an instance of the closure class corresponding
1212 /// to the given nested function. 1224 /// to the given nested function.
1213 ClosureClassElement makeSubFunction(ast.FunctionExpression node) { 1225 ClosureClassElement makeSubFunction(ast.FunctionExpression node) {
1214 ClosureClassMap innerMap = 1226 ClosureClassMap innerMap =
1215 compiler.closureToClassMapper.getMappingForNestedFunction(node); 1227 compiler.closureToClassMapper.getMappingForNestedFunction(node);
1216 ClosureClassElement closureClass = innerMap.closureClassElement; 1228 ClosureClassElement closureClass = innerMap.closureClassElement;
1217 return closureClass; 1229 return closureClass;
1218 } 1230 }
1219 1231
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1310 } 1322 }
1311 1323
1312 /// Builds the IR for an [expression] taken from a different [context]. 1324 /// Builds the IR for an [expression] taken from a different [context].
1313 /// 1325 ///
1314 /// Such expressions need to be compiled with a different [sourceFile] and 1326 /// Such expressions need to be compiled with a different [sourceFile] and
1315 /// [elements] mapping. 1327 /// [elements] mapping.
1316 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { 1328 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
1317 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( 1329 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
1318 context.resolvedAst.elements, 1330 context.resolvedAst.elements,
1319 compiler, 1331 compiler,
1320 elementSourceFile(context)); 1332 sourceInformationBuilder.forContext(context));
1321 return visitor.withBuilder(irBuilder, () => visitor.visit(expression)); 1333 return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
1322 } 1334 }
1323 1335
1324 /// Builds the IR for a constant taken from a different [context]. 1336 /// Builds the IR for a constant taken from a different [context].
1325 /// 1337 ///
1326 /// Such constants need to be compiled with a different [sourceFile] and 1338 /// Such constants need to be compiled with a different [sourceFile] and
1327 /// [elements] mapping. 1339 /// [elements] mapping.
1328 ir.Primitive inlineConstant(AstElement context, ast.Expression exp) { 1340 ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
1329 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( 1341 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
1330 context.resolvedAst.elements, 1342 context.resolvedAst.elements,
1331 compiler, 1343 compiler,
1332 elementSourceFile(context)); 1344 sourceInformationBuilder.forContext(context));
1333 return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp)); 1345 return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
1334 } 1346 }
1335 1347
1336 /// Builds the IR for a given constructor. 1348 /// Builds the IR for a given constructor.
1337 /// 1349 ///
1338 /// 1. Evaluates all own or inherited field initializers. 1350 /// 1. Evaluates all own or inherited field initializers.
1339 /// 2. Creates the object and assigns its fields. 1351 /// 2. Creates the object and assigns its fields.
1340 /// 3. Calls constructor body and super constructor bodies. 1352 /// 3. Calls constructor body and super constructor bodies.
1341 /// 4. Returns the created object. 1353 /// 4. Returns the created object.
1342 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) { 1354 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) {
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1704 for (int i=0; i < selector.positionalArgumentCount; i++) { 1716 for (int i=0; i < selector.positionalArgumentCount; i++) {
1705 result.add(arguments[i]); 1717 result.add(arguments[i]);
1706 } 1718 }
1707 for (String argName in selector.getOrderedNamedArguments()) { 1719 for (String argName in selector.getOrderedNamedArguments()) {
1708 int nameIndex = selector.namedArguments.indexOf(argName); 1720 int nameIndex = selector.namedArguments.indexOf(argName);
1709 int translatedIndex = selector.positionalArgumentCount + nameIndex; 1721 int translatedIndex = selector.positionalArgumentCount + nameIndex;
1710 result.add(arguments[translatedIndex]); 1722 result.add(arguments[translatedIndex]);
1711 } 1723 }
1712 return result; 1724 return result;
1713 } 1725 }
1714
1715 } 1726 }
1716 1727
1728 /// Interface for generating [SourceInformation] for the CPS.
1729 class SourceInformationBuilder {
1730 const SourceInformationBuilder();
1731
1732 /// Create a [SourceInformationBuilder] for [element].
1733 SourceInformationBuilder forContext(AstElement element) => this;
1734
1735 /// Generate [SourceInformation] for the read access in [node].
1736 SourceInformation buildGet(ast.Node node) => null;
floitsch 2015/02/24 19:58:12 The "build" reads redundant at the use-sites, but
1737
1738 /// Generate [SourceInformation] for the invocation in [node].
1739 SourceInformation buildCall(ast.Node node) => null;
1740 }
1741
1742 /// [SourceInformationBuilder] that generates [PositionSourceInformation].
1743 class PositionSourceInformationBuilder implements SourceInformationBuilder {
1744 final SourceFile sourceFile;
1745 final String name;
1746
1747 PositionSourceInformationBuilder(AstElement element)
1748 : sourceFile = element.compilationUnit.script.file,
1749 name = element.name;
1750
1751 @override
1752 SourceInformation buildGet(ast.Node node) {
1753 return new PositionSourceInformation(
1754 new TokenSourceLocation(sourceFile, node.getBeginToken(), name));
1755 }
1756
1757 @override
1758 SourceInformation buildCall(ast.Node node) {
1759 return new PositionSourceInformation(
1760 new TokenSourceLocation(sourceFile, node.getBeginToken(), name));
1761 }
1762
1763 @override
1764 SourceInformationBuilder forContext(AstElement element) {
floitsch 2015/02/24 19:58:12 I'm not sure I like this. Is this just to avoid ha
Johnni Winther 2015/02/26 10:21:34 It is made to handle the choice of strategy at one
1765 return new PositionSourceInformationBuilder(element);
1766 }
1767 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698