Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(886)

Unified Diff: pkg/compiler/lib/src/inferrer/ast_inferrer_engine.dart

Issue 2993713002: Move most code from AstInferrerEngine to InferrerEngineImpl (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/inferrer/inferrer_engine.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/inferrer/ast_inferrer_engine.dart
diff --git a/pkg/compiler/lib/src/inferrer/ast_inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/ast_inferrer_engine.dart
index 66e380b04d09e249bff4e6b45562a6655dfd758d..0c0e24217f0b4ec0fdea8ff548c7fb7c54729a8e 100644
--- a/pkg/compiler/lib/src/inferrer/ast_inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/ast_inferrer_engine.dart
@@ -11,18 +11,12 @@ import '../elements/elements.dart';
import '../elements/entities.dart';
import '../resolution/tree_elements.dart';
import '../tree/nodes.dart' as ast;
-import '../types/constants.dart';
import '../types/types.dart';
-import '../universe/selector.dart';
import '../util/util.dart';
import '../world.dart';
-import 'closure_tracer.dart';
-import 'debug.dart' as debug;
-import 'locals_handler.dart';
import 'builder.dart';
import 'builder_kernel.dart';
import 'inferrer_engine.dart';
-import 'type_graph_dump.dart';
import 'type_graph_nodes.dart';
import 'type_system.dart';
@@ -35,11 +29,7 @@ class AstInferrerEngine extends InferrerEngineImpl<ast.Node> {
GlobalTypeInferenceElementData<ast.Node> createElementData() =>
new AstGlobalTypeInferenceElementData();
- void runOverAllElements() {
- if (compiler.disableTypeInference) return;
- if (compiler.options.verbose) {
- compiler.progress.reset();
- }
+ void analyzeAllElements() {
sortResolvedAsts().forEach((ResolvedAst resolvedAst) {
if (compiler.shouldPrintProgress) {
reporter.log('Added $addedInGraph elements in inferencing graph.');
@@ -55,336 +45,62 @@ class AstInferrerEngine extends InferrerEngineImpl<ast.Node> {
types.withMember(member, () => analyze(member, body, null));
});
reporter.log('Added $addedInGraph elements in inferencing graph.');
+ }
- TypeGraphDump dump = debug.PRINT_GRAPH ? new TypeGraphDump(this) : null;
-
- dump?.beforeAnalysis();
- buildWorkQueue();
- refine();
-
- // Try to infer element types of lists and compute their escape information.
- types.allocatedLists.values.forEach((TypeInformation info) {
- analyzeListAndEnqueue(info);
- });
-
- // Try to infer the key and value types for maps and compute the values'
- // escape information.
- types.allocatedMaps.values.forEach((TypeInformation info) {
- analyzeMapAndEnqueue(info);
- });
-
- Set<FunctionEntity> bailedOutOn = new Set<FunctionEntity>();
-
- // Trace closures to potentially infer argument types.
- types.allocatedClosures.forEach((dynamic info) {
- void trace(
- Iterable<FunctionEntity> elements, ClosureTracerVisitor tracer) {
- tracer.run();
- if (!tracer.continueAnalyzing) {
- elements.forEach((FunctionEntity _element) {
- MethodElement element = _element;
- MethodElement implementation = element.implementation;
- closedWorldRefiner.registerMightBePassedToApply(element);
- if (debug.VERBOSE) {
- print("traced closure $element as ${true} (bail)");
- }
- implementation.functionSignature
- .forEachParameter((FormalElement _parameter) {
- ParameterElement parameter = _parameter;
- types
- .getInferredTypeOfParameter(parameter)
- .giveUp(this, clearAssignments: false);
- });
- });
- bailedOutOn.addAll(elements);
- return;
- }
- elements
- .where((e) => !bailedOutOn.contains(e))
- .forEach((FunctionEntity _element) {
- MethodElement element = _element;
- MethodElement implementation = element.implementation;
- implementation.functionSignature
- .forEachParameter((FormalElement _parameter) {
- ParameterElement parameter = _parameter;
- ParameterTypeInformation info =
- types.getInferredTypeOfParameter(parameter);
- info.maybeResume();
- workQueue.add(info);
- });
- if (tracer.tracedType.mightBePassedToFunctionApply) {
- closedWorldRefiner.registerMightBePassedToApply(element);
- }
- if (debug.VERBOSE) {
- print("traced closure $element as "
- "${closedWorldRefiner
- .getCurrentlyKnownMightBePassedToApply(element)}");
- }
- });
- }
-
- if (info is ClosureTypeInformation) {
- Iterable<FunctionEntity> elements = [info.closure];
- trace(elements, new ClosureTracerVisitor(elements, info, this));
- } else if (info is CallSiteTypeInformation) {
- if (info is StaticCallSiteTypeInformation &&
- info.selector != null &&
- info.selector.isCall) {
- // This is a constructor call to a class with a call method. So we
- // need to trace the call method here.
- MethodElement calledElement = info.calledElement;
- assert(calledElement.isGenerativeConstructor);
- ClassElement cls = calledElement.enclosingClass;
- MethodElement callMethod = cls.lookupMember(Identifiers.call);
- if (callMethod == null) {
- callMethod = cls.lookupMember(Identifiers.noSuchMethod_);
- }
- assert(callMethod != null, failedAt(cls));
- Iterable<FunctionEntity> elements = [callMethod];
- trace(elements, new 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<FunctionEntity> elements = new List<FunctionEntity>.from(
- info.callees.where((e) => e.isFunction));
- trace(elements, new ClosureTracerVisitor(elements, info, this));
- }
- } else if (info is MemberTypeInformation) {
- trace(<FunctionEntity>[info.member],
- new StaticTearOffClosureTracerVisitor(info.member, info, this));
- } else if (info is ParameterTypeInformation) {
- failedAt(
- NO_LOCATION_SPANNABLE, 'Unexpected closure allocation info $info');
- }
+ void forEachParameter(
+ covariant MethodElement method, void f(Local parameter)) {
+ MethodElement implementation = method.implementation;
+ implementation.functionSignature
+ .forEachParameter((FormalElement _parameter) {
+ ParameterElement parameter = _parameter;
+ f(parameter);
});
+ }
- dump?.beforeTracing();
-
- // Reset all nodes that use lists/maps that have been inferred, as well
- // as nodes that use elements fetched from these lists/maps. The
- // workset for a new run of the analysis will be these nodes.
- Set<TypeInformation> seenTypes = new Set<TypeInformation>();
- while (!workQueue.isEmpty) {
- TypeInformation info = workQueue.remove();
- if (seenTypes.contains(info)) continue;
- // If the node cannot be reset, we do not need to update its users either.
- if (!info.reset(this)) continue;
- seenTypes.add(info);
- workQueue.addAll(info.users);
- }
-
- workQueue.addAll(seenTypes);
- refine();
-
- if (debug.PRINT_SUMMARY) {
- types.allocatedLists.values.forEach((_info) {
- ListTypeInformation info = _info;
- print('${info.type} '
- 'for ${info.originalType.allocationNode} '
- 'at ${info.originalType.allocationElement} '
- 'after ${info.refineCount}');
- });
- types.allocatedMaps.values.forEach((_info) {
- MapTypeInformation info = _info;
- print('${info.type} '
- 'for ${info.originalType.allocationNode} '
- 'at ${info.originalType.allocationElement} '
- 'after ${info.refineCount}');
- });
- types.allocatedClosures.forEach((TypeInformation info) {
- if (info is ElementTypeInformation) {
- print('${info.getInferredSignature(types)} for '
- '${info.debugName}');
- } else if (info is ClosureTypeInformation) {
- print('${info.getInferredSignature(types)} for '
- '${info.debugName}');
- } else if (info is DynamicCallSiteTypeInformation) {
- for (MemberEntity target in info.targets) {
- if (target is FunctionEntity) {
- print(
- '${types.getInferredSignatureOfMethod(target)} for ${target}');
- } else {
- print(
- '${types.getInferredTypeOfMember(target).type} for ${target}');
- }
- }
- } else if (info is StaticCallSiteTypeInformation) {
- ClassElement cls = info.calledElement.enclosingClass;
- MethodElement callMethod = cls.lookupMember(Identifiers.call);
- print('${types.getInferredSignatureOfMethod(callMethod)} for ${cls}');
- } else {
- print('${info.type} for some unknown kind of closure');
- }
- });
- analyzedElements.forEach((MemberEntity elem) {
- TypeInformation type = types.getInferredTypeOfMember(elem);
- print('${elem} :: ${type} from ${type.assignments} ');
- });
+ FunctionEntity lookupCallMethod(covariant ClassElement cls) {
+ MethodElement callMethod = cls.lookupMember(Identifiers.call);
+ if (callMethod == null) {
+ callMethod = cls.lookupMember(Identifiers.noSuchMethod_);
}
- dump?.afterAnalysis();
-
- reporter.log('Inferred $overallRefineCount types.');
-
- processLoopInformation();
+ return callMethod;
}
- void analyze(MemberEntity element, ast.Node body, ArgumentsTypes arguments) {
- assert(!(element is MemberElement && !element.isDeclaration));
- if (analyzedElements.contains(element)) return;
- analyzedElements.add(element);
-
+ TypeInformation computeMemberTypeInformation(
+ MemberEntity member, ast.Node body) {
dynamic visitor = compiler.options.kernelGlobalInference
- ? new KernelTypeGraphBuilder(element, compiler, this)
- : new ElementGraphBuilder(element, compiler, this);
- TypeInformation type;
- reporter.withCurrentElement(element, () {
- // ignore: UNDEFINED_METHOD
- type = visitor.run();
- });
- addedInGraph++;
+ ? new KernelTypeGraphBuilder(member, compiler, this)
+ : new ElementGraphBuilder(member, compiler, this);
+ // ignore: UNDEFINED_METHOD
+ return visitor.run();
+ }
- if (element.isField) {
- FieldElement field = element;
- if (field.isFinal || field.isConst) {
- // If [element] is final and has an initializer, we record
- // the inferred type.
- if (body != null) {
- if (type is! ListTypeInformation && type is! MapTypeInformation) {
- // For non-container types, the constant handler does
- // constant folding that could give more precise results.
- ConstantExpression constant = field.constant;
- if (constant != null) {
- ConstantValue value =
- compiler.backend.constants.getConstantValue(constant);
- if (value != null) {
- if (value.isFunction) {
- FunctionConstantValue functionConstant = value;
- MethodElement function = functionConstant.element;
- type = types.allocateClosure(function);
- } else {
- // Although we might find a better type, we have to keep
- // the old type around to ensure that we get a complete view
- // of the type graph and do not drop any flow edges.
- TypeMask refinedType = computeTypeMask(closedWorld, value);
- assert(TypeMask.assertIsNormalized(refinedType, closedWorld));
- type = new NarrowTypeInformation(type, refinedType);
- types.allocatedTypes.add(type);
- }
- } else {
- assert(
- field.isInstanceMember ||
- constant.isImplicit ||
- constant.isPotential,
- failedAt(
- field,
- "Constant expression without value: "
- "${constant.toStructuredText()}."));
- }
- }
- }
- recordTypeOfField(field, type);
- } else if (!element.isInstanceMember) {
- recordTypeOfField(field, types.nullType);
- }
- } else if (body == null) {
- // Only update types of static fields if there is no
- // assignment. Instance fields are dealt with in the constructor.
- if (element.isStatic || element.isTopLevel) {
- recordTypeOfField(field, type);
- }
- } else {
- recordTypeOfField(field, type);
- }
- if ((element.isStatic || element.isTopLevel) &&
- body != null &&
- !element.isConst) {
- dynamic argument = body;
- // TODO(13429): We could do better here by using the
- // constant handler to figure out if it's a lazy field or not.
- if (argument.asSend() != null ||
- (argument.asNewExpression() != null && !argument.isConst)) {
- recordTypeOfField(field, types.nullType);
- }
- }
- } else {
- FunctionEntity method = element;
- recordReturnType(method, type);
- }
+ bool isFieldInitializerPotentiallyNull(
+ FieldEntity field, ast.Node initializer) {
+ dynamic argument = initializer;
+ // TODO(13429): We could do better here by using the
+ // constant handler to figure out if it's a lazy field or not.
+ return argument.asSend() != null ||
+ (argument.asNewExpression() != null && !argument.isConst);
}
- void updateParameterAssignments(TypeInformation caller, MemberEntity callee,
- ArgumentsTypes arguments, Selector selector, TypeMask mask,
- {bool remove, bool addToQueue: true}) {
- if (callee.name == Identifiers.noSuchMethod_) return;
- if (callee.isField) {
- if (selector.isSetter) {
- ElementTypeInformation info = types.getInferredTypeOfMember(callee);
- if (remove) {
- info.removeAssignment(arguments.positional[0]);
- } else {
- info.addAssignment(arguments.positional[0]);
- }
- if (addToQueue) workQueue.add(info);
- }
- } else if (callee.isGetter) {
- return;
- } else if (selector != null && selector.isGetter) {
- // We are tearing a function off and thus create a closure.
- assert(callee.isFunction);
- MethodElement method = callee;
- MemberTypeInformation info = types.getInferredTypeOfMember(method);
- if (remove) {
- info.closurizedCount--;
- } else {
- info.closurizedCount++;
- if (Elements.isStaticOrTopLevel(method)) {
- types.allocatedClosures.add(info);
- } else {
- // We add the call-site type information here so that we
- // can benefit from further refinement of the selector.
- types.allocatedClosures.add(caller);
- }
- FunctionElement function = method.implementation;
- FunctionSignature signature = function.functionSignature;
- signature.forEachParameter((FormalElement _parameter) {
- ParameterElement parameter = _parameter;
- ParameterTypeInformation info =
- types.getInferredTypeOfParameter(parameter);
- info.tagAsTearOffClosureParameter(this);
- if (addToQueue) workQueue.add(info);
- });
+ ConstantValue getFieldConstant(covariant FieldElement field) {
+ ConstantExpression constant = field.constant;
+ if (constant != null) {
+ ConstantValue value =
+ compiler.backend.constants.getConstantValue(constant);
+ if (value == null) {
+ assert(
+ field.isInstanceMember ||
+ constant.isImplicit ||
+ constant.isPotential,
+ failedAt(
+ field,
+ "Constant expression without value: "
+ "${constant.toStructuredText()}."));
}
- } else {
- MethodElement method = callee;
- FunctionElement function = method.implementation;
- FunctionSignature signature = function.functionSignature;
- int parameterIndex = 0;
- bool visitingRequiredParameter = true;
- signature.forEachParameter((FormalElement _parameter) {
- ParameterElement parameter = _parameter;
- if (signature.hasOptionalParameters &&
- parameter == signature.optionalParameters.first) {
- visitingRequiredParameter = false;
- }
- TypeInformation type = visitingRequiredParameter
- ? arguments.positional[parameterIndex]
- : signature.optionalParametersAreNamed
- ? arguments.named[parameter.name]
- : parameterIndex < arguments.positional.length
- ? arguments.positional[parameterIndex]
- : null;
- if (type == null) type = getDefaultTypeOfParameter(parameter);
- TypeInformation info = types.getInferredTypeOfParameter(parameter);
- if (remove) {
- info.removeAssignment(type);
- } else {
- info.addAssignment(type);
- }
- parameterIndex++;
- if (addToQueue) workQueue.add(info);
- });
+ return value;
}
+ return null;
}
// Sorts the resolved elements by size. We do this for this inferrer
« no previous file with comments | « no previous file | pkg/compiler/lib/src/inferrer/inferrer_engine.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698