mirror of
https://github.com/dart-lang/sdk
synced 2024-10-01 19:19:16 +00:00
dart2js: use WorldImpact for dump_info
BUG= R=sigmund@google.com Review URL: https://codereview.chromium.org/1422323007 .
This commit is contained in:
parent
6a6103318c
commit
0df916cce0
|
@ -187,7 +187,6 @@ class CodegenRegistry extends Registry {
|
|||
|
||||
void registerDynamicUse(DynamicUse dynamicUse) {
|
||||
worldImpact.registerDynamicUse(dynamicUse);
|
||||
compiler.dumpInfoTask.elementUsesSelector(currentElement, dynamicUse);
|
||||
}
|
||||
|
||||
void registerTypeUse(TypeUse typeUse) {
|
||||
|
@ -263,6 +262,8 @@ class CodegenWorkItem extends WorkItem {
|
|||
if (world.isProcessed(element)) return const WorldImpact();
|
||||
|
||||
registry = new CodegenRegistry(compiler, element);
|
||||
return compiler.codegen(this, world);
|
||||
var impact = compiler.codegen(this, world);
|
||||
compiler.dumpInfoTask.registerImpact(element, impact);
|
||||
return impact;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ import 'deferred_load.dart' show OutputUnit;
|
|||
import 'js_backend/js_backend.dart' show JavaScriptBackend;
|
||||
import 'js_emitter/full_emitter/emitter.dart' as full show Emitter;
|
||||
import 'js/js.dart' as jsAst;
|
||||
import 'universe/use.dart' show
|
||||
DynamicUse;
|
||||
import 'universe/universe.dart' show ReceiverConstraint;
|
||||
import 'universe/world_impact.dart' show WorldImpact;
|
||||
import 'info/send_info.dart' show collectSendMeasurements;
|
||||
|
||||
class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> {
|
||||
|
@ -52,10 +52,10 @@ class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> {
|
|||
/// Whether to emit information about [element].
|
||||
///
|
||||
/// By default we emit information for any element that contributes to the
|
||||
/// output size. Either becuase the it is a function being emitted or inlined,
|
||||
/// output size. Either because the it is a function being emitted or inlined,
|
||||
/// or because it is an element that holds dependencies to other elements.
|
||||
bool shouldKeep(Element element) {
|
||||
return compiler.dumpInfoTask.selectorsFromElement.containsKey(element) ||
|
||||
return compiler.dumpInfoTask.impacts.containsKey(element) ||
|
||||
compiler.dumpInfoTask.inlineCount.containsKey(element);
|
||||
}
|
||||
|
||||
|
@ -349,7 +349,7 @@ class ElementInfoCollector extends BaseElementVisitor<Info, dynamic> {
|
|||
|
||||
class Selection {
|
||||
final Element selectedElement;
|
||||
final TypeMask mask;
|
||||
final ReceiverConstraint mask;
|
||||
Selection(this.selectedElement, this.mask);
|
||||
}
|
||||
|
||||
|
@ -386,12 +386,13 @@ class DumpInfoTask extends CompilerTask implements InfoReporter {
|
|||
// pretty-printed contents.
|
||||
final Map<jsAst.Node, int> _nodeToSize = <jsAst.Node, int>{};
|
||||
|
||||
final Map<Element, Set<DynamicUse>> selectorsFromElement = {};
|
||||
final Map<Element, int> inlineCount = <Element, int>{};
|
||||
// A mapping from an element to a list of elements that are
|
||||
// inlined inside of it.
|
||||
final Map<Element, List<Element>> inlineMap = <Element, List<Element>>{};
|
||||
|
||||
final Map<Element, WorldImpact> impacts = <Element, WorldImpact>{};
|
||||
|
||||
/// Register the size of the generated output.
|
||||
void reportSize(int programSize) {
|
||||
_programSize = programSize;
|
||||
|
@ -404,40 +405,35 @@ class DumpInfoTask extends CompilerTask implements InfoReporter {
|
|||
inlineMap[inlinedFrom].add(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers that a function uses a selector in the
|
||||
* function body
|
||||
*/
|
||||
void elementUsesSelector(Element element, DynamicUse selector) {
|
||||
if (compiler.dumpInfo) {
|
||||
selectorsFromElement
|
||||
.putIfAbsent(element, () => new Set<DynamicUse>())
|
||||
.add(selector);
|
||||
}
|
||||
}
|
||||
|
||||
final Map<Element, Set<Element>> _dependencies = {};
|
||||
void registerDependency(Element source, Element target) {
|
||||
_dependencies.putIfAbsent(source, () => new Set()).add(target);
|
||||
}
|
||||
|
||||
void registerImpact(Element element, WorldImpact impact) {
|
||||
if (compiler.dumpInfo) {
|
||||
impacts[element] = impact;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterable of [Selection]s that are used by
|
||||
* [element]. Each [Selection] contains an element that is
|
||||
* used and the selector that selected the element.
|
||||
*/
|
||||
Iterable<Selection> getRetaining(Element element) {
|
||||
if (!selectorsFromElement.containsKey(element)) {
|
||||
return const <Selection>[];
|
||||
} else {
|
||||
return selectorsFromElement[element].expand((DynamicUse selector) {
|
||||
return compiler.world.allFunctions
|
||||
.filter(selector.selector, selector.mask)
|
||||
.map((element) {
|
||||
return new Selection(element, selector.mask);
|
||||
});
|
||||
});
|
||||
}
|
||||
var impact = impacts[element];
|
||||
if (impact == null) return const <Selection>[];
|
||||
|
||||
var selections = <Selection>[];
|
||||
selections.addAll(impact.dynamicUses.expand((dynamicUse) {
|
||||
return compiler.world.allFunctions
|
||||
.filter(dynamicUse.selector, dynamicUse.mask)
|
||||
.map((e) => new Selection(e, dynamicUse.mask));
|
||||
}));
|
||||
selections.addAll(impact.staticUses
|
||||
.map((staticUse) => new Selection(staticUse.element, null)));
|
||||
return selections;
|
||||
}
|
||||
|
||||
// Returns true if we care about tracking the size of
|
||||
|
|
|
@ -888,8 +888,7 @@ class ResolutionEnqueuer extends Enqueuer {
|
|||
/// [Enqueuer] which is specific to code generation.
|
||||
class CodegenEnqueuer extends Enqueuer {
|
||||
final Queue<CodegenWorkItem> queue;
|
||||
final Map<Element, js.Expression> generatedCode =
|
||||
new Map<Element, js.Expression>();
|
||||
final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{};
|
||||
|
||||
final Set<Element> newlyEnqueuedElements;
|
||||
|
||||
|
|
|
@ -334,12 +334,6 @@ abstract class TypeMask implements ReceiverConstraint {
|
|||
*/
|
||||
TypeMask intersection(TypeMask other, ClassWorld classWorld);
|
||||
|
||||
/**
|
||||
* Returns whether this [TypeMask] applied to [selector] can hit a
|
||||
* [noSuchMethod].
|
||||
*/
|
||||
bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld);
|
||||
|
||||
/**
|
||||
* Returns whether [element] is a potential target when being
|
||||
* invoked on this type mask. [selector] is used to ensure library
|
||||
|
|
|
@ -19,6 +19,8 @@ import '../world.dart' show
|
|||
|
||||
import 'selector.dart' show
|
||||
Selector;
|
||||
import 'universe.dart' show
|
||||
ReceiverConstraint;
|
||||
|
||||
// TODO(kasperl): This actually holds getters and setters just fine
|
||||
// too and stricly they aren't functions. Maybe this needs a better
|
||||
|
@ -64,36 +66,37 @@ class FunctionSet {
|
|||
|
||||
/// Returns an object that allows iterating over all the functions
|
||||
/// that may be invoked with the given [selector].
|
||||
Iterable<Element> filter(Selector selector, TypeMask mask) {
|
||||
return query(selector, mask).functions;
|
||||
Iterable<Element> filter(Selector selector, ReceiverConstraint constraint) {
|
||||
return query(selector, constraint).functions;
|
||||
}
|
||||
|
||||
/// Returns the mask for the potential receivers of a dynamic call to
|
||||
/// [selector] on [mask].
|
||||
/// [selector] on [constraint].
|
||||
///
|
||||
/// This will reduce the set of classes in [mask] to a [TypeMask] of the set
|
||||
/// of classes that actually implement the selected member or implement the
|
||||
/// handling 'noSuchMethod' where the selected member is unimplemented.
|
||||
TypeMask receiverType(Selector selector, TypeMask mask) {
|
||||
return query(selector, mask).computeMask(classWorld);
|
||||
/// This will narrow the constraints of [constraint] to a [TypeMask] of the
|
||||
/// set of classes that actually implement the selected member or implement
|
||||
/// the handling 'noSuchMethod' where the selected member is unimplemented.
|
||||
TypeMask receiverType(Selector selector, ReceiverConstraint constraint) {
|
||||
return query(selector, constraint).computeMask(classWorld);
|
||||
}
|
||||
|
||||
SelectorMask _createSelectorMask(
|
||||
Selector selector, TypeMask mask, ClassWorld classWorld) {
|
||||
return mask != null
|
||||
? new SelectorMask(selector, mask)
|
||||
Selector selector, ReceiverConstraint constraint, ClassWorld classWorld) {
|
||||
return constraint != null
|
||||
? new SelectorMask(selector, constraint)
|
||||
: new SelectorMask(selector,
|
||||
new TypeMask.subclass(classWorld.objectClass, classWorld));
|
||||
}
|
||||
|
||||
/// Returns the set of functions that can be the target of a call to
|
||||
/// [selector] on a receiver of type [mask] including 'noSuchMethod' methods
|
||||
/// where applicable.
|
||||
FunctionSetQuery query(Selector selector, TypeMask mask) {
|
||||
/// [selector] on a receiver constrained by [constraint] including
|
||||
/// 'noSuchMethod' methods where applicable.
|
||||
FunctionSetQuery query(Selector selector, ReceiverConstraint constraint) {
|
||||
String name = selector.name;
|
||||
SelectorMask selectorMask = _createSelectorMask(selector, mask, classWorld);
|
||||
SelectorMask selectorMask =
|
||||
_createSelectorMask(selector, constraint, classWorld);
|
||||
SelectorMask noSuchMethodMask =
|
||||
new SelectorMask(Selectors.noSuchMethod_, selectorMask.mask);
|
||||
new SelectorMask(Selectors.noSuchMethod_, selectorMask.constraint);
|
||||
FunctionSetNode node = nodes[name];
|
||||
FunctionSetNode noSuchMethods = nodes[Identifiers.noSuchMethod_];
|
||||
if (node != null) {
|
||||
|
@ -115,38 +118,38 @@ class FunctionSet {
|
|||
}
|
||||
}
|
||||
|
||||
/// A selector/mask pair representing the dynamic invocation of [selector] on
|
||||
/// a receiver of type [mask].
|
||||
/// A selector/constraint pair representing the dynamic invocation of [selector]
|
||||
/// on a receiver constrained by [constraint].
|
||||
class SelectorMask {
|
||||
final Selector selector;
|
||||
final TypeMask mask;
|
||||
final ReceiverConstraint constraint;
|
||||
final int hashCode;
|
||||
|
||||
SelectorMask(Selector selector, TypeMask mask)
|
||||
SelectorMask(Selector selector, ReceiverConstraint constraint)
|
||||
: this.selector = selector,
|
||||
this.mask = mask,
|
||||
this.constraint = constraint,
|
||||
this.hashCode =
|
||||
Hashing.mixHashCodeBits(selector.hashCode, mask.hashCode) {
|
||||
assert(mask != null);
|
||||
Hashing.mixHashCodeBits(selector.hashCode, constraint.hashCode) {
|
||||
assert(constraint != null);
|
||||
}
|
||||
|
||||
String get name => selector.name;
|
||||
|
||||
bool applies(Element element, ClassWorld classWorld) {
|
||||
if (!selector.appliesUnnamed(element, classWorld)) return false;
|
||||
return mask.canHit(element, selector, classWorld);
|
||||
return constraint.canHit(element, selector, classWorld);
|
||||
}
|
||||
|
||||
bool needsNoSuchMethodHandling(ClassWorld classWorld) {
|
||||
return mask.needsNoSuchMethodHandling(selector, classWorld);
|
||||
return constraint.needsNoSuchMethodHandling(selector, classWorld);
|
||||
}
|
||||
|
||||
bool operator ==(other) {
|
||||
if (identical(this, other)) return true;
|
||||
return selector == other.selector && mask == other.mask;
|
||||
return selector == other.selector && constraint == other.constraint;
|
||||
}
|
||||
|
||||
String toString() => '($selector,$mask)';
|
||||
String toString() => '($selector,$constraint)';
|
||||
}
|
||||
|
||||
/// A node in the [FunctionSet] caching all [FunctionSetQuery] object for
|
||||
|
|
|
@ -39,6 +39,10 @@ abstract class ReceiverConstraint {
|
|||
/// invoked on a receiver with this constraint. [selector] is used to ensure
|
||||
/// library privacy is taken into account.
|
||||
bool canHit(Element element, Selector selector, ClassWorld classWorld);
|
||||
|
||||
/// Returns whether this [TypeMask] applied to [selector] can hit a
|
||||
/// [noSuchMethod].
|
||||
bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld);
|
||||
}
|
||||
|
||||
/// The combined constraints on receivers all the dynamic call sites of the same
|
||||
|
@ -58,7 +62,7 @@ abstract class ReceiverConstraint {
|
|||
/// new A().foo(a, b);
|
||||
/// new B().foo(0, 42);
|
||||
///
|
||||
/// the selector constaints for dynamic calls to 'foo' with two positional
|
||||
/// the selector constraints for dynamic calls to 'foo' with two positional
|
||||
/// arguments could be 'receiver of exact instance `A` or `B`'.
|
||||
abstract class SelectorConstraints {
|
||||
/// Returns `true` if [selector] applies to [element] under these constraints
|
||||
|
|
|
@ -62,7 +62,6 @@ class WorldImpactBuilder {
|
|||
Setlet<DynamicUse> _dynamicUses;
|
||||
Setlet<StaticUse> _staticUses;
|
||||
Setlet<TypeUse> _typeUses;
|
||||
Setlet<LocalFunctionElement> _closures;
|
||||
|
||||
void registerDynamicUse(DynamicUse dynamicUse) {
|
||||
assert(dynamicUse != null);
|
||||
|
|
Loading…
Reference in a new issue