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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart

Issue 366853007: dart2dart: Support for inner functions in new IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: SVN rebase Created 6 years, 5 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 library dart2js.ir_builder; 5 library dart2js.ir_builder;
6 6
7 import 'ir_nodes.dart' as ir; 7 import 'ir_nodes.dart' as ir;
8 import '../elements/elements.dart'; 8 import '../elements/elements.dart';
9 import '../dart2jslib.dart'; 9 import '../dart2jslib.dart';
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 // arguments, and what the arguments are. 199 // arguments, and what the arguments are.
200 final Map<Element, int> variableIndex; 200 final Map<Element, int> variableIndex;
201 final List<Element> index2variable; 201 final List<Element> index2variable;
202 final List<ir.Parameter> freeVars; 202 final List<ir.Parameter> freeVars;
203 final List<ir.Primitive> assignedVars; 203 final List<ir.Primitive> assignedVars;
204 204
205 ConstExpBuilder constantBuilder; 205 ConstExpBuilder constantBuilder;
206 206
207 final List<ConstDeclaration> localConstants; 207 final List<ConstDeclaration> localConstants;
208 208
209 FunctionElement currentFunction;
210 final DetectClosureVariables closureLocals;
211
209 /// Construct a top-level visitor. 212 /// Construct a top-level visitor.
210 IrBuilder(TreeElements elements, Compiler compiler, this.sourceFile) 213 IrBuilder(TreeElements elements, Compiler compiler, this.sourceFile)
211 : returnContinuation = new ir.Continuation.retrn(), 214 : returnContinuation = new ir.Continuation.retrn(),
212 parameters = <ir.Parameter>[], 215 parameters = <ir.Parameter>[],
213 variableIndex = <Element, int>{}, 216 variableIndex = <Element, int>{},
214 freeVars = null, 217 freeVars = null,
215 assignedVars = <ir.Primitive>[], 218 assignedVars = <ir.Primitive>[],
216 index2variable = <Element>[], 219 index2variable = <Element>[],
217 localConstants = <ConstDeclaration>[], 220 localConstants = <ConstDeclaration>[],
221 closureLocals = new DetectClosureVariables(elements),
218 super(elements, compiler) { 222 super(elements, compiler) {
219 constantBuilder = new ConstExpBuilder(this); 223 constantBuilder = new ConstExpBuilder(this);
220 } 224 }
221 225
222 /// Construct a delimited visitor. 226 /// Construct a delimited visitor.
223 IrBuilder.delimited(IrBuilder parent) 227 IrBuilder.delimited(IrBuilder parent)
224 : sourceFile = parent.sourceFile, 228 : sourceFile = parent.sourceFile,
225 returnContinuation = parent.returnContinuation, 229 returnContinuation = parent.returnContinuation,
226 parameters = parent.parameters, 230 parameters = parent.parameters,
227 variableIndex = parent.variableIndex, 231 variableIndex = parent.variableIndex,
228 freeVars = new List<ir.Parameter>.generate( 232 freeVars = new List<ir.Parameter>.generate(
229 parent.assignedVars.length, (_) => new ir.Parameter(null), 233 parent.assignedVars.length, (_) => new ir.Parameter(null),
230 growable: false), 234 growable: false),
231 assignedVars = new List<ir.Primitive>.generate( 235 assignedVars = new List<ir.Primitive>.generate(
232 parent.assignedVars.length, (_) => null), 236 parent.assignedVars.length, (_) => null),
233 index2variable = new List<Element>.from(parent.index2variable), 237 index2variable = new List<Element>.from(parent.index2variable),
234 constantBuilder = parent.constantBuilder, 238 constantBuilder = parent.constantBuilder,
235 localConstants = parent.localConstants, 239 localConstants = parent.localConstants,
240 currentFunction = parent.currentFunction,
241 closureLocals = parent.closureLocals,
236 super(parent.elements, parent.compiler); 242 super(parent.elements, parent.compiler);
237 243
238 /** 244 /**
239 * Builds the [ir.FunctionDefinition] for a function element. In case the 245 * Builds the [ir.FunctionDefinition] for a function element. In case the
240 * function uses features that cannot be expressed in the IR, this function 246 * function uses features that cannot be expressed in the IR, this function
241 * returns `null`. 247 * returns `null`.
242 */ 248 */
243 ir.FunctionDefinition buildFunction(FunctionElement functionElement) { 249 ir.FunctionDefinition buildFunction(FunctionElement functionElement) {
244 return nullIfGiveup(() => buildFunctionInternal(functionElement)); 250 return nullIfGiveup(() => buildFunctionInternal(functionElement));
245 } 251 }
246 252
247 ir.FunctionDefinition buildFunctionInternal(FunctionElement element) { 253 ir.FunctionDefinition buildFunctionInternal(FunctionElement element) {
248 assert(invariant(element, element.isImplementation)); 254 assert(invariant(element, element.isImplementation));
255 currentFunction = element;
249 ast.FunctionExpression function = element.node; 256 ast.FunctionExpression function = element.node;
250 assert(function != null); 257 assert(function != null);
251 assert(!function.modifiers.isExternal); 258 assert(!function.modifiers.isExternal);
252 assert(elements[function] != null); 259 assert(elements[function] != null);
253 260
261 closureLocals.visit(function);
262
254 root = current = null; 263 root = current = null;
255 264
256 FunctionSignature signature = element.functionSignature; 265 FunctionSignature signature = element.functionSignature;
257 signature.orderedForEachParameter((parameterElement) { 266 signature.orderedForEachParameter((ParameterElement parameterElement) {
267 // TODO(asgerf): Handle parameters with default values. (Use a ConstExp)
268 if (parameterElement.initializer != null) {
269 giveup(parameterElement.node, 'Function parameter with default value');
270 }
258 ir.Parameter parameter = new ir.Parameter(parameterElement); 271 ir.Parameter parameter = new ir.Parameter(parameterElement);
259 parameters.add(parameter); 272 parameters.add(parameter);
260 variableIndex[parameterElement] = assignedVars.length; 273 if (isClosureVariable(parameterElement)) {
261 assignedVars.add(parameter); 274 add(new ir.SetClosureVariable(parameterElement, parameter));
262 index2variable.add(parameterElement); 275 } else {
276 variableIndex[parameterElement] = assignedVars.length;
277 assignedVars.add(parameter);
278 index2variable.add(parameterElement);
279 }
263 }); 280 });
264 281
265 visit(function.body); 282 visit(function.body);
266 ensureReturn(function); 283 ensureReturn(function);
267 return new ir.FunctionDefinition(returnContinuation, parameters, root, 284 return new ir.FunctionDefinition(element, returnContinuation, parameters,
268 localConstants); 285 root, localConstants);
269 } 286 }
270 287
271 ConstantSystem get constantSystem => compiler.backend.constantSystem; 288 ConstantSystem get constantSystem => compiler.backend.constantSystem;
272 289
273 bool get isOpen => root == null || current != null; 290 bool get isOpen => root == null || current != null;
274 291
275 // Plug an expression into the 'hole' in the context being accumulated. The 292 // Plug an expression into the 'hole' in the context being accumulated. The
276 // empty context (just a hole) is represented by root (and current) being 293 // empty context (just a hole) is represented by root (and current) being
277 // null. Since the hole in the current context is filled by this function, 294 // null. Since the hole in the current context is filled by this function,
278 // the new hole must be in the newly added expression---which becomes the 295 // the new hole must be in the newly added expression---which becomes the
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 reachingDefinition.substituteFor(bodyBuilder.freeVars[i]); 525 reachingDefinition.substituteFor(bodyBuilder.freeVars[i]);
509 } else { 526 } else {
510 condBuilder.assignedVars[i].substituteFor(bodyBuilder.freeVars[i]); 527 condBuilder.assignedVars[i].substituteFor(bodyBuilder.freeVars[i]);
511 } 528 }
512 reachingDefinition.substituteFor(condBuilder.freeVars[i]); 529 reachingDefinition.substituteFor(condBuilder.freeVars[i]);
513 } 530 }
514 } 531 }
515 532
516 ir.Primitive visitFor(ast.For node) { 533 ir.Primitive visitFor(ast.For node) {
517 assert(isOpen); 534 assert(isOpen);
535 // TODO(asgerf): Handle closure variables declared in a for-loop.
536 if (node.initializer is ast.VariableDefinitions) {
537 ast.VariableDefinitions definitions = node.initializer;
538 for (ast.Node definition in definitions.definitions.nodes) {
539 Element element = elements[definition];
540 if (isClosureVariable(element)) {
541 return giveup(definition, 'Closure variable in for loop initializer');
542 }
543 }
544 }
545
518 // For loops use three named continuations: the entry to the condition, 546 // For loops use three named continuations: the entry to the condition,
519 // the entry to the body, and the loop exit (break). The CPS translation 547 // the entry to the body, and the loop exit (break). The CPS translation
520 // of [[for (initializer; condition; update) body; successor]] is: 548 // of [[for (initializer; condition; update) body; successor]] is:
521 // 549 //
522 // [[initializer]]; 550 // [[initializer]];
523 // let cont loop(x, ...) = 551 // let cont loop(x, ...) =
524 // let cont exit() = [[successor]] in 552 // let cont exit() = [[successor]] in
525 // let cont body() = [[body]]; [[update]]; loop(v, ...) in 553 // let cont body() = [[body]]; [[update]]; loop(v, ...) in
526 // let prim cond = [[condition]] in 554 // let prim cond = [[condition]] in
527 // branch cond (body, exit) in 555 // branch cond (body, exit) in
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 for (ast.SendSet definition in node.definitions.nodes) { 752 for (ast.SendSet definition in node.definitions.nodes) {
725 assert(!definition.arguments.isEmpty); 753 assert(!definition.arguments.isEmpty);
726 assert(definition.arguments.tail.isEmpty); 754 assert(definition.arguments.tail.isEmpty);
727 VariableElement element = elements[definition]; 755 VariableElement element = elements[definition];
728 ConstExp value = constantBuilder.visit(definition.arguments.head); 756 ConstExp value = constantBuilder.visit(definition.arguments.head);
729 localConstants.add(new ConstDeclaration(element, value)); 757 localConstants.add(new ConstDeclaration(element, value));
730 } 758 }
731 } else { 759 } else {
732 for (ast.Node definition in node.definitions.nodes) { 760 for (ast.Node definition in node.definitions.nodes) {
733 Element element = elements[definition]; 761 Element element = elements[definition];
762 ir.Primitive initialValue;
734 // Definitions are either SendSets if there is an initializer, or 763 // Definitions are either SendSets if there is an initializer, or
735 // Identifiers if there is no initializer. 764 // Identifiers if there is no initializer.
736 if (definition is ast.SendSet) { 765 if (definition is ast.SendSet) {
737 assert(!definition.arguments.isEmpty); 766 assert(!definition.arguments.isEmpty);
738 assert(definition.arguments.tail.isEmpty); 767 assert(definition.arguments.tail.isEmpty);
739 ir.Primitive initialValue = visit(definition.arguments.head); 768 initialValue = visit(definition.arguments.head);
769 } else {
770 assert(definition is ast.Identifier);
771 // The initial value is null.
772 // TODO(kmillikin): Consider pooling constants.
773 initialValue = makePrimConst(constantSystem.createNull());
774 add(new ir.LetPrim(initialValue));
775 }
776 if (isClosureVariable(element)) {
777 add(new ir.SetClosureVariable(element, initialValue,
778 isDeclaration: true));
779 } else {
740 // In case a primitive was introduced for the initializer expression, 780 // In case a primitive was introduced for the initializer expression,
741 // use this variable element to help derive a good name for it. 781 // use this variable element to help derive a good name for it.
742 initialValue.useElementAsHint(element); 782 initialValue.useElementAsHint(element);
743 variableIndex[element] = assignedVars.length; 783 variableIndex[element] = assignedVars.length;
744 assignedVars.add(initialValue); 784 assignedVars.add(initialValue);
745 index2variable.add(element); 785 index2variable.add(element);
746 } else {
747 assert(definition is ast.Identifier);
748 // The initial value is null.
749 // TODO(kmillikin): Consider pooling constants.
750 ir.Constant constant = makePrimConst(constantSystem.createNull());
751 constant.useElementAsHint(element);
752 add(new ir.LetPrim(constant));
753 variableIndex[element] = assignedVars.length;
754 assignedVars.add(constant);
755 index2variable.add(element);
756 } 786 }
757 } 787 }
758 } 788 }
759 return null; 789 return null;
760 } 790 }
761 791
762 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 792 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
763 // where (C', x) = Build(e, C) 793 // where (C', x) = Build(e, C)
764 // 794 //
765 // Return without a subexpression is translated as if it were return null. 795 // Return without a subexpression is translated as if it were return null.
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 ir.Primitive visitAssert(ast.Send node) { 982 ir.Primitive visitAssert(ast.Send node) {
953 assert(isOpen); 983 assert(isOpen);
954 return giveup(node, 'Assert'); 984 return giveup(node, 'Assert');
955 } 985 }
956 986
957 ir.Primitive visitNamedArgument(ast.NamedArgument node) { 987 ir.Primitive visitNamedArgument(ast.NamedArgument node) {
958 assert(isOpen); 988 assert(isOpen);
959 return visit(node.expression); 989 return visit(node.expression);
960 } 990 }
961 991
992 ir.Primitive continueWithExpression(ir.Expression build(ir.Continuation k)) {
993 ir.Parameter v = new ir.Parameter(null);
994 ir.Continuation k = new ir.Continuation([v]);
995 ir.Expression expression = build(k);
996 add(new ir.LetCont(k, expression));
997 return v;
998 }
999
962 ir.Primitive translateClosureCall(ir.Primitive receiver, 1000 ir.Primitive translateClosureCall(ir.Primitive receiver,
963 Selector closureSelector, 1001 Selector closureSelector,
964 ast.NodeList arguments) { 1002 ast.NodeList arguments) {
965 Selector namedCallSelector = new Selector(closureSelector.kind, 1003 Selector namedCallSelector = new Selector(closureSelector.kind,
966 "call", 1004 "call",
967 closureSelector.library, 1005 closureSelector.library,
968 closureSelector.argumentCount, 1006 closureSelector.argumentCount,
969 closureSelector.namedArguments); 1007 closureSelector.namedArguments);
970 List<ir.Primitive> args = arguments.nodes.mapToList(visit, growable:false); 1008 List<ir.Primitive> args = arguments.nodes.mapToList(visit, growable:false);
971 ir.Parameter v = new ir.Parameter(null); 1009 return continueWithExpression(
972 ir.Continuation k = new ir.Continuation([v]); 1010 (k) => new ir.InvokeMethod(receiver, namedCallSelector, k, args));
973 ir.Expression invoke =
974 new ir.InvokeMethod(receiver, namedCallSelector, k, args);
975 add(new ir.LetCont(k, invoke));
976 return v;
977 } 1011 }
978 1012
979 ir.Primitive visitClosureSend(ast.Send node) { 1013 ir.Primitive visitClosureSend(ast.Send node) {
980 assert(isOpen); 1014 assert(isOpen);
981 Element element = elements[node]; 1015 Element element = elements[node];
982 ir.Primitive closureTarget; 1016 ir.Primitive closureTarget;
983 if (element == null) { 1017 if (element == null) {
984 closureTarget = visit(node.selector); 1018 closureTarget = visit(node.selector);
1019 } else if (isClosureVariable(element)) {
1020 closureTarget = new ir.GetClosureVariable(element);
1021 add(new ir.LetPrim(closureTarget));
985 } else { 1022 } else {
986 assert(Elements.isLocal(element)); 1023 assert(Elements.isLocal(element));
987 closureTarget = lookupLocal(element); 1024 closureTarget = lookupLocal(element);
988 } 1025 }
989 Selector closureSelector = elements.getSelector(node); 1026 Selector closureSelector = elements.getSelector(node);
990 return translateClosureCall(closureTarget, closureSelector, 1027 return translateClosureCall(closureTarget, closureSelector,
991 node.argumentsNode); 1028 node.argumentsNode);
992 } 1029 }
993 1030
994 /// If [node] is null, returns this. 1031 /// If [node] is null, returns this.
(...skipping 18 matching lines...) Expand all
1013 } 1050 }
1014 1051
1015 ir.Primitive visitDynamicSend(ast.Send node) { 1052 ir.Primitive visitDynamicSend(ast.Send node) {
1016 assert(isOpen); 1053 assert(isOpen);
1017 Selector selector = elements.getSelector(node); 1054 Selector selector = elements.getSelector(node);
1018 ir.Primitive receiver = visitReceiver(node.receiver); 1055 ir.Primitive receiver = visitReceiver(node.receiver);
1019 List<ir.Primitive> arguments = new List<ir.Primitive>(); 1056 List<ir.Primitive> arguments = new List<ir.Primitive>();
1020 for (ast.Node n in node.arguments) { 1057 for (ast.Node n in node.arguments) {
1021 arguments.add(visit(n)); 1058 arguments.add(visit(n));
1022 } 1059 }
1023 ir.Parameter v = new ir.Parameter(null); 1060 return continueWithExpression(
1024 ir.Continuation k = new ir.Continuation([v]); 1061 (k) => createDynamicInvoke(node, selector, receiver, k, arguments));
1025 ir.Expression invoke =
1026 createDynamicInvoke(node, selector, receiver, k, arguments);
1027 add(new ir.LetCont(k, invoke));
1028 return v;
1029 } 1062 }
1030 1063
1031 _GetterElements translateGetter(ast.Send node, Selector selector) { 1064 _GetterElements translateGetter(ast.Send node, Selector selector) {
1032 Element element = elements[node]; 1065 Element element = elements[node];
1033 ir.Primitive result; 1066 ir.Primitive result;
1034 ir.Primitive receiver; 1067 ir.Primitive receiver;
1035 ir.Primitive index; 1068 ir.Primitive index;
1036 1069
1037 if (Elements.isErroneousElement(element)) { 1070 if (Elements.isErroneousElement(element)) {
1038 giveup(node, 'Erroneous element on GetterSend'); 1071 return giveup(node, 'Erroneous element on GetterSend');
1039 return null;
1040 } 1072 }
1041 1073
1042 if (element != null && element.isConst) { 1074 if (element != null && element.isConst) {
1043 // Reference to constant local, top-level or static field 1075 // Reference to constant local, top-level or static field
1044
1045 result = translateConstant(node); 1076 result = translateConstant(node);
1077 } else if (isClosureVariable(element)) {
1078 result = new ir.GetClosureVariable(element);
1079 add(new ir.LetPrim(result));
1046 } else if (Elements.isLocal(element)) { 1080 } else if (Elements.isLocal(element)) {
1047 // Reference to local variable 1081 // Reference to local variable
1048
1049 result = lookupLocal(element); 1082 result = lookupLocal(element);
1050 } else if (element == null || 1083 } else if (element == null ||
1051 Elements.isInstanceField(element) || 1084 Elements.isInstanceField(element) ||
1052 Elements.isInstanceMethod(element) || 1085 Elements.isInstanceMethod(element) ||
1053 selector.isIndex || 1086 selector.isIndex ||
1054 node.isSuperCall) { 1087 node.isSuperCall) {
1055 // Dynamic dispatch to a getter. Sometimes resolution will suggest a target 1088 // Dynamic dispatch to a getter. Sometimes resolution will suggest a target
1056 // element, but in these cases we must still emit a dynamic dispatch. The 1089 // element, but in these cases we must still emit a dynamic dispatch. The
1057 // target element may be an instance method in case we are converting a 1090 // target element may be an instance method in case we are converting a
1058 // method to a function object. 1091 // method to a function object.
1059 1092
1060 receiver = visitReceiver(node.receiver); 1093 receiver = visitReceiver(node.receiver);
1061 List<ir.Primitive> arguments = new List<ir.Primitive>(); 1094 List<ir.Primitive> arguments = new List<ir.Primitive>();
1062 if (selector.isIndex) { 1095 if (selector.isIndex) {
1063 index = visit(node.arguments.head); 1096 index = visit(node.arguments.head);
1064 arguments.add(index); 1097 arguments.add(index);
1065 } 1098 }
1066 1099
1067 ir.Parameter v = new ir.Parameter(null);
1068 ir.Continuation k = new ir.Continuation([v]);
1069 assert(selector.kind == SelectorKind.GETTER || 1100 assert(selector.kind == SelectorKind.GETTER ||
1070 selector.kind == SelectorKind.INDEX); 1101 selector.kind == SelectorKind.INDEX);
1071 ir.Expression invoke = 1102 result = continueWithExpression(
1072 createDynamicInvoke(node, selector, receiver, k, arguments); 1103 (k) => createDynamicInvoke(node, selector, receiver, k, arguments));
1073 add(new ir.LetCont(k, invoke)); 1104 } else if (element.isField || element.isGetter || element.isSetter) {
1074 result = v; 1105 // Access to a static field or getter (non-static case handled above).
1075 } else if (element.isField || element.isGetter || 1106 // Even if there is only a setter, we compile as if it was a getter,
1076 // Access to a static field or getter (non-static case handled above). 1107 // so the vm can fail at runtime.
1077 // Even if there is only a setter, we compile as if it was a getter,
1078 // so the vm can fail at runtime.
1079
1080 element.isSetter) {
1081 ir.Parameter v = new ir.Parameter(null);
1082 ir.Continuation k = new ir.Continuation([v]);
1083 assert(selector.kind == SelectorKind.GETTER || 1108 assert(selector.kind == SelectorKind.GETTER ||
1084 selector.kind == SelectorKind.SETTER); 1109 selector.kind == SelectorKind.SETTER);
1085 ir.Expression invoke = 1110 result = continueWithExpression(
1086 new ir.InvokeStatic(element, selector, k, []); 1111 (k) => new ir.InvokeStatic(element, selector, k, []));
1087 add(new ir.LetCont(k, invoke));
1088 result = v;
1089 } else if (Elements.isStaticOrTopLevelFunction(element)) { 1112 } else if (Elements.isStaticOrTopLevelFunction(element)) {
1090 // Convert a top-level or static function to a function object. 1113 // Convert a top-level or static function to a function object.
1091
1092 result = translateConstant(node); 1114 result = translateConstant(node);
1093 } else { 1115 } else {
1094 throw "Unexpected SendSet getter: $node, $element"; 1116 throw "Unexpected SendSet getter: $node, $element";
1095 } 1117 }
1096 return new _GetterElements( 1118 return new _GetterElements(
1097 result: result,index: index, receiver: receiver); 1119 result: result,index: index, receiver: receiver);
1098 } 1120 }
1099 1121
1100 ir.Primitive visitGetterSend(ast.Send node) { 1122 ir.Primitive visitGetterSend(ast.Send node) {
1101 assert(isOpen); 1123 assert(isOpen);
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1247 if (type.isMalformed) return giveup(node, "Malformed type for is"); 1269 if (type.isMalformed) return giveup(node, "Malformed type for is");
1248 ir.Primitive receiver = visit(node.receiver); 1270 ir.Primitive receiver = visit(node.receiver);
1249 ir.IsCheck isCheck = new ir.IsCheck(receiver, type); 1271 ir.IsCheck isCheck = new ir.IsCheck(receiver, type);
1250 add(new ir.LetPrim(isCheck)); 1272 add(new ir.LetPrim(isCheck));
1251 return node.isIsNotCheck ? buildNegation(isCheck) : isCheck; 1273 return node.isIsNotCheck ? buildNegation(isCheck) : isCheck;
1252 } 1274 }
1253 if (op.source == "as") { 1275 if (op.source == "as") {
1254 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); 1276 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
1255 if (type.isMalformed) return giveup(node, "Malformed type for as"); 1277 if (type.isMalformed) return giveup(node, "Malformed type for as");
1256 ir.Primitive receiver = visit(node.receiver); 1278 ir.Primitive receiver = visit(node.receiver);
1257 ir.Parameter v = new ir.Parameter(null); 1279 return continueWithExpression(
1258 ir.Continuation k = new ir.Continuation([v]); 1280 (k) => new ir.AsCast(receiver, type, k));
1259 ir.AsCast asCast = new ir.AsCast(receiver, type, k);
1260 add(new ir.LetCont(k, asCast));
1261 return v;
1262 } 1281 }
1263 return giveup(node); 1282 return giveup(node);
1264 } 1283 }
1265 1284
1266 // Build(StaticSend(f, arguments), C) = C[C'[InvokeStatic(f, xs)]] 1285 // Build(StaticSend(f, arguments), C) = C[C'[InvokeStatic(f, xs)]]
1267 // where (C', xs) = arguments.fold(Build, C) 1286 // where (C', xs) = arguments.fold(Build, C)
1268 ir.Primitive visitStaticSend(ast.Send node) { 1287 ir.Primitive visitStaticSend(ast.Send node) {
1269 assert(isOpen); 1288 assert(isOpen);
1270 Element element = elements[node]; 1289 Element element = elements[node];
1271 // TODO(lry): support constructors / factory calls. 1290 // TODO(lry): support constructors / factory calls.
1272 if (element.isConstructor) return giveup(node, 'StaticSend: constructor'); 1291 if (element.isConstructor) return giveup(node, 'StaticSend: constructor');
1273 // TODO(lry): support foreign functions. 1292 // TODO(lry): support foreign functions.
1274 if (element.isForeign(compiler)) return giveup(node, 'StaticSend: foreign'); 1293 if (element.isForeign(compiler)) return giveup(node, 'StaticSend: foreign');
1275 // TODO(lry): for elements that could not be resolved emit code to throw a 1294 // TODO(lry): for elements that could not be resolved emit code to throw a
1276 // [NoSuchMethodError]. 1295 // [NoSuchMethodError].
1277 if (element.isErroneous) return giveup(node, 'StaticSend: erroneous'); 1296 if (element.isErroneous) return giveup(node, 'StaticSend: erroneous');
1278 // TODO(lry): generate IR for object identicality. 1297 // TODO(lry): generate IR for object identicality.
1279 if (element == compiler.identicalFunction) { 1298 if (element == compiler.identicalFunction) {
1280 return giveup(node, 'StaticSend: identical'); 1299 return giveup(node, 'StaticSend: identical');
1281 } 1300 }
1282 1301
1283 Selector selector = elements.getSelector(node); 1302 Selector selector = elements.getSelector(node);
1284 1303
1285 // TODO(lry): support default arguments, need support for locals. 1304 // TODO(lry): support default arguments, need support for locals.
1286 List<ir.Definition> arguments = node.arguments.mapToList(visit, 1305 List<ir.Definition> arguments = node.arguments.mapToList(visit,
1287 growable:false); 1306 growable:false);
1288 ir.Parameter v = new ir.Parameter(null); 1307 return continueWithExpression(
1289 ir.Continuation k = new ir.Continuation([v]); 1308 (k) => new ir.InvokeStatic(element, selector, k, arguments));
1290 ir.Expression invoke =
1291 new ir.InvokeStatic(element, selector, k, arguments);
1292 add(new ir.LetCont(k, invoke));
1293 return v;
1294 } 1309 }
1295 1310
1296 ir.Primitive visitSuperSend(ast.Send node) { 1311 ir.Primitive visitSuperSend(ast.Send node) {
1297 assert(isOpen); 1312 assert(isOpen);
1298 if (node.isPropertyAccess) { 1313 if (node.isPropertyAccess) {
1299 return visitGetterSend(node); 1314 return visitGetterSend(node);
1300 } else { 1315 } else {
1301 return visitDynamicSend(node); 1316 return visitDynamicSend(node);
1302 } 1317 }
1303 } 1318 }
1304 1319
1305 visitTypePrefixSend(ast.Send node) { 1320 visitTypePrefixSend(ast.Send node) {
1306 compiler.internalError(node, "visitTypePrefixSend should not be called."); 1321 compiler.internalError(node, "visitTypePrefixSend should not be called.");
1307 } 1322 }
1308 1323
1309 ir.Primitive visitTypeLiteralSend(ast.Send node) { 1324 ir.Primitive visitTypeLiteralSend(ast.Send node) {
1310 assert(isOpen); 1325 assert(isOpen);
1311 // If the user is trying to invoke the type literal or variable, 1326 // If the user is trying to invoke the type literal or variable,
1312 // it must be treated as a function call. 1327 // it must be treated as a function call.
1313 if (node.argumentsNode != null) { 1328 if (node.argumentsNode != null) {
1314 // TODO(sigurdm): Change this to match proposed semantics of issue #19725. 1329 // TODO(sigurdm): Handle this to match proposed semantics of issue #19725.
1315 return visitDynamicSend(node); 1330 return giveup(node, 'Type literal invoked as function');
1316 } 1331 }
1317 1332
1318 DartType type = elements.getTypeLiteralType(node); 1333 DartType type = elements.getTypeLiteralType(node);
1319 if (type is TypeVariableType) { 1334 if (type is TypeVariableType) {
1320 ir.Primitive prim = new ir.ReifyTypeVar(type.element); 1335 ir.Primitive prim = new ir.ReifyTypeVar(type.element);
1321 add(new ir.LetPrim(prim)); 1336 add(new ir.LetPrim(prim));
1322 return prim; 1337 return prim;
1323 } else { 1338 } else {
1324 return translateConstant(node); 1339 return translateConstant(node);
1325 } 1340 }
1326 } 1341 }
1327 1342
1343 /// True if [element] is a local variable, local function, or parameter that
1344 /// is accessed from an inner function. Recursive self-references in a local
1345 /// function count as closure accesses.
1346 bool isClosureVariable(Element element) {
1347 return closureLocals.isClosureVariable(element);
1348 }
1349
1328 ir.Primitive visitSendSet(ast.SendSet node) { 1350 ir.Primitive visitSendSet(ast.SendSet node) {
1329 assert(isOpen); 1351 assert(isOpen);
1330 Element element = elements[node]; 1352 Element element = elements[node];
1331 ast.Operator op = node.assignmentOperator; 1353 ast.Operator op = node.assignmentOperator;
1332 // For complex operators, this is the result of getting (before assigning) 1354 // For complex operators, this is the result of getting (before assigning)
1333 ir.Primitive originalValue; 1355 ir.Primitive originalValue;
1334 // For []+= style operators, this saves the index. 1356 // For []+= style operators, this saves the index.
1335 ir.Primitive index; 1357 ir.Primitive index;
1336 ir.Primitive receiver; 1358 ir.Primitive receiver;
1337 // This is what gets assigned. 1359 // This is what gets assigned.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1379 arg = visit(assignArg); 1401 arg = visit(assignArg);
1380 } 1402 }
1381 valueToStore = new ir.Parameter(null); 1403 valueToStore = new ir.Parameter(null);
1382 ir.Continuation k = new ir.Continuation([valueToStore]); 1404 ir.Continuation k = new ir.Continuation([valueToStore]);
1383 ir.Expression invoke = 1405 ir.Expression invoke =
1384 new ir.InvokeMethod(originalValue, operatorSelector, k, [arg]); 1406 new ir.InvokeMethod(originalValue, operatorSelector, k, [arg]);
1385 add(new ir.LetCont(k, invoke)); 1407 add(new ir.LetCont(k, invoke));
1386 } 1408 }
1387 1409
1388 // Set the value 1410 // Set the value
1389 if (Elements.isLocal(element)) { 1411 if (isClosureVariable(element)) {
1412 add(new ir.SetClosureVariable(element, valueToStore));
1413 } else if (Elements.isLocal(element)) {
1390 valueToStore.useElementAsHint(element); 1414 valueToStore.useElementAsHint(element);
1391 assignedVars[variableIndex[element]] = valueToStore; 1415 assignedVars[variableIndex[element]] = valueToStore;
1392 } else if (Elements.isStaticOrTopLevel(element)) { 1416 } else if (Elements.isStaticOrTopLevel(element)) {
1393 assert(element.isField || element.isSetter); 1417 assert(element.isField || element.isSetter);
1394 ir.Parameter v = new ir.Parameter(null);
1395 ir.Continuation k = new ir.Continuation([v]);
1396 Selector selector = elements.getSelector(node); 1418 Selector selector = elements.getSelector(node);
1397 ir.InvokeStatic invoke = 1419 continueWithExpression(
1398 new ir.InvokeStatic(element, selector, k, [valueToStore]); 1420 (k) => new ir.InvokeStatic(element, selector, k, [valueToStore]));
1399 add(new ir.LetCont(k, invoke));
1400 } else { 1421 } else {
1401 if (element != null && Elements.isUnresolved(element)) { 1422 if (element != null && Elements.isUnresolved(element)) {
1402 return giveup(node, 'SendSet: non-local, non-static, unresolved'); 1423 return giveup(node, 'SendSet: non-local, non-static, unresolved');
1403 } 1424 }
1404 // Setter or index-setter invocation 1425 // Setter or index-setter invocation
1405 ir.Parameter v = new ir.Parameter(null);
1406 ir.Continuation k = new ir.Continuation([v]);
1407 Selector selector = elements.getSelector(node); 1426 Selector selector = elements.getSelector(node);
1408 assert(selector.kind == SelectorKind.SETTER || 1427 assert(selector.kind == SelectorKind.SETTER ||
1409 selector.kind == SelectorKind.INDEX); 1428 selector.kind == SelectorKind.INDEX);
1410 List<ir.Definition> arguments = selector.isIndexSet 1429 List<ir.Definition> arguments = selector.isIndexSet
1411 ? [index, valueToStore] 1430 ? [index, valueToStore]
1412 : [valueToStore]; 1431 : [valueToStore];
1413 ir.Expression invoke = 1432 continueWithExpression(
1414 createDynamicInvoke(node, selector, receiver, k, arguments); 1433 (k) => createDynamicInvoke(node, selector, receiver, k, arguments));
1415 add(new ir.LetCont(k, invoke));
1416 } 1434 }
1417 1435
1418 if (node.isPostfix) { 1436 if (node.isPostfix) {
1419 assert(originalValue != null); 1437 assert(originalValue != null);
1420 return originalValue; 1438 return originalValue;
1421 } else { 1439 } else {
1422 return valueToStore; 1440 return valueToStore;
1423 } 1441 }
1424 } 1442 }
1425 1443
1426 ir.Primitive visitNewExpression(ast.NewExpression node) { 1444 ir.Primitive visitNewExpression(ast.NewExpression node) {
1427 assert(isOpen); 1445 assert(isOpen);
1428 if (node.isConst) { 1446 if (node.isConst) {
1429 return translateConstant(node); 1447 return translateConstant(node);
1430 } 1448 }
1431 FunctionElement element = elements[node.send]; 1449 FunctionElement element = elements[node.send];
1432 if (Elements.isUnresolved(element)) { 1450 if (Elements.isUnresolved(element)) {
1433 return giveup(node, 'NewExpression: unresolved constructor'); 1451 return giveup(node, 'NewExpression: unresolved constructor');
1434 } 1452 }
1435 Selector selector = elements.getSelector(node.send); 1453 Selector selector = elements.getSelector(node.send);
1436 ast.Node selectorNode = node.send.selector; 1454 ast.Node selectorNode = node.send.selector;
1437 GenericType type = elements.getType(node); 1455 GenericType type = elements.getType(node);
1438 List<ir.Primitive> args = 1456 List<ir.Primitive> args =
1439 node.send.arguments.mapToList(visit, growable:false); 1457 node.send.arguments.mapToList(visit, growable:false);
1440 ir.Parameter v = new ir.Parameter(null); 1458 return continueWithExpression(
1441 ir.Continuation k = new ir.Continuation([v]); 1459 (k) => new ir.InvokeConstructor(type, element,selector, k, args));
1442 ir.InvokeConstructor invoke =
1443 new ir.InvokeConstructor(type, element,selector, k, args);
1444 add(new ir.LetCont(k, invoke));
1445 return v;
1446 } 1460 }
1447 1461
1448 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) { 1462 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
1449 assert(isOpen); 1463 assert(isOpen);
1450 ir.Primitive first = visit(node.first); 1464 ir.Primitive first = visit(node.first);
1451 ir.Primitive second = visit(node.second); 1465 ir.Primitive second = visit(node.second);
1452 ir.Parameter v = new ir.Parameter(null); 1466 return continueWithExpression(
1453 ir.Continuation k = new ir.Continuation([v]); 1467 (k) => new ir.ConcatenateStrings(k, [first, second]));
1454 ir.ConcatenateStrings concat =
1455 new ir.ConcatenateStrings(k, [first, second]);
1456 add(new ir.LetCont(k, concat));
1457 return v;
1458 } 1468 }
1459 1469
1460 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) { 1470 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) {
1461 assert(isOpen); 1471 assert(isOpen);
1462 List<ir.Primitive> arguments = []; 1472 List<ir.Primitive> arguments = [];
1463 arguments.add(visitLiteralString(node.string)); 1473 arguments.add(visitLiteralString(node.string));
1464 var it = node.parts.iterator; 1474 var it = node.parts.iterator;
1465 while (it.moveNext()) { 1475 while (it.moveNext()) {
1466 ast.StringInterpolationPart part = it.current; 1476 ast.StringInterpolationPart part = it.current;
1467 arguments.add(visit(part.expression)); 1477 arguments.add(visit(part.expression));
1468 arguments.add(visitLiteralString(part.string)); 1478 arguments.add(visitLiteralString(part.string));
1469 } 1479 }
1470 ir.Parameter v = new ir.Parameter(null); 1480 return continueWithExpression(
1471 ir.Continuation k = new ir.Continuation([v]); 1481 (k) => new ir.ConcatenateStrings(k, arguments));
1472 ir.ConcatenateStrings concat = new ir.ConcatenateStrings(k, arguments);
1473 add(new ir.LetCont(k, concat));
1474 return v;
1475 } 1482 }
1476 1483
1477 ir.Primitive translateConstant(ast.Node node, [Constant value]) { 1484 ir.Primitive translateConstant(ast.Node node, [Constant value]) {
1478 assert(isOpen); 1485 assert(isOpen);
1479 if (value == null) { 1486 if (value == null) {
1480 value = getConstantForNode(node); 1487 value = getConstantForNode(node);
1481 } 1488 }
1482 ir.Primitive primitive = makeConst(constantBuilder.visit(node), value); 1489 ir.Primitive primitive = makeConst(constantBuilder.visit(node), value);
1483 add(new ir.LetPrim(primitive)); 1490 add(new ir.LetPrim(primitive));
1484 return primitive; 1491 return primitive;
1485 } 1492 }
1486 1493
1494 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) {
1495 return new IrBuilder(elements, compiler, sourceFile)
1496 .buildFunctionInternal(elements[node]);
1497 }
1498
1499 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
1500 FunctionElement element = elements[node];
1501 ir.FunctionDefinition inner = makeSubFunction(node);
1502 ir.CreateFunction prim = new ir.CreateFunction(inner);
1503 add(new ir.LetPrim(prim));
1504 return prim;
1505 }
1506
1507 ir.Primitive visitFunctionDeclaration(ast.FunctionDeclaration node) {
1508 FunctionElement element = elements[node.function];
1509 ir.FunctionDefinition inner = makeSubFunction(node.function);
1510 if (isClosureVariable(element)) {
1511 add(new ir.DeclareFunction(element, inner));
1512 } else {
1513 ir.CreateFunction prim = new ir.CreateFunction(inner);
1514 add(new ir.LetPrim(prim));
1515 variableIndex[element] = assignedVars.length;
1516 assignedVars.add(prim);
1517 index2variable.add(element);
1518 prim.useElementAsHint(element);
1519 }
1520 return null;
1521 }
1522
1487 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; 1523 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
1488 1524
1489 ir.Primitive giveup(ast.Node node, [String reason]) { 1525 dynamic giveup(ast.Node node, [String reason]) {
1490 throw ABORT_IRNODE_BUILDER; 1526 throw ABORT_IRNODE_BUILDER;
1491 } 1527 }
1492 1528
1493 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { 1529 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) {
1494 try { 1530 try {
1495 return action(); 1531 return action();
1496 } catch(e, tr) { 1532 } catch(e, tr) {
1497 if (e == ABORT_IRNODE_BUILDER) { 1533 if (e == ABORT_IRNODE_BUILDER) {
1498 return null; 1534 return null;
1499 } 1535 }
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1655 ConstExp visitConditional(ast.Conditional node) { 1691 ConstExp visitConditional(ast.Conditional node) {
1656 BoolConstant condition = computeConstant(node.condition); 1692 BoolConstant condition = computeConstant(node.condition);
1657 return visit(condition.isTrue ? node.thenExpression : node.elseExpression); 1693 return visit(condition.isTrue ? node.thenExpression : node.elseExpression);
1658 } 1694 }
1659 1695
1660 ConstExp visitNode(ast.Node node) { 1696 ConstExp visitNode(ast.Node node) {
1661 throw "Unexpected constant: $node"; 1697 throw "Unexpected constant: $node";
1662 } 1698 }
1663 1699
1664 } 1700 }
1701
1702 /// Classifies local variables and local functions as 'closure variables'.
1703 /// A closure variable is one that is accessed from an inner function nested
1704 /// one or more levels inside the one that declares it.
1705 class DetectClosureVariables extends ast.Visitor {
1706 final TreeElements elements;
1707 DetectClosureVariables(this.elements);
1708
1709 FunctionElement currentFunction;
1710 Set<Element> usedFromClosure = new Set<Element>();
1711 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>();
1712
1713 bool isClosureVariable(Element element) => usedFromClosure.contains(element);
1714
1715 void markAsClosureVariable(Element element) {
1716 usedFromClosure.add(element);
1717 }
1718
1719 visit(ast.Node node) => node.accept(this);
1720
1721 visitNode(ast.Node node) {
1722 node.visitChildren(this);
1723 }
1724
1725 visitSend(ast.Send node) {
1726 Element element = elements[node];
1727 if (Elements.isLocal(element) &&
1728 !element.isConst &&
1729 element.enclosingElement != currentFunction) {
1730 markAsClosureVariable(element);
1731 }
1732 node.visitChildren(this);
1733 }
1734
1735 visitFunctionExpression(ast.FunctionExpression node) {
1736 FunctionElement oldFunction = currentFunction;
1737 currentFunction = elements[node];
1738 visit(node.body);
1739 currentFunction = oldFunction;
1740 }
1741
1742 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698