diff --git a/pkg/compiler/lib/src/inferrer/closure_tracer.dart b/pkg/compiler/lib/src/inferrer/closure_tracer.dart index 1d49aa7c7d7..bd5372d5044 100644 --- a/pkg/compiler/lib/src/inferrer/closure_tracer.dart +++ b/pkg/compiler/lib/src/inferrer/closure_tracer.dart @@ -107,9 +107,6 @@ class ClosureTracerVisitor extends TracerVisitor { } } - bool _checkIfCurrentUser(MemberEntity element) => - inferrer.types.getInferredTypeOfMember(element) == currentUser; - bool _checkIfFunctionApply(MemberEntity element) { return inferrer.closedWorld.commonElements.isFunctionApplyMethod(element); } @@ -118,8 +115,9 @@ class ClosureTracerVisitor extends TracerVisitor { visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) { super.visitDynamicCallSiteTypeInformation(info); final selector = info.selector!; + final user = currentUser; if (selector.isCall) { - if (info.arguments!.contains(currentUser)) { + if (info.arguments!.contains(user)) { if (info.hasClosureCallTargets || info.concreteTargets.any((element) => !element.isFunction)) { bailout('Passed to a closure'); @@ -127,8 +125,13 @@ class ClosureTracerVisitor extends TracerVisitor { if (info.concreteTargets.any(_checkIfFunctionApply)) { _tagAsFunctionApplyTarget("dynamic call"); } - } else if (info.concreteTargets.any(_checkIfCurrentUser)) { - _registerCallForLaterAnalysis(info); + } else { + if (user is MemberTypeInformation) { + final currentUserMember = user.member; + if (info.concreteTargets.contains(currentUserMember)) { + _registerCallForLaterAnalysis(info); + } + } } } else if (selector.isGetter && selector.memberName == Names.call) { // We are potentially tearing off ourself here diff --git a/pkg/compiler/lib/src/inferrer/engine.dart b/pkg/compiler/lib/src/inferrer/engine.dart index edb2c8b12ba..c65b4cd848d 100644 --- a/pkg/compiler/lib/src/inferrer/engine.dart +++ b/pkg/compiler/lib/src/inferrer/engine.dart @@ -316,95 +316,98 @@ class InferrerEngine { _buildWorkQueue(); metrics.refine1.measure(_refine); - // Try to infer element types of lists and compute their escape information. - types.allocatedLists.values.forEach((ListTypeInformation info) { - analyzeListAndEnqueue(info); - }); + metrics.trace.measure(() { + // Try to infer element types of lists and compute their escape information. + types.allocatedLists.values.forEach((ListTypeInformation info) { + analyzeListAndEnqueue(info); + }); - // Try to infer element types of sets and compute their escape information. - types.allocatedSets.values.forEach((SetTypeInformation info) { - analyzeSetAndEnqueue(info); - }); + // Try to infer element types of sets and compute their escape information. + types.allocatedSets.values.forEach((SetTypeInformation info) { + analyzeSetAndEnqueue(info); + }); - // Try to infer the key and value types for maps and compute the values' - // escape information. - types.allocatedMaps.values.forEach((MapTypeInformation info) { - analyzeMapAndEnqueue(info); - }); + // Try to infer the key and value types for maps and compute the values' + // escape information. + types.allocatedMaps.values.forEach((MapTypeInformation info) { + analyzeMapAndEnqueue(info); + }); - Set bailedOutOn = Set(); + Set bailedOutOn = Set(); - // Trace closures to potentially infer argument types. - types.allocatedClosures.forEach((dynamic info) { - void trace( - Iterable elements, ClosureTracerVisitor tracer) { - tracer.run(); - if (!tracer.continueAnalyzing) { - elements.forEach((FunctionEntity element) { - inferredDataBuilder.registerMightBePassedToApply(element); - if (debug.VERBOSE) { - print("traced closure $element as ${true} (bail)"); - } - types.strategy.forEachParameter(element, (Local parameter) { - types - .getInferredTypeOfParameter(parameter) - .giveUp(this, clearInputs: false); + // Trace closures to potentially infer argument types. + types.allocatedClosures.forEach((dynamic info) { + void trace( + Iterable elements, ClosureTracerVisitor tracer) { + tracer.run(); + if (!tracer.continueAnalyzing) { + elements.forEach((FunctionEntity element) { + inferredDataBuilder.registerMightBePassedToApply(element); + if (debug.VERBOSE) { + print("traced closure $element as ${true} (bail)"); + } + types.strategy.forEachParameter(element, (Local parameter) { + types + .getInferredTypeOfParameter(parameter) + .giveUp(this, clearInputs: false); + }); }); + bailedOutOn.addAll(elements); + return; + } + elements + .where((e) => !bailedOutOn.contains(e)) + .forEach((FunctionEntity element) { + types.strategy.forEachParameter(element, (Local parameter) { + ParameterTypeInformation info = + types.getInferredTypeOfParameter(parameter); + info.maybeResume(); + _workQueue.add(info); + }); + if (tracer.tracedType.mightBePassedToFunctionApply) { + inferredDataBuilder.registerMightBePassedToApply(element); + } + if (debug.VERBOSE) { + print("traced closure $element as " + "${inferredDataBuilder.getCurrentlyKnownMightBePassedToApply(element)}"); + } }); - bailedOutOn.addAll(elements); - return; } - elements - .where((e) => !bailedOutOn.contains(e)) - .forEach((FunctionEntity element) { - types.strategy.forEachParameter(element, (Local parameter) { - ParameterTypeInformation info = - types.getInferredTypeOfParameter(parameter); - info.maybeResume(); - _workQueue.add(info); - }); - if (tracer.tracedType.mightBePassedToFunctionApply) { - inferredDataBuilder.registerMightBePassedToApply(element); - } - if (debug.VERBOSE) { - print("traced closure $element as " - "${inferredDataBuilder.getCurrentlyKnownMightBePassedToApply(element)}"); - } - }); - } - if (info is ClosureTypeInformation) { - Iterable elements = [info.closure]; - trace(elements, ClosureTracerVisitor(elements, info, this)); - } else if (info is CallSiteTypeInformation) { - final selector = info.selector; - if (info is StaticCallSiteTypeInformation && - selector != null && - selector.isCall) { - // This is a constructor call to a class with a call method. So we - // need to trace the call method here. - final calledElement = info.calledElement; - assert(calledElement is ConstructorEntity && - calledElement.isGenerativeConstructor); - final cls = calledElement.enclosingClass!; - final callMethod = _lookupCallMethod(cls)!; - Iterable elements = [callMethod]; - trace(elements, ClosureTracerVisitor(elements, info, this)); - } else { - // We only are interested in functions here, as other targets - // of this closure call are not a root to trace but an intermediate - // for some other function. - Iterable elements = List.from( - info.callees.where((e) => e.isFunction)); + if (info is ClosureTypeInformation) { + Iterable elements = [info.closure]; trace(elements, ClosureTracerVisitor(elements, info, this)); + } else if (info is CallSiteTypeInformation) { + final selector = info.selector; + if (info is StaticCallSiteTypeInformation && + selector != null && + selector.isCall) { + // This is a constructor call to a class with a call method. So we + // need to trace the call method here. + final calledElement = info.calledElement; + assert(calledElement is ConstructorEntity && + calledElement.isGenerativeConstructor); + final cls = calledElement.enclosingClass!; + final callMethod = _lookupCallMethod(cls)!; + Iterable elements = [callMethod]; + trace(elements, ClosureTracerVisitor(elements, info, this)); + } else { + // We only are interested in functions here, as other targets + // of this closure call are not a root to trace but an intermediate + // for some other function. + Iterable elements = List.from( + info.callees.where((e) => e.isFunction)); + trace(elements, ClosureTracerVisitor(elements, info, this)); + } + } else if (info is MemberTypeInformation) { + final member = info.member as FunctionEntity; + trace( + [member], StaticTearOffClosureTracerVisitor(member, info, this)); + } else if (info is ParameterTypeInformation) { + failedAt(NO_LOCATION_SPANNABLE, + 'Unexpected closure allocation info $info'); } - } else if (info is MemberTypeInformation) { - final member = info.member as FunctionEntity; - trace([member], StaticTearOffClosureTracerVisitor(member, info, this)); - } else if (info is ParameterTypeInformation) { - failedAt( - NO_LOCATION_SPANNABLE, 'Unexpected closure allocation info $info'); - } + }); }); dump?.beforeTracing(); @@ -1137,6 +1140,7 @@ class _InferrerEngineMetrics extends MetricsBase { final time = DurationMetric('time'); final analyze = DurationMetric('time.analyze'); final refine1 = DurationMetric('time.refine1'); + final trace = DurationMetric('time.trace'); final refine2 = DurationMetric('time.refine2'); final elementsInGraph = CountMetric('count.elementsInGraph'); final allTypesCount = CountMetric('count.allTypes'); @@ -1148,6 +1152,7 @@ class _InferrerEngineMetrics extends MetricsBase { secondary = [ analyze, refine1, + trace, refine2, elementsInGraph, allTypesCount, diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart index dd58180a5bb..a3182cdd4ba 100644 --- a/pkg/compiler/lib/src/inferrer/node_tracer.dart +++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart @@ -473,12 +473,11 @@ abstract class TracerVisitor implements TypeInformationVisitor { bailout('Passed to noSuchMethod'); } - Iterable inferredTargetTypes = - info.concreteTargets.map((MemberEntity entity) { - return inferrer.types.getInferredTypeOfMember(entity); - }); - if (inferredTargetTypes.any((user) => user == currentUser)) { - addNewEscapeInformation(info); + final user = currentUser; + if (user is MemberTypeInformation) { + if (info.concreteTargets.contains(user.member)) { + addNewEscapeInformation(info); + } } } diff --git a/pkg/compiler/lib/src/inferrer_experimental/closure_tracer.dart b/pkg/compiler/lib/src/inferrer_experimental/closure_tracer.dart index 1d49aa7c7d7..bd5372d5044 100644 --- a/pkg/compiler/lib/src/inferrer_experimental/closure_tracer.dart +++ b/pkg/compiler/lib/src/inferrer_experimental/closure_tracer.dart @@ -107,9 +107,6 @@ class ClosureTracerVisitor extends TracerVisitor { } } - bool _checkIfCurrentUser(MemberEntity element) => - inferrer.types.getInferredTypeOfMember(element) == currentUser; - bool _checkIfFunctionApply(MemberEntity element) { return inferrer.closedWorld.commonElements.isFunctionApplyMethod(element); } @@ -118,8 +115,9 @@ class ClosureTracerVisitor extends TracerVisitor { visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) { super.visitDynamicCallSiteTypeInformation(info); final selector = info.selector!; + final user = currentUser; if (selector.isCall) { - if (info.arguments!.contains(currentUser)) { + if (info.arguments!.contains(user)) { if (info.hasClosureCallTargets || info.concreteTargets.any((element) => !element.isFunction)) { bailout('Passed to a closure'); @@ -127,8 +125,13 @@ class ClosureTracerVisitor extends TracerVisitor { if (info.concreteTargets.any(_checkIfFunctionApply)) { _tagAsFunctionApplyTarget("dynamic call"); } - } else if (info.concreteTargets.any(_checkIfCurrentUser)) { - _registerCallForLaterAnalysis(info); + } else { + if (user is MemberTypeInformation) { + final currentUserMember = user.member; + if (info.concreteTargets.contains(currentUserMember)) { + _registerCallForLaterAnalysis(info); + } + } } } else if (selector.isGetter && selector.memberName == Names.call) { // We are potentially tearing off ourself here diff --git a/pkg/compiler/lib/src/inferrer_experimental/engine.dart b/pkg/compiler/lib/src/inferrer_experimental/engine.dart index 1b159893daa..94625da3bb1 100644 --- a/pkg/compiler/lib/src/inferrer_experimental/engine.dart +++ b/pkg/compiler/lib/src/inferrer_experimental/engine.dart @@ -316,95 +316,98 @@ class InferrerEngine { _buildWorkQueue(); metrics.refine1.measure(_refine); - // Try to infer element types of lists and compute their escape information. - types.allocatedLists.values.forEach((ListTypeInformation info) { - analyzeListAndEnqueue(info); - }); + metrics.trace.measure(() { + // Try to infer element types of lists and compute their escape information. + types.allocatedLists.values.forEach((ListTypeInformation info) { + analyzeListAndEnqueue(info); + }); - // Try to infer element types of sets and compute their escape information. - types.allocatedSets.values.forEach((SetTypeInformation info) { - analyzeSetAndEnqueue(info); - }); + // Try to infer element types of sets and compute their escape information. + types.allocatedSets.values.forEach((SetTypeInformation info) { + analyzeSetAndEnqueue(info); + }); - // Try to infer the key and value types for maps and compute the values' - // escape information. - types.allocatedMaps.values.forEach((MapTypeInformation info) { - analyzeMapAndEnqueue(info); - }); + // Try to infer the key and value types for maps and compute the values' + // escape information. + types.allocatedMaps.values.forEach((MapTypeInformation info) { + analyzeMapAndEnqueue(info); + }); - Set bailedOutOn = Set(); + Set bailedOutOn = Set(); - // Trace closures to potentially infer argument types. - types.allocatedClosures.forEach((dynamic info) { - void trace( - Iterable elements, ClosureTracerVisitor tracer) { - tracer.run(); - if (!tracer.continueAnalyzing) { - elements.forEach((FunctionEntity element) { - inferredDataBuilder.registerMightBePassedToApply(element); - if (debug.VERBOSE) { - print("traced closure $element as ${true} (bail)"); - } - types.strategy.forEachParameter(element, (Local parameter) { - types - .getInferredTypeOfParameter(parameter) - .giveUp(this, clearInputs: false); + // Trace closures to potentially infer argument types. + types.allocatedClosures.forEach((dynamic info) { + void trace( + Iterable elements, ClosureTracerVisitor tracer) { + tracer.run(); + if (!tracer.continueAnalyzing) { + elements.forEach((FunctionEntity element) { + inferredDataBuilder.registerMightBePassedToApply(element); + if (debug.VERBOSE) { + print("traced closure $element as ${true} (bail)"); + } + types.strategy.forEachParameter(element, (Local parameter) { + types + .getInferredTypeOfParameter(parameter) + .giveUp(this, clearInputs: false); + }); }); + bailedOutOn.addAll(elements); + return; + } + elements + .where((e) => !bailedOutOn.contains(e)) + .forEach((FunctionEntity element) { + types.strategy.forEachParameter(element, (Local parameter) { + ParameterTypeInformation info = + types.getInferredTypeOfParameter(parameter); + info.maybeResume(); + _workQueue.add(info); + }); + if (tracer.tracedType.mightBePassedToFunctionApply) { + inferredDataBuilder.registerMightBePassedToApply(element); + } + if (debug.VERBOSE) { + print("traced closure $element as " + "${inferredDataBuilder.getCurrentlyKnownMightBePassedToApply(element)}"); + } }); - bailedOutOn.addAll(elements); - return; } - elements - .where((e) => !bailedOutOn.contains(e)) - .forEach((FunctionEntity element) { - types.strategy.forEachParameter(element, (Local parameter) { - ParameterTypeInformation info = - types.getInferredTypeOfParameter(parameter); - info.maybeResume(); - _workQueue.add(info); - }); - if (tracer.tracedType.mightBePassedToFunctionApply) { - inferredDataBuilder.registerMightBePassedToApply(element); - } - if (debug.VERBOSE) { - print("traced closure $element as " - "${inferredDataBuilder.getCurrentlyKnownMightBePassedToApply(element)}"); - } - }); - } - if (info is ClosureTypeInformation) { - Iterable elements = [info.closure]; - trace(elements, ClosureTracerVisitor(elements, info, this)); - } else if (info is CallSiteTypeInformation) { - final selector = info.selector; - if (info is StaticCallSiteTypeInformation && - selector != null && - selector.isCall) { - // This is a constructor call to a class with a call method. So we - // need to trace the call method here. - final calledElement = info.calledElement; - assert(calledElement is ConstructorEntity && - calledElement.isGenerativeConstructor); - final cls = calledElement.enclosingClass!; - final callMethod = _lookupCallMethod(cls)!; - Iterable elements = [callMethod]; - trace(elements, ClosureTracerVisitor(elements, info, this)); - } else { - // We only are interested in functions here, as other targets - // of this closure call are not a root to trace but an intermediate - // for some other function. - Iterable elements = List.from( - info.callees.where((e) => e.isFunction)); + if (info is ClosureTypeInformation) { + Iterable elements = [info.closure]; trace(elements, ClosureTracerVisitor(elements, info, this)); + } else if (info is CallSiteTypeInformation) { + final selector = info.selector; + if (info is StaticCallSiteTypeInformation && + selector != null && + selector.isCall) { + // This is a constructor call to a class with a call method. So we + // need to trace the call method here. + final calledElement = info.calledElement; + assert(calledElement is ConstructorEntity && + calledElement.isGenerativeConstructor); + final cls = calledElement.enclosingClass!; + final callMethod = _lookupCallMethod(cls)!; + Iterable elements = [callMethod]; + trace(elements, ClosureTracerVisitor(elements, info, this)); + } else { + // We only are interested in functions here, as other targets + // of this closure call are not a root to trace but an intermediate + // for some other function. + Iterable elements = List.from( + info.callees.where((e) => e.isFunction)); + trace(elements, ClosureTracerVisitor(elements, info, this)); + } + } else if (info is MemberTypeInformation) { + final member = info.member as FunctionEntity; + trace( + [member], StaticTearOffClosureTracerVisitor(member, info, this)); + } else if (info is ParameterTypeInformation) { + failedAt(NO_LOCATION_SPANNABLE, + 'Unexpected closure allocation info $info'); } - } else if (info is MemberTypeInformation) { - final member = info.member as FunctionEntity; - trace([member], StaticTearOffClosureTracerVisitor(member, info, this)); - } else if (info is ParameterTypeInformation) { - failedAt( - NO_LOCATION_SPANNABLE, 'Unexpected closure allocation info $info'); - } + }); }); dump?.beforeTracing(); @@ -1137,6 +1140,7 @@ class _InferrerEngineMetrics extends MetricsBase { final time = DurationMetric('time'); final analyze = DurationMetric('time.analyze'); final refine1 = DurationMetric('time.refine1'); + final trace = DurationMetric('time.trace'); final refine2 = DurationMetric('time.refine2'); final elementsInGraph = CountMetric('count.elementsInGraph'); final allTypesCount = CountMetric('count.allTypes'); @@ -1148,6 +1152,7 @@ class _InferrerEngineMetrics extends MetricsBase { secondary = [ analyze, refine1, + trace, refine2, elementsInGraph, allTypesCount, diff --git a/pkg/compiler/lib/src/inferrer_experimental/node_tracer.dart b/pkg/compiler/lib/src/inferrer_experimental/node_tracer.dart index e8a474f36c7..69c1b89983e 100644 --- a/pkg/compiler/lib/src/inferrer_experimental/node_tracer.dart +++ b/pkg/compiler/lib/src/inferrer_experimental/node_tracer.dart @@ -473,12 +473,11 @@ abstract class TracerVisitor implements TypeInformationVisitor { bailout('Passed to noSuchMethod'); } - Iterable inferredTargetTypes = - info.concreteTargets.map((MemberEntity entity) { - return inferrer.types.getInferredTypeOfMember(entity); - }); - if (inferredTargetTypes.any((user) => user == currentUser)) { - addNewEscapeInformation(info); + final user = currentUser; + if (user is MemberTypeInformation) { + if (info.concreteTargets.contains(user.member)) { + addNewEscapeInformation(info); + } } }