| Index: pkg/compiler/lib/src/cps_ir/inline.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/inline.dart b/pkg/compiler/lib/src/cps_ir/inline.dart
|
| index b341869dba88569b615ccb131d6c0427b426ff6f..08375a2468d6e1fbf3055306a47bbcbe1b24660b 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/inline.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/inline.dart
|
| @@ -222,14 +222,12 @@ class Inliner implements Pass {
|
| class SizeVisitor extends TrampolineRecursiveVisitor {
|
| int size = 0;
|
|
|
| - void countArgument(Reference<Primitive> argument, Parameter parameter) {
|
| + void countArgument(Primitive argument, Parameter parameter) {
|
| // If a parameter is unused and the corresponding argument has only the
|
| // one use at the invocation, then inlining the call might enable
|
| // elimination of the argument. This 'pays for itself' by decreasing the
|
| // cost of inlining at the call site.
|
| - if (argument != null &&
|
| - argument.definition.hasExactlyOneUse &&
|
| - parameter.hasNoUses) {
|
| + if (argument != null && argument.hasExactlyOneUse && parameter.hasNoUses) {
|
| --size;
|
| }
|
| }
|
| @@ -237,9 +235,15 @@ class SizeVisitor extends TrampolineRecursiveVisitor {
|
| static int sizeOf(InvocationPrimitive invoke, FunctionDefinition function) {
|
| SizeVisitor visitor = new SizeVisitor();
|
| visitor.visit(function);
|
| - visitor.countArgument(invoke.receiverRef, function.thisParameter);
|
| + if (invoke.callingConvention == CallingConvention.Intercepted) {
|
| + // Note that if the invocation is a dummy-intercepted call, then the
|
| + // target has an unused interceptor parameter, but the caller provides
|
| + // no interceptor argument.
|
| + visitor.countArgument(invoke.interceptor, function.interceptorParameter);
|
| + }
|
| + visitor.countArgument(invoke.receiver, function.receiverParameter);
|
| for (int i = 0; i < invoke.argumentRefs.length; ++i) {
|
| - visitor.countArgument(invoke.argumentRefs[i], function.parameters[i]);
|
| + visitor.countArgument(invoke.argument(i), function.parameters[i]);
|
| }
|
| return visitor.size;
|
| }
|
| @@ -285,7 +289,6 @@ class JsSizeVisitor extends js.BaseVisitor {
|
| }
|
| }
|
|
|
| -
|
| class InliningVisitor extends TrampolineRecursiveVisitor {
|
| final Inliner _inliner;
|
|
|
| @@ -328,8 +331,8 @@ class InliningVisitor extends TrampolineRecursiveVisitor {
|
| return next;
|
| }
|
|
|
| - TypeMask abstractType(Reference<Primitive> ref) {
|
| - return ref.definition.type ?? typeSystem.dynamicType;
|
| + TypeMask abstractType(Primitive def) {
|
| + return def.type ?? typeSystem.dynamicType;
|
| }
|
|
|
| /// Build the IR term for the function that adapts a call site targeting a
|
| @@ -337,6 +340,9 @@ class InliningVisitor extends TrampolineRecursiveVisitor {
|
| FunctionDefinition buildAdapter(InvokeMethod node, FunctionElement target) {
|
| Parameter thisParameter = new Parameter(new ThisParameterLocal(target))
|
| ..type = node.receiver.type;
|
| + Parameter interceptorParameter = node.interceptorRef != null
|
| + ? new Parameter(null)
|
| + : null;
|
| List<Parameter> parameters = new List<Parameter>.generate(
|
| node.argumentRefs.length,
|
| (int index) {
|
| @@ -349,10 +355,6 @@ class InliningVisitor extends TrampolineRecursiveVisitor {
|
|
|
| FunctionSignature signature = target.functionSignature;
|
| int requiredParameterCount = signature.requiredParameterCount;
|
| - if (node.callingConvention == CallingConvention.Intercepted ||
|
| - node.callingConvention == CallingConvention.DummyIntercepted) {
|
| - ++requiredParameterCount;
|
| - }
|
| List<Primitive> arguments = new List<Primitive>.generate(
|
| requiredParameterCount,
|
| (int index) => parameters[index]);
|
| @@ -396,14 +398,19 @@ class InliningVisitor extends TrampolineRecursiveVisitor {
|
| Selector newSelector =
|
| new Selector(node.selector.kind, node.selector.memberName,
|
| newCallStructure);
|
| - Primitive result = cps.invokeMethod(thisParameter, newSelector, node.mask,
|
| - arguments, node.callingConvention);
|
| + Primitive result = cps.invokeMethod(thisParameter,
|
| + newSelector,
|
| + node.mask,
|
| + arguments,
|
| + interceptor: interceptorParameter,
|
| + callingConvention: node.callingConvention);
|
| result.type = typeSystem.getInvokeReturnType(node.selector, node.mask);
|
| returnContinuation.parameters.single.type = result.type;
|
| cps.invokeContinuation(returnContinuation, <Primitive>[result]);
|
| return new FunctionDefinition(target, thisParameter, parameters,
|
| returnContinuation,
|
| - cps.root);
|
| + cps.root,
|
| + interceptorParameter: interceptorParameter);
|
| }
|
|
|
| // Given an invocation and a known target, possibly perform inlining.
|
| @@ -444,9 +451,9 @@ class InliningVisitor extends TrampolineRecursiveVisitor {
|
| return null;
|
| }
|
|
|
| - Reference<Primitive> dartReceiver = invoke.dartReceiverRef;
|
| + Primitive receiver = invoke.receiver;
|
| TypeMask abstractReceiver =
|
| - dartReceiver == null ? null : abstractType(dartReceiver);
|
| + receiver == null ? null : abstractType(receiver);
|
| // The receiver is non-null in a method body, unless the receiver is known
|
| // to be `null` (isEmpty covers `null` and unreachable).
|
| TypeMask abstractReceiverInMethod = abstractReceiver == null
|
| @@ -455,7 +462,7 @@ class InliningVisitor extends TrampolineRecursiveVisitor {
|
| ? abstractReceiver
|
| : abstractReceiver.nonNullable();
|
| List<TypeMask> abstractArguments =
|
| - invoke.argumentRefs.map(abstractType).toList();
|
| + invoke.arguments.map(abstractType).toList();
|
| var cachedResult = _inliner.cache.get(target, callStructure,
|
| abstractReceiverInMethod,
|
| abstractArguments);
|
| @@ -469,17 +476,12 @@ class InliningVisitor extends TrampolineRecursiveVisitor {
|
| List<Primitive> arguments = invoke.arguments.toList();
|
| // Add a null check to the inlined function body if necessary. The
|
| // cached function body does not contain the null check.
|
| - if (dartReceiver != null && abstractReceiver.isNullable) {
|
| - Primitive check = nullReceiverGuard(
|
| - invoke, _fragment, dartReceiver.definition, abstractReceiver);
|
| - if (invoke.callingConvention == CallingConvention.Intercepted) {
|
| - arguments[0] = check;
|
| - } else {
|
| - receiver = check;
|
| - }
|
| + if (receiver != null && abstractReceiver.isNullable) {
|
| + receiver = nullReceiverGuard(
|
| + invoke, _fragment, receiver, abstractReceiver);
|
| }
|
| return _fragment.inlineFunction(function, receiver, arguments,
|
| - hint: invoke.hint);
|
| + interceptor: invoke.interceptor, hint: invoke.hint);
|
| }
|
|
|
| // Positive inlining result in the cache.
|
| @@ -513,22 +515,11 @@ class InliningVisitor extends TrampolineRecursiveVisitor {
|
| }
|
| } else {
|
| function = compileToCpsIr(target);
|
| - void setValue(Variable variable, Reference<Primitive> value) {
|
| - variable.type = value.definition.type;
|
| + if (function.receiverParameter != null) {
|
| + function.receiverParameter.type = abstractReceiverInMethod;
|
| }
|
| - if (invoke.callingConvention == CallingConvention.Intercepted) {
|
| - setValue(function.thisParameter, invoke.receiverRef);
|
| - function.parameters[0].type = abstractReceiverInMethod;
|
| - for (int i = 1; i < invoke.argumentRefs.length; ++i) {
|
| - setValue(function.parameters[i], invoke.argumentRefs[i]);
|
| - }
|
| - } else {
|
| - if (invoke.receiverRef != null) {
|
| - function.thisParameter.type = abstractReceiverInMethod;
|
| - }
|
| - for (int i = 0; i < invoke.argumentRefs.length; ++i) {
|
| - setValue(function.parameters[i], invoke.argumentRefs[i]);
|
| - }
|
| + for (int i = 0; i < invoke.argumentRefs.length; ++i) {
|
| + function.parameters[i].type = invoke.argument(i).type;
|
| }
|
| optimizeBeforeInlining(function);
|
| }
|
| @@ -582,7 +573,7 @@ class InliningVisitor extends TrampolineRecursiveVisitor {
|
|
|
| @override
|
| Primitive visitInvokeMethod(InvokeMethod node) {
|
| - Primitive receiver = node.dartReceiver;
|
| + Primitive receiver = node.receiver;
|
| Element element = world.locateSingleElement(node.selector, receiver.type);
|
| if (element == null || element is! FunctionElement) return null;
|
| if (node.selector.isGetter != element.isGetter) return null;
|
|
|