Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/codegen.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart |
| index 70481949e4f0104278efdbdc9f56b54aedd80600..5caaf1c2c17e130f2f447bfc09c5a51627dd9de1 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart |
| @@ -471,12 +471,28 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| /** |
| * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET]. |
| + * Also, skip all trailing constant `null` arguments. JavaScript will fill |
| + * missing arguments with `undefined` anyway. For functions that rely on |
| + * 'arguments.lenght' in JavaScript, [allArgsRequired] should be set to |
|
sra1
2014/10/24 23:31:59
`arguments.length`
herhut
2014/11/06 13:14:43
Done.
|
| + * `true`. |
| */ |
| List<js.Expression> visitArguments(List<HInstruction> inputs, |
| - {int start: HInvoke.ARGUMENTS_OFFSET}) { |
| + {int start: HInvoke.ARGUMENTS_OFFSET, |
| + bool allArgsRequired: false}) { |
| assert(inputs.length >= start); |
| - List<js.Expression> result = new List<js.Expression>(inputs.length - start); |
| - for (int i = start; i < inputs.length; i++) { |
| + int max; |
| + if (allArgsRequired) { |
| + max = inputs.length; |
| + } else { |
| + for (max = inputs.length; max > start; --max) { |
| + HInstruction input = inputs[max-1]; |
| + if (input is! HConstant) break; |
| + HConstant constant = input; |
| + if (!constant.constant.isNull) break; |
| + } |
| + } |
| + List<js.Expression> result = new List<js.Expression>(max - start); |
| + for (int i = start; i < max; i++) { |
| use(inputs[i]); |
| result[i - start] = pop(); |
| } |
| @@ -1513,12 +1529,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| js.Expression object = pop(); |
| String name = node.selector.name; |
| String methodName; |
| - List<js.Expression> arguments = visitArguments(node.inputs); |
| + bool allArgsRequired = false; |
| Element target = node.element; |
| if (target != null && !node.isInterceptedCall) { |
| if (target == backend.jsArrayAdd) { |
| methodName = 'push'; |
| + allArgsRequired = true; |
| } else if (target == backend.jsArrayRemoveLast) { |
| methodName = 'pop'; |
| } else if (target == backend.jsStringSplit) { |
| @@ -1534,6 +1551,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| methodName = target.fixedBackendName; |
| } |
| } |
| + // TODO(herhut): Add proper calling conventions to encode when arguments |
| + // may be dropped. |
| + List<js.Expression> arguments = visitArguments(node.inputs, |
| + allArgsRequired: allArgsRequired); |
| if (methodName == null) { |
| methodName = backend.namer.invocationName(node.selector); |