mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:10:22 +00:00
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:
parent
8f90265176
commit
f743594375
27 changed files with 635 additions and 514 deletions
|
@ -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';
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:');
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue