Remove unused file.

R=kasperl@google.com

Review URL: https://codereview.chromium.org//119013002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@31252 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
ngeoffray@google.com 2013-12-19 08:33:53 +00:00
parent 963e6d6af1
commit d9f262fe2b

View file

@ -1,507 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of type_graph_inferrer;
/**
* A set of selector names that [List] implements, that we know do not
* change the element type of the list, or let the list escape to code
* that might change the element type.
*/
Set<String> okSelectorsSet = new Set<String>.from(
const <String>[
// From Object.
'==',
'hashCode',
'toString',
'noSuchMethod',
'runtimeType',
// From Iterable.
'iterator',
'map',
'where',
'expand',
'contains',
'forEach',
'reduce',
'fold',
'every',
'join',
'any',
'toList',
'toSet',
'length',
'isEmpty',
'isNotEmpty',
'take',
'takeWhile',
'skip',
'skipWhile',
'first',
'last',
'single',
'firstWhere',
'lastWhere',
'singleWhere',
'elementAt',
// From List.
'[]',
'length',
'reversed',
'sort',
'indexOf',
'lastIndexOf',
'clear',
'remove',
'removeAt',
'removeLast',
'removeWhere',
'retainWhere',
'sublist',
'getRange',
'removeRange',
'asMap',
// From JSArray.
'checkMutable',
'checkGrowable',
]);
Set<String> doNotChangeLengthSelectorsSet = new Set<String>.from(
const <String>[
// From Object.
'==',
'hashCode',
'toString',
'noSuchMethod',
'runtimeType',
// From Iterable.
'iterator',
'map',
'where',
'expand',
'contains',
'forEach',
'reduce',
'fold',
'every',
'join',
'any',
'toList',
'toSet',
'length',
'isEmpty',
'isNotEmpty',
'take',
'takeWhile',
'skip',
'skipWhile',
'first',
'last',
'single',
'firstWhere',
'lastWhere',
'singleWhere',
'elementAt',
// From List.
'[]',
'[]=',
'length',
'reversed',
'sort',
'indexOf',
'lastIndexOf',
'sublist',
'getRange',
'asMap',
// From JSArray.
'checkMutable',
'checkGrowable',
]);
// A set of selectors we know do not escape the elements inside the
// list.
Set<String> doesNotEscapeElementSet = new Set<String>.from(
const <String>[
// From Object.
'==',
'hashCode',
'toString',
'noSuchMethod',
'runtimeType',
// From Iterable.
'isEmpty',
'isNotEmpty',
'length',
'any',
'contains',
'every',
'join',
// From List.
'add',
'addAll',
'clear',
'fillRange',
'indexOf',
'insert',
'insertAll',
'lastIndexOf',
'remove',
'removeRange',
'replaceRange',
'setAll',
'setRange',
'shuffle',
'[]=',
// From JSArray.
'checkMutable',
'checkGrowable',
]);
bool _VERBOSE = false;
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>[];
// Work list of containers to analyze after analyzing the users of a
// [TypeInformation] that may be [container]. We know [container]
// has been stored in these containers and we must check how
// [container] escapes from these containers.
final List<ListTypeInformation> containersToAnalyze =
<ListTypeInformation>[];
final Setlet<TypeInformation> flowsInto = new Setlet<TypeInformation>();
// The current [TypeInformation] in the analysis.
TypeInformation currentUser;
bool continueAnalyzing = true;
void addNewEscapeInformation(TypeInformation info) {
if (flowsInto.contains(info)) return;
flowsInto.add(info);
workList.add(info);
}
void analyze() {
// Collect the [TypeInformation] where the container can flow in,
// as well as the operations done on all these [TypeInformation]s.
addNewEscapeInformation(tracedType);
while (!workList.isEmpty) {
currentUser = workList.removeLast();
currentUser.users.forEach((TypeInformation info) {
analyzedElements.add(info.owner);
info.accept(this);
});
while (!containersToAnalyze.isEmpty) {
analyzeStoredIntoContainer(containersToAnalyze.removeLast());
}
if (!continueAnalyzing) break;
if (analyzedElements.length > MAX_ANALYSIS_COUNT) {
bailout('Too many users');
break;
}
}
}
void bailout(String reason) {
if (_VERBOSE) {
print('Bailing out on $tracedType because: $reason');
}
continueAnalyzing = false;
}
void visitNarrowTypeInformation(NarrowTypeInformation info) {
addNewEscapeInformation(info);
}
void visitPhiElementTypeInformation(PhiElementTypeInformation info) {
addNewEscapeInformation(info);
}
void visitElementInContainerTypeInformation(
ElementInContainerTypeInformation info) {
addNewEscapeInformation(info);
}
visitListTypeInformation(ListTypeInformation info) {
containersToAnalyze.add(info);
}
void visitConcreteTypeInformation(ConcreteTypeInformation info) {}
void visitClosureTypeInformation(ClosureTypeInformation info) {}
void visitClosureCallSiteTypeInformation(
ClosureCallSiteTypeInformation info) {}
visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
Element called = info.calledElement;
if (inferrer.types.getInferredTypeOf(called) == currentUser) {
addNewEscapeInformation(info);
}
}
void analyzeStoredIntoContainer(ListTypeInformation container) {
inferrer.analyzeContainer(container);
if (container.bailedOut) {
bailout('Stored in a container that bailed out');
} else {
container.flowsInto.forEach((flow) {
flow.users.forEach((user) {
if (user is !DynamicCallSiteTypeInformation) return;
if (user.receiver != flow) return;
if (returnsElementTypeSet.contains(user.selector)) {
addNewEscapeInformation(user);
} else if (!doesNotEscapeElementSet.contains(user.selector.name)) {
bailout('Escape from a container');
}
});
});
}
}
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;
List<TypeInformation> arguments = info.arguments.positional;
return (selectorName == '[]=' && currentUser == arguments[1])
|| (selectorName == 'insert' && currentUser == arguments[0])
|| (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');
}
}
Iterable<Element> inferredTargetTypes = info.targets.map((element) {
return inferrer.types.getInferredTypeOf(element);
});
if (inferredTargetTypes.any((user) => user == 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');
}
bool isClosure(Element element) {
if (!element.isFunction()) return false;
Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
return outermost.declaration != element.declaration;
}
void visitElementTypeInformation(ElementTypeInformation info) {
Element element = info.element;
if (element.isParameter()
&& inferrer.isNativeElement(element.enclosingElement)) {
bailout('Passed to a native method');
}
if (info.isClosurized()) {
bailout('Returned from a closurized method');
}
if (isClosure(info.element)) {
bailout('Returned from a closure');
}
if (compiler.backend.isNeededForReflection(info.element)) {
bailout('Escape in reflection');
}
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) {
super.visitStaticCallSiteTypeInformation(info);
Element called = info.calledElement;
if (called.isForeign(compiler) && called.name == 'JS') {
bailout('Used in JS ${info.call}');
}
}
visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
super.visitDynamicCallSiteTypeInformation(info);
Selector selector = info.selector;
String selectorName = selector.name;
if (currentUser == info.receiver) {
if (!okSelectorsSet.contains(selectorName)) {
if (selector.isCall()) {
int positionalLength = info.arguments.positional.length;
if (selectorName == 'add') {
if (positionalLength == 1) {
assignments.add(info.arguments.positional[0]);
}
} else if (selectorName == 'insert') {
if (positionalLength == 2) {
assignments.add(info.arguments.positional[1]);
}
} else {
bailout('Used in a not-ok selector');
return;
}
} else if (selector.isIndexSet()) {
assignments.add(info.arguments.positional[1]);
} else if (!selector.isIndex()) {
bailout('Used in a not-ok selector');
return;
}
}
if (!doNotChangeLengthSelectorsSet.contains(selectorName)) {
callsGrowableMethod = true;
}
if (selectorName == 'length' && selector.isSetter()) {
callsGrowableMethod = true;
assignments.add(inferrer.types.nullType);
}
} else if (selector.isCall()
&& !info.targets.every((element) => element.isFunction())) {
bailout('Passed to a closure');
return;
}
}
}
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.disableHandleSpecialCases = true;
} else {
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.signatureApplies(element, compiler)) return;
inferrer.updateParameterAssignments(
info, element, info.arguments, selector, remove: false,
addToQueue: false);
}
visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
super.visitClosureCallSiteTypeInformation(info);
if (info.closure == currentUser) {
analyzeCall(info);
} else {
bailout('Passed to a closure');
}
}
visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
super.visitStaticCallSiteTypeInformation(info);
Element called = info.calledElement;
if (called.isForeign(compiler) && called.name == 'JS') {
bailout('Used in JS ${info.call}');
}
}
bool checkIfCurrentUser(element) {
return inferrer.types.getInferredTypeOf(element) == currentUser;
}
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');
} else if (info.targets.any((element) => checkIfCurrentUser(element))) {
analyzeCall(info);
}
}
}
}