| Index: sdk/lib/_internal/compiler/implementation/inferrer/closure_tracer.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/closure_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/closure_tracer.dart
|
| index 0814f6ef906b772ec09b1f9bdea0d1164814e048..07b0c958afc4165f02c97f91770ee140bec3547b 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/inferrer/closure_tracer.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/inferrer/closure_tracer.dart
|
| @@ -4,38 +4,50 @@
|
|
|
| part of type_graph_inferrer;
|
|
|
| -class ClosureTracerVisitor extends TracerVisitor {
|
| - final FunctionElement tracedElement;
|
| +class ClosureTracerVisitor extends TracerVisitor<ApplyableTypeInformation> {
|
| + final Iterable<FunctionElement> tracedElements;
|
|
|
| - ClosureTracerVisitor(this.tracedElement, tracedType, inferrer)
|
| + ClosureTracerVisitor(this.tracedElements, tracedType, inferrer)
|
| : super(tracedType, inferrer);
|
|
|
| void run() {
|
| - tracedElement.functionSignature.forEachParameter((Element parameter) {
|
| - ElementTypeInformation info = inferrer.types.getInferredTypeOf(parameter);
|
| - info.abandonInferencing = false;
|
| + tracedElements.forEach((FunctionElement e) {
|
| + e.functionSignature.forEachParameter((Element parameter) {
|
| + ElementTypeInformation info =
|
| + inferrer.types.getInferredTypeOf(parameter);
|
| + info.abandonInferencing = info.abandonInferencing &&
|
| + !info.mightResume;
|
| + });
|
| });
|
| analyze();
|
| - tracedElement.functionSignature.forEachParameter((Element parameter) {
|
| - ElementTypeInformation info = inferrer.types.getInferredTypeOf(parameter);
|
| - if (continueAnalyzing) {
|
| - info.disableHandleSpecialCases = true;
|
| - } else {
|
| - info.giveUp(inferrer);
|
| - }
|
| + tracedElements.forEach((FunctionElement e) {
|
| + e.functionSignature.forEachParameter((Element parameter) {
|
| + ElementTypeInformation info =
|
| + inferrer.types.getInferredTypeOf(parameter);
|
| + if (continueAnalyzing) {
|
| + info.disableHandleSpecialCases = true;
|
| + } else {
|
| + info.giveUp(inferrer);
|
| + }
|
| + });
|
| });
|
| }
|
|
|
| - visitMapTypeInformation(MapTypeInformation info) {
|
| - bailout('Stored in a map');
|
| + void tagAsFunctionApplyTarget([String reason]) {
|
| + tracedType.mightBePassedToFunctionApply = true;
|
| + if (_VERBOSE) {
|
| + print("Closure $tracedType might be passed to apply: $reason");
|
| + }
|
| }
|
|
|
| void analyzeCall(CallSiteTypeInformation info) {
|
| Selector selector = info.selector;
|
| - if (!selector.signatureApplies(tracedElement, compiler)) return;
|
| - inferrer.updateParameterAssignments(
|
| - info, tracedElement, info.arguments, selector, remove: false,
|
| - addToQueue: false);
|
| + tracedElements.forEach((FunctionElement e) {
|
| + if (!selector.signatureApplies(e, compiler)) return;
|
| + inferrer.updateParameterAssignments(
|
| + info, e, info.arguments, selector, remove: false,
|
| + addToQueue: false);
|
| + });
|
| }
|
|
|
| visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
|
| @@ -64,18 +76,29 @@ class ClosureTracerVisitor extends TracerVisitor {
|
| // where `foo` is a getter.
|
| analyzeCall(info);
|
| }
|
| + if (checkIfFunctionApply(called) && info.arguments.contains(currentUser)) {
|
| + tagAsFunctionApplyTarget("static call");
|
| + }
|
| }
|
|
|
| bool checkIfCurrentUser(element) {
|
| return inferrer.types.getInferredTypeOf(element) == currentUser;
|
| }
|
|
|
| + bool checkIfFunctionApply(element) {
|
| + return compiler.functionApplyMethod == element;
|
| + }
|
| +
|
| visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
|
| super.visitDynamicCallSiteTypeInformation(info);
|
| if (info.selector.isCall()) {
|
| - if (info.arguments.contains(currentUser)
|
| - && !info.targets.every((element) => element.isFunction())) {
|
| - bailout('Passed to a closure');
|
| + if (info.arguments.contains(currentUser)) {
|
| + if (!info.targets.every((element) => element.isFunction())) {
|
| + bailout('Passed to a closure');
|
| + }
|
| + if (info.targets.any(checkIfFunctionApply)) {
|
| + tagAsFunctionApplyTarget("dynamic call");
|
| + }
|
| } else if (info.targets.any((element) => checkIfCurrentUser(element))) {
|
| analyzeCall(info);
|
| }
|
| @@ -85,11 +108,11 @@ class ClosureTracerVisitor extends TracerVisitor {
|
|
|
| class StaticTearOffClosureTracerVisitor extends ClosureTracerVisitor {
|
| StaticTearOffClosureTracerVisitor(tracedElement, tracedType, inferrer)
|
| - : super(tracedElement, tracedType, inferrer);
|
| + : super([tracedElement], tracedType, inferrer);
|
|
|
| visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
|
| super.visitStaticCallSiteTypeInformation(info);
|
| - if (info.calledElement == tracedElement
|
| + if (info.calledElement == tracedElements.first
|
| && info.selector != null
|
| && info.selector.isGetter()) {
|
| addNewEscapeInformation(info);
|
|
|