Chromium Code Reviews| Index: lib/compiler/implementation/ssa/builder.dart |
| diff --git a/lib/compiler/implementation/ssa/builder.dart b/lib/compiler/implementation/ssa/builder.dart |
| index fbffcde651006065b105446665748ec054d53735..8e2fe5d80058ded1e9d78d6789b12615d30ecf76 100644 |
| --- a/lib/compiler/implementation/ssa/builder.dart |
| +++ b/lib/compiler/implementation/ssa/builder.dart |
| @@ -2296,6 +2296,15 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| push(result); |
| } |
| + void pushInvokeHelper4(Element helper, HInstruction a0, HInstruction a1, |
| + HInstruction a2, HInstruction a3) { |
| + HInstruction reference = new HStatic(helper); |
| + add(reference); |
| + List<HInstruction> inputs = <HInstruction>[reference, a0, a1, a2, a3]; |
| + HInstruction result = new HInvokeStatic(inputs); |
| + push(result); |
| + } |
| + |
| visitOperatorSend(node) { |
| assert(node.selector is Operator); |
| if (!methodInterceptionEnabled) { |
| @@ -2728,16 +2737,17 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| push(new HInvokeSuper(inputs)); |
| } else if (element.isFunction() || element.isGenerativeConstructor()) { |
| // TODO(5347): Try to avoid the need for calling [implementation] before |
| - // calling [addStaticSendArgumentsToList]. |
| + // calling [addStaticSendArgumentsToList] and |
| + // [generateWrongArgumentCoundError]. |
|
ngeoffray
2012/10/25 11:24:09
generateWrongArgumentCoundError doesn't use functi
karlklose
2012/10/25 13:55:44
Done.
|
| + FunctionElement function = element.implementation; |
| bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| - element.implementation, |
| - inputs); |
| + function, inputs); |
| if (!succeeded) { |
| - // TODO(ngeoffray): Match the VM behavior and throw an |
| - // exception at runtime. |
| - compiler.cancel('Unimplemented non-matching static call', node: node); |
| + generateWrongArgumentCountError(node, element, |
| + argumentNodes: node.arguments); |
| + } else { |
| + push(new HInvokeSuper(inputs)); |
| } |
| - push(new HInvokeSuper(inputs)); |
| } else { |
| target = new HInvokeSuper(inputs); |
| add(target); |
| @@ -2936,9 +2946,9 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| constructor.implementation, |
| inputs); |
| if (!succeeded) { |
| - // TODO(ngeoffray): Match the VM behavior and throw an |
| - // exception at runtime. |
| - compiler.cancel('Unimplemented non-matching static call', node: node); |
| + generateWrongArgumentCountError(node, constructor, |
| + argumentNodes: node.arguments); |
| + return; |
| } |
| TypeAnnotation annotation = node.getTypeAnnotation(); |
| @@ -2979,7 +2989,8 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| argumentNodes: node.arguments); |
| return; |
| } |
| - if (identical(element, compiler.assertMethod) && !compiler.enableUserAssertions) { |
| + if (identical(element, compiler.assertMethod) |
| + && !compiler.enableUserAssertions) { |
| stack.add(graph.addConstantNull(constantSystem)); |
| return; |
| } |
| @@ -2998,9 +3009,9 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| element.implementation, |
| inputs); |
| if (!succeeded) { |
| - // TODO(ngeoffray): Match the VM behavior and throw an |
| - // exception at runtime. |
| - compiler.cancel('Unimplemented non-matching static call', node: node); |
| + generateWrongArgumentCountError(node, element, |
| + argumentNodes: node.arguments); |
| + return; |
| } |
| // TODO(kasperl): Try to use the general inlining infrastructure for |
| @@ -3056,7 +3067,8 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| void generateThrowNoSuchMethod(Node diagnosticNode, |
| String methodName, |
| {Link<Node> argumentNodes, |
| - List<HInstruction> argumentValues}) { |
| + List<HInstruction> argumentValues, |
| + List<String> existingArguments}) { |
| Element helper = |
| compiler.findHelper(const SourceString('throwNoSuchMethod')); |
| Constant receiverConstant = |
| @@ -3076,7 +3088,41 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| } |
| HInstruction arguments = new HLiteralList(argumentValues); |
| add(arguments); |
| - pushInvokeHelper3(helper, receiver, name, arguments); |
| + if (existingArguments != null) { |
| + List<HInstruction> existingNames = <HInstruction>[]; |
| + for (String name in existingArguments) { |
| + HInstruction nameConstant = |
| + graph.addConstantString(new DartString.literal(name), |
| + diagnosticNode, constantSystem); |
| + existingNames.add(nameConstant); |
| + } |
| + HInstruction existingNamesList = new HLiteralList(existingNames); |
| + add(existingNamesList); |
| + pushInvokeHelper4(helper, receiver, name, arguments, existingNamesList); |
| + } else { |
| + pushInvokeHelper3(helper, receiver, name, arguments); |
| + } |
| + } |
| + |
| + /** |
| + * Generate code to throw a [NoSuchMethodError] exception for calling a |
| + * method with a wrong number of arguments or mismatching named optional |
| + * arguments. |
| + */ |
| + void generateWrongArgumentCountError(Node diagnosticNode, |
| + FunctionElement function, |
| + {Link<Node> argumentNodes, |
|
ahe
2012/10/25 13:34:04
Why do you need optional arguments here?
|
| + List<HInstruction> argumentValues}) { |
| + List<String> existingArguments = <String>[]; |
| + FunctionSignature signature = function.computeSignature(compiler); |
| + signature.forEachParameter((Element parameter) { |
| + existingArguments.add(parameter.name.slowToString()); |
| + }); |
| + generateThrowNoSuchMethod(diagnosticNode, |
| + function.name.slowToString(), |
| + argumentNodes: argumentNodes, |
| + argumentValues: argumentValues, |
| + existingArguments: existingArguments); |
| } |
| visitNewExpression(NewExpression node) { |