blob: 8292be429c36eb5b297096411a4f9d127a18468a [file] [log] [blame]
// Copyright (c) 2015, 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.
/// Computes measurements about sends in a function.
library compiler.src.info.send_info;
import 'dart:convert';
import 'package:dart2js_info/src/measurements.dart';
import 'package:dart2js_info/src/util.dart' show
recursiveDiagnosticString;
import '../common.dart';
import '../common/tasks.dart' show
CompilerTask;
import '../compiler.dart' show
Compiler;
import '../dart_types.dart';
import '../closure.dart';
import '../elements/elements.dart';
import '../elements/visitor.dart' show
ElementVisitor;
import '../resolution/operators.dart';
import '../resolution/semantic_visitor.dart';
import '../resolution/tree_elements.dart';
import '../constants/expressions.dart';
import '../parser/partial_elements.dart' show
PartialElement;
import '../tree/tree.dart';
import '../universe/call_structure.dart' show
CallStructure;
import '../universe/selector.dart' show
Selector;
import 'analysis_result.dart';
import 'naive_analysis_result.dart';
import 'trusted_types_analysis_result.dart';
/// Collects a set of [Measurements] about send expressions in the function [f].
// TODO(sigmund): collect information on initializers too.
Measurements collectSendMeasurements(FunctionElement f,
Compiler compiler) {
DiagnosticReporter reporter = compiler.reporter;
return reporter.withCurrentElement(f, () {
// TODO(sigmund): enable for platform too.
if (f.library.isPlatformLibrary) return null;
var name = _qualifiedName(f);
if (!f.hasNode) {
if (f is PartialElement) return const Measurements.unreachableFunction();
assert (f is ConstructorElement && f.isSynthesized);
// TODO(sigmund): measure synthethic forwarding sends, measure
// initializers
return new Measurements.reachableFunction();
}
if (!f.hasResolvedAst) {
_debug('no resolved ast ${f.runtimeType}');
return null;
}
var resolvedAst = f.resolvedAst;
if (resolvedAst.node == null) {
_debug('no node ${f.runtimeType}');
return null;
}
var def = resolvedAst.elements.getFunctionDefinition(resolvedAst.node);
if (def == null) {
assert (f is PartialElement);
return const Measurements.unreachableFunction();
}
var visitor = new _StatsTraversalVisitor(
compiler, resolvedAst.elements,
reporter.spanFromSpannable(resolvedAst.node).uri);
resolvedAst.node.accept(visitor);
return visitor.measurements;
});
}
_qualifiedName(FunctionElement f) {
var cls = f.enclosingClass;
return (cls != null) ? '${cls.name}.${f.name}' : f.name;
}
/// Visitor that categorizes data about an individual send.
class _StatsVisitor<T> extends Visitor
with SemanticSendResolvedMixin<dynamic, T>
implements SemanticSendVisitor<dynamic, T> {
// TODO(sigmund): consider passing in several AnalysisResults at once, so we
// can compute the different metrics together.
/// Information we know about the program from static analysis.
final AnalysisResult info;
/// Results from this function.
final Measurements measurements;
final DiagnosticReporter reporter;
final TreeElements elements;
SemanticSendVisitor<dynamic, T> get sendVisitor => this;
_StatsVisitor(this.reporter, this.elements, this.info, Uri sourceUri)
: measurements = new Measurements.reachableFunction(sourceUri);
visitNode(Node node) => throw "unhandled ${node.runtimeType}: $node";
apply(Node node, T arg) => throw "missing apply ${node.runtimeType}: $node";
internalError(Node node, String arg) => throw "internal error on $node";
visitSend(Send node) {
_checkInvariant(node, 'before');
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.send, span.begin, span.end);
if (node is SendSet) {
if ((node.assignmentOperator != null &&
node.assignmentOperator.source != '=') ||
node.isPrefix ||
node.isPostfix) {
assert(!node.isIfNullAssignment);
// We count get and set separately in case one of them is defined by the
// other could be a nSM error.
measurements.record(Metric.send, span.begin, span.end);
measurements.record(Metric.send, span.begin, span.end);
} else if (node.isIfNullAssignment) {
measurements.record(Metric.send, span.begin, span.end);
}
}
super.visitSend(node);
_checkInvariant(node, 'after ');
}
visitNewExpression(NewExpression node) {
_checkInvariant(node, 'before');
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.send, span.begin, span.end);
super.visitNewExpression(node);
_checkInvariant(node, 'after ');
}
/// A monomorphic local variable read.
///
/// See [Metric.send] for a full categorization of sends.
handleLocal(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.monomorphicSend, span.begin, span.end);
measurements.record(Metric.localSend, span.begin, span.end);
}
/// A monomorphic virual call on [node], where we know which function is the
/// target of the call (for example, because only one type in a class
/// hierarchy implements a function with a given name).
///
/// See [Metric.send] for a full categorization of sends.
handleSingleInstance(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.monomorphicSend, span.begin, span.end);
measurements.record(Metric.instanceSend, span.begin, span.end);
}
/// A monomorphic call that goes through an interceptor. This is equivalent in
/// terms of what the compiler knows as we do with [handleSignleInstance], and
/// because we know the target of the call, we also know that it doesn't live
/// in the object instance, but on an interceptor on the side.
///
/// See [Metric.send] for a full categorization of sends.
handleSingleInterceptor(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.monomorphicSend, span.begin, span.end);
measurements.record(Metric.interceptorSend, span.begin, span.end);
}
/// A polymorphic call that goes through an interceptor.
///
/// See [Metric.send] for a full categorization of sends.
handleMultiInterceptor(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.polymorphicSend, span.begin, span.end);
measurements.record(Metric.multiInterceptorSend, span.begin, span.end);
}
handleConstructor(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.monomorphicSend, span.begin, span.end);
measurements.record(Metric.constructorSend, span.begin, span.end);
}
handleDynamic(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.polymorphicSend, span.begin, span.end);
measurements.record(Metric.dynamicSend, span.begin, span.end);
}
handleVirtual(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.polymorphicSend, span.begin, span.end);
measurements.record(Metric.virtualSend, span.begin, span.end);
}
handleNSMError(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.monomorphicSend, span.begin, span.end);
measurements.record(Metric.nsmErrorSend, span.begin, span.end);
}
handleNSMSingle(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.monomorphicSend, span.begin, span.end);
measurements.record(Metric.singleNsmCallSend, span.begin, span.end);
}
handleNSMSuper(Node node, ClassElement type) {
var superclass = type.superclass;
var member = superclass.lookupMember('noSuchMethod');
if (!member.enclosingClass.isObject) {
handleNSMSingle(node);
} else {
handleNSMError(node);
}
}
handleNSMAny(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.polymorphicSend, span.begin, span.end);
measurements.record(Metric.multiNsmCallSend, span.begin, span.end);
}
handleSuper(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.monomorphicSend, span.begin, span.end);
measurements.record(Metric.superSend, span.begin, span.end);
}
handleTypeVariable(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.monomorphicSend, span.begin, span.end);
measurements.record(Metric.typeVariableSend, span.begin, span.end);
}
handleStatic(Node node) {
var span = reporter.spanFromSpannable(node);
measurements.record(Metric.monomorphicSend, span.begin, span.end);
measurements.record(Metric.staticSend, span.begin, span.end);
}
handleNoSend(Node node) {
measurements.popLast(Metric.send);
}
void handleDynamicProperty(Node node, Node receiver, Selector selector) {
// staticSend: no (automatically)
// superSend: no (automatically)
// localSend: no (automatically)
// constructorSend: no (automatically)
// typeVariableSend: no (automatically)
// nsmErrorSend: receiver has no `selector` nor nSM.
// singleNsmCallSend: receiver has no `selector`, but definitely has `nSM`
// instanceSend: receiver has `selector`, no need to use an interceptor
// interceptorSend: receiver has `selector`, but we know we need an
// interceptor to get it
// multiNsmCallSend: receiver has no `selector`, not sure if receiver has
// nSM, or not sure which nSM is called (does this one
// matter, or does nSM is treated like an instance method
// call)?
// virtualSend: receiver has `selector`, we know we do not need an
// interceptor, not sure which specific type implements
// the selector.
// multiInterceptorSend: multiple possible receiver types, all using an
// interceptor to get the `selector`, might be
// possbile to pick a special selector logic for this
// combination?
// dynamicSend: any combination of the above.
ReceiverInfo receiverInfo = info.infoForReceiver(receiver);
SelectorInfo selectorInfo = info.infoForSelector(receiver, selector);
Boolish hasSelector = selectorInfo.exists;
Boolish hasNsm = receiverInfo.hasNoSuchMethod;
if (hasSelector == Boolish.no) {
if (hasNsm == Boolish.no) {
handleNSMError(node);
} else if (hasNsm == Boolish.yes) {
if (receiverInfo.possibleNsmTargets == 1) {
handleNSMSingle(node);
} else {
handleNSMAny(node);
}
} else {
handleDynamic(node);
}
return;
}
Boolish usesInterceptor = selectorInfo.usesInterceptor;
if (hasSelector == Boolish.yes) {
if (selectorInfo.isAccurate && selectorInfo.possibleTargets == 1) {
assert (usesInterceptor != Boolish.maybe);
if (usesInterceptor == Boolish.yes) {
handleSingleInterceptor(node);
} else {
handleSingleInstance(node);
}
} else {
if (usesInterceptor == Boolish.no) {
handleVirtual(node);
} else if (usesInterceptor == Boolish.yes) {
handleMultiInterceptor(node);
} else {
handleDynamic(node);
}
}
return;
}
handleDynamic(node);
}
void handleThisProperty(Send node, Selector selector) {
handleDynamicProperty(node, node.receiver, selector);
}
void handleIndex(Node node) {
handleDynamic(node);
}
void handleOperator(Node node) {
handleDynamic(node);
}
void handleInvoke(Node node) {
handleDynamic(node);
}
void handleEquals(Node node) {
handleDynamic(node);
}
// Constructors
void visitAbstractClassConstructorInvoke(NewExpression node,
ConstructorElement element, InterfaceType type, NodeList arguments,
CallStructure callStructure, T arg) {
handleConstructor(node);
}
void visitBoolFromEnvironmentConstructorInvoke(NewExpression node,
BoolFromEnvironmentConstantExpression constant, T arg) {
handleConstructor(node);
}
void visitConstConstructorInvoke(
NewExpression node, ConstructedConstantExpression constant, T arg) {
handleConstructor(node);
}
void visitGenerativeConstructorInvoke(NewExpression node,
ConstructorElement constructor, InterfaceType type, NodeList arguments,
CallStructure callStructure, T arg) {
handleConstructor(node);
}
void visitIntFromEnvironmentConstructorInvoke(NewExpression node,
IntFromEnvironmentConstantExpression constant, T arg) {
handleConstructor(node);
}
void visitRedirectingFactoryConstructorInvoke(NewExpression node,
ConstructorElement constructor, InterfaceType type,
ConstructorElement effectiveTarget, InterfaceType effectiveTargetType,
NodeList arguments, CallStructure callStructure, T arg) {
handleConstructor(node);
}
void visitRedirectingGenerativeConstructorInvoke(NewExpression node,
ConstructorElement constructor, InterfaceType type, NodeList arguments,
CallStructure callStructure, T arg) {
handleConstructor(node);
}
void visitStringFromEnvironmentConstructorInvoke(NewExpression node,
StringFromEnvironmentConstantExpression constant, T arg) {
handleConstructor(node);
}
// Dynamic sends
// TODO(sigmund): many many things to add:
// -- support for operators, indexers, etc.
// -- logic about nullables
// -- int, JSArray
// -- all interceptors
void visitBinary(
Send node, Node left, BinaryOperator operator, Node right, T arg) {
handleOperator(node);
}
void visitCompoundIndexSet(SendSet node, Node receiver, Node index,
AssignmentOperator operator, Node rhs, T arg) {
handleIndex(node); // t1 = receiver[index]
handleOperator(node); // t2 = t1 op rhs
handleIndex(node); // receiver[index] = t2
}
void visitDynamicPropertyCompound(Send node, Node receiver,
Name name, AssignmentOperator operator, Node rhs, T arg) {
handleDynamicProperty(node, receiver, new Selector.getter(name));
handleOperator(node);
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitDynamicPropertyGet(
Send node, Node receiver, Name name, T arg) {
handleDynamicProperty(node, receiver, new Selector.getter(name));
}
void visitDynamicPropertyInvoke(
Send node, Node receiver, NodeList arguments, Selector selector, T arg) {
handleDynamicProperty(node, receiver, selector);
}
void visitDynamicPropertyPostfix(Send node, Node receiver,
Name name, IncDecOperator operator, T arg) {
handleDynamicProperty(node, receiver, new Selector.getter(name));
handleOperator(node);
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitDynamicPropertyPrefix(Send node, Node receiver, Name name,
IncDecOperator operator, T arg) {
handleDynamicProperty(node, receiver, new Selector.getter(name));
handleOperator(node);
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitDynamicPropertySet(
SendSet node, Node receiver, Name name, Node rhs, T arg) {
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitDynamicPropertySetIfNull(
Send node, Node receiver, Name name, Node rhs, T arg) {
// read to check for null?
handleDynamicProperty(node, receiver, new Selector.getter(name));
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitEquals(Send node, Node left, Node right, T arg) {
handleEquals(node);
}
void visitExpressionInvoke(Send node, Node expression, NodeList arguments,
CallStructure callStructure, T arg) {
handleInvoke(node);
}
void visitIfNotNullDynamicPropertyCompound(Send node, Node receiver,
Name name, AssignmentOperator operator, Node rhs, T arg) {
handleDynamicProperty(node, receiver, new Selector.getter(name));
handleOperator(node);
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitIfNotNullDynamicPropertyGet(
Send node, Node receiver, Name name, T arg) {
handleDynamicProperty(node, receiver, new Selector.getter(name));
}
void visitIfNotNullDynamicPropertyInvoke(
Send node, Node receiver, NodeList arguments, Selector selector, T arg) {
handleDynamicProperty(node, receiver, selector);
}
void visitIfNotNullDynamicPropertyPostfix(Send node, Node receiver, Name name,
IncDecOperator operator, T arg) {
handleDynamicProperty(node, receiver, new Selector.getter(name));
handleOperator(node);
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitIfNotNullDynamicPropertyPrefix(Send node, Node receiver, Name name,
IncDecOperator operator, T arg) {
handleDynamicProperty(node, receiver, new Selector.getter(name));
handleOperator(node);
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitIfNotNullDynamicPropertySet(
SendSet node, Node receiver, Name name, Node rhs, T arg) {
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitIfNotNullDynamicPropertySetIfNull(
Send node, Node receiver, Name name, Node rhs, T arg) {
handleDynamicProperty(node, receiver, new Selector.getter(name));
handleDynamicProperty(node, receiver, new Selector.setter(name));
}
void visitIndex(Send node, Node receiver, Node index, T arg) {
handleIndex(node);
}
void visitIndexPostfix(
Send node, Node receiver, Node index, IncDecOperator operator, T arg) {
handleIndex(node);
handleOperator(node);
handleIndex(node);
}
void visitIndexPrefix(
Send node, Node receiver, Node index, IncDecOperator operator, T arg) {
handleIndex(node);
handleOperator(node);
handleIndex(node);
}
void visitIndexSet(SendSet node, Node receiver, Node index, Node rhs, T arg) {
handleIndex(node);
}
void visitLocalVariableCompound(Send node, LocalVariableElement variable,
AssignmentOperator operator, Node rhs, T arg) {
handleLocal(node);
handleOperator(node);
handleLocal(node);
}
void visitLocalVariableInvoke(Send node, LocalVariableElement variable,
NodeList arguments, CallStructure callStructure, T arg) {
handleInvoke(node);
}
void visitLocalVariablePostfix(Send node, LocalVariableElement variable,
IncDecOperator operator, T arg) {
handleLocal(node);
handleOperator(node);
handleLocal(node);
}
void visitLocalVariablePrefix(Send node, LocalVariableElement variable,
IncDecOperator operator, T arg) {
handleLocal(node);
handleOperator(node);
handleLocal(node);
}
void visitNotEquals(Send node, Node left, Node right, T arg) {
handleEquals(node);
}
void visitParameterCompound(Send node, ParameterElement parameter,
AssignmentOperator operator, Node rhs, T arg) {
handleLocal(node);
handleOperator(node);
handleLocal(node);
}
void visitParameterInvoke(Send node, ParameterElement parameter,
NodeList arguments, CallStructure callStructure, T arg) {
handleInvoke(node);
}
void visitParameterPostfix(
Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
handleLocal(node);
handleOperator(node);
handleLocal(node);
}
void visitParameterPrefix(
Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
handleLocal(node);
handleOperator(node);
handleLocal(node);
}
void visitStaticFieldCompound(Send node, FieldElement field,
AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitStaticFieldInvoke(Send node, FieldElement field, NodeList arguments,
CallStructure callStructure, T arg) {
handleInvoke(node);
}
void visitStaticFieldPostfix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitStaticFieldPrefix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitStaticGetterInvoke(Send node, FunctionElement getter,
NodeList arguments, CallStructure callStructure, T arg) {
handleInvoke(node);
}
void visitStaticGetterSetterCompound(Send node, FunctionElement getter,
FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitStaticGetterSetterPostfix(Send node, FunctionElement getter,
FunctionElement setter, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitStaticGetterSetterPrefix(Send node, FunctionElement getter,
FunctionElement setter, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitSuperFieldCompound(Send node, FieldElement field,
AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperFieldFieldCompound(Send node, FieldElement readField,
FieldElement writtenField, AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperFieldFieldPostfix(Send node, FieldElement readField,
FieldElement writtenField, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperFieldFieldPrefix(Send node, FieldElement readField,
FieldElement writtenField, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperFieldFieldSetIfNull(
Send node, FieldElement readField, FieldElement writtenField, Node rhs,
T arg) {
handleSuper(node);
handleNSMSuper(node, readField.enclosingClass);
}
void visitSuperFieldInvoke(Send node, FieldElement field, NodeList arguments,
CallStructure callStructure, T arg) {
handleInvoke(node);
}
void visitSuperFieldPostfix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperFieldPrefix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperFieldSetterCompound(Send node, FieldElement field,
FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperFieldSetterPostfix(Send node, FieldElement field,
FunctionElement setter, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperFieldSetterPrefix(Send node, FieldElement field,
FunctionElement setter, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperFieldSetterSetIfNull(Send node, FieldElement field,
FunctionElement setter, Node rhs, T arg) {
handleSuper(node);
handleSuper(node);
}
void visitSuperGetterFieldCompound(Send node, FunctionElement getter,
FieldElement field, AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperGetterFieldPostfix(Send node, FunctionElement getter,
FieldElement field, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperGetterFieldPrefix(Send node, FunctionElement getter,
FieldElement field, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperGetterFieldSetIfNull(Send node, FunctionElement getter,
FieldElement field, Node rhs, T arg) {
handleSuper(node);
handleSuper(node);
}
void visitSuperGetterInvoke(Send node, FunctionElement getter,
NodeList arguments, CallStructure callStructure, T arg) {
handleInvoke(node);
}
void visitSuperGetterSetterCompound(Send node, FunctionElement getter,
FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperGetterSetterPostfix(Send node, FunctionElement getter,
FunctionElement setter, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperGetterSetterPrefix(Send node, FunctionElement getter,
FunctionElement setter, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperGetterSetterSetIfNull(Send node, FunctionElement getter,
FunctionElement setter, Node rhs, T arg) {
handleSuper(node);
handleSuper(node);
}
void visitSuperIndexPostfix(Send node, MethodElement indexFunction,
MethodElement indexSetFunction, Node index, IncDecOperator operator,
T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperIndexPrefix(Send node, MethodElement indexFunction,
MethodElement indexSetFunction, Node index, IncDecOperator operator,
T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitSuperMethodSetterCompound(Send node, FunctionElement method,
FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
handleNSMSuper(node, method.enclosingClass);
handleSuper(node);
}
void visitSuperMethodSetterPostfix(Send node, FunctionElement method,
FunctionElement setter, IncDecOperator operator, T arg) {
handleSuper(node);
handleNSMSuper(node, method.enclosingClass);
handleSuper(node);
}
void visitSuperMethodSetterPrefix(Send node, FunctionElement method,
FunctionElement setter, IncDecOperator operator, T arg) {
handleSuper(node);
handleNSMSuper(node, method.enclosingClass);
handleSuper(node);
}
void visitSuperMethodSetterSetIfNull(Send node, FunctionElement method,
FunctionElement setter, Node rhs, T arg) {
handleSuper(node);
handleSuper(node);
}
void visitThisPropertyCompound(Send node, Name name,
AssignmentOperator operator, Node rhs, T arg) {
handleThisProperty(node, new Selector.getter(name));
handleOperator(node);
handleThisProperty(node, new Selector.setter(name));
}
void visitThisPropertyInvoke(
Send node, NodeList arguments, Selector selector, T arg) {
handleThisProperty(node, selector);
}
void visitThisPropertyPostfix(Send node, Name name, IncDecOperator operator,
T arg) {
handleThisProperty(node, new Selector.getter(name));
handleOperator(node);
handleThisProperty(node, new Selector.setter(name));
}
void visitThisPropertyPrefix(Send node, Name name, IncDecOperator operator,
T arg) {
handleThisProperty(node, new Selector.getter(name));
handleOperator(node);
handleThisProperty(node, new Selector.setter(name));
}
void visitTopLevelFieldCompound(Send node, FieldElement field,
AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitTopLevelFieldInvoke(Send node, FieldElement field,
NodeList arguments, CallStructure callStructure, T arg) {
handleInvoke(node);
}
void visitTopLevelFieldPostfix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitTopLevelFieldPrefix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitTopLevelGetterInvoke(Send node, FunctionElement getter,
NodeList arguments, CallStructure callStructure, T arg) {
handleInvoke(node);
}
void visitTopLevelGetterSetterCompound(Send node, FunctionElement getter,
FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitTopLevelGetterSetterPostfix(Send node, FunctionElement getter,
FunctionElement setter, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitTopLevelGetterSetterPrefix(Send node, FunctionElement getter,
FunctionElement setter, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleStatic(node);
}
void visitUnary(Send node, UnaryOperator operator, Node expression, T arg) {
handleDynamic(node);
}
// Local variable sends
void visitLocalFunctionGet(Send node, LocalFunctionElement function, T arg) {
handleLocal(node);
}
void visitLocalFunctionInvoke(Send node, LocalFunctionElement function,
NodeList arguments, CallStructure callStructure, T arg) {
handleLocal(node);
}
void visitLocalVariableGet(Send node, LocalVariableElement variable, T arg) {
handleLocal(node);
}
void visitLocalVariableSet(
SendSet node, LocalVariableElement variable, Node rhs, T arg) {
handleLocal(node);
}
void visitLocalVariableSetIfNull(
SendSet node, LocalVariableElement variable, Node rhs, T arg) {
handleLocal(node);
handleLocal(node);
}
void visitParameterGet(Send node, ParameterElement parameter, T arg) {
handleLocal(node);
}
void visitParameterSet(
SendSet node, ParameterElement parameter, Node rhs, T arg) {
handleLocal(node);
}
void visitParameterSetIfNull(
Send node, ParameterElement parameter, Node rhs, T arg) {
handleLocal(node);
handleLocal(node);
}
// Super monomorphic sends
void visitSuperBinary(Send node, FunctionElement function,
BinaryOperator operator, Node argument, T arg) {
handleSuper(node);
}
void visitSuperEquals(
Send node, FunctionElement function, Node argument, T arg) {
handleSuper(node);
}
void visitSuperFieldGet(Send node, FieldElement field, T arg) {
handleSuper(node);
}
void visitSuperFieldSet(SendSet node, FieldElement field, Node rhs, T arg) {
handleSuper(node);
}
void visitSuperFieldSetIfNull(
SendSet node, FieldElement field, Node rhs, T arg) {
handleSuper(node);
handleSuper(node);
}
void visitSuperGetterGet(Send node, FunctionElement getter, T arg) {
handleSuper(node);
}
void visitSuperGetterSet(
SendSet node, FunctionElement getter, Node rhs, T arg) {
handleSuper(node);
}
void visitSuperIndex(Send node, FunctionElement function, Node index, T arg) {
handleSuper(node);
}
void visitSuperIndexSet(
SendSet node, FunctionElement function, Node index, Node rhs, T arg) {
handleSuper(node);
}
void visitSuperMethodGet(Send node, MethodElement method, T arg) {
handleSuper(node);
}
void visitSuperMethodInvoke(Send node, MethodElement method,
NodeList arguments, CallStructure callStructure, T arg) {
handleSuper(node);
}
void visitSuperNotEquals(
Send node, FunctionElement function, Node argument, T arg) {
handleSuper(node);
}
void visitSuperSetterSet(
SendSet node, FunctionElement setter, Node rhs, T arg) {
handleSuper(node);
}
void visitSuperUnary(
Send node, UnaryOperator operator, FunctionElement function, T arg) {
handleSuper(node);
}
// Statically known "no such method" sends
void visitConstructorIncompatibleInvoke(NewExpression node,
ConstructorElement constructor, InterfaceType type, NodeList arguments,
CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitFinalLocalVariableCompound(Send node, LocalVariableElement variable,
AssignmentOperator operator, Node rhs, T arg) {
handleLocal(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalLocalVariablePostfix(Send node, LocalVariableElement variable,
IncDecOperator operator, T arg) {
handleLocal(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalLocalVariablePrefix(Send node, LocalVariableElement variable,
IncDecOperator operator, T arg) {
handleLocal(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalLocalVariableSet(
SendSet node, LocalVariableElement variable, Node rhs, T arg) {
handleNSMError(node);
}
void visitFinalLocalVariableSetIfNull(
SendSet node, LocalVariableElement variable, Node rhs, T arg) {
handleLocal(node); // read for null
handleNSMError(node); // set fails
}
void visitFinalParameterCompound(Send node, ParameterElement parameter,
AssignmentOperator operator, Node rhs, T arg) {
handleLocal(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalParameterPostfix(
Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
handleLocal(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalParameterPrefix(
Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
handleLocal(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalParameterSet(
SendSet node, ParameterElement parameter, Node rhs, T arg) {
handleNSMError(node);
}
void visitFinalParameterSetIfNull(
SendSet node, ParameterElement parameter, Node rhs, T arg) {
handleLocal(node);
handleNSMError(node);
}
void visitFinalStaticFieldCompound(Send node, FieldElement field,
AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalStaticFieldPostfix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalStaticFieldPrefix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalStaticFieldSet(
SendSet node, FieldElement field, Node rhs, T arg) {
handleNSMError(node);
}
void visitFinalStaticFieldSetIfNull(
SendSet node, FieldElement field, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node);
}
void visitFinalSuperFieldSetIfNull(Send node, FieldElement field,
Node rhs, T arg) {
handleSuper(node);
handleNSMSuper(node, field.enclosingClass);
}
void visitFinalSuperFieldCompound(Send node, FieldElement field,
AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
handleOperator(node);
handleNSMSuper(node, field.enclosingClass);
}
void visitFinalSuperFieldPostfix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleNSMSuper(node, field.enclosingClass);
}
void visitFinalSuperFieldPrefix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleNSMSuper(node, field.enclosingClass);
}
void visitFinalSuperFieldSet(
SendSet node, FieldElement field, Node rhs, T arg) {
handleNSMSuper(node, field.enclosingClass);
}
void visitFinalTopLevelFieldCompound(Send node, FieldElement field,
AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalTopLevelFieldPostfix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalTopLevelFieldPrefix(
Send node, FieldElement field, IncDecOperator operator, T arg) {
handleStatic(node);
handleOperator(node);
handleNSMError(node);
}
void visitFinalTopLevelFieldSet(
SendSet node, FieldElement field, Node rhs, T arg) {
handleNSMError(node);
}
void visitFinalTopLevelFieldSetIfNull(
SendSet node, FieldElement field, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node);
}
void visitTopLevelGetterSetterSetIfNull(Send node, FunctionElement getter,
FunctionElement setter, Node rhs, T arg) {
handleStatic(node);
handleStatic(node);
}
void visitTopLevelMethodSetterSetIfNull(Send node, FunctionElement method,
FunctionElement setter, Node rhs, T arg) {
handleStatic(node);
handleStatic(node);
}
void visitTopLevelMethodSetIfNull(Send node, FunctionElement method,
Node rhs, T arg) {
handleStatic(node);
handleNSMError(node);
}
void visitLocalFunctionIncompatibleInvoke(Send node,
LocalFunctionElement function, NodeList arguments,
CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitLocalFunctionCompound(Send node, LocalFunctionElement function,
AssignmentOperator operator, Node rhs, T arg) {
handleLocal(node);
handleNSMError(node);
handleNoSend(node);
}
void visitLocalFunctionPostfix(Send node, LocalFunctionElement function,
IncDecOperator operator, T arg) {
handleLocal(node);
handleNSMError(node);
handleNoSend(node);
}
void visitLocalFunctionPrefix(Send node, LocalFunctionElement function,
IncDecOperator operator, T arg) {
handleLocal(node);
handleNSMError(node);
handleNoSend(node);
}
void visitLocalFunctionSet(
SendSet node, LocalFunctionElement function, Node rhs, T arg) {
handleNSMError(node);
}
void visitLocalFunctionSetIfNull(
SendSet node, LocalFunctionElement function, Node rhs, T arg) {
handleLocal(node);
handleNSMError(node);
}
void visitStaticFunctionIncompatibleInvoke(Send node, MethodElement function,
NodeList arguments, CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitStaticFunctionSet(
Send node, MethodElement function, Node rhs, T arg) {
handleNSMError(node);
}
void visitStaticMethodCompound(Send node, MethodElement method,
AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node); // operator on a method closure yields nSM
handleNoSend(node); // setter is not invoked, don't count it.
}
void visitStaticMethodPostfix(
Send node, MethodElement method, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitStaticMethodPrefix(
Send node, MethodElement method, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitStaticMethodSetterCompound(Send node, MethodElement method,
MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node); // operator on a method closure yields nSM
handleNoSend(node); // setter is not invoked, don't count it.
}
void visitStaticMethodSetterPostfix(Send node, FunctionElement getter,
FunctionElement setter, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitStaticMethodSetterPrefix(Send node, FunctionElement getter,
FunctionElement setter, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitStaticSetterGet(Send node, FunctionElement setter, T arg) {
handleNSMError(node);
}
void visitStaticSetterInvoke(Send node, FunctionElement setter,
NodeList arguments, CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitSuperMethodCompound(Send node, FunctionElement method,
AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
// An operator send on a method closure yields nSM
handleNSMSuper(node, method.enclosingClass);
handleNoSend(node); // setter is not invoked, don't count it.
}
void visitSuperMethodIncompatibleInvoke(Send node, MethodElement method,
NodeList arguments, CallStructure callStructure, T arg) {
handleNSMSuper(node, method.enclosingClass);
}
void visitSuperMethodPostfix(
Send node, FunctionElement method, IncDecOperator operator, T arg) {
handleSuper(node);
handleNSMSuper(node, method.enclosingClass);
handleNoSend(node);
}
void visitSuperMethodPrefix(
Send node, FunctionElement method, IncDecOperator operator, T arg) {
handleSuper(node);
handleNSMSuper(node, method.enclosingClass);
handleNoSend(node);
}
void visitSuperMethodSet(Send node, MethodElement method, Node rhs, T arg) {
handleNSMSuper(node, method.enclosingClass);
}
void visitSuperMethodSetIfNull(
Send node, MethodElement method, Node rhs, T arg) {
handleNSMSuper(node, method.enclosingClass);
}
void visitSuperSetterGet(Send node, FunctionElement setter, T arg) {
handleNSMSuper(node, setter.enclosingClass);
}
void visitSuperSetterInvoke(Send node, FunctionElement setter,
NodeList arguments, CallStructure callStructure, T arg) {
handleNSMSuper(node, setter.enclosingClass);
}
void visitTopLevelFunctionIncompatibleInvoke(Send node,
MethodElement function, NodeList arguments, CallStructure callStructure,
T arg) {
handleNSMError(node);
}
void visitTopLevelFunctionSet(
Send node, MethodElement function, Node rhs, T arg) {
handleNSMError(node);
}
void visitTopLevelGetterSet(
SendSet node, FunctionElement getter, Node rhs, T arg) {
handleNSMError(node);
}
void visitTopLevelMethodCompound(Send node, FunctionElement method,
AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node); // operator on a method closure yields nSM
handleNoSend(node); // setter is not invoked, don't count it.
}
void visitTopLevelMethodPostfix(
Send node, MethodElement method, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitTopLevelMethodPrefix(
Send node, MethodElement method, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitTopLevelMethodSetterCompound(Send node, FunctionElement method,
FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node); // operator on a method closure yields nSM
handleNoSend(node); // setter is not invoked, don't count it.
}
void visitTopLevelMethodSetterPostfix(Send node, FunctionElement method,
FunctionElement setter, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitTopLevelMethodSetterPrefix(Send node, FunctionElement method,
FunctionElement setter, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitTopLevelSetterGet(Send node, FunctionElement setter, T arg) {
handleNSMError(node);
}
void visitTopLevelSetterInvoke(Send node, FunctionElement setter,
NodeList arguments, CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitTypeVariableTypeLiteralCompound(Send node,
TypeVariableElement element, AssignmentOperator operator, Node rhs,
T arg) {
handleTypeVariable(node);
handleNSMError(node); // operator on a method closure yields nSM
handleNoSend(node); // setter is not invoked, don't count it.
}
void visitTypeVariableTypeLiteralGet(
Send node, TypeVariableElement element, T arg) {
handleTypeVariable(node);
}
void visitTypeVariableTypeLiteralInvoke(Send node,
TypeVariableElement element, NodeList arguments,
CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitTypeVariableTypeLiteralPostfix(
Send node, TypeVariableElement element, IncDecOperator operator, T arg) {
handleTypeVariable(node);
handleNSMError(node);
handleNoSend(node);
}
void visitTypeVariableTypeLiteralPrefix(
Send node, TypeVariableElement element, IncDecOperator operator, T arg) {
handleTypeVariable(node);
handleNSMError(node);
handleNoSend(node);
}
void visitTypeVariableTypeLiteralSet(
SendSet node, TypeVariableElement element, Node rhs, T arg) {
handleNSMError(node);
}
void visitTypeVariableTypeLiteralSetIfNull(
SendSet node, TypeVariableElement element, Node rhs, T arg) {
handleTypeVariable(node);
handleNSMError(node);
}
void visitTypedefTypeLiteralCompound(Send node, ConstantExpression constant,
AssignmentOperator operator, Node rhs, T arg) {
handleTypeVariable(node);
handleNSMError(node);
handleNoSend(node);
}
void visitTypedefTypeLiteralGet(
Send node, ConstantExpression constant, T arg) {
handleTypeVariable(node);
}
void visitTypedefTypeLiteralInvoke(Send node, ConstantExpression constant,
NodeList arguments, CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitTypedefTypeLiteralPostfix(
Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
handleTypeVariable(node);
handleNSMError(node);
handleNoSend(node);
}
void visitTypedefTypeLiteralPrefix(
Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
handleTypeVariable(node);
handleNSMError(node);
handleNoSend(node);
}
void visitTypedefTypeLiteralSet(
SendSet node, ConstantExpression constant, Node rhs, T arg) {
handleNSMError(node);
}
void visitTypedefTypeLiteralSetIfNull(
SendSet node, ConstantExpression constant, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node);
}
void visitUnresolvedClassConstructorInvoke(NewExpression node,
Element element, DartType type, NodeList arguments, Selector selector,
T arg) {
handleNSMError(node);
}
void visitUnresolvedCompound(Send node, Element element,
AssignmentOperator operator, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedConstructorInvoke(NewExpression node, Element constructor,
DartType type, NodeList arguments, Selector selector, T arg) {
handleNSMError(node);
}
void visitUnresolvedGet(Send node, Element element, T arg) {
handleNSMError(node);
}
void visitUnresolvedInvoke(Send node, Element element, NodeList arguments,
Selector selector, T arg) {
handleNSMError(node);
}
void visitUnresolvedPostfix(
Send node, Element element, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedPrefix(
Send node, Element element, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedRedirectingFactoryConstructorInvoke(NewExpression node,
ConstructorElement constructor, InterfaceType type, NodeList arguments,
CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitUnresolvedSet(Send node, Element element, Node rhs, T arg) {
handleNSMError(node);
}
void visitUnresolvedSetIfNull(Send node, Element element, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
}
void visitUnresolvedStaticGetterCompound(Send node, Element element,
MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedStaticGetterPostfix(Send node, Element element,
MethodElement setter, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedStaticGetterPrefix(Send node, Element element,
MethodElement setter, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedStaticGetterSetIfNull(Send node, Element element,
MethodElement setter, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
}
void visitUnresolvedStaticSetterCompound(Send node, MethodElement getter,
Element element, AssignmentOperator operator, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedStaticSetterPostfix(Send node, MethodElement getter,
Element element, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedStaticSetterPrefix(Send node, MethodElement getter,
Element element, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedStaticSetterSetIfNull(Send node, MethodElement getter,
Element element, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
}
void visitUnresolvedSuperBinary(Send node, Element element,
BinaryOperator operator, Node argument, T arg) {
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperCompound(Send node, Element element,
AssignmentOperator operator, Node rhs, T arg) {
handleNSMSuper(node, element.enclosingClass);
// TODO(sigmund): we should only count the next 2 if we know that the
// superclass has a nSM method.
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperCompoundIndexSet(Send node, Element element,
Node index, AssignmentOperator operator, Node rhs, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleNoSend(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperGet(Send node, Element element, T arg) {
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperSetIfNull(
Send node, Element element, Node rhs, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleNoSend(node);
}
void visitUnresolvedSuperGetterCompound(Send node, Element element,
MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleSuper(node);
}
void visitUnresolvedSuperGetterCompoundIndexSet(Send node, Element element,
MethodElement setter, Node index, AssignmentOperator operator, Node rhs,
T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleSuper(node);
}
void visitUnresolvedSuperGetterIndexPostfix(Send node, Element element,
MethodElement setter, Node index, IncDecOperator operator, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleSuper(node);
}
void visitUnresolvedSuperGetterIndexPrefix(Send node, Element element,
MethodElement setter, Node index, IncDecOperator operator, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleSuper(node);
}
void visitUnresolvedSuperGetterPostfix(Send node, Element element,
MethodElement setter, IncDecOperator operator, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleSuper(node);
}
void visitUnresolvedSuperGetterPrefix(Send node, Element element,
MethodElement setter, IncDecOperator operator, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleSuper(node);
}
void visitUnresolvedSuperGetterSetIfNull(Send node, Element element,
MethodElement setter, Node rhs, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleSuper(node);
}
void visitUnresolvedSuperIndex(
Send node, Element element, Node index, T arg) {
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperIndexPostfix(
Send node, Element element, Node index, IncDecOperator operator, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperIndexPrefix(
Send node, Element element, Node index, IncDecOperator operator, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperIndexSet(
Send node, Element element, Node index, Node rhs, T arg) {
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperInvoke(Send node, Element element,
NodeList arguments, Selector selector, T arg) {
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperPostfix(
Send node, Element element, IncDecOperator operator, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperPrefix(
Send node, Element element, IncDecOperator operator, T arg) {
handleNSMSuper(node, element.enclosingClass);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperSetterCompound(Send node, MethodElement getter,
Element element, AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperSetterCompoundIndexSet(Send node,
MethodElement getter, Element element, Node index,
AssignmentOperator operator, Node rhs, T arg) {
handleSuper(node);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperSetterIndexPostfix(Send node,
MethodElement indexFunction, Element element, Node index,
IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperSetterIndexPrefix(Send node,
MethodElement indexFunction, Element element, Node index,
IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperSetterPostfix(Send node, MethodElement getter,
Element element, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperSetterPrefix(Send node, MethodElement getter,
Element element, IncDecOperator operator, T arg) {
handleSuper(node);
handleOperator(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperSetterSetIfNull(Send node, MethodElement getter,
Element element, Node rhs, T arg) {
handleSuper(node);
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedSuperUnary(
Send node, UnaryOperator operator, Element element, T arg) {
handleNSMSuper(node, element.enclosingClass);
}
void visitUnresolvedTopLevelGetterCompound(Send node, Element element,
MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedTopLevelGetterPostfix(Send node, Element element,
MethodElement setter, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedTopLevelGetterPrefix(Send node, Element element,
MethodElement setter, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedTopLevelGetterSetIfNull(Send node, Element element,
MethodElement setter, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
}
void visitUnresolvedTopLevelSetterCompound(Send node, MethodElement getter,
Element element, AssignmentOperator operator, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedTopLevelSetterPostfix(Send node, MethodElement getter,
Element element, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedTopLevelSetterPrefix(Send node, MethodElement getter,
Element element, IncDecOperator operator, T arg) {
handleNSMError(node);
handleNoSend(node);
handleNoSend(node);
}
void visitUnresolvedTopLevelSetterSetIfNull(Send node, MethodElement getter,
Element element, Node rhs, T arg) {
handleNSMError(node);
handleNoSend(node);
}
// Static
void visitConstantGet(Send node, ConstantExpression constant, T arg) {
handleStatic(node);
}
void visitConstantInvoke(Send node, ConstantExpression constant,
NodeList arguments, CallStructure callStreucture, T arg) {
handleStatic(node);
}
void visitFactoryConstructorInvoke(NewExpression node,
ConstructorElement constructor, InterfaceType type, NodeList arguments,
CallStructure callStructure, T arg) {
handleStatic(node);
}
void visitStaticFieldGet(Send node, FieldElement field, T arg) {
handleStatic(node);
}
void visitStaticFieldSet(SendSet node, FieldElement field, Node rhs, T arg) {
handleStatic(node);
}
void visitStaticFieldSetIfNull(
SendSet node, FieldElement field, Node rhs, T arg) {
handleStatic(node);
handleStatic(node);
}
void visitStaticFunctionGet(Send node, MethodElement function, T arg) {
handleStatic(node);
}
void visitStaticFunctionInvoke(Send node, MethodElement function,
NodeList arguments, CallStructure callStructure, T arg) {
handleStatic(node);
}
void visitStaticGetterGet(Send node, FunctionElement getter, T arg) {
handleStatic(node);
}
void visitStaticGetterSet(
SendSet node, FunctionElement getter, Node rhs, T arg) {
handleStatic(node);
}
void visitStaticSetterSet(
SendSet node, FunctionElement setter, Node rhs, T arg) {
handleStatic(node);
}
void visitStaticGetterSetterSetIfNull(
Send node,
FunctionElement getter,
FunctionElement setter,
Node rhs,
T arg) {
handleStatic(node);
handleStatic(node);
}
void visitStaticMethodSetterSetIfNull(
Send node,
MethodElement method,
MethodElement setter,
Node rhs,
T arg) {
handleStatic(node);
handleStatic(node);
}
void visitStaticMethodSetIfNull(
Send node,
FunctionElement method,
Node rhs,
T arg) {
handleStatic(node);
handleNSMError(node);
}
void visitTopLevelFieldGet(Send node, FieldElement field, T arg) {
handleStatic(node);
}
void visitTopLevelFieldSet(
SendSet node, FieldElement field, Node rhs, T arg) {
handleStatic(node);
}
void visitTopLevelFieldSetIfNull(
SendSet node, FieldElement field, Node rhs, T arg) {
handleStatic(node);
handleStatic(node);
}
void visitTopLevelFunctionGet(Send node, MethodElement function, T arg) {
handleStatic(node);
}
void visitTopLevelFunctionInvoke(Send node, MethodElement function,
NodeList arguments, CallStructure callStructure, T arg) {
handleStatic(node);
}
void visitTopLevelGetterGet(Send node, FunctionElement getter, T arg) {
handleStatic(node);
}
void visitTopLevelSetterSet(
SendSet node, FunctionElement setter, Node rhs, T arg) {
handleStatic(node);
}
// Virtual
void visitSuperCompoundIndexSet(SendSet node, MethodElement getter,
MethodElement setter, Node index, AssignmentOperator operator, Node rhs,
T arg) {
handleSuper(node);
handleOperator(node);
handleSuper(node);
}
void visitThisGet(Identifier node, T arg) {
handleLocal(node); // TODO(sigmund): should we add a metric for "this"?
}
void visitThisInvoke(
Send node, NodeList arguments, CallStructure callStructure, T arg) {
// TODO(sigmund): implement (treat like this.call())
handleDynamic(node);
}
void visitThisPropertyGet(Send node, Name name, T arg) {
handleThisProperty(node, new Selector.getter(name));
}
void visitThisPropertySet(SendSet node, Name name, Node rhs, T arg) {
handleThisProperty(node, new Selector.setter(name));
}
void visitThisPropertySetIfNull(Send node, Name name, Node rhs, T arg) {
handleThisProperty(node, new Selector.getter(name));
handleThisProperty(node, new Selector.setter(name));
}
// Not count
void errorNonConstantConstructorInvoke(NewExpression node, Element element,
DartType type, NodeList arguments, CallStructure callStructure, T arg) {
handleNoSend(node);
}
void errorUndefinedBinaryExpression(
Send node, Node left, Operator operator, Node right, T arg) {
handleNoSend(node);
}
void errorUndefinedUnaryExpression(
Send node, Operator operator, Node expression, T arg) {
handleNoSend(node);
}
void errorInvalidGet(
Send node,
ErroneousElement error,
T arg) {
handleNoSend(node);
}
void errorInvalidInvoke(
Send node,
ErroneousElement error,
NodeList arguments,
Selector selector,
T arg) {
handleNoSend(node);
}
void errorInvalidSet(
Send node,
ErroneousElement error,
Node rhs,
T arg) {
handleNoSend(node);
}
void errorInvalidSetIfNull(
Send node, ErroneousElement error, Node rhs, T arg) {
handleNoSend(node);
handleNoSend(node);
}
void errorInvalidPrefix(
Send node,
ErroneousElement error,
IncDecOperator operator,
T arg) {
handleNoSend(node);
}
void errorInvalidPostfix(
Send node,
ErroneousElement error,
IncDecOperator operator,
T arg) {
handleNoSend(node);
}
void errorInvalidCompound(
Send node,
ErroneousElement error,
AssignmentOperator operator,
Node rhs,
T arg) {
handleNoSend(node);
}
void errorInvalidUnary(
Send node,
UnaryOperator operator,
ErroneousElement error,
T arg) {
handleNoSend(node);
}
void errorInvalidEquals(
Send node,
ErroneousElement error,
Node right,
T arg) {
handleNoSend(node);
}
void errorInvalidNotEquals(
Send node,
ErroneousElement error,
Node right,
T arg) {
handleNoSend(node);
}
void errorInvalidBinary(
Send node,
ErroneousElement error,
BinaryOperator operator,
Node right,
T arg) {
handleNoSend(node);
}
void errorInvalidIndex(
Send node,
ErroneousElement error,
Node index,
T arg) {
handleNoSend(node);
}
void errorInvalidIndexSet(
Send node,
ErroneousElement error,
Node index,
Node rhs,
T arg) {
handleNoSend(node);
}
void errorInvalidCompoundIndexSet(
Send node,
ErroneousElement error,
Node index,
AssignmentOperator operator,
Node rhs,
T arg) {
handleNoSend(node);
handleNoSend(node);
handleNoSend(node);
}
void errorInvalidIndexPrefix(
Send node,
ErroneousElement error,
Node index,
IncDecOperator operator,
T arg) {
handleNoSend(node);
handleNoSend(node);
}
void errorInvalidIndexPostfix(
Send node,
ErroneousElement error,
Node index,
IncDecOperator operator,
T arg) {
handleNoSend(node);
handleNoSend(node);
}
void previsitDeferredAccess(
Send node,
PrefixElement prefix,
T arg) {
}
void visitAs(Send node, Node expression, DartType type, T arg) {
handleNoSend(node);
}
void visitClassTypeLiteralCompound(Send node, ConstantExpression constant,
AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitClassTypeLiteralGet(Send node, ConstantExpression constant, T arg) {
handleStatic(node);
}
void visitClassTypeLiteralInvoke(Send node, ConstantExpression constant,
NodeList arguments, CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitClassTypeLiteralPostfix(
Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitClassTypeLiteralPrefix(
Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitClassTypeLiteralSet(
SendSet node, ConstantExpression constant, Node rhs, T arg) {
handleNSMError(node);
}
void visitClassTypeLiteralSetIfNull(
SendSet node, ConstantExpression constant, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node);
}
void visitDynamicTypeLiteralCompound(Send node, ConstantExpression constant,
AssignmentOperator operator, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitDynamicTypeLiteralGet(
Send node, ConstantExpression constant, T arg) {
handleNSMError(node);
}
void visitDynamicTypeLiteralInvoke(Send node, ConstantExpression constant,
NodeList arguments, CallStructure callStructure, T arg) {
handleNSMError(node);
}
void visitDynamicTypeLiteralPostfix(
Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitDynamicTypeLiteralPrefix(
Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
handleStatic(node);
handleNSMError(node);
handleNoSend(node);
}
void visitDynamicTypeLiteralSet(
SendSet node, ConstantExpression constant, Node rhs, T arg) {
handleNSMError(node);
}
void visitDynamicTypeLiteralSetIfNull(
SendSet node, ConstantExpression constant, Node rhs, T arg) {
handleStatic(node);
handleNSMError(node);
}
void visitIfNull(Send node, Node left, Node right, T arg) {
handleNoSend(node);
}
void visitIs(Send node, Node expression, DartType type, T arg) {
handleNoSend(node);
}
void visitIsNot(Send node, Node expression, DartType type, T arg) {
handleNoSend(node);
}
void visitLogicalAnd(Send node, Node left, Node right, T arg) {
handleNoSend(node);
}
void visitLogicalOr(Send node, Node left, Node right, T arg) {
handleNoSend(node);
}
void visitNot(Send node, Node expression, T arg) {
handleNoSend(node);
}
String last;
_checkInvariant(node, String msg) {
msg = '$msg ${recursiveDiagnosticString(measurements, Metric.send)}';
if (!measurements.checkInvariant(Metric.send) ||
!measurements.checkInvariant(Metric.monomorphicSend) ||
!measurements.checkInvariant(Metric.polymorphicSend)) {
reporter.reportErrorMessage(node,
MessageKind.GENERIC, {'text': 'bad\n-- $msg\nlast:\n-- $last\n'});
last = msg;
} else {
last = msg;
}
}
}
/// Visitor that collects statistics for a single function.
class _StatsTraversalVisitor<T> extends TraversalVisitor<dynamic, T>
implements SemanticSendVisitor<dynamic, T> {
final DiagnosticReporter reporter;
final _StatsVisitor statsVisitor;
Measurements get measurements => statsVisitor.measurements;
_StatsTraversalVisitor(
Compiler compiler, TreeElements elements, Uri sourceUri)
: reporter = compiler.reporter,
statsVisitor = new _StatsVisitor(compiler.reporter, elements,
// TODO(sigmund): accept a list of analyses, so we can compare them
// together.
true
? new TrustTypesAnalysisResult(elements, compiler.world)
: new NaiveAnalysisResult(),
sourceUri),
super(elements);
void visitSend(Send node) {
try {
node.accept(statsVisitor);
} catch (e, t) {
reporter.reportErrorMessage(
node, MessageKind.GENERIC, {'text': '$e\n$t'});
}
super.visitSend(node);
}
void visitNewExpression(NewExpression node) {
try {
node.accept(statsVisitor);
} catch (e, t) {
reporter.reportErrorMessage(
node, MessageKind.GENERIC, {'text': '$e\n$t'});
}
super.visitNewExpression(node);
}
}
/// Helper to visit elements recursively
// TODO(sigmund): maybe generalize and move to elements/visitor.dart?
abstract class RecursiveElementVisitor<R, A> extends ElementVisitor<R, A> {
@override
R visitWarnOnUseElement(WarnOnUseElement e, A arg) =>
e.wrappedElement.accept(this, arg);
R visitScopeContainerElement(ScopeContainerElement e, A arg) {
e.forEachLocalMember((l) => l.accept(this, arg));
return null;
}
@override
R visitCompilationUnitElement(CompilationUnitElement e, A arg) {
e.forEachLocalMember((l) => l.accept(this, arg));
return null;
}
@override
R visitLibraryElement(LibraryElement e, A arg) {
e.implementation.compilationUnits.forEach((u) => u.accept(this, arg));
return null;
}
@override
R visitVariableElement(VariableElement e, A arg) => null;
@override
R visitParameterElement(ParameterElement e, A arg) => null;
@override
R visitFormalElement(FormalElement e, A arg) => null;
@override
R visitFieldElement(FieldElement e, A arg) => null;
@override
R visitFieldParameterElement(InitializingFormalElement e, A arg) => null;
@override
R visitAbstractFieldElement(AbstractFieldElement e, A arg) => null;
@override
R visitFunctionElement(FunctionElement e, A arg) => null;
@override
R visitConstructorElement(ConstructorElement e, A arg) {
return visitFunctionElement(e, arg);
}
@override
R visitConstructorBodyElement(ConstructorBodyElement e, A arg) {
return visitFunctionElement(e.constructor, arg);
}
@override
R visitClassElement(ClassElement e, A arg) {
return visitScopeContainerElement(e, arg);
}
@override
R visitEnumClassElement(EnumClassElement e, A arg) {
return visitClassElement(e, arg);
}
@override
R visitBoxFieldElement(BoxFieldElement e, A arg) => null;
@override
R visitClosureClassElement(ClosureClassElement e, A arg) {
return visitClassElement(e, arg);
}
@override
R visitClosureFieldElement(ClosureFieldElement e, A arg) {
return visitVariableElement(e, arg);
}
}
// TODO(sigmund): get rid of debug messages.
_debug(String message) {
print('debug: $message');
}