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

Unified Diff: sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart

Issue 111803002: Implement tracing for function expressions and statements, and infer types of parameters of these c… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years 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
Index: sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
===================================================================
--- sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart (revision 31020)
+++ sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart (working copy)
@@ -169,12 +169,17 @@
bool _VERBOSE = false;
-class ContainerTracerVisitor implements TypeInformationVisitor {
- final ListTypeInformation container;
+abstract class TracerVisitor implements TypeInformationVisitor {
+ final TypeInformation tracedType;
final TypeGraphInferrerEngine inferrer;
final Compiler compiler;
+ static const int MAX_ANALYSIS_COUNT = 16;
+ final Setlet<Element> analyzedElements = new Setlet<Element>();
+ TracerVisitor(this.tracedType, inferrer)
+ : this.inferrer = inferrer, this.compiler = inferrer.compiler;
+
// Work list that gets populated with [TypeInformation] that could
// contain the container.
final List<TypeInformation> workList = <TypeInformation>[];
@@ -186,31 +191,22 @@
final List<ListTypeInformation> containersToAnalyze =
<ListTypeInformation>[];
+ final Setlet<TypeInformation> flowsInto = new Setlet<TypeInformation>();
+
// The current [TypeInformation] in the analysis.
TypeInformation currentUser;
-
- // The list of found assignments to the container.
- final List<TypeInformation> assignments = <TypeInformation>[];
-
- bool callsGrowableMethod = false;
bool continueAnalyzing = true;
-
- static const int MAX_ANALYSIS_COUNT = 16;
- final Setlet<Element> analyzedElements = new Setlet<Element>();
- ContainerTracerVisitor(this.container, inferrer)
- : this.inferrer = inferrer, this.compiler = inferrer.compiler;
-
void addNewEscapeInformation(TypeInformation info) {
- if (container.flowsInto.contains(info)) return;
- container.flowsInto.add(info);
+ if (flowsInto.contains(info)) return;
+ flowsInto.add(info);
workList.add(info);
}
- List<TypeInformation> run() {
+ void analyze() {
// Collect the [TypeInformation] where the container can flow in,
// as well as the operations done on all these [TypeInformation]s.
- addNewEscapeInformation(container);
+ addNewEscapeInformation(tracedType);
while (!workList.isEmpty) {
currentUser = workList.removeLast();
currentUser.users.forEach((TypeInformation info) {
@@ -226,35 +222,24 @@
break;
}
}
-
- if (continueAnalyzing) {
- if (!callsGrowableMethod && container.inferredLength == null) {
- container.inferredLength = container.originalLength;
- }
- return assignments;
- }
- return null;
}
void bailout(String reason) {
if (_VERBOSE) {
- ContainerTypeMask mask = container.type;
- print('Bailing out on ${mask.allocationNode} ${mask.allocationElement} '
- 'because: $reason');
+ print('Bailing out on $tracedType because: $reason');
}
continueAnalyzing = false;
- callsGrowableMethod = true;
}
- visitNarrowTypeInformation(NarrowTypeInformation info) {
+ void visitNarrowTypeInformation(NarrowTypeInformation info) {
addNewEscapeInformation(info);
}
- visitPhiElementTypeInformation(PhiElementTypeInformation info) {
+ void visitPhiElementTypeInformation(PhiElementTypeInformation info) {
addNewEscapeInformation(info);
}
- visitElementInContainerTypeInformation(
+ void visitElementInContainerTypeInformation(
ElementInContainerTypeInformation info) {
addNewEscapeInformation(info);
}
@@ -263,21 +248,12 @@
containersToAnalyze.add(info);
}
- visitMapTypeInformation(MapTypeInformation info) {
- bailout('Stored in a map');
- }
+ void visitConcreteTypeInformation(ConcreteTypeInformation info) {}
- visitConcreteTypeInformation(ConcreteTypeInformation info) {}
+ void visitClosureTypeInformation(ConcreteTypeInformation info) {}
- visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
- bailout('Passed to a closure');
- }
-
visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
Element called = info.calledElement;
- if (called.isForeign(compiler) && called.name == 'JS') {
- bailout('Used in JS ${info.call}');
- }
if (inferrer.types.getInferredTypeOf(called) == currentUser) {
addNewEscapeInformation(info);
}
@@ -303,6 +279,7 @@
}
bool isAddedToContainer(DynamicCallSiteTypeInformation info) {
+ if (info.arguments == null) return false;
var receiverType = info.receiver.type;
if (!receiverType.isContainer) return false;
String selectorName = info.selector.name;
@@ -312,6 +289,88 @@
|| (selectorName == 'add' && currentUser == arguments[0]);
}
+ void visitDynamicCallSiteTypeInformation(
+ DynamicCallSiteTypeInformation info) {
+ if (isAddedToContainer(info)) {
+ ContainerTypeMask mask = info.receiver.type;
+ if (mask.allocationNode != null) {
+ ListTypeInformation container =
+ inferrer.types.allocatedLists[mask.allocationNode];
+ containersToAnalyze.add(container);
+ } else {
+ // The [ContainerTypeMask] is a union of two containers, and
+ // we lose track of where these containers have been allocated
+ // at this point.
+ bailout('Stored in too many containers');
+ }
+ }
+
+ if (info.targets
kasperl 2013/12/11 07:35:35 Consider using a local variable for the result of
ngeoffray 2013/12/16 11:47:43 Done.
+ .map((element) => inferrer.types.getInferredTypeOf(element))
+ .any((other) => other == currentUser)) {
+ addNewEscapeInformation(info);
+ }
+ }
+
+ bool isParameterOfListAddingMethod(Element element) {
+ if (!element.isParameter()) return false;
+ if (element.getEnclosingClass() != compiler.backend.listImplementation) {
+ return false;
+ }
+ Element method = element.enclosingElement;
+ return (method.name == '[]=')
+ || (method.name == 'add')
+ || (method.name == 'insert');
+ }
+
+ void visitElementTypeInformation(ElementTypeInformation info) {
+ if (isParameterOfListAddingMethod(info.element)) {
+ // These elements are being handled in
+ // [visitDynamicCallSiteTypeInformation].
+ return;
+ }
+ addNewEscapeInformation(info);
+ }
+}
+
+class ContainerTracerVisitor extends TracerVisitor {
+ // The list of found assignments to the container.
+ final List<TypeInformation> assignments = <TypeInformation>[];
+ bool callsGrowableMethod = false;
+
+ ContainerTracerVisitor(tracedType, inferrer) : super(tracedType, inferrer);
+
+ List<TypeInformation> run() {
+ analyze();
+ ListTypeInformation container = tracedType;
+ if (continueAnalyzing) {
+ if (!callsGrowableMethod && container.inferredLength == null) {
+ container.inferredLength = container.originalLength;
+ }
+ container.flowsInto.addAll(flowsInto);
+ return assignments;
+ } else {
+ callsGrowableMethod = true;
+ return null;
+ }
+ }
+
+ visitMapTypeInformation(MapTypeInformation info) {
+ bailout('Stored in a map');
+ }
+
+ visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
+ bailout('Passed to a closure');
+ }
+
+ visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
+ Element called = info.calledElement;
+ if (called.isForeign(compiler) && called.name == 'JS') {
+ bailout('Used in JS ${info.call}');
+ }
+ super.visitStaticCallSiteTypeInformation(info);
kasperl 2013/12/11 07:35:35 Is it important to call the super method at the bo
ngeoffray 2013/12/16 11:47:43 Done.
+ }
+
visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
Selector selector = info.selector;
String selectorName = selector.name;
@@ -349,44 +408,100 @@
&& !info.targets.every((element) => element.isFunction())) {
bailout('Passed to a closure');
return;
- } else if (isAddedToContainer(info)) {
- ContainerTypeMask mask = info.receiver.type;
- if (mask.allocationNode != null) {
- ListTypeInformation container =
- inferrer.types.allocatedLists[mask.allocationNode];
- containersToAnalyze.add(container);
+ }
+ super.visitDynamicCallSiteTypeInformation(info);
+ }
+
+ bool isClosure(Element element) {
+ if (!element.isFunction()) return false;
+ Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
+ return outermost.declaration != element.declaration;
+ }
+
+ visitElementTypeInformation(ElementTypeInformation info) {
+ if (isClosure(info.element)) {
+ bailout('Returned from a closure');
+ }
+ if (compiler.backend.isNeededForReflection(info.element)) {
+ bailout('Escape in reflection');
+ }
+ super.visitElementTypeInformation(info);
+ }
+}
+
+class ClosureTracerVisitor extends TracerVisitor {
+ ClosureTracerVisitor(tracedType, inferrer) : super(tracedType, inferrer);
+
+ void run() {
+ ClosureTypeInformation closure = tracedType;
+ FunctionElement element = closure.element;
+ element.functionSignature.forEachParameter((Element parameter) {
+ ElementTypeInformation info = inferrer.types.getInferredTypeOf(parameter);
+ info.abandonInferencing = false;
+ });
+ analyze();
+ element.functionSignature.forEachParameter((Element parameter) {
+ ElementTypeInformation info = inferrer.types.getInferredTypeOf(parameter);
+ if (continueAnalyzing) {
+ info.turnSpecialNonSpecial = true;
} else {
- // The [ContainerTypeMask] is a union of two containers, and
- // we lose track of where these containers have been allocated
- // at this point.
- bailout('Stored in too many containers');
+ info.giveUp(inferrer);
}
+ });
+ }
+
+ visitMapTypeInformation(MapTypeInformation info) {
+ bailout('Stored in a map');
+ }
+
+ void analyzeCall(CallSiteTypeInformation info) {
+ ClosureTypeInformation closure = tracedType;
+ FunctionElement element = closure.element;
+ Selector selector = info.selector;
+ if (!selector.appliesUntyped(element, compiler)) return;
+ inferrer.updateParameterAssignments(
+ info, element, info.arguments, selector, remove: false,
+ addToQueue: false);
+ }
+
+ visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
+ if (info.closure == currentUser) {
+ analyzeCall(info);
+ } else {
+ bailout('Passed to a closure');
}
+ }
- if (info.targets
- .map((element) => inferrer.types.getInferredTypeOf(element))
- .any((other) => other == currentUser)) {
- addNewEscapeInformation(info);
+ visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
+ Element called = info.calledElement;
+ if (called.isForeign(compiler) && called.name == 'JS') {
+ bailout('Used in JS ${info.call}');
}
+ super.visitStaticCallSiteTypeInformation(info);
}
+ bool checkIfCurrentUser(element) {
+ return inferrer.types.getInferredTypeOf(element) == currentUser;
+ }
+
+ visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
+ if (info.selector.isCall()) {
+ if (info.arguments.contains(currentUser)
+ && !info.targets.every((element) => element.isFunction())) {
+ bailout('Passed to a closure');
+ } else if (info.targets.any((element) => checkIfCurrentUser(element))) {
+ analyzeCall(info);
+ }
+ }
+ super.visitDynamicCallSiteTypeInformation(info);
+ }
+
bool isClosure(Element element) {
if (!element.isFunction()) return false;
Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
return outermost.declaration != element.declaration;
}
- bool isParameterOfListAddingMethod(Element element) {
- if (!element.isParameter()) return false;
- if (element.getEnclosingClass() != compiler.backend.listImplementation) {
- return false;
- }
- Element method = element.enclosingElement;
- return (method.name == '[]=')
- || (method.name == 'add')
- || (method.name == 'insert');
- }
-
visitElementTypeInformation(ElementTypeInformation info) {
if (isClosure(info.element)) {
bailout('Returned from a closure');
@@ -394,11 +509,6 @@
if (compiler.backend.isNeededForReflection(info.element)) {
bailout('Escape in reflection');
}
- if (isParameterOfListAddingMethod(info.element)) {
- // These elements are being handled in
- // [visitDynamicCallSiteTypeInformation].
- return;
- }
- addNewEscapeInformation(info);
+ super.visitElementTypeInformation(info);
}
}

Powered by Google App Engine
This is Rietveld 408576698