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

Side by Side Diff: frog/leg/ssa/builder.dart

Issue 9301038: Support named arguments for statically resolved calls. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 class Interceptors { 5 class Interceptors {
6 Compiler compiler; 6 Compiler compiler;
7 Interceptors(Compiler this.compiler); 7 Interceptors(Compiler this.compiler);
8 8
9 SourceString mapOperatorToMethodName(Operator op) { 9 SourceString mapOperatorToMethodName(Operator op) {
10 String name = op.source.stringValue; 10 String name = op.source.stringValue;
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 201
202 HGraph buildFactory(ClassElement classElement, 202 HGraph buildFactory(ClassElement classElement,
203 ConstructorBodyElement bodyElement, 203 ConstructorBodyElement bodyElement,
204 FunctionElement functionElement) { 204 FunctionElement functionElement) {
205 // The initializer list could contain closures. 205 // The initializer list could contain closures.
206 translateClosures(functionElement); 206 translateClosures(functionElement);
207 openFunction(functionElement); 207 openFunction(functionElement);
208 208
209 FunctionExpression function = functionElement.parseNode(compiler); 209 FunctionExpression function = functionElement.parseNode(compiler);
210 NodeList initializers = function.initializers; 210 NodeList initializers = function.initializers;
211 NodeList parameters = function.parameters;
212 // Run through the initializers. 211 // Run through the initializers.
213 if (initializers !== null) { 212 if (initializers !== null) {
214 for (Link<Node> link = initializers.nodes; 213 for (Link<Node> link = initializers.nodes;
215 !link.isEmpty(); 214 !link.isEmpty();
216 link = link.tail) { 215 link = link.tail) {
217 assert(link.head is Send); 216 assert(link.head is Send);
218 if (link.head is !SendSet) { 217 if (link.head is !SendSet) {
219 compiler.unimplemented('SsaBuilder.buildFactory super-init'); 218 compiler.unimplemented('SsaBuilder.buildFactory super-init');
220 } else { 219 } else {
221 SendSet init = link.head; 220 SendSet init = link.head;
(...skipping 21 matching lines...) Expand all
243 } 242 }
244 } 243 }
245 HForeignNew newObject = new HForeignNew(classElement, fieldValues); 244 HForeignNew newObject = new HForeignNew(classElement, fieldValues);
246 add(newObject); 245 add(newObject);
247 246
248 // Call the method body. 247 // Call the method body.
249 SourceString methodName = bodyElement.name; 248 SourceString methodName = bodyElement.name;
250 249
251 List bodyCallInputs = <HInstruction>[]; 250 List bodyCallInputs = <HInstruction>[];
252 bodyCallInputs.add(newObject); 251 bodyCallInputs.add(newObject);
253 for (Link link = parameters.nodes; !link.isEmpty(); link = link.tail) { 252 FunctionParameters parameters = functionElement.computeParameters(compiler);
254 Link<Node> nodeLink = link.head.definitions.nodes; 253 parameters.forEachParameter((Element parameterElement) {
255 // We expect exactly one identifier.
256 assert(!nodeLink.isEmpty() && nodeLink.tail.isEmpty());
257 Node current = nodeLink.head;
258 Element parameterElement = elements[current];
259 HInstruction currentValue = definitions[parameterElement]; 254 HInstruction currentValue = definitions[parameterElement];
260 bodyCallInputs.add(currentValue); 255 bodyCallInputs.add(currentValue);
261 } 256 });
262 add(new HInvokeDynamicMethod(null, methodName, bodyCallInputs)); 257 add(new HInvokeDynamicMethod(null, methodName, bodyCallInputs));
263 close(new HReturn(newObject)).addSuccessor(graph.exit); 258 close(new HReturn(newObject)).addSuccessor(graph.exit);
264 return closeFunction(); 259 return closeFunction();
265 } 260 }
266 261
267 void openFunction(FunctionElement functionElement) { 262 void openFunction(FunctionElement functionElement) {
268 stack = new List<HInstruction>(); 263 stack = new List<HInstruction>();
269 definitions = new Map<Element, HInstruction>(); 264 definitions = new Map<Element, HInstruction>();
270 265
271 graph = new HGraph(); 266 graph = new HGraph();
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 push(new HIs(elements[node.arguments.head], expression)); 875 push(new HIs(elements[node.arguments.head], expression));
881 } else { 876 } else {
882 visit(node.receiver); 877 visit(node.receiver);
883 visit(node.argumentsNode); 878 visit(node.argumentsNode);
884 var right = pop(); 879 var right = pop();
885 var left = pop(); 880 var left = pop();
886 visitBinary(left, op, right); 881 visitBinary(left, op, right);
887 } 882 }
888 } 883 }
889 884
890 addVisitedSendArgumentsToList(Link<Node> link, List<HInstruction> list) { 885 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) {
886 Selector selector = elements.getSelector(node);
887 if (selector.namedArgumentCount == 0) {
888 addGenericSendArgumentsToList(node.arguments, list);
889 } else {
890 compiler.cancel(
891 'Unimplemented named argument for dynamic sends', node: node);
892 }
893 }
894
895 void addStaticSendArgumentsToList(Send node,
896 FunctionElement element,
897 List<HInstruction> list) {
898 Selector selector = elements.getSelector(node);
899 if (!selector.applies(compiler, element)) {
900 // TODO(ngeoffray): Match the VM behavior and throw an
901 // exception at runtime.
902 compiler.cancel('Unimplemented non-matching static call', node: node);
903 } else if (selector.namedArgumentCount == 0) {
904 addGenericSendArgumentsToList(node.arguments, list);
905 } else {
906 // If there are named arguments, provide them in the order
907 // expected by the called function, which is the source order.
908 FunctionParameters parameters = element.computeParameters(compiler);
909
910 // Visit positional arguments and add them to the list.
911 Link<Node> arguments = node.arguments;
912 int positionalArgumentCount = selector.positionalArgumentCount;
913 for (int i = 0;
914 i < positionalArgumentCount;
915 arguments = arguments.tail, i++) {
916 visit(arguments.head);
917 list.add(pop());
918 }
919
920 // Visit named arguments and add them into a temporary list.
921 List<HInstruction> namedArguments = <HInstruction>[];
922 for (; !arguments.isEmpty(); arguments = arguments.tail) {
923 visit(arguments.head);
924 namedArguments.add(pop());
925 }
926
927 Link<Element> remainingNamedParameters = parameters.optionalParameters;
928 // Skip the optional parameters that have been given in the
929 // positional arguments.
930 for (int i = parameters.requiredParameterCount;
931 i < positionalArgumentCount;
932 i++) {
933 remainingNamedParameters = remainingNamedParameters.tail;
934 }
935
936 // Loop over the remaining named parameters, and try to find
937 // their values: either in the temporary list or using the
938 // default value.
939 for (;
940 !remainingNamedParameters.isEmpty();
941 remainingNamedParameters = remainingNamedParameters.tail) {
942 Element parameter = remainingNamedParameters.head;
943 int foundIndex = -1;
944 for (int i = 0; i < selector.namedArguments.length; i++) {
945 SourceString name = selector.namedArguments[i];
946 if (name == parameter.name) {
947 foundIndex = i;
948 break;
949 }
950 }
951 if (foundIndex != -1) {
952 list.add(namedArguments[foundIndex]);
953 } else {
954 // TODO(ngeoffray): Add the default value.
floitsch 2012/01/31 15:52:41 If it is not too difficult I would prefer checking
ngeoffray 2012/01/31 16:46:17 We don't support default values for parameters yet
955 push(new HLiteral(null, HType.UNKNOWN));
956 list.add(pop());
957 }
958 }
959 }
960 }
961
962 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) {
891 for (; !link.isEmpty(); link = link.tail) { 963 for (; !link.isEmpty(); link = link.tail) {
892 visit(link.head); 964 visit(link.head);
893 list.add(pop()); 965 list.add(pop());
894 } 966 }
895 } 967 }
896 968
897 visitDynamicSend(Send node) { 969 visitDynamicSend(Send node) {
898 Selector selector = elements.getSelector(node); 970 Selector selector = elements.getSelector(node);
899 var inputs = <HInstruction>[]; 971 var inputs = <HInstruction>[];
900 972
(...skipping 18 matching lines...) Expand all
919 if (methodInterceptionEnabled) { 991 if (methodInterceptionEnabled) {
920 interceptor = interceptors.getStaticInterceptor(dartMethodName, 992 interceptor = interceptors.getStaticInterceptor(dartMethodName,
921 node.argumentCount()); 993 node.argumentCount());
922 } 994 }
923 if (interceptor != null) { 995 if (interceptor != null) {
924 HStatic target = new HStatic(interceptor); 996 HStatic target = new HStatic(interceptor);
925 add(target); 997 add(target);
926 inputs.add(target); 998 inputs.add(target);
927 visit(node.receiver); 999 visit(node.receiver);
928 inputs.add(pop()); 1000 inputs.add(pop());
929 addVisitedSendArgumentsToList(node.arguments, inputs); 1001 addGenericSendArgumentsToList(node.arguments, inputs);
930 push(new HInvokeInterceptor(selector, dartMethodName, false, inputs)); 1002 push(new HInvokeInterceptor(selector, dartMethodName, false, inputs));
931 return; 1003 return;
932 } 1004 }
933 1005
934 if (node.receiver === null) { 1006 if (node.receiver === null) {
935 HThis receiver = thisDefinition; 1007 HThis receiver = thisDefinition;
936 if (receiver === null) { 1008 if (receiver === null) {
937 compiler.unimplemented("Ssa.visitDynamicSend.", node: node); 1009 compiler.unimplemented("Ssa.visitDynamicSend.", node: node);
938 } 1010 }
939 inputs.add(receiver); 1011 inputs.add(receiver);
940 } else { 1012 } else {
941 visit(node.receiver); 1013 visit(node.receiver);
942 inputs.add(pop()); 1014 inputs.add(pop());
943 } 1015 }
944 1016
945 addVisitedSendArgumentsToList(node.arguments, inputs); 1017 addDynamicSendArgumentsToList(node, inputs);
946 1018
947 // The first entry in the inputs list is the receiver. 1019 // The first entry in the inputs list is the receiver.
948 push(new HInvokeDynamicMethod(selector, dartMethodName, inputs)); 1020 push(new HInvokeDynamicMethod(selector, dartMethodName, inputs));
949 1021
950 if (isNotEquals) { 1022 if (isNotEquals) {
951 HNot not = new HNot(popBoolified()); 1023 HNot not = new HNot(popBoolified());
952 push(not); 1024 push(not);
953 } 1025 }
954 } 1026 }
955 1027
956 visitClosureSend(Send node) { 1028 visitClosureSend(Send node) {
957 Selector selector = elements.getSelector(node); 1029 Selector selector = elements.getSelector(node);
958 assert(node.receiver === null); 1030 assert(node.receiver === null);
959 Element element = elements[node]; 1031 Element element = elements[node];
960 HInstruction closureTarget; 1032 HInstruction closureTarget;
961 if (element === null) { 1033 if (element === null) {
962 visit(node.selector); 1034 visit(node.selector);
963 closureTarget = pop(); 1035 closureTarget = pop();
964 } else { 1036 } else {
965 assert(element.kind === ElementKind.VARIABLE || 1037 assert(element.kind === ElementKind.VARIABLE ||
966 element.kind === ElementKind.PARAMETER); 1038 element.kind === ElementKind.PARAMETER);
967 closureTarget = definitions[element]; 1039 closureTarget = definitions[element];
968 assert(closureTarget !== null); 1040 assert(closureTarget !== null);
969 } 1041 }
970 var inputs = <HInstruction>[]; 1042 var inputs = <HInstruction>[];
971 inputs.add(closureTarget); 1043 inputs.add(closureTarget);
972 addVisitedSendArgumentsToList(node.arguments, inputs); 1044 addDynamicSendArgumentsToList(node, inputs);
973 push(new HInvokeClosure(selector, inputs)); 1045 push(new HInvokeClosure(selector, inputs));
974 } 1046 }
975 1047
976 visitForeignSend(Send node) { 1048 visitForeignSend(Send node) {
977 Identifier selector = node.selector; 1049 Identifier selector = node.selector;
978 switch (selector.source.stringValue) { 1050 switch (selector.source.stringValue) {
979 case "JS": 1051 case "JS":
980 Link<Node> link = node.arguments; 1052 Link<Node> link = node.arguments;
981 // If the invoke is on foreign code, don't visit the first 1053 // If the invoke is on foreign code, don't visit the first
982 // argument, which is the type, and the second argument, 1054 // argument, which is the type, and the second argument,
983 // which is the foreign code. 1055 // which is the foreign code.
984 link = link.tail.tail; 1056 link = link.tail.tail;
985 List<HInstruction> inputs = <HInstruction>[]; 1057 List<HInstruction> inputs = <HInstruction>[];
986 addVisitedSendArgumentsToList(link, inputs); 1058 addGenericSendArgumentsToList(link, inputs);
987 LiteralString type = node.arguments.head; 1059 LiteralString type = node.arguments.head;
988 LiteralString literal = node.arguments.tail.head; 1060 LiteralString literal = node.arguments.tail.head;
989 compiler.ensure(literal is LiteralString); 1061 compiler.ensure(literal is LiteralString);
990 compiler.ensure(type is LiteralString); 1062 compiler.ensure(type is LiteralString);
991 compiler.ensure(literal.value.stringValue[0] == '@'); 1063 compiler.ensure(literal.value.stringValue[0] == '@');
992 push(new HForeign(unquote(literal, 1), unquote(type, 0), inputs)); 1064 push(new HForeign(unquote(literal, 1), unquote(type, 0), inputs));
993 break; 1065 break;
994 case "UNINTERCEPTED": 1066 case "UNINTERCEPTED":
995 Link<Node> link = node.arguments; 1067 Link<Node> link = node.arguments;
996 if (!link.tail.isEmpty()) { 1068 if (!link.tail.isEmpty()) {
997 compiler.cancel('More than one expression in UNINTERCEPTED()'); 1069 compiler.cancel('More than one expression in UNINTERCEPTED()');
998 } 1070 }
999 Expression expression = link.head; 1071 Expression expression = link.head;
1000 disableMethodInterception(); 1072 disableMethodInterception();
1001 visit(expression); 1073 visit(expression);
1002 enableMethodInterception(); 1074 enableMethodInterception();
1003 break; 1075 break;
1004 case "JS_HAS_EQUALS": 1076 case "JS_HAS_EQUALS":
1005 List<HInstruction> inputs = <HInstruction>[]; 1077 List<HInstruction> inputs = <HInstruction>[];
1006 if (!node.arguments.tail.isEmpty()) { 1078 if (!node.arguments.tail.isEmpty()) {
1007 compiler.cancel('More than one expression in JS_HAS_EQUALS()'); 1079 compiler.cancel('More than one expression in JS_HAS_EQUALS()');
1008 } 1080 }
1009 addVisitedSendArgumentsToList(node.arguments, inputs); 1081 addGenericSendArgumentsToList(node.arguments, inputs);
1010 String name = compiler.namer.instanceMethodName( 1082 String name = compiler.namer.instanceMethodName(
1011 Namer.OPERATOR_EQUALS, 1); 1083 Namer.OPERATOR_EQUALS, 1);
1012 push(new HForeign( 1084 push(new HForeign(
1013 new SourceString('\$0.$name'), const SourceString('bool'), inputs)); 1085 new SourceString('\$0.$name'), const SourceString('bool'), inputs));
1014 break; 1086 break;
1015 default: 1087 default:
1016 throw "Unknown foreign: ${node.selector}"; 1088 throw "Unknown foreign: ${node.selector}";
1017 } 1089 }
1018 } 1090 }
1019 1091
1020 visitSuperSend(Send node) { 1092 visitSuperSend(Send node) {
1021 Selector selector = elements.getSelector(node); 1093 Selector selector = elements.getSelector(node);
1022 Element element = elements[node]; 1094 Element element = elements[node];
1023 HStatic target = new HStatic(element); 1095 HStatic target = new HStatic(element);
1024 HThis context = thisDefinition; 1096 HThis context = thisDefinition;
1025 if (context === null) { 1097 if (context === null) {
1026 compiler.unimplemented("Ssa.visitSuperSend without thisDefinition.", 1098 compiler.unimplemented("Ssa.visitSuperSend without thisDefinition.",
1027 node: node); 1099 node: node);
1028 } 1100 }
1029 add(target); 1101 add(target);
1030 var inputs = <HInstruction>[target, context]; 1102 var inputs = <HInstruction>[target, context];
1031 addVisitedSendArgumentsToList(node.arguments, inputs); 1103 addStaticSendArgumentsToList(node, element, inputs);
1032 push(new HInvokeSuper(selector, inputs)); 1104 push(new HInvokeSuper(selector, inputs));
1033 } 1105 }
1034 1106
1035 visitStaticSend(Send node) { 1107 visitStaticSend(Send node) {
1036 Selector selector = elements.getSelector(node); 1108 Selector selector = elements.getSelector(node);
1037 Element element = elements[node]; 1109 Element element = elements[node];
1038 HStatic target = new HStatic(element); 1110 HStatic target = new HStatic(element);
1039 add(target); 1111 add(target);
1040 var inputs = <HInstruction>[]; 1112 var inputs = <HInstruction>[];
1041 inputs.add(target); 1113 inputs.add(target);
1042 addVisitedSendArgumentsToList(node.arguments, inputs); 1114 addStaticSendArgumentsToList(node, element, inputs);
1043 push(new HInvokeStatic(selector, inputs)); 1115 push(new HInvokeStatic(selector, inputs));
1044 } 1116 }
1045 1117
1046 visitSend(Send node) { 1118 visitSend(Send node) {
1047 if (node.selector is Operator && methodInterceptionEnabled) { 1119 if (node.selector is Operator && methodInterceptionEnabled) {
1048 visitOperatorSend(node); 1120 visitOperatorSend(node);
1049 } else if (node.isPropertyAccess) { 1121 } else if (node.isPropertyAccess) {
1050 generateGetter(node, elements[node]); 1122 generateGetter(node, elements[node]);
1051 } else if (Elements.isClosureSend(node, elements)) { 1123 } else if (Elements.isClosureSend(node, elements)) {
1052 visitClosureSend(node); 1124 visitClosureSend(node);
1053 } else if (node.isSuperCall) { 1125 } else if (node.isSuperCall) {
1054 visitSuperSend(node); 1126 visitSuperSend(node);
1055 } else { 1127 } else {
1056 Element element = elements[node]; 1128 Element element = elements[node];
1057 if (element === null) { 1129 if (element === null) {
1058 // Example: f() with 'f' unbound. 1130 // Example: f() with 'f' unbound.
1059 // This can only happen inside an instance method. 1131 // This can only happen inside an instance method.
1060 visitDynamicSend(node); 1132 visitDynamicSend(node);
1133 } else if (element.kind == ElementKind.CLASS) {
1134 compiler.internalError("Cannot generate code for send", node: node);
1061 } else if (element.isInstanceMember()) { 1135 } else if (element.isInstanceMember()) {
1062 // Example: f() with 'f' bound to instance method. 1136 // Example: f() with 'f' bound to instance method.
1063 visitDynamicSend(node); 1137 visitDynamicSend(node);
1064 } else if (element.kind === ElementKind.FOREIGN) { 1138 } else if (element.kind === ElementKind.FOREIGN) {
1065 visitForeignSend(node); 1139 visitForeignSend(node);
1066 } else if (!element.isInstanceMember()) { 1140 } else if (!element.isInstanceMember()) {
1067 // Example: A.f() or f() with 'f' bound to a static function. 1141 // Example: A.f() or f() with 'f' bound to a static function.
1068 // Also includes new A() or new A.named() which is treated like a 1142 // Also includes new A() or new A.named() which is treated like a
1069 // static call to a factory. 1143 // static call to a factory.
1070 visitStaticSend(node); 1144 visitStaticSend(node);
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 1479
1406 visitLiteralMap(LiteralMap node) { 1480 visitLiteralMap(LiteralMap node) {
1407 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node); 1481 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node);
1408 } 1482 }
1409 1483
1410 visitLiteralMapEntry(LiteralMapEntry node) { 1484 visitLiteralMapEntry(LiteralMapEntry node) {
1411 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node); 1485 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node);
1412 } 1486 }
1413 1487
1414 visitNamedArgument(NamedArgument node) { 1488 visitNamedArgument(NamedArgument node) {
1415 compiler.unimplemented('SsaBuilder.visitNamedArgument', node: node); 1489 visit(node.expression);
1416 } 1490 }
1417 1491
1418 visitSwitchStatement(SwitchStatement node) { 1492 visitSwitchStatement(SwitchStatement node) {
1419 compiler.unimplemented('SsaBuilder.visitSwitchStatement', node: node); 1493 compiler.unimplemented('SsaBuilder.visitSwitchStatement', node: node);
1420 } 1494 }
1421 1495
1422 visitTryStatement(TryStatement node) { 1496 visitTryStatement(TryStatement node) {
1423 compiler.unimplemented('SsaBuilder.visitTryStatement', node: node); 1497 compiler.unimplemented('SsaBuilder.visitTryStatement', node: node);
1424 } 1498 }
1425 1499
1426 visitScriptTag(ScriptTag node) { 1500 visitScriptTag(ScriptTag node) {
1427 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node); 1501 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node);
1428 } 1502 }
1429 1503
1430 visitCatchBlock(CatchBlock node) { 1504 visitCatchBlock(CatchBlock node) {
1431 compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node); 1505 compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node);
1432 } 1506 }
1433 1507
1434 visitTypedef(Typedef node) { 1508 visitTypedef(Typedef node) {
1435 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); 1509 compiler.unimplemented('SsaBuilder.visitTypedef', node: node);
1436 } 1510 }
1437 } 1511 }
OLDNEW
« no previous file with comments | « frog/leg/resolver.dart ('k') | frog/leg/ssa/codegen.dart » ('j') | frog/leg/universe.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698