Handle flags at member level

Change-Id: I5fa438789fc1ac52007efeb6ada607f5c51ec037
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108401
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
This commit is contained in:
Johnni Winther 2019-07-10 14:08:33 +00:00 committed by commit-bot@chromium.org
parent 8f90265176
commit f743594375
27 changed files with 635 additions and 514 deletions

View file

@ -68,6 +68,8 @@ class CodegenImpact extends WorldImpact {
class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
static const String tag = 'codegen-impact';
@override
final MemberEntity member;
Set<Pair<DartType, DartType>> _typeVariableBoundsSubtypeChecks;
Set<String> _constSymbols;
List<Set<ClassEntity>> _specializedGetInterceptors;
@ -78,9 +80,10 @@ class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
Set<FunctionEntity> _nativeMethods;
Set<Selector> _oneShotInterceptors;
_CodegenImpact();
_CodegenImpact(this.member);
_CodegenImpact.internal(
this.member,
Set<DynamicUse> dynamicUses,
Set<StaticUse> staticUses,
Set<TypeUse> typeUses,
@ -98,6 +101,7 @@ class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
factory _CodegenImpact.readFromDataSource(DataSource source) {
source.begin(tag);
MemberEntity member = source.readMember();
Set<DynamicUse> dynamicUses = source
.readList(() => DynamicUse.readFromDataSource(source),
emptyAsNull: true)
@ -139,6 +143,7 @@ class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
?.toSet();
source.end(tag);
return new _CodegenImpact.internal(
member,
dynamicUses,
staticUses,
typeUses,
@ -157,6 +162,7 @@ class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
@override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeMember(member);
sink.writeList(dynamicUses, (DynamicUse use) => use.writeToDataSink(sink),
allowNull: true);
sink.writeList(staticUses, (StaticUse use) => use.writeToDataSink(sink),
@ -192,9 +198,11 @@ class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
@override
void apply(WorldImpactVisitor visitor) {
staticUses.forEach(visitor.visitStaticUse);
dynamicUses.forEach(visitor.visitDynamicUse);
typeUses.forEach(visitor.visitTypeUse);
staticUses.forEach((StaticUse use) => visitor.visitStaticUse(member, use));
dynamicUses.forEach((DynamicUse use) => visitor.visitDynamicUse);
typeUses.forEach((TypeUse use) => visitor.visitTypeUse(member, use));
constantUses
.forEach((ConstantUse use) => visitor.visitConstantUse(member, use));
}
void registerTypeVariableBoundsSubtypeCheck(
@ -331,7 +339,7 @@ class CodegenRegistry {
List<ModularExpression> _expressions;
CodegenRegistry(this._elementEnvironment, this._currentElement)
: this._worldImpact = new _CodegenImpact();
: this._worldImpact = new _CodegenImpact(_currentElement);
@override
String toString() => 'CodegenRegistry for $_currentElement';

View file

@ -179,14 +179,14 @@ abstract class DeferredLoadTask extends CompilerTask {
///
/// The collected dependent elements and constants are are added to
/// [elements] and [constants] respectively.
void _collectDirectMemberDependencies(
void _collectDirectMemberDependencies(KClosedWorld closedWorld,
MemberEntity element, Dependencies dependencies) {
// TODO(sigurdm): We want to be more specific about this - need a better
// way to query "liveness".
if (!compiler.resolutionWorldBuilder.isMemberUsed(element)) {
return;
}
_collectDependenciesFromImpact(element, dependencies);
_collectDependenciesFromImpact(closedWorld, element, dependencies);
collectConstantsInBody(element, dependencies);
}
@ -195,7 +195,9 @@ abstract class DeferredLoadTask extends CompilerTask {
///
/// Adds the results to [elements] and [constants].
void _collectAllElementsAndConstantsResolvedFromClass(
ClassEntity element, Dependencies dependencies) {
KClosedWorld closedWorld,
ClassEntity element,
Dependencies dependencies) {
// If we see a class, add everything its live instance members refer
// to. Static members are not relevant, unless we are processing
// extra dependencies due to mirrors.
@ -203,7 +205,7 @@ abstract class DeferredLoadTask extends CompilerTask {
if (!compiler.resolutionWorldBuilder.isMemberUsed(member)) return;
if (!member.isInstanceMember) return;
dependencies.addMember(member);
_collectDirectMemberDependencies(member, dependencies);
_collectDirectMemberDependencies(closedWorld, member, dependencies);
}
ClassEntity cls = element;
@ -219,21 +221,24 @@ abstract class DeferredLoadTask extends CompilerTask {
///
/// Adds the results to [elements] and [constants].
void _collectAllElementsAndConstantsResolvedFromMember(
MemberEntity element, Dependencies dependencies) {
KClosedWorld closedWorld,
MemberEntity element,
Dependencies dependencies) {
if (element is FunctionEntity) {
_collectTypeDependencies(
elementEnvironment.getFunctionType(element), dependencies);
}
if (element.isStatic || element.isTopLevel || element.isConstructor) {
dependencies.addMember(element);
_collectDirectMemberDependencies(element, dependencies);
_collectDirectMemberDependencies(closedWorld, element, dependencies);
}
if (element is ConstructorEntity && element.isGenerativeConstructor) {
// When instantiating a class, we record a reference to the
// constructor, not the class itself. We must add all the
// instance members of the constructor's class.
ClassEntity cls = element.enclosingClass;
_collectAllElementsAndConstantsResolvedFromClass(cls, dependencies);
_collectAllElementsAndConstantsResolvedFromClass(
closedWorld, cls, dependencies);
}
// Other elements, in particular instance members, are ignored as
@ -265,13 +270,14 @@ abstract class DeferredLoadTask extends CompilerTask {
}
/// Extract any dependencies that are known from the impact of [element].
void _collectDependenciesFromImpact(
void _collectDependenciesFromImpact(KClosedWorld closedWorld,
MemberEntity element, Dependencies dependencies) {
WorldImpact worldImpact = compiler.impactCache[element];
compiler.impactStrategy.visitImpact(
element,
worldImpact,
new WorldImpactVisitorImpl(visitStaticUse: (StaticUse staticUse) {
new WorldImpactVisitorImpl(
visitStaticUse: (MemberEntity member, StaticUse staticUse) {
Entity usedEntity = staticUse.element;
if (usedEntity is MemberEntity) {
dependencies.addMember(usedEntity, staticUse.deferredImport);
@ -306,7 +312,7 @@ abstract class DeferredLoadTask extends CompilerTask {
break;
default:
}
}, visitTypeUse: (TypeUse typeUse) {
}, visitTypeUse: (MemberEntity member, TypeUse typeUse) {
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.TYPE_LITERAL:
@ -327,17 +333,21 @@ abstract class DeferredLoadTask extends CompilerTask {
_collectTypeDependencies(type, dependencies);
break;
case TypeUseKind.AS_CAST:
if (!compiler.options.omitAsCasts) {
if (!closedWorld.annotationsData.omitAsCasts(element)) {
_collectTypeDependencies(type, dependencies);
}
break;
case TypeUseKind.IMPLICIT_CAST:
if (compiler.options.implicitDowncastCheckPolicy.isEmitted) {
if (closedWorld.annotationsData
.getImplicitDowncastCheckPolicy(element)
.isEmitted) {
_collectTypeDependencies(type, dependencies);
}
break;
case TypeUseKind.PARAMETER_CHECK:
if (compiler.options.parameterCheckPolicy.isEmitted) {
if (closedWorld.annotationsData
.getParameterCheckPolicy(element)
.isEmitted) {
_collectTypeDependencies(type, dependencies);
}
break;
@ -346,7 +356,7 @@ abstract class DeferredLoadTask extends CompilerTask {
failedAt(element, "Unexpected type use: $typeUse.");
break;
}
}, visitDynamicUse: (DynamicUse dynamicUse) {
}, visitDynamicUse: (MemberEntity member, DynamicUse dynamicUse) {
// TODO(johnniwinther): Use rti need data to skip unneeded type
// arguments.
_collectTypeArgumentDependencies(
@ -360,8 +370,12 @@ abstract class DeferredLoadTask extends CompilerTask {
/// import set, we stop and enqueue a new recursive update in [queue].
///
/// Invariants: oldSet is either null or a subset of newSet.
void _updateConstantRecursive(ConstantValue constant, ImportSet oldSet,
ImportSet newSet, WorkQueue queue) {
void _updateConstantRecursive(
KClosedWorld closedWorld,
ConstantValue constant,
ImportSet oldSet,
ImportSet newSet,
WorkQueue queue) {
if (constant == null) return;
var currentSet = _constantToSet[constant];
@ -375,19 +389,21 @@ abstract class DeferredLoadTask extends CompilerTask {
_constantToSet[constant] = newSet;
if (constant is ConstructedConstantValue) {
ClassEntity cls = constant.type.element;
_updateClassRecursive(cls, oldSet, newSet, queue);
_updateClassRecursive(closedWorld, cls, oldSet, newSet, queue);
}
if (constant is InstantiationConstantValue) {
for (DartType type in constant.typeArguments) {
if (type is InterfaceType) {
_updateClassRecursive(type.element, oldSet, newSet, queue);
_updateClassRecursive(
closedWorld, type.element, oldSet, newSet, queue);
}
}
}
constant.getDependencies().forEach((ConstantValue dependency) {
// Constants are not allowed to refer to deferred constants, so
// no need to check for a deferred type literal here.
_updateConstantRecursive(dependency, oldSet, newSet, queue);
_updateConstantRecursive(
closedWorld, dependency, oldSet, newSet, queue);
});
} else {
assert(
@ -401,8 +417,8 @@ abstract class DeferredLoadTask extends CompilerTask {
}
}
void _updateClassRecursive(ClassEntity element, ImportSet oldSet,
ImportSet newSet, WorkQueue queue) {
void _updateClassRecursive(KClosedWorld closedWorld, ClassEntity element,
ImportSet oldSet, ImportSet newSet, WorkQueue queue) {
if (element == null) return;
ImportSet currentSet = _classToSet[element];
@ -419,17 +435,18 @@ abstract class DeferredLoadTask extends CompilerTask {
_classToSet[element] = newSet;
Dependencies dependencies = new Dependencies();
_collectAllElementsAndConstantsResolvedFromClass(element, dependencies);
_collectAllElementsAndConstantsResolvedFromClass(
closedWorld, element, dependencies);
LibraryEntity library = element.library;
_processDependencies(
library, dependencies, oldSet, newSet, queue, element);
closedWorld, library, dependencies, oldSet, newSet, queue, element);
} else {
queue.addClass(element, newSet);
}
}
void _updateMemberRecursive(MemberEntity element, ImportSet oldSet,
ImportSet newSet, WorkQueue queue) {
void _updateMemberRecursive(KClosedWorld closedWorld, MemberEntity element,
ImportSet oldSet, ImportSet newSet, WorkQueue queue) {
if (element == null) return;
ImportSet currentSet = _memberToSet[element];
@ -446,11 +463,12 @@ abstract class DeferredLoadTask extends CompilerTask {
_memberToSet[element] = newSet;
Dependencies dependencies = new Dependencies();
_collectAllElementsAndConstantsResolvedFromMember(element, dependencies);
_collectAllElementsAndConstantsResolvedFromMember(
closedWorld, element, dependencies);
LibraryEntity library = element.library;
_processDependencies(
library, dependencies, oldSet, newSet, queue, element);
closedWorld, library, dependencies, oldSet, newSet, queue, element);
} else {
queue.addMember(element, newSet);
}
@ -542,8 +560,14 @@ abstract class DeferredLoadTask extends CompilerTask {
}
}
void _processDependencies(LibraryEntity library, Dependencies dependencies,
ImportSet oldSet, ImportSet newSet, WorkQueue queue, Spannable context) {
void _processDependencies(
KClosedWorld closedWorld,
LibraryEntity library,
Dependencies dependencies,
ImportSet oldSet,
ImportSet newSet,
WorkQueue queue,
Spannable context) {
dependencies.classes.forEach((ClassEntity cls, DependencyInfo info) {
_fixClassDependencyInfo(info, cls, library, context);
if (info.isDeferred) {
@ -553,7 +577,7 @@ abstract class DeferredLoadTask extends CompilerTask {
}
}
} else {
_updateClassRecursive(cls, oldSet, newSet, queue);
_updateClassRecursive(closedWorld, cls, oldSet, newSet, queue);
}
});
@ -566,7 +590,7 @@ abstract class DeferredLoadTask extends CompilerTask {
}
}
} else {
_updateMemberRecursive(member, oldSet, newSet, queue);
_updateMemberRecursive(closedWorld, member, oldSet, newSet, queue);
}
});
@ -584,7 +608,7 @@ abstract class DeferredLoadTask extends CompilerTask {
}
}
} else {
_updateConstantRecursive(constant, oldSet, newSet, queue);
_updateConstantRecursive(closedWorld, constant, oldSet, newSet, queue);
}
});
}
@ -773,7 +797,7 @@ abstract class DeferredLoadTask extends CompilerTask {
void emptyQueue() {
while (queue.isNotEmpty) {
WorkItem item = queue.nextItem();
item.update(this, queue);
item.update(this, closedWorld, queue);
}
}
@ -1167,7 +1191,7 @@ abstract class WorkItem {
WorkItem(this.importsToAdd);
void update(DeferredLoadTask task, WorkQueue queue);
void update(DeferredLoadTask task, KClosedWorld closedWorld, WorkQueue queue);
}
/// Summary of the work that needs to be done on a class.
@ -1178,11 +1202,12 @@ class ClassWorkItem extends WorkItem {
ClassWorkItem(this.cls, ImportSet newSet) : super(newSet);
@override
void update(DeferredLoadTask task, WorkQueue queue) {
void update(
DeferredLoadTask task, KClosedWorld closedWorld, WorkQueue queue) {
queue.pendingClasses.remove(cls);
ImportSet oldSet = task._classToSet[cls];
ImportSet newSet = task.importSets.union(oldSet, importsToAdd);
task._updateClassRecursive(cls, oldSet, newSet, queue);
task._updateClassRecursive(closedWorld, cls, oldSet, newSet, queue);
}
}
@ -1194,11 +1219,12 @@ class MemberWorkItem extends WorkItem {
MemberWorkItem(this.member, ImportSet newSet) : super(newSet);
@override
void update(DeferredLoadTask task, WorkQueue queue) {
void update(
DeferredLoadTask task, KClosedWorld closedWorld, WorkQueue queue) {
queue.pendingMembers.remove(member);
ImportSet oldSet = task._memberToSet[member];
ImportSet newSet = task.importSets.union(oldSet, importsToAdd);
task._updateMemberRecursive(member, oldSet, newSet, queue);
task._updateMemberRecursive(closedWorld, member, oldSet, newSet, queue);
}
}
@ -1210,11 +1236,12 @@ class ConstantWorkItem extends WorkItem {
ConstantWorkItem(this.constant, ImportSet newSet) : super(newSet);
@override
void update(DeferredLoadTask task, WorkQueue queue) {
void update(
DeferredLoadTask task, KClosedWorld closedWorld, WorkQueue queue) {
queue.pendingConstants.remove(constant);
ImportSet oldSet = task._constantToSet[constant];
ImportSet newSet = task.importSets.union(oldSet, importsToAdd);
task._updateConstantRecursive(constant, oldSet, newSet, queue);
task._updateConstantRecursive(closedWorld, constant, oldSet, newSet, queue);
}
}

View file

@ -465,14 +465,14 @@ class DumpInfoTask extends CompilerTask implements InfoReporter {
compiler.impactStrategy.visitImpact(
entity,
impact,
new WorldImpactVisitorImpl(visitDynamicUse: (dynamicUse) {
new WorldImpactVisitorImpl(visitDynamicUse: (member, dynamicUse) {
AbstractValue mask = dynamicUse.receiverConstraint;
selections.addAll(closedWorld
// TODO(het): Handle `call` on `Closure` through
// `world.includesClosureCall`.
.locateMembers(dynamicUse.selector, mask)
.map((MemberEntity e) => new Selection(e, mask)));
}, visitStaticUse: (staticUse) {
}, visitStaticUse: (member, staticUse) {
selections.add(new Selection(staticUse.element, null));
}),
IMPACT_USE);

View file

@ -13,10 +13,10 @@ import 'common.dart';
import 'common_elements.dart' show ElementEnvironment;
import 'constants/values.dart';
import 'compiler.dart' show Compiler;
import 'options.dart';
import 'elements/entities.dart';
import 'elements/types.dart';
import 'inferrer/types.dart';
import 'js_backend/annotations.dart';
import 'js_backend/backend.dart' show CodegenInputs;
import 'js_backend/enqueuer.dart';
import 'universe/member_usage.dart';
@ -184,8 +184,8 @@ abstract class EnqueuerListener {
abstract class EnqueuerImpl extends Enqueuer {
CompilerTask get task;
void checkClass(ClassEntity cls);
void processStaticUse(StaticUse staticUse);
void processTypeUse(TypeUse typeUse);
void processStaticUse(MemberEntity member, StaticUse staticUse);
void processTypeUse(MemberEntity member, TypeUse typeUse);
void processDynamicUse(DynamicUse dynamicUse);
void processConstantUse(ConstantUse constantUse);
EnqueuerListener get listener;
@ -235,7 +235,6 @@ class ResolutionEnqueuer extends EnqueuerImpl {
@override
final CompilerTask task;
final String name;
final CompilerOptions _options;
@override
final EnqueuerListener listener;
@ -244,6 +243,7 @@ class ResolutionEnqueuer extends EnqueuerImpl {
final ResolutionEnqueuerWorldBuilder _worldBuilder;
final WorkItemBuilder _workItemBuilder;
final DiagnosticReporter _reporter;
final AnnotationsData _annotationsData;
@override
bool queueIsClosed = false;
@ -256,8 +256,8 @@ class ResolutionEnqueuer extends EnqueuerImpl {
// applying additional impacts before re-emptying the queue.
void Function() onEmptyForTesting;
ResolutionEnqueuer(this.task, this._options, this._reporter, this.listener,
this._worldBuilder, this._workItemBuilder,
ResolutionEnqueuer(this.task, this._reporter, this.listener,
this._worldBuilder, this._workItemBuilder, this._annotationsData,
[this.name = 'resolution enqueuer']) {
_impactVisitor = new EnqueuerImplImpactVisitor(this);
}
@ -365,7 +365,7 @@ class ResolutionEnqueuer extends EnqueuerImpl {
}
@override
void processStaticUse(StaticUse staticUse) {
void processStaticUse(MemberEntity member, StaticUse staticUse) {
task.measureSubtask('resolution.staticUse', () {
_worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
// TODO(johnniwinther): Add `ResolutionWorldBuilder.registerConstructorUse`
@ -383,7 +383,7 @@ class ResolutionEnqueuer extends EnqueuerImpl {
}
@override
void processTypeUse(TypeUse typeUse) {
void processTypeUse(MemberEntity member, TypeUse typeUse) {
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.INSTANTIATION:
@ -399,17 +399,17 @@ class ResolutionEnqueuer extends EnqueuerImpl {
_registerIsCheck(type);
break;
case TypeUseKind.AS_CAST:
if (!_options.omitAsCasts) {
if (!_annotationsData.omitAsCasts(member)) {
_registerIsCheck(type);
}
break;
case TypeUseKind.IMPLICIT_CAST:
if (_options.implicitDowncastCheckPolicy.isEmitted) {
if (_annotationsData.getImplicitDowncastCheckPolicy(member).isEmitted) {
_registerIsCheck(type);
}
break;
case TypeUseKind.PARAMETER_CHECK:
if (_options.parameterCheckPolicy.isEmitted) {
if (_annotationsData.getParameterCheckPolicy(member).isEmitted) {
_registerIsCheck(type);
}
break;
@ -525,22 +525,22 @@ class EnqueuerImplImpactVisitor implements WorldImpactVisitor {
EnqueuerImplImpactVisitor(this.enqueuer);
@override
void visitDynamicUse(DynamicUse dynamicUse) {
void visitDynamicUse(MemberEntity member, DynamicUse dynamicUse) {
enqueuer.processDynamicUse(dynamicUse);
}
@override
void visitStaticUse(StaticUse staticUse) {
enqueuer.processStaticUse(staticUse);
void visitStaticUse(MemberEntity member, StaticUse staticUse) {
enqueuer.processStaticUse(member, staticUse);
}
@override
void visitTypeUse(TypeUse typeUse) {
enqueuer.processTypeUse(typeUse);
void visitTypeUse(MemberEntity member, TypeUse typeUse) {
enqueuer.processTypeUse(member, typeUse);
}
@override
void visitConstantUse(ConstantUse constantUse) {
void visitConstantUse(MemberEntity member, ConstantUse constantUse) {
enqueuer.processConstantUse(constantUse);
}
}

View file

@ -469,11 +469,7 @@ abstract class MemberTypeInformation extends ElementTypeInformation
AbstractValue potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer) {
if (inferrer.options.assignmentCheckPolicy.isTrusted ||
inferrer.options.assignmentCheckPolicy.isEmitted) {
return _potentiallyNarrowType(mask, inferrer);
}
return mask;
return _potentiallyNarrowType(mask, inferrer);
}
AbstractValue _potentiallyNarrowType(
@ -803,7 +799,9 @@ class ParameterTypeInformation extends ElementTypeInformation {
AbstractValue potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer) {
if (inferrer.options.parameterCheckPolicy.isTrusted) {
if (inferrer.closedWorld.annotationsData
.getParameterCheckPolicy(method)
.isTrusted) {
// In checked or strong mode we don't trust the types of the arguments
// passed to a parameter. The means that the checking of a parameter is
// based on the actual arguments.

View file

@ -74,6 +74,38 @@ class PragmaAnnotation {
6, 'assumeDynamic',
forFunctionsOnly: true, internalOnly: true);
static const PragmaAnnotation omitAsCasts = const PragmaAnnotation(
7, 'omitAsCasts',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation emitAsCasts = const PragmaAnnotation(
8, 'emitAsCasts',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation omitImplicitChecks = const PragmaAnnotation(
9, 'omitImplicitChecks',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation emitImplicitChecks = const PragmaAnnotation(
10, 'emitImplicitChecks',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation omitParameterChecks = const PragmaAnnotation(
11, 'omitParameterChecks',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation emitParameterChecks = const PragmaAnnotation(
12, 'emitParameterChecks',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation omitImplicitDowncasts = const PragmaAnnotation(
13, 'omitImplicitDowncasts',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation emitImplicitDowncasts = const PragmaAnnotation(
14, 'emitImplicitDowncasts',
forFunctionsOnly: false, internalOnly: false);
static const List<PragmaAnnotation> values = [
noInline,
tryInline,
@ -82,7 +114,42 @@ class PragmaAnnotation {
noThrows,
noSideEffects,
assumeDynamic,
omitAsCasts,
emitAsCasts,
omitImplicitChecks,
emitImplicitChecks,
omitParameterChecks,
emitParameterChecks,
omitImplicitDowncasts,
emitImplicitDowncasts,
];
static const Map<PragmaAnnotation, Set<PragmaAnnotation>> implies = {
omitImplicitChecks: {omitParameterChecks, omitImplicitDowncasts},
emitImplicitChecks: {emitParameterChecks, emitImplicitDowncasts},
};
static const Map<PragmaAnnotation, Set<PragmaAnnotation>> excludes = {
noInline: {tryInline},
tryInline: {noInline},
omitImplicitChecks: {
emitImplicitChecks,
emitParameterChecks,
emitImplicitDowncasts
},
emitImplicitChecks: {
omitImplicitChecks,
omitParameterChecks,
omitImplicitDowncasts
},
omitParameterChecks: {emitParameterChecks},
emitParameterChecks: {omitParameterChecks},
omitImplicitDowncasts: {emitImplicitDowncasts},
emitImplicitDowncasts: {omitImplicitDowncasts},
};
static const Map<PragmaAnnotation, Set<PragmaAnnotation>> requires = {
noThrows: {noInline},
noSideEffects: {noInline},
};
}
List<PragmaAnnotationData> computePragmaAnnotationData(
@ -124,7 +191,7 @@ EnumSet<PragmaAnnotation> processMemberAnnotations(
DiagnosticReporter reporter,
ir.Member member,
List<PragmaAnnotationData> pragmaAnnotationData) {
EnumSet<PragmaAnnotation> values = new EnumSet<PragmaAnnotation>();
EnumSet<PragmaAnnotation> annotations = new EnumSet<PragmaAnnotation>();
Uri uri = member.enclosingLibrary.importUri;
bool platformAnnotationsAllowed =
@ -137,7 +204,7 @@ EnumSet<PragmaAnnotation> processMemberAnnotations(
for (PragmaAnnotation annotation in PragmaAnnotation.values) {
if (annotation.name == suffix) {
found = true;
values.add(annotation);
annotations.add(annotation);
if (data.hasOptions) {
reporter.reportErrorMessage(
@ -179,36 +246,52 @@ EnumSet<PragmaAnnotation> processMemberAnnotations(
{'text': "Unknown dart2js pragma @pragma('$name')"});
}
}
if (values.contains(PragmaAnnotation.tryInline) &&
values.contains(PragmaAnnotation.noInline)) {
reporter.reportErrorMessage(
computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
'text': "@pragma('dart2js:tryInline') must not be used with "
"@pragma('dart2js:noInline')."
});
values.remove(PragmaAnnotation.tryInline);
for (PragmaAnnotation annotation
in annotations.iterable(PragmaAnnotation.values)) {
Set<PragmaAnnotation> implies = PragmaAnnotation.implies[annotation];
if (implies != null) {
for (PragmaAnnotation other in implies) {
if (annotations.contains(other)) {
reporter.reportHintMessage(
computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
'text': "@pragma('dart2js:${annotation.name}') implies "
"@pragma('dart2js:${annotation.name}')."
});
}
}
}
Set<PragmaAnnotation> excludes = PragmaAnnotation.excludes[annotation];
if (excludes != null) {
for (PragmaAnnotation other in excludes) {
if (annotations.contains(other)) {
reporter.reportErrorMessage(
computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
'text': "@pragma('dart2js:${annotation.name}') must not be used "
"with @pragma('dart2js:${annotation.name}')."
});
}
}
}
Set<PragmaAnnotation> requires = PragmaAnnotation.requires[annotation];
if (requires != null) {
for (PragmaAnnotation other in requires) {
if (!annotations.contains(other)) {
reporter.reportErrorMessage(
computeSourceSpanFromTreeNode(member), MessageKind.GENERIC, {
'text': "@pragma('dart2js:${annotation.name}') should always be "
"combined with @pragma('dart2js:${annotation.name}')."
});
}
}
}
}
if (values.contains(PragmaAnnotation.noThrows) &&
!values.contains(PragmaAnnotation.noInline)) {
reporter.internalError(
computeSourceSpanFromTreeNode(member),
"@pragma('dart2js:noThrows') should always be combined with "
"@pragma('dart2js:noInline').");
}
if (values.contains(PragmaAnnotation.noSideEffects) &&
!values.contains(PragmaAnnotation.noInline)) {
reporter.internalError(
computeSourceSpanFromTreeNode(member),
"@pragma('dart2js:noSideEffects') should always be combined with "
"@pragma('dart2js:noInline').");
}
return values;
return annotations;
}
abstract class AnnotationsData {
/// Deserializes a [AnnotationsData] object from [source].
factory AnnotationsData.readFromDataSource(DataSource source) =
factory AnnotationsData.readFromDataSource(
CompilerOptions options, DataSource source) =
AnnotationsDataImpl.readFromDataSource;
/// Serializes this [AnnotationsData] to [sink].
@ -254,6 +337,28 @@ abstract class AnnotationsData {
/// Calls [f] for all functions with a `@pragma('dart2js:noSideEffects')`
/// annotation.
void forEachNoSideEffects(void f(FunctionEntity function));
/// What should the compiler do with parameter type assertions in [member].
///
/// If [member] is `null`, the default policy is returned.
CheckPolicy getParameterCheckPolicy(MemberEntity member);
/// What should the compiler do with implicit downcasts in [member].
///
/// If [member] is `null`, the default policy is returned.
CheckPolicy getImplicitDowncastCheckPolicy(MemberEntity member);
/// What the compiler should do with a boolean value in a condition context
/// in [member] when the language specification says it is a runtime error for
/// it to be null.
///
/// If [member] is `null`, the default policy is returned.
CheckPolicy getConditionCheckPolicy(MemberEntity member);
/// Whether to omit as casts.
///
/// If [member] is `null`, the default policy is returned.
bool omitAsCasts(MemberEntity member);
}
class AnnotationsDataImpl implements AnnotationsData {
@ -261,17 +366,27 @@ class AnnotationsDataImpl implements AnnotationsData {
/// debugging data stream.
static const String tag = 'annotations-data';
final CheckPolicy _defaultParameterCheckPolicy;
final CheckPolicy _defaultImplicitDowncastCheckPolicy;
final CheckPolicy _defaultConditionCheckPolicy;
final bool _defaultOmitAsCasts;
final Map<MemberEntity, EnumSet<PragmaAnnotation>> pragmaAnnotations;
AnnotationsDataImpl(this.pragmaAnnotations);
AnnotationsDataImpl(CompilerOptions options, this.pragmaAnnotations)
: this._defaultParameterCheckPolicy = options.defaultParameterCheckPolicy,
this._defaultImplicitDowncastCheckPolicy =
options.defaultImplicitDowncastCheckPolicy,
this._defaultConditionCheckPolicy = options.defaultConditionCheckPolicy,
this._defaultOmitAsCasts = options.defaultOmitAsCasts;
factory AnnotationsDataImpl.readFromDataSource(DataSource source) {
factory AnnotationsDataImpl.readFromDataSource(
CompilerOptions options, DataSource source) {
source.begin(tag);
Map<MemberEntity, EnumSet<PragmaAnnotation>> pragmaAnnotations =
source.readMemberMap(
(MemberEntity member) => new EnumSet.fromValue(source.readInt()));
source.end(tag);
return new AnnotationsDataImpl(pragmaAnnotations);
return new AnnotationsDataImpl(options, pragmaAnnotations);
}
@override
@ -356,6 +471,82 @@ class AnnotationsDataImpl implements AnnotationsData {
}
});
}
@override
CheckPolicy getParameterCheckPolicy(MemberEntity member) {
if (member != null) {
EnumSet<PragmaAnnotation> annotations = pragmaAnnotations[member];
if (annotations != null) {
if (annotations.contains(PragmaAnnotation.omitImplicitChecks)) {
return CheckPolicy.trusted;
} else if (annotations.contains(PragmaAnnotation.emitImplicitChecks)) {
return CheckPolicy.checked;
} else if (annotations.contains(PragmaAnnotation.omitParameterChecks)) {
return CheckPolicy.trusted;
} else if (annotations.contains(PragmaAnnotation.emitParameterChecks)) {
return CheckPolicy.checked;
}
}
}
return _defaultParameterCheckPolicy;
}
@override
CheckPolicy getImplicitDowncastCheckPolicy(MemberEntity member) {
if (member != null) {
EnumSet<PragmaAnnotation> annotations = pragmaAnnotations[member];
if (annotations != null) {
if (annotations.contains(PragmaAnnotation.omitImplicitChecks)) {
return CheckPolicy.trusted;
} else if (annotations.contains(PragmaAnnotation.emitImplicitChecks)) {
return CheckPolicy.checked;
} else if (annotations
.contains(PragmaAnnotation.omitImplicitDowncasts)) {
return CheckPolicy.trusted;
} else if (annotations
.contains(PragmaAnnotation.emitImplicitDowncasts)) {
return CheckPolicy.checked;
}
}
}
return _defaultImplicitDowncastCheckPolicy;
}
@override
CheckPolicy getConditionCheckPolicy(MemberEntity member) {
if (member != null) {
EnumSet<PragmaAnnotation> annotations = pragmaAnnotations[member];
if (annotations != null) {
if (annotations.contains(PragmaAnnotation.omitImplicitChecks)) {
return CheckPolicy.trusted;
} else if (annotations.contains(PragmaAnnotation.emitImplicitChecks)) {
return CheckPolicy.checked;
} else if (annotations
.contains(PragmaAnnotation.omitImplicitDowncasts)) {
return CheckPolicy.trusted;
} else if (annotations
.contains(PragmaAnnotation.emitImplicitDowncasts)) {
return CheckPolicy.checked;
}
}
}
return _defaultConditionCheckPolicy;
}
@override
bool omitAsCasts(MemberEntity member) {
if (member != null) {
EnumSet<PragmaAnnotation> annotations = pragmaAnnotations[member];
if (annotations != null) {
if (annotations.contains(PragmaAnnotation.omitAsCasts)) {
return true;
} else if (annotations.contains(PragmaAnnotation.emitAsCasts)) {
return false;
}
}
}
return _defaultOmitAsCasts;
}
}
class AnnotationsDataBuilder {
@ -368,7 +559,7 @@ class AnnotationsDataBuilder {
}
}
AnnotationsData close() {
return new AnnotationsDataImpl(pragmaAnnotations);
AnnotationsData close(CompilerOptions options) {
return new AnnotationsDataImpl(options, pragmaAnnotations);
}
}

View file

@ -13,7 +13,7 @@ import '../common_elements.dart' show ElementEnvironment;
import '../elements/entities.dart';
import '../elements/types.dart';
import '../enqueue.dart';
import '../options.dart';
import '../js_backend/annotations.dart';
import '../universe/codegen_world_builder.dart';
import '../universe/member_usage.dart';
import '../universe/use.dart'
@ -43,7 +43,7 @@ class CodegenEnqueuer extends EnqueuerImpl {
final CompilerTask task;
@override
final EnqueuerListener listener;
final CompilerOptions _options;
final AnnotationsData _annotationsData;
WorldImpactVisitor _impactVisitor;
@ -59,8 +59,8 @@ class CodegenEnqueuer extends EnqueuerImpl {
static const ImpactUseCase IMPACT_USE =
const ImpactUseCase('CodegenEnqueuer');
CodegenEnqueuer(this.task, this._options, this._worldBuilder,
this._workItemBuilder, this.listener)
CodegenEnqueuer(this.task, this._worldBuilder, this._workItemBuilder,
this.listener, this._annotationsData)
: this.name = 'codegen enqueuer' {
_impactVisitor = new EnqueuerImplImpactVisitor(this);
}
@ -166,13 +166,13 @@ class CodegenEnqueuer extends EnqueuerImpl {
}
@override
void processStaticUse(StaticUse staticUse) {
void processStaticUse(MemberEntity member, StaticUse staticUse) {
task.measureSubtask('codegen.staticUse', () {
_worldBuilder.registerStaticUse(staticUse, _applyMemberUse);
switch (staticUse.kind) {
case StaticUseKind.CONSTRUCTOR_INVOKE:
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
processTypeUse(new TypeUse.instantiation(staticUse.type));
processTypeUse(member, new TypeUse.instantiation(staticUse.type));
break;
case StaticUseKind.INLINING:
// TODO(johnniwinther): Should this be tracked with _MemberUsage ?
@ -185,7 +185,7 @@ class CodegenEnqueuer extends EnqueuerImpl {
}
@override
void processTypeUse(TypeUse typeUse) {
void processTypeUse(MemberEntity member, TypeUse typeUse) {
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.INSTANTIATION:
@ -199,17 +199,17 @@ class CodegenEnqueuer extends EnqueuerImpl {
_registerIsCheck(type);
break;
case TypeUseKind.AS_CAST:
if (!_options.omitAsCasts) {
if (!_annotationsData.omitAsCasts(member)) {
_registerIsCheck(type);
}
break;
case TypeUseKind.IMPLICIT_CAST:
if (_options.implicitDowncastCheckPolicy.isEmitted) {
if (_annotationsData.getImplicitDowncastCheckPolicy(member).isEmitted) {
_registerIsCheck(type);
}
break;
case TypeUseKind.PARAMETER_CHECK:
if (_options.parameterCheckPolicy.isEmitted) {
if (_annotationsData.getParameterCheckPolicy(member).isEmitted) {
_registerIsCheck(type);
}
break;

View file

@ -19,13 +19,13 @@ import '../elements/types.dart';
import '../js_emitter/native_emitter.dart';
import '../native/enqueue.dart';
import '../native/behavior.dart';
import '../options.dart';
import '../universe/feature.dart';
import '../universe/selector.dart';
import '../universe/use.dart';
import '../universe/world_impact.dart' show TransformedWorldImpact, WorldImpact;
import '../util/util.dart';
import '../world.dart';
import 'annotations.dart';
import 'backend_impact.dart';
import 'backend_usage.dart';
import 'custom_elements_analysis.dart';
@ -35,7 +35,6 @@ import 'native_data.dart';
import 'runtime_types.dart';
class JavaScriptImpactTransformer extends ImpactTransformer {
final CompilerOptions _options;
final ElementEnvironment _elementEnvironment;
final CommonElements _commonElements;
final BackendImpacts _impacts;
@ -45,9 +44,9 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
final RuntimeTypesNeedBuilder _rtiNeedBuilder;
final ClassHierarchyBuilder _classHierarchyBuilder;
final AnnotationsData _annotationsData;
JavaScriptImpactTransformer(
this._options,
this._elementEnvironment,
this._commonElements,
this._impacts,
@ -56,7 +55,8 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
this._backendUsageBuilder,
this._customElementsResolutionAnalysis,
this._rtiNeedBuilder,
this._classHierarchyBuilder);
this._classHierarchyBuilder,
this._annotationsData);
@override
WorldImpact transformResolutionImpact(ResolutionImpact worldImpact) {
@ -158,18 +158,22 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
onIsCheck(type, transformed);
break;
case TypeUseKind.AS_CAST:
if (!_options.omitAsCasts) {
if (!_annotationsData.omitAsCasts(worldImpact.member)) {
onIsCheck(type, transformed);
hasAsCast = true;
}
break;
case TypeUseKind.IMPLICIT_CAST:
if (_options.implicitDowncastCheckPolicy.isEmitted) {
if (_annotationsData
.getImplicitDowncastCheckPolicy(worldImpact.member)
.isEmitted) {
onIsCheck(type, transformed);
}
break;
case TypeUseKind.PARAMETER_CHECK:
if (_options.parameterCheckPolicy.isEmitted) {
if (_annotationsData
.getParameterCheckPolicy(worldImpact.member)
.isEmitted) {
onIsCheck(type, transformed);
}
break;
@ -343,7 +347,6 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
}
class CodegenImpactTransformer {
final CompilerOptions _options;
final JClosedWorld _closedWorld;
final ElementEnvironment _elementEnvironment;
final CommonElements _commonElements;
@ -358,7 +361,6 @@ class CodegenImpactTransformer {
final NativeEmitter _nativeEmitter;
CodegenImpactTransformer(
this._options,
this._closedWorld,
this._elementEnvironment,
this._commonElements,

View file

@ -19,6 +19,7 @@ import '../ir/runtime_type_analysis.dart';
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
import '../js_emitter/js_emitter.dart' show ModularEmitter;
import '../kernel/kelements.dart';
import '../options.dart';
import '../serialization/serialization.dart';
import '../universe/class_hierarchy.dart';
@ -1643,24 +1644,31 @@ class RuntimeTypesNeedBuilderImpl extends _RuntimeTypesBase
}
}
if (options.parameterCheckPolicy.isEmitted) {
void checkFunction(Entity function, FunctionType type) {
for (FunctionTypeVariable typeVariable in type.typeVariables) {
DartType bound = typeVariable.bound;
if (!bound.isDynamic &&
!bound.isVoid &&
bound != closedWorld.commonElements.objectType) {
potentiallyNeedTypeArguments(function);
break;
}
void checkFunction(Entity function, FunctionType type) {
for (FunctionTypeVariable typeVariable in type.typeVariables) {
DartType bound = typeVariable.bound;
if (!bound.isDynamic &&
!bound.isVoid &&
bound != closedWorld.commonElements.objectType) {
potentiallyNeedTypeArguments(function);
break;
}
}
}
closedWorld.forEachGenericMethod((FunctionEntity method) {
closedWorld.forEachGenericMethod((FunctionEntity method) {
if (closedWorld.annotationsData
.getParameterCheckPolicy(method)
.isEmitted) {
checkFunction(method, _elementEnvironment.getFunctionType(method));
});
for (Local function in closedWorld.genericLocalFunctions) {
}
});
for (KLocalFunction function in closedWorld.genericLocalFunctions) {
if (closedWorld.annotationsData
// TODO(johnniwinther): Support @pragma on local functions and use
// this here instead of the enclosing member.
.getParameterCheckPolicy(function.memberContext)
.isEmitted) {
checkFunction(
function, _elementEnvironment.getLocalFunctionType(function));
}
@ -2149,8 +2157,10 @@ class RuntimeTypesImpl extends _RuntimeTypesBase
});
liveClasses.forEach(processClass);
if (options.parameterCheckPolicy.isEmitted) {
codegenWorld.forEachGenericMethod((FunctionEntity method) {
codegenWorld.forEachGenericMethod((FunctionEntity method) {
if (_closedWorld.annotationsData
.getParameterCheckPolicy(method)
.isEmitted) {
if (_rtiNeed.methodNeedsTypeArguments(method)) {
for (TypeVariableType typeVariable
in _elementEnvironment.getFunctionTypeVariables(method)) {
@ -2161,8 +2171,8 @@ class RuntimeTypesImpl extends _RuntimeTypesBase
bound, TypeVisitorState.covariantTypeArgument);
}
}
});
}
}
});
cachedRequiredChecks = _computeChecks(classUseMap);
rtiChecksBuilderClosed = true;

View file

@ -18,7 +18,6 @@ import '../js_backend/custom_elements_analysis.dart'
import '../js_backend/native_data.dart';
import '../js_backend/interceptor_data.dart';
import '../native/enqueue.dart';
import '../options.dart';
import '../universe/codegen_world_builder.dart';
import '../universe/selector.dart' show Selector;
import '../world.dart' show JClosedWorld;
@ -26,7 +25,6 @@ import '../world.dart' show JClosedWorld;
import 'code_emitter_task.dart' show Emitter;
class InterceptorStubGenerator {
final CompilerOptions _options;
final CommonElements _commonElements;
final Emitter _emitter;
final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
@ -36,7 +34,6 @@ class InterceptorStubGenerator {
final JClosedWorld _closedWorld;
InterceptorStubGenerator(
this._options,
this._commonElements,
this._emitter,
this._nativeCodegenEnqueuer,
@ -304,7 +301,12 @@ class InterceptorStubGenerator {
// checked mode, so we don't optimize the interceptor if the
// _compiler has type assertions enabled.
if (selector.isIndexSet &&
(_options.parameterCheckPolicy.isEmitted || !containsArray)) {
// TODO(johnniwinther): Support annotations on the possible targets
// and used their parameter check policy here.
(_closedWorld.annotationsData
.getParameterCheckPolicy(null)
.isEmitted ||
!containsArray)) {
return null;
}
if (!containsArray && !containsString) {

View file

@ -89,7 +89,9 @@ class FieldVisitor {
js.Name accessorName = _namer.fieldAccessorName(field);
js.Name fieldName = _namer.fieldPropertyName(field);
bool needsCheckedSetter = false;
if (_options.parameterCheckPolicy.isEmitted &&
if (_closedWorld.annotationsData
.getParameterCheckPolicy(field)
.isEmitted &&
needsSetter &&
!canAvoidGeneratedCheckedSetter(field)) {
needsCheckedSetter = true;

View file

@ -337,7 +337,6 @@ class ProgramBuilder {
js.Expression _buildTypeToInterceptorMap() {
InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
_options,
_commonElements,
_task.emitter,
_nativeCodegenEnqueuer,
@ -1010,7 +1009,6 @@ class ProgramBuilder {
Iterable<StaticStubMethod> _generateGetInterceptorMethods() {
InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
_options,
_commonElements,
_task.emitter,
_nativeCodegenEnqueuer,
@ -1115,7 +1113,6 @@ class ProgramBuilder {
Iterable<StaticStubMethod> _generateOneShotInterceptors() {
InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
_options,
_commonElements,
_task.emitter,
_nativeCodegenEnqueuer,

View file

@ -13,10 +13,10 @@ import '../elements/types.dart';
import '../ir/closure.dart';
import '../ir/element_map.dart';
import '../ir/static_type_cache.dart';
import '../js_backend/annotations.dart';
import '../js_model/element_map.dart';
import '../js_model/env.dart';
import '../ordered_typeset.dart';
import '../options.dart';
import '../serialization/serialization.dart';
import '../ssa/type_builder.dart';
import '../universe/selector.dart';
@ -151,7 +151,7 @@ class ClosureDataImpl implements ClosureData {
class ClosureDataBuilder {
final JsToElementMap _elementMap;
final GlobalLocalsMap _globalLocalsMap;
final CompilerOptions _options;
final AnnotationsData _annotationsData;
/// Map of the scoping information that corresponds to a particular entity.
Map<MemberEntity, ScopeInfo> _scopeMap = {};
@ -163,7 +163,8 @@ class ClosureDataBuilder {
Map<ir.LocalFunction, ClosureRepresentationInfo>
_localClosureRepresentationMap = {};
ClosureDataBuilder(this._elementMap, this._globalLocalsMap, this._options);
ClosureDataBuilder(
this._elementMap, this._globalLocalsMap, this._annotationsData);
void _updateScopeBasedOnRtiNeed(KernelScopeInfo scope, ClosureRtiNeed rtiNeed,
MemberEntity outermostEntity) {
@ -174,16 +175,14 @@ class ClosureDataBuilder {
return true;
break;
case VariableUseKind.implicitCast:
if (_options.implicitDowncastCheckPolicy.isEmitted) {
if (_annotationsData
.getImplicitDowncastCheckPolicy(outermostEntity)
.isEmitted) {
return true;
}
break;
case VariableUseKind.localType:
if (_options.assignmentCheckPolicy.isEmitted) {
return true;
}
break;
case VariableUseKind.constructorTypeArgument:
ConstructorEntity constructor =
_elementMap.getConstructor(usage.member);
@ -213,7 +212,9 @@ class ClosureDataBuilder {
}
break;
case VariableUseKind.memberParameter:
if (_options.parameterCheckPolicy.isEmitted) {
if (_annotationsData
.getParameterCheckPolicy(outermostEntity)
.isEmitted) {
return true;
} else {
FunctionEntity method = _elementMap.getMethod(usage.member);
@ -223,7 +224,9 @@ class ClosureDataBuilder {
}
break;
case VariableUseKind.localParameter:
if (_options.parameterCheckPolicy.isEmitted) {
if (_annotationsData
.getParameterCheckPolicy(outermostEntity)
.isEmitted) {
return true;
} else if (rtiNeed
.localFunctionNeedsSignature(usage.localFunction)) {
@ -231,26 +234,20 @@ class ClosureDataBuilder {
}
break;
case VariableUseKind.memberReturnType:
if (_options.assignmentCheckPolicy.isEmitted) {
FunctionEntity method = _elementMap.getMethod(usage.member);
if (rtiNeed.methodNeedsSignature(method)) {
return true;
} else {
FunctionEntity method = _elementMap.getMethod(usage.member);
if (rtiNeed.methodNeedsSignature(method)) {
return true;
}
}
break;
case VariableUseKind.localReturnType:
if (_options.assignmentCheckPolicy.isEmitted) {
return true;
} else if (rtiNeed
.localFunctionNeedsSignature(usage.localFunction)) {
if (rtiNeed.localFunctionNeedsSignature(usage.localFunction)) {
return true;
}
break;
case VariableUseKind.fieldType:
if (_options.assignmentCheckPolicy.isEmitted ||
_options.parameterCheckPolicy.isEmitted) {
if (_annotationsData
.getParameterCheckPolicy(outermostEntity)
.isEmitted) {
return true;
}
break;

View file

@ -169,7 +169,7 @@ class JsBackendStrategy implements BackendStrategy {
closedWorld.annotationsData);
GlobalLocalsMap _globalLocalsMap = new GlobalLocalsMap();
ClosureDataBuilder closureDataBuilder = new ClosureDataBuilder(
_elementMap, _globalLocalsMap, _compiler.options);
_elementMap, _globalLocalsMap, closedWorld.annotationsData);
JsClosedWorldBuilder closedWorldBuilder = new JsClosedWorldBuilder(
_elementMap,
_globalLocalsMap,
@ -256,7 +256,6 @@ class JsBackendStrategy implements BackendStrategy {
commonElements, elementEnvironment, closedWorld.nativeData);
return new CodegenEnqueuer(
task,
_compiler.options,
new CodegenWorldBuilderImpl(
closedWorld,
_compiler.abstractValueStrategy.createSelectorStrategy(),
@ -277,7 +276,8 @@ class JsBackendStrategy implements BackendStrategy {
closedWorld.backendUsage,
closedWorld.rtiNeed,
customElementsCodegenAnalysis,
nativeCodegenEnqueuer));
nativeCodegenEnqueuer),
closedWorld.annotationsData);
}
/// Called before the compiler starts running the codegen enqueuer.
@ -308,7 +308,6 @@ class JsBackendStrategy implements BackendStrategy {
closedWorld.commonElements, _compiler.options.experimentNewRti);
_codegenImpactTransformer = new CodegenImpactTransformer(
_compiler.options,
closedWorld,
closedWorld.elementEnvironment,
closedWorld.commonElements,

View file

@ -163,7 +163,7 @@ class JsClosedWorld implements JClosedWorld {
source.readClassMap(() => source.readClasses().toSet());
AnnotationsData annotationsData =
new AnnotationsData.readFromDataSource(source);
new AnnotationsData.readFromDataSource(options, source);
ClosureData closureData =
new ClosureData.readFromDataSource(elementMap, source);

View file

@ -196,7 +196,7 @@ class JsClosedWorldBuilder {
JFieldAnalysis.from(closedWorld, map, _options);
AnnotationsDataImpl oldAnnotationsData = closedWorld.annotationsData;
AnnotationsData annotationsData = new AnnotationsDataImpl(
AnnotationsData annotationsData = new AnnotationsDataImpl(_options,
map.toBackendMemberMap(oldAnnotationsData.pragmaAnnotations, identity));
OutputUnitData outputUnitData =

View file

@ -58,8 +58,7 @@ class KernelImpactBuilder extends ImpactBuilderBase
VariableScopeModel variableScopeModel,
this._annotations,
this._constantValuefier)
: this.impactBuilder =
new ResolutionWorldImpactBuilder('${currentMember}'),
: this.impactBuilder = new ResolutionWorldImpactBuilder(currentMember),
super(elementMap.typeEnvironment, elementMap.classHierarchy,
variableScopeModel);
@ -95,8 +94,7 @@ class KernelImpactConverter extends KernelImpactRegistryMixin {
KernelImpactConverter(this.elementMap, this.currentMember, this.reporter,
this._options, this._constantValuefier)
: this.impactBuilder =
new ResolutionWorldImpactBuilder('${currentMember}');
: this.impactBuilder = new ResolutionWorldImpactBuilder(currentMember);
@override
ir.TypeEnvironment get typeEnvironment => elementMap.typeEnvironment;

View file

@ -158,8 +158,14 @@ class KernelFrontendStrategy extends FrontendStrategy {
ClassQueries classQueries = new KernelClassQueries(elementMap);
ClassHierarchyBuilder classHierarchyBuilder =
new ClassHierarchyBuilder(commonElements, classQueries);
AnnotationsDataBuilder annotationsDataBuilder =
new AnnotationsDataBuilder();
// TODO(johnniwinther): This is a hack. The annotation data is built while
// using it. With CFE constants the annotations data can be built fully
// before creating the resolution enqueuer.
AnnotationsData annotationsData = new AnnotationsDataImpl(
compiler.options, annotationsDataBuilder.pragmaAnnotations);
impactTransformer = new JavaScriptImpactTransformer(
compiler.options,
elementEnvironment,
commonElements,
impacts,
@ -168,15 +174,13 @@ class KernelFrontendStrategy extends FrontendStrategy {
_backendUsageBuilder,
_customElementsResolutionAnalysis,
rtiNeedBuilder,
classHierarchyBuilder);
classHierarchyBuilder,
annotationsData);
InterceptorDataBuilder interceptorDataBuilder =
new InterceptorDataBuilderImpl(
nativeBasicData, elementEnvironment, commonElements);
AnnotationsDataBuilder annotationsDataBuilder =
new AnnotationsDataBuilder();
return new ResolutionEnqueuer(
task,
compiler.options,
compiler.reporter,
new ResolutionEnqueuerListener(
compiler.options,
@ -220,7 +224,8 @@ class KernelFrontendStrategy extends FrontendStrategy {
compiler.impactCache,
_fieldAnalysis,
_modularStrategy,
_irAnnotationData));
_irAnnotationData),
annotationsData);
}
@override

View file

@ -255,34 +255,29 @@ class CompilerOptions implements DiagnosticOptions {
/// Whether to omit implicit strong mode checks.
bool omitImplicitChecks = false;
/// Whether to omit as casts.
bool omitAsCasts = false;
/// Whether to omit as casts by default.
bool defaultOmitAsCasts = false;
/// Whether to omit class type arguments only needed for `toString` on
/// `Object.runtimeType`.
bool laxRuntimeTypeToString = false;
/// What should the compiler do with type assertions of assignments.
///
/// This is an internal configuration option derived from other flags.
CheckPolicy assignmentCheckPolicy;
/// What should the compiler do with parameter type assertions.
///
/// This is an internal configuration option derived from other flags.
CheckPolicy parameterCheckPolicy;
CheckPolicy defaultParameterCheckPolicy;
/// What should the compiler do with implicit downcasts.
///
/// This is an internal configuration option derived from other flags.
CheckPolicy implicitDowncastCheckPolicy;
CheckPolicy defaultImplicitDowncastCheckPolicy;
/// What the compiler should do with a boolean value in a condition context
/// when the language specification says it is a runtime error for it to be
/// null.
///
/// This is an internal configuration option derived from other flags.
CheckPolicy conditionCheckPolicy;
CheckPolicy defaultConditionCheckPolicy;
/// Whether to generate code compliant with content security policy (CSP).
bool useContentSecurityPolicy = false;
@ -410,7 +405,7 @@ class CompilerOptions implements DiagnosticOptions {
platformBinaries ?? _extractUriOption(options, '--platform-binaries=')
..sourceMapUri = _extractUriOption(options, '--source-map=')
..omitImplicitChecks = _hasOption(options, Flags.omitImplicitChecks)
..omitAsCasts = _hasOption(options, Flags.omitAsCasts)
..defaultOmitAsCasts = _hasOption(options, Flags.omitAsCasts)
..laxRuntimeTypeToString =
_hasOption(options, Flags.laxRuntimeTypeToString)
..testMode = _hasOption(options, Flags.testMode)
@ -492,15 +487,14 @@ class CompilerOptions implements DiagnosticOptions {
// Strong mode always trusts type annotations (inferred or explicit), so
// assignments checks should be trusted.
assignmentCheckPolicy = CheckPolicy.trusted;
if (omitImplicitChecks) {
parameterCheckPolicy = CheckPolicy.trusted;
implicitDowncastCheckPolicy = CheckPolicy.trusted;
conditionCheckPolicy = CheckPolicy.trusted;
defaultParameterCheckPolicy = CheckPolicy.trusted;
defaultImplicitDowncastCheckPolicy = CheckPolicy.trusted;
defaultConditionCheckPolicy = CheckPolicy.trusted;
} else {
parameterCheckPolicy = CheckPolicy.checked;
implicitDowncastCheckPolicy = CheckPolicy.checked;
conditionCheckPolicy = CheckPolicy.checked;
defaultParameterCheckPolicy = CheckPolicy.checked;
defaultImplicitDowncastCheckPolicy = CheckPolicy.checked;
defaultConditionCheckPolicy = CheckPolicy.checked;
}
if (_disableMinification) {

View file

@ -6,7 +6,7 @@ library dart2js.resolution.registry;
import '../common/resolution.dart' show ResolutionImpact;
import '../constants/expressions.dart';
import '../elements/entities.dart' show ClassEntity;
import '../elements/entities.dart' show ClassEntity, MemberEntity;
import '../universe/feature.dart';
import '../universe/world_impact.dart' show WorldImpact, WorldImpactBuilderImpl;
import '../util/enumset.dart' show EnumSet;
@ -14,7 +14,8 @@ import '../util/util.dart' show Setlet;
class ResolutionWorldImpactBuilder extends WorldImpactBuilderImpl
implements ResolutionImpact {
final String name;
@override
final MemberEntity member;
EnumSet<Feature> _features;
Setlet<MapLiteralUse> _mapLiterals;
Setlet<SetLiteralUse> _setLiterals;
@ -26,7 +27,7 @@ class ResolutionWorldImpactBuilder extends WorldImpactBuilderImpl
Set<RuntimeTypeUse> _runtimeTypeUses;
Set<GenericInstantiation> _genericInstantiations;
ResolutionWorldImpactBuilder(this.name);
ResolutionWorldImpactBuilder(this.member);
@override
bool get isEmpty => false;
@ -144,7 +145,7 @@ class ResolutionWorldImpactBuilder extends WorldImpactBuilderImpl
@override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('ResolutionWorldImpactBuilder($name)');
sb.write('ResolutionWorldImpactBuilder($member)');
WorldImpact.printOn(sb, this);
if (_features != null) {
sb.write('\n features:');

View file

@ -472,7 +472,9 @@ class KernelSsaGraphBuilder extends ir.Visitor {
}
if (targetElement.isInstanceMember) {
if (fieldData.isEffectivelyFinal ||
!options.parameterCheckPolicy.isEmitted) {
!closedWorld.annotationsData
.getParameterCheckPolicy(targetElement)
.isEmitted) {
// No need for a checked setter.
return null;
}
@ -581,7 +583,8 @@ class KernelSsaGraphBuilder extends ir.Visitor {
_inLazyInitializerExpression = node.isStatic;
FieldEntity field = _elementMap.getMember(node);
_openFunction(field, checks: TargetChecks.none);
if (node.isInstanceMember && options.parameterCheckPolicy.isEmitted) {
if (node.isInstanceMember &&
closedWorld.annotationsData.getParameterCheckPolicy(field).isEmitted) {
HInstruction thisInstruction = localsHandler.readThis(
sourceInformation: _sourceInformationBuilder.buildGet(node));
// Use dynamic type because the type computed by the inferrer is
@ -593,7 +596,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
// to be the first parameter.
graph.entry.addBefore(graph.entry.last, parameter);
HInstruction value = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
parameter, _getDartTypeIfValid(node.type));
field, parameter, _getDartTypeIfValid(node.type));
if (!_fieldAnalysis.getFieldData(field).isElided) {
add(new HFieldSet(_abstractValueDomain, field, thisInstruction, value));
}
@ -603,7 +606,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
HInstruction fieldValue = pop();
HInstruction checkInstruction =
_typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
fieldValue, _getDartTypeIfValid(node.type));
field, fieldValue, _getDartTypeIfValid(node.type));
stack.add(checkInstruction);
} else {
stack.add(graph.addConstantNull(closedWorld));
@ -624,7 +627,8 @@ class KernelSsaGraphBuilder extends ir.Visitor {
/// non-null bool.
HInstruction popBoolified() {
HInstruction value = pop();
return _typeBuilder.potentiallyCheckOrTrustTypeOfCondition(value);
return _typeBuilder.potentiallyCheckOrTrustTypeOfCondition(
_currentFrame.member, value);
}
/// Extend current method parameters with parameters for the class type
@ -761,7 +765,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
DartType type = _elementEnvironment.getFieldType(member);
type = localsHandler.substInContext(type);
constructorArguments.add(_typeBuilder
.potentiallyCheckOrTrustTypeOfAssignment(value, type));
.potentiallyCheckOrTrustTypeOfAssignment(member, value, type));
}
}
});
@ -1436,7 +1440,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
(targetChecks.checkCovariantParameters &&
(variable.isGenericCovariantImpl || variable.isCovariant))) {
newParameter = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
newParameter, type);
targetElement, newParameter, type);
} else {
newParameter = _typeBuilder.trustTypeOfParameter(newParameter, type);
}
@ -1450,7 +1454,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
void _checkTypeVariableBounds(FunctionEntity method) {
if (_rtiNeed.methodNeedsTypeArguments(method) &&
options.parameterCheckPolicy.isEmitted) {
closedWorld.annotationsData.getParameterCheckPolicy(method).isEmitted) {
ir.FunctionNode function = getFunctionNode(_elementMap, method);
for (ir.TypeParameter typeParameter in function.typeParameters) {
Local local = _localsMap.getLocalTypeVariable(
@ -1791,7 +1795,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
}*/
} else {
value = _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
value, _returnType);
_currentFrame.member, value, _returnType);
}
}
_handleInTryStatement();
@ -2058,7 +2062,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
Local loopVariableLocal = _localsMap.getLocalVariable(node.variable);
HInstruction value = _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
pop(), _getDartTypeIfValid(node.variable.type));
_currentFrame.member, pop(), _getDartTypeIfValid(node.variable.type));
localsHandler.updateLocal(loopVariableLocal, value,
sourceInformation: sourceInformation);
// Hint to name loop value after name of loop variable.
@ -2413,8 +2417,11 @@ class KernelSsaGraphBuilder extends ir.Visitor {
return;
}
if ((!node.isTypeError && !options.omitAsCasts) ||
options.implicitDowncastCheckPolicy.isEmitted) {
if ((!node.isTypeError &&
!closedWorld.annotationsData.omitAsCasts(_currentFrame.member)) ||
closedWorld.annotationsData
.getImplicitDowncastCheckPolicy(_currentFrame.member)
.isEmitted) {
HInstruction converted = _typeBuilder.buildTypeConversion(
expressionInstruction,
localsHandler.substInContext(type),
@ -3384,7 +3391,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
_abstractValueDomain,
target,
_typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
value, _getDartTypeIfValid(staticTarget.setterType))));
target, value, _getDartTypeIfValid(staticTarget.setterType))));
}
}
stack.add(value);
@ -3535,7 +3542,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
localsHandler.updateLocal(
local,
_typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
value, _getDartTypeIfValid(variable.type)),
_currentFrame.member, value, _getDartTypeIfValid(variable.type)),
sourceInformation: sourceInformation);
}
@ -6208,8 +6215,8 @@ class KernelSsaGraphBuilder extends ir.Visitor {
if (trusted) {
checkedOrTrusted = _typeBuilder.trustTypeOfParameter(argument, type);
} else {
checkedOrTrusted =
_typeBuilder.potentiallyCheckOrTrustTypeOfParameter(argument, type);
checkedOrTrusted = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
function, argument, type);
}
localsHandler.updateLocal(parameter, checkedOrTrusted);
});

View file

@ -9,7 +9,6 @@ import '../elements/entities.dart';
import '../elements/names.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/types.dart';
import '../options.dart';
import '../universe/call_structure.dart';
import '../universe/selector.dart';
import '../world.dart' show JClosedWorld;
@ -24,11 +23,8 @@ import 'types.dart';
class InvokeDynamicSpecializer {
const InvokeDynamicSpecializer();
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return AbstractValueFactory.inferredResultTypeForSelector(
instruction.selector, instruction.receiverType, results);
}
@ -37,7 +33,6 @@ class InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -121,7 +116,6 @@ class IndexAssignSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -134,13 +128,17 @@ class IndexAssignSpecializer extends InvokeDynamicSpecializer {
}
// TODO(johnniwinther): Merge this and the following if statement.
if (index.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse &&
options.parameterCheckPolicy.isEmitted) {
// TODO(johnniwinther): Support annotations on the possible targets
// and used their parameter check policy here.
closedWorld.annotationsData.getParameterCheckPolicy(null).isEmitted) {
// We want the right checked mode error.
return null;
}
HInstruction value = instruction.inputs[3];
if (options.parameterCheckPolicy.isEmitted) {
// TODO(johnniwinther): Support annotations on the possible targets
// and used their parameter check policy here.
if (closedWorld.annotationsData.getParameterCheckPolicy(null).isEmitted) {
if (!_valueParameterCheckAlwaysSucceeds(
instruction, receiver, value, commonElements, closedWorld)) {
return null;
@ -193,7 +191,6 @@ class IndexSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -206,7 +203,9 @@ class IndexSpecializer extends InvokeDynamicSpecializer {
if (instruction.inputs[2]
.isInteger(abstractValueDomain)
.isPotentiallyFalse &&
options.parameterCheckPolicy.isEmitted) {
// TODO(johnniwinther): Support annotations on the possible targets
// and used their parameter check policy here.
closedWorld.annotationsData.getParameterCheckPolicy(null).isEmitted) {
// We want the right checked mode error.
return null;
}
@ -234,11 +233,8 @@ class BitNotSpecializer extends InvokeDynamicSpecializer {
}
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
// All bitwise operations on primitive types either produce an
// integer or throw an error.
if (instruction.inputs[1]
@ -246,8 +242,7 @@ class BitNotSpecializer extends InvokeDynamicSpecializer {
.isDefinitelyTrue) {
return closedWorld.abstractValueDomain.uint32Type;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
@ -255,17 +250,13 @@ class BitNotSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
HInstruction input = instruction.inputs[1];
if (input.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
HBitNot converted = new HBitNot(
input,
instruction.selector,
computeTypeFromInputTypes(
instruction, results, options, closedWorld));
HBitNot converted = new HBitNot(input, instruction.selector,
computeTypeFromInputTypes(instruction, results, closedWorld));
log?.registerBitNot(instruction, converted);
return converted;
}
@ -282,11 +273,8 @@ class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
}
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
HInstruction operand = instruction.inputs[1];
if (operand
.isNumberOrNull(closedWorld.abstractValueDomain)
@ -305,8 +293,7 @@ class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
}
return closedWorld.abstractValueDomain.numType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
@ -314,17 +301,13 @@ class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
HInstruction input = instruction.inputs[1];
if (input.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
HNegate converted = new HNegate(
input,
instruction.selector,
computeTypeFromInputTypes(
instruction, results, options, closedWorld));
HNegate converted = new HNegate(input, instruction.selector,
computeTypeFromInputTypes(instruction, results, closedWorld));
log?.registerUnaryNegate(instruction, converted);
return converted;
}
@ -341,19 +324,15 @@ class AbsSpecializer extends InvokeDynamicSpecializer {
}
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
HInstruction input = instruction.inputs[1];
if (input
.isNumberOrNull(closedWorld.abstractValueDomain)
.isDefinitelyTrue) {
return closedWorld.abstractValueDomain.excludeNull(input.instructionType);
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
@ -361,17 +340,13 @@ class AbsSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
HInstruction input = instruction.inputs[1];
if (input.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
HAbs converted = new HAbs(
input,
instruction.selector,
computeTypeFromInputTypes(
instruction, results, options, closedWorld));
HAbs converted = new HAbs(input, instruction.selector,
computeTypeFromInputTypes(instruction, results, closedWorld));
log?.registerAbs(instruction, converted);
return converted;
}
@ -386,11 +361,8 @@ abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
const BinaryArithmeticSpecializer();
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
HInstruction left = instruction.inputs[1];
HInstruction right = instruction.inputs[2];
if (left
@ -412,8 +384,7 @@ abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
}
return closedWorld.abstractValueDomain.numType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
bool isBuiltin(HInvokeDynamic instruction, JClosedWorld closedWorld) {
@ -430,13 +401,12 @@ abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
if (isBuiltin(instruction, closedWorld)) {
HInstruction builtin =
newBuiltinVariant(instruction, results, options, closedWorld);
newBuiltinVariant(instruction, results, closedWorld);
if (log != null) {
registerOptimization(log, instruction, builtin);
}
@ -470,11 +440,8 @@ abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
right.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue;
}
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld);
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld);
void registerOptimization(
OptimizationTestLog log, HInstruction original, HInstruction converted);
@ -484,19 +451,15 @@ class AddSpecializer extends BinaryArithmeticSpecializer {
const AddSpecializer();
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
if (inputsAreUInt31(instruction, closedWorld)) {
return closedWorld.abstractValueDomain.uint32Type;
}
if (inputsArePositiveIntegers(instruction, closedWorld)) {
return closedWorld.abstractValueDomain.positiveIntType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
@ -505,16 +468,13 @@ class AddSpecializer extends BinaryArithmeticSpecializer {
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HAdd(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -533,25 +493,18 @@ class DivideSpecializer extends BinaryArithmeticSpecializer {
}
@override
AbstractValue computeTypeFromInputTypes(
HInstruction instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInstruction instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
HInstruction left = instruction.inputs[1];
if (left.isNumberOrNull(closedWorld.abstractValueDomain).isDefinitelyTrue) {
return closedWorld.abstractValueDomain.doubleType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HDivide(instruction.inputs[1], instruction.inputs[2],
instruction.selector, closedWorld.abstractValueDomain.doubleType);
}
@ -567,16 +520,12 @@ class ModuloSpecializer extends BinaryArithmeticSpecializer {
const ModuloSpecializer();
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
if (inputsArePositiveIntegers(instruction, closedWorld)) {
return closedWorld.abstractValueDomain.positiveIntType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
@ -585,11 +534,8 @@ class ModuloSpecializer extends BinaryArithmeticSpecializer {
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
// Modulo cannot be mapped to the native operator (different semantics).
// We can use HRemainder if both inputs are non-negative and the receiver
@ -636,8 +582,7 @@ class ModuloSpecializer extends BinaryArithmeticSpecializer {
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(
instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
// TODO(sra):
// a % N --> a & (N-1), N=2^k, where a>=0, does not have -0.0 problem.
@ -662,16 +607,12 @@ class RemainderSpecializer extends BinaryArithmeticSpecializer {
const RemainderSpecializer();
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
if (inputsArePositiveIntegers(instruction, closedWorld)) {
return closedWorld.abstractValueDomain.positiveIntType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
@ -680,16 +621,13 @@ class RemainderSpecializer extends BinaryArithmeticSpecializer {
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HRemainder(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -708,29 +646,22 @@ class MultiplySpecializer extends BinaryArithmeticSpecializer {
}
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
if (inputsArePositiveIntegers(instruction, closedWorld)) {
return closedWorld.abstractValueDomain.positiveIntType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HMultiply(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -749,16 +680,13 @@ class SubtractSpecializer extends BinaryArithmeticSpecializer {
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HSubtract(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -777,19 +705,15 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
}
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
if (hasUint31Result(instruction, closedWorld)) {
return closedWorld.abstractValueDomain.uint31Type;
}
if (inputsArePositiveIntegers(instruction, closedWorld)) {
return closedWorld.abstractValueDomain.positiveIntType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
bool isNotZero(HInstruction instruction) {
@ -831,7 +755,6 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -843,7 +766,7 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
isNotZero(right)) {
if (hasUint31Result(instruction, closedWorld)) {
HInstruction converted =
newBuiltinVariant(instruction, results, options, closedWorld);
newBuiltinVariant(instruction, results, closedWorld);
if (log != null) {
registerOptimization(log, instruction, converted);
}
@ -863,16 +786,13 @@ class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HTruncatingDivide(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -886,19 +806,15 @@ abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
const BinaryBitOpSpecializer();
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
// All bitwise operations on number types either produce an unsigned 32-bit
// integer or throw an error.
HInstruction left = instruction.inputs[1];
if (left.isNumberOrNull(closedWorld.abstractValueDomain).isDefinitelyTrue) {
return closedWorld.abstractValueDomain.uint32Type;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
bool argumentLessThan32(HInstruction instruction) {
@ -945,7 +861,6 @@ class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -954,7 +869,7 @@ class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
if (left.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
if (argumentLessThan32(right)) {
HInstruction converted =
newBuiltinVariant(instruction, results, options, closedWorld);
newBuiltinVariant(instruction, results, closedWorld);
if (log != null) {
registerOptimization(log, instruction, converted);
}
@ -976,16 +891,13 @@ class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HShiftLeft(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -999,17 +911,13 @@ class ShiftRightSpecializer extends BinaryBitOpSpecializer {
const ShiftRightSpecializer();
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
HInstruction left = instruction.inputs[1];
if (left.isUInt32(closedWorld.abstractValueDomain).isDefinitelyTrue) {
return left.instructionType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
@ -1017,7 +925,6 @@ class ShiftRightSpecializer extends BinaryBitOpSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -1026,7 +933,7 @@ class ShiftRightSpecializer extends BinaryBitOpSpecializer {
if (left.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
if (argumentLessThan32(right) && isPositive(left, closedWorld)) {
HInstruction converted =
newBuiltinVariant(instruction, results, options, closedWorld);
newBuiltinVariant(instruction, results, closedWorld);
if (log != null) {
registerOptimization(log, instruction, converted);
}
@ -1061,16 +968,13 @@ class ShiftRightSpecializer extends BinaryBitOpSpecializer {
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HShiftRight(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -1094,32 +998,25 @@ class BitOrSpecializer extends BinaryBitOpSpecializer {
}
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
HInstruction left = instruction.inputs[1];
HInstruction right = instruction.inputs[2];
if (left.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue &&
right.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue) {
return closedWorld.abstractValueDomain.uint31Type;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HBitOr(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -1138,11 +1035,8 @@ class BitAndSpecializer extends BinaryBitOpSpecializer {
}
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
HInstruction left = instruction.inputs[1];
HInstruction right = instruction.inputs[2];
if (left
@ -1152,21 +1046,17 @@ class BitAndSpecializer extends BinaryBitOpSpecializer {
right.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue)) {
return closedWorld.abstractValueDomain.uint31Type;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HBitAnd(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -1185,32 +1075,25 @@ class BitXorSpecializer extends BinaryBitOpSpecializer {
}
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
HInstruction left = instruction.inputs[1];
HInstruction right = instruction.inputs[2];
if (left.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue &&
right.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue) {
return closedWorld.abstractValueDomain.uint31Type;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
HInstruction newBuiltinVariant(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
return new HBitXor(
instruction.inputs[1],
instruction.inputs[2],
instruction.selector,
computeTypeFromInputTypes(instruction, results, options, closedWorld));
computeTypeFromInputTypes(instruction, results, closedWorld));
}
@override
@ -1224,18 +1107,14 @@ abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
const RelationalSpecializer();
@override
AbstractValue computeTypeFromInputTypes(
HInvokeDynamic instruction,
GlobalTypeInferenceResults results,
CompilerOptions options,
JClosedWorld closedWorld) {
AbstractValue computeTypeFromInputTypes(HInvokeDynamic instruction,
GlobalTypeInferenceResults results, JClosedWorld closedWorld) {
if (instruction.inputs[1]
.isPrimitiveOrNull(closedWorld.abstractValueDomain)
.isDefinitelyTrue) {
return closedWorld.abstractValueDomain.boolType;
}
return super
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
return super.computeTypeFromInputTypes(instruction, results, closedWorld);
}
@override
@ -1243,7 +1122,6 @@ abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -1275,7 +1153,6 @@ class EqualsSpecializer extends RelationalSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -1432,7 +1309,6 @@ class CodeUnitAtSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -1466,7 +1342,6 @@ class CompareToSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -1516,7 +1391,6 @@ abstract class IdempotentStringOperationSpecializer
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -1563,7 +1437,6 @@ class PatternMatchSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {
@ -1597,7 +1470,6 @@ class RoundSpecializer extends InvokeDynamicSpecializer {
HInvokeDynamic instruction,
HGraph graph,
GlobalTypeInferenceResults results,
CompilerOptions options,
JCommonElements commonElements,
JClosedWorld closedWorld,
OptimizationTestLog log) {

View file

@ -83,7 +83,7 @@ class SsaOptimizerTask extends CompilerTask {
new SsaTypeConversionInserter(closedWorld),
new SsaRedundantPhiEliminator(),
new SsaDeadPhiEliminator(),
new SsaTypePropagator(globalInferenceResults, _options,
new SsaTypePropagator(globalInferenceResults,
closedWorld.commonElements, closedWorld, log),
// After type propagation, more instructions can be
// simplified.
@ -93,7 +93,7 @@ class SsaOptimizerTask extends CompilerTask {
new SsaInstructionSimplifier(globalInferenceResults, _options,
codegen.rtiSubstitutions, closedWorld, registry, log),
new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
new SsaTypePropagator(globalInferenceResults, _options,
new SsaTypePropagator(globalInferenceResults,
closedWorld.commonElements, closedWorld, log),
// Run a dead code eliminator before LICM because dead
// interceptors are often in the way of LICM'able instructions.
@ -101,7 +101,7 @@ class SsaOptimizerTask extends CompilerTask {
new SsaGlobalValueNumberer(closedWorld.abstractValueDomain),
// After GVN, some instructions might need their type to be
// updated because they now have different inputs.
new SsaTypePropagator(globalInferenceResults, _options,
new SsaTypePropagator(globalInferenceResults,
closedWorld.commonElements, closedWorld, log),
codeMotion = new SsaCodeMotion(closedWorld.abstractValueDomain),
loadElimination = new SsaLoadElimination(closedWorld),
@ -111,7 +111,7 @@ class SsaOptimizerTask extends CompilerTask {
// controlled by a test on the value, so redo 'conversion insertion' to
// learn from the refined type.
new SsaTypeConversionInserter(closedWorld),
new SsaTypePropagator(globalInferenceResults, _options,
new SsaTypePropagator(globalInferenceResults,
closedWorld.commonElements, closedWorld, log),
new SsaValueRangeAnalyzer(closedWorld, this),
// Previous optimizations may have generated new
@ -133,7 +133,7 @@ class SsaOptimizerTask extends CompilerTask {
dce.eliminatedSideEffects ||
loadElimination.newGvnCandidates) {
phases = <OptimizationPhase>[
new SsaTypePropagator(globalInferenceResults, _options,
new SsaTypePropagator(globalInferenceResults,
closedWorld.commonElements, closedWorld, log),
new SsaGlobalValueNumberer(closedWorld.abstractValueDomain),
new SsaCodeMotion(closedWorld.abstractValueDomain),
@ -146,7 +146,7 @@ class SsaOptimizerTask extends CompilerTask {
];
} else {
phases = <OptimizationPhase>[
new SsaTypePropagator(globalInferenceResults, _options,
new SsaTypePropagator(globalInferenceResults,
closedWorld.commonElements, closedWorld, log),
// Run the simplifier to remove unneeded type checks inserted by
// type propagation.
@ -519,14 +519,8 @@ class SsaInstructionSimplifier extends HBaseVisitor
}
// Try converting the instruction to a builtin instruction.
HInstruction instruction = node.specializer.tryConvertToBuiltin(
node,
_graph,
_globalInferenceResults,
_options,
commonElements,
_closedWorld,
_log);
HInstruction instruction = node.specializer.tryConvertToBuiltin(node,
_graph, _globalInferenceResults, commonElements, _closedWorld, _log);
if (instruction != null) {
return instruction;
}
@ -551,7 +545,9 @@ class SsaInstructionSimplifier extends HBaseVisitor
} else if (applies(commonElements.jsArrayAdd)) {
// The codegen special cases array calls, but does not
// inline argument type checks.
if (!_options.parameterCheckPolicy.isEmitted ||
if (!_closedWorld.annotationsData
.getParameterCheckPolicy(commonElements.jsArrayAdd)
.isEmitted ||
input is HLiteralList) {
target = commonElements.jsArrayAdd;
}
@ -799,7 +795,11 @@ class SsaInstructionSimplifier extends HBaseVisitor
}
// If the target has no checks don't let a bad type stop us inlining.
if (!_options.parameterCheckPolicy.isEmitted) return;
if (!_closedWorld.annotationsData
.getParameterCheckPolicy(method)
.isEmitted) {
return;
}
AbstractValue parameterAbstractValue = _abstractValueDomain
.getAbstractValueForNativeMethodParameterType(parameterType);
@ -1323,7 +1323,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
// Use `node.inputs.last` in case the call follows the interceptor calling
// convention, but is not a call on an interceptor.
HInstruction value = node.inputs.last;
if (_options.parameterCheckPolicy.isEmitted) {
if (_closedWorld.annotationsData.getParameterCheckPolicy(field).isEmitted) {
if (_options.experimentNewRti) {
// TODO(sra): Implement inlining of setters with checks for new rti.
node.needsCheck = true;

View file

@ -9,6 +9,7 @@ import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../js_model/type_recipe.dart';
import '../io/source_information.dart';
import '../options.dart';
import '../universe/use.dart' show TypeUse;
import '../world.dart';
@ -112,12 +113,14 @@ abstract class TypeBuilder {
}
HInstruction potentiallyCheckOrTrustTypeOfParameter(
HInstruction original, DartType type) {
MemberEntity memberContext, HInstruction original, DartType type) {
if (type == null) return original;
HInstruction checkedOrTrusted = original;
if (builder.options.parameterCheckPolicy.isTrusted) {
CheckPolicy parameterCheckPolicy = builder.closedWorld.annotationsData
.getParameterCheckPolicy(memberContext);
if (parameterCheckPolicy.isTrusted) {
checkedOrTrusted = _trustType(original, type);
} else if (builder.options.parameterCheckPolicy.isEmitted) {
} else if (parameterCheckPolicy.isEmitted) {
checkedOrTrusted = _checkType(original, type);
}
if (checkedOrTrusted == original) return original;
@ -129,25 +132,23 @@ abstract class TypeBuilder {
/// instruction that checks the type is what we expect or automatically
/// trusts the written type.
HInstruction potentiallyCheckOrTrustTypeOfAssignment(
HInstruction original, DartType type) {
MemberEntity memberContext, HInstruction original, DartType type) {
if (type == null) return original;
HInstruction checkedOrTrusted = original;
if (builder.options.assignmentCheckPolicy.isTrusted) {
checkedOrTrusted = _trustType(original, type);
} else if (builder.options.assignmentCheckPolicy.isEmitted) {
checkedOrTrusted = _checkType(original, type);
}
HInstruction checkedOrTrusted = _trustType(original, type);
if (checkedOrTrusted == original) return original;
builder.add(checkedOrTrusted);
return checkedOrTrusted;
}
HInstruction potentiallyCheckOrTrustTypeOfCondition(HInstruction original) {
HInstruction potentiallyCheckOrTrustTypeOfCondition(
MemberEntity memberContext, HInstruction original) {
DartType boolType = _closedWorld.commonElements.boolType;
HInstruction checkedOrTrusted = original;
if (builder.options.conditionCheckPolicy.isTrusted) {
CheckPolicy conditionCheckPolicy = builder.closedWorld.annotationsData
.getConditionCheckPolicy(memberContext);
if (conditionCheckPolicy.isTrusted) {
checkedOrTrusted = _trustType(original, boolType);
} else if (builder.options.conditionCheckPolicy.isEmitted) {
} else if (conditionCheckPolicy.isEmitted) {
checkedOrTrusted = _checkBoolConverion(original);
}
if (checkedOrTrusted == original) return original;

View file

@ -7,7 +7,6 @@ import '../elements/entities.dart';
import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/types.dart';
import '../options.dart';
import '../universe/selector.dart' show Selector;
import '../world.dart' show JClosedWorld;
import 'logging.dart';
@ -37,15 +36,14 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
new Map<HInstruction, Function>();
final GlobalTypeInferenceResults results;
final CompilerOptions options;
final CommonElements commonElements;
final JClosedWorld closedWorld;
final OptimizationTestLog _log;
@override
String get name => 'SsaTypePropagator';
SsaTypePropagator(this.results, this.options, this.commonElements,
this.closedWorld, this._log);
SsaTypePropagator(
this.results, this.commonElements, this.closedWorld, this._log);
AbstractValueDomain get abstractValueDomain =>
closedWorld.abstractValueDomain;
@ -499,6 +497,6 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
}
return instruction.specializer
.computeTypeFromInputTypes(instruction, results, options, closedWorld);
.computeTypeFromInputTypes(instruction, results, closedWorld);
}
}

View file

@ -1056,7 +1056,7 @@ class ResolutionWorldBuilderImpl extends WorldBuilderBase
mixinUses: _classHierarchyBuilder.mixinUses,
typesImplementedBySubclasses: typesImplementedBySubclasses,
classHierarchy: _classHierarchyBuilder.close(),
annotationsData: _annotationsDataBuilder.close(),
annotationsData: _annotationsDataBuilder.close(_options),
isChecks: _isChecks,
staticTypeArgumentDependencies: staticTypeArgumentDependencies,
dynamicTypeArgumentDependencies: dynamicTypeArgumentDependencies,

View file

@ -4,6 +4,7 @@
library dart2js.universe.world_impact;
import '../elements/entities.dart';
import '../util/util.dart' show Setlet;
import 'use.dart';
@ -21,6 +22,8 @@ import 'use.dart';
class WorldImpact {
const WorldImpact();
MemberEntity get member => null;
Iterable<DynamicUse> get dynamicUses => const <DynamicUse>[];
Iterable<StaticUse> get staticUses => const <StaticUse>[];
@ -37,10 +40,12 @@ class WorldImpact {
bool get isEmpty => true;
void apply(WorldImpactVisitor visitor) {
staticUses.forEach(visitor.visitStaticUse);
dynamicUses.forEach(visitor.visitDynamicUse);
typeUses.forEach(visitor.visitTypeUse);
constantUses.forEach(visitor.visitConstantUse);
staticUses.forEach((StaticUse use) => visitor.visitStaticUse(member, use));
dynamicUses
.forEach((DynamicUse use) => visitor.visitDynamicUse(member, use));
typeUses.forEach((TypeUse use) => visitor.visitTypeUse(member, use));
constantUses
.forEach((ConstantUse use) => visitor.visitConstantUse(member, use));
}
@override
@ -53,6 +58,8 @@ class WorldImpact {
}
static void printOn(StringBuffer sb, WorldImpact worldImpact) {
sb.write('member: ${worldImpact.member}');
void add(String title, Iterable iterable) {
if (iterable.isNotEmpty) {
sb.write('\n $title:');
@ -221,6 +228,9 @@ class TransformedWorldImpact implements WorldImpact, WorldImpactBuilder {
TransformedWorldImpact(this.worldImpact);
@override
MemberEntity get member => worldImpact.member;
@override
bool get isEmpty {
return worldImpact.isEmpty &&
@ -288,10 +298,12 @@ class TransformedWorldImpact implements WorldImpact, WorldImpactBuilder {
@override
void apply(WorldImpactVisitor visitor) {
staticUses.forEach(visitor.visitStaticUse);
dynamicUses.forEach(visitor.visitDynamicUse);
typeUses.forEach(visitor.visitTypeUse);
constantUses.forEach(visitor.visitConstantUse);
staticUses.forEach((StaticUse use) => visitor.visitStaticUse(member, use));
dynamicUses
.forEach((DynamicUse use) => visitor.visitDynamicUse(member, use));
typeUses.forEach((TypeUse use) => visitor.visitTypeUse(member, use));
constantUses
.forEach((ConstantUse use) => visitor.visitConstantUse(member, use));
}
@override
@ -333,14 +345,14 @@ class ImpactStrategy {
/// Visitor used to process the uses of a [WorldImpact].
abstract class WorldImpactVisitor {
void visitStaticUse(StaticUse staticUse);
void visitDynamicUse(DynamicUse dynamicUse);
void visitTypeUse(TypeUse typeUse);
void visitConstantUse(ConstantUse typeUse);
void visitStaticUse(MemberEntity member, StaticUse staticUse);
void visitDynamicUse(MemberEntity member, DynamicUse dynamicUse);
void visitTypeUse(MemberEntity member, TypeUse typeUse);
void visitConstantUse(MemberEntity member, ConstantUse typeUse);
}
// TODO(johnniwinther): Remove these when we get anonymous local classes.
typedef void VisitUse<U>(U use);
typedef void VisitUse<U>(MemberEntity member, U use);
class WorldImpactVisitorImpl implements WorldImpactVisitor {
final VisitUse<StaticUse> _visitStaticUse;
@ -359,30 +371,30 @@ class WorldImpactVisitorImpl implements WorldImpactVisitor {
_visitConstantUse = visitConstantUse;
@override
void visitStaticUse(StaticUse use) {
void visitStaticUse(MemberEntity member, StaticUse use) {
if (_visitStaticUse != null) {
_visitStaticUse(use);
_visitStaticUse(member, use);
}
}
@override
void visitDynamicUse(DynamicUse use) {
void visitDynamicUse(MemberEntity member, DynamicUse use) {
if (_visitDynamicUse != null) {
_visitDynamicUse(use);
_visitDynamicUse(member, use);
}
}
@override
void visitTypeUse(TypeUse use) {
void visitTypeUse(MemberEntity member, TypeUse use) {
if (_visitTypeUse != null) {
_visitTypeUse(use);
_visitTypeUse(member, use);
}
}
@override
void visitConstantUse(ConstantUse use) {
void visitConstantUse(MemberEntity member, ConstantUse use) {
if (_visitConstantUse != null) {
_visitConstantUse(use);
_visitConstantUse(member, use);
}
}
}