mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 21:40:07 +00:00
Avoid eager enqueueing from resolution
BUG= R=sigurdm@google.com Review URL: https://codereview.chromium.org/1376863004.
This commit is contained in:
parent
76b7203c19
commit
dda38dfe47
|
@ -227,7 +227,7 @@ abstract class Backend {
|
|||
/// Call this method to enable support for isolates.
|
||||
void enableIsolateSupport(Enqueuer enqueuer) {}
|
||||
|
||||
void registerRequiredType(DartType type, Element enclosingElement) {}
|
||||
void registerRequiredType(DartType type) {}
|
||||
|
||||
void registerConstSymbol(String name, Registry registry) {}
|
||||
void registerNewSymbol(Registry registry) {}
|
||||
|
@ -401,4 +401,4 @@ abstract class ForeignResolver {
|
|||
|
||||
/// Resolves [typeName] to a type in the context of [node].
|
||||
DartType resolveTypeFromString(Node node, String typeName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ class CodegenWorkItem extends WorkItem {
|
|||
// generation could spuriously be adding dependencies on things we know we
|
||||
// don't need.
|
||||
assert(invariant(element,
|
||||
compiler.enqueuer.resolution.hasBeenResolved(element),
|
||||
compiler.enqueuer.resolution.hasBeenProcessed(element),
|
||||
message: "$element has not been resolved."));
|
||||
assert(invariant(element, element.resolvedAst.elements != null,
|
||||
message: 'Resolution tree is null for $element in codegen work item'));
|
||||
|
|
|
@ -10,7 +10,8 @@ import '../compiler.dart' show
|
|||
import '../core_types.dart' show
|
||||
CoreTypes;
|
||||
import '../dart_types.dart' show
|
||||
DartType;
|
||||
DartType,
|
||||
InterfaceType;
|
||||
import '../diagnostics/diagnostic_listener.dart' show
|
||||
DiagnosticReporter;
|
||||
import '../elements/elements.dart' show
|
||||
|
@ -20,7 +21,9 @@ import '../elements/elements.dart' show
|
|||
ErroneousElement,
|
||||
FunctionElement,
|
||||
FunctionSignature,
|
||||
LocalFunctionElement,
|
||||
MetadataAnnotation,
|
||||
MethodElement,
|
||||
TypedefElement,
|
||||
TypeVariableElement;
|
||||
import '../enqueue.dart' show
|
||||
|
@ -30,6 +33,10 @@ import '../tree/tree.dart' show
|
|||
AsyncForIn,
|
||||
Send,
|
||||
TypeAnnotation;
|
||||
import '../universe/universe.dart' show
|
||||
UniverseSelector;
|
||||
import '../util/util.dart' show
|
||||
Setlet;
|
||||
import 'registry.dart' show
|
||||
Registry;
|
||||
import 'work.dart' show
|
||||
|
@ -46,6 +53,7 @@ class ResolutionWorkItem extends WorkItem {
|
|||
|
||||
WorldImpact run(Compiler compiler, ResolutionEnqueuer world) {
|
||||
WorldImpact impact = compiler.analyze(this, world);
|
||||
impact = compiler.backend.resolutionCallbacks.transformImpact(impact);
|
||||
_isAnalyzed = true;
|
||||
return impact;
|
||||
}
|
||||
|
@ -53,8 +61,13 @@ class ResolutionWorkItem extends WorkItem {
|
|||
bool get isAnalyzed => _isAnalyzed;
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Rename this to something like `BackendResolutionApi`
|
||||
// and clean up the interface.
|
||||
/// Backend callbacks function specific to the resolution phase.
|
||||
class ResolutionCallbacks {
|
||||
///
|
||||
WorldImpact transformImpact(ResolutionWorldImpact worldImpact) => worldImpact;
|
||||
|
||||
/// Register that an assert has been seen.
|
||||
void onAssert(bool hasMessage, Registry registry) {}
|
||||
|
||||
|
@ -133,6 +146,256 @@ class ResolutionCallbacks {
|
|||
void onIncDecOperation(Registry registry) {}
|
||||
}
|
||||
|
||||
class ResolutionWorldImpact extends WorldImpact {
|
||||
const ResolutionWorldImpact();
|
||||
|
||||
// TODO(johnniwinther): Remove this.
|
||||
void registerDependency(Element element) {}
|
||||
|
||||
Iterable<Feature> get features => const <Feature>[];
|
||||
Iterable<DartType> get requiredTypes => const <DartType>[];
|
||||
Iterable<MapLiteralUse> get mapLiterals => const <MapLiteralUse>[];
|
||||
Iterable<ListLiteralUse> get listLiterals => const <ListLiteralUse>[];
|
||||
Iterable<DartType> get typeLiterals => const <DartType>[];
|
||||
Iterable<String> get constSymbolNames => const <String>[];
|
||||
}
|
||||
|
||||
/// A language feature seen during resolution.
|
||||
// TODO(johnniwinther): Should mirror usage be part of this?
|
||||
enum Feature {
|
||||
/// Invocation of a generative construction on an abstract class.
|
||||
ABSTRACT_CLASS_INSTANTIATION,
|
||||
/// An assert statement with no message.
|
||||
ASSERT,
|
||||
/// An assert statement with a message.
|
||||
ASSERT_WITH_MESSAGE,
|
||||
/// A method with an `async` body modifier.
|
||||
ASYNC,
|
||||
/// An asynchronous for in statement like `await for (var e in i) {}`.
|
||||
ASYNC_FOR_IN,
|
||||
/// A method with an `async*` body modifier.
|
||||
ASYNC_STAR,
|
||||
/// A catch statement.
|
||||
CATCH_STATEMENT,
|
||||
/// A compile time error.
|
||||
COMPILE_TIME_ERROR,
|
||||
/// A fall through in a switch case.
|
||||
FALL_THROUGH_ERROR,
|
||||
/// A ++/-- operation.
|
||||
INC_DEC_OPERATION,
|
||||
/// A field whose initialization is not a constant.
|
||||
LAZY_FIELD,
|
||||
/// A call to `new Symbol`.
|
||||
NEW_SYMBOL,
|
||||
/// A catch clause with a variable for the stack trace.
|
||||
STACK_TRACE_IN_CATCH,
|
||||
/// String interpolation.
|
||||
STRING_INTERPOLATION,
|
||||
/// An implicit call to `super.noSuchMethod`, like calling an unresolved
|
||||
/// super method.
|
||||
SUPER_NO_SUCH_METHOD,
|
||||
/// A redirection to the `Symbol` constructor.
|
||||
SYMBOL_CONSTRUCTOR,
|
||||
/// An synchronous for in statement, like `for (var e in i) {}`.
|
||||
SYNC_FOR_IN,
|
||||
/// A method with a `sync*` body modifier.
|
||||
SYNC_STAR,
|
||||
/// A throw expression.
|
||||
THROW_EXPRESSION,
|
||||
/// An implicit throw of a `NoSuchMethodError`, like calling an unresolved
|
||||
/// static method.
|
||||
THROW_NO_SUCH_METHOD,
|
||||
/// An implicit throw of a runtime error, like
|
||||
THROW_RUNTIME_ERROR,
|
||||
/// The need for a type variable bound check, like instantiation of a generic
|
||||
/// type whose type variable have non-trivial bounds.
|
||||
TYPE_VARIABLE_BOUNDS_CHECK,
|
||||
}
|
||||
|
||||
/// A use of a map literal seen during resolution.
|
||||
class MapLiteralUse {
|
||||
final InterfaceType type;
|
||||
final bool isConstant;
|
||||
final bool isEmpty;
|
||||
|
||||
MapLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false});
|
||||
|
||||
int get hashCode {
|
||||
return
|
||||
type.hashCode * 13 +
|
||||
isConstant.hashCode * 17 +
|
||||
isEmpty.hashCode * 19;
|
||||
}
|
||||
|
||||
bool operator ==(other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other is! MapLiteralUse) return false;
|
||||
return
|
||||
type == other.type &&
|
||||
isConstant == other.isConstant &&
|
||||
isEmpty == other.isEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
/// A use of a list literal seen during resolution.
|
||||
class ListLiteralUse {
|
||||
final InterfaceType type;
|
||||
final bool isConstant;
|
||||
final bool isEmpty;
|
||||
|
||||
ListLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false});
|
||||
|
||||
int get hashCode {
|
||||
return
|
||||
type.hashCode * 13 +
|
||||
isConstant.hashCode * 17 +
|
||||
isEmpty.hashCode * 19;
|
||||
}
|
||||
|
||||
bool operator ==(other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other is! ListLiteralUse) return false;
|
||||
return
|
||||
type == other.type &&
|
||||
isConstant == other.isConstant &&
|
||||
isEmpty == other.isEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutable implementation of [WorldImpact] used to transform
|
||||
/// [ResolutionWorldImpact] to [WorldImpact].
|
||||
// TODO(johnniwinther): Remove [Registry] when dependency is tracked directly
|
||||
// on [WorldImpact].
|
||||
class TransformedWorldImpact implements WorldImpact, Registry {
|
||||
final ResolutionWorldImpact worldImpact;
|
||||
|
||||
Setlet<Element> _staticUses;
|
||||
Setlet<InterfaceType> _instantiatedTypes;
|
||||
Setlet<UniverseSelector> _dynamicGetters;
|
||||
Setlet<UniverseSelector> _dynamicInvocations;
|
||||
Setlet<UniverseSelector> _dynamicSetters;
|
||||
|
||||
TransformedWorldImpact(this.worldImpact);
|
||||
|
||||
@override
|
||||
Iterable<DartType> get asCasts => worldImpact.asCasts;
|
||||
|
||||
@override
|
||||
Iterable<DartType> get checkedModeChecks => worldImpact.checkedModeChecks;
|
||||
|
||||
@override
|
||||
Iterable<MethodElement> get closurizedFunctions {
|
||||
return worldImpact.closurizedFunctions;
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<UniverseSelector> get dynamicGetters {
|
||||
return _dynamicGetters != null
|
||||
? _dynamicGetters : worldImpact.dynamicGetters;
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<UniverseSelector> get dynamicInvocations {
|
||||
return _dynamicInvocations != null
|
||||
? _dynamicInvocations : worldImpact.dynamicInvocations;
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<UniverseSelector> get dynamicSetters {
|
||||
return _dynamicSetters != null
|
||||
? _dynamicSetters : worldImpact.dynamicSetters;
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<DartType> get isChecks => worldImpact.isChecks;
|
||||
|
||||
@override
|
||||
Iterable<Element> get staticUses {
|
||||
if (_staticUses == null) {
|
||||
return worldImpact.staticUses;
|
||||
}
|
||||
return _staticUses;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isForResolution => true;
|
||||
|
||||
_unsupported(String message) => throw new UnsupportedError(message);
|
||||
|
||||
@override
|
||||
Iterable<Element> get otherDependencies => _unsupported('otherDependencies');
|
||||
|
||||
// TODO(johnniwinther): Remove this.
|
||||
@override
|
||||
void registerAssert(bool hasMessage) => _unsupported('registerAssert');
|
||||
|
||||
@override
|
||||
void registerDependency(Element element) {
|
||||
worldImpact.registerDependency(element);
|
||||
}
|
||||
|
||||
@override
|
||||
void registerDynamicGetter(UniverseSelector selector) {
|
||||
if (_dynamicGetters == null) {
|
||||
_dynamicGetters = new Setlet<UniverseSelector>();
|
||||
_dynamicGetters.addAll(worldImpact.dynamicGetters);
|
||||
}
|
||||
_dynamicGetters.add(selector);
|
||||
}
|
||||
|
||||
@override
|
||||
void registerDynamicInvocation(UniverseSelector selector) {
|
||||
if (_dynamicInvocations == null) {
|
||||
_dynamicInvocations = new Setlet<UniverseSelector>();
|
||||
_dynamicInvocations.addAll(worldImpact.dynamicInvocations);
|
||||
}
|
||||
_dynamicInvocations.add(selector);
|
||||
}
|
||||
|
||||
@override
|
||||
void registerDynamicSetter(UniverseSelector selector) {
|
||||
if (_dynamicSetters == null) {
|
||||
_dynamicSetters = new Setlet<UniverseSelector>();
|
||||
_dynamicSetters.addAll(worldImpact.dynamicSetters);
|
||||
}
|
||||
_dynamicSetters.add(selector);
|
||||
}
|
||||
|
||||
@override
|
||||
void registerGetOfStaticFunction(FunctionElement element) {
|
||||
_unsupported('registerGetOfStaticFunction($element)');
|
||||
}
|
||||
|
||||
@override
|
||||
void registerInstantiation(InterfaceType type) {
|
||||
// TODO(johnniwinther): Remove this when dependency tracking is done on
|
||||
// the world impact itself.
|
||||
registerDependency(type.element);
|
||||
if (_instantiatedTypes == null) {
|
||||
_instantiatedTypes = new Setlet<InterfaceType>();
|
||||
}
|
||||
_instantiatedTypes.add(type);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<InterfaceType> get instantiatedTypes {
|
||||
return _instantiatedTypes != null
|
||||
? _instantiatedTypes : const <InterfaceType>[];
|
||||
}
|
||||
|
||||
@override
|
||||
void registerStaticInvocation(Element element) {
|
||||
if (_staticUses == null) {
|
||||
_staticUses = new Setlet<Element>();
|
||||
_staticUses.addAll(worldImpact.staticUses);
|
||||
}
|
||||
_staticUses.add(element);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<LocalFunctionElement> get closures => worldImpact.closures;
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Rename to `Resolver` or `ResolverContext`.
|
||||
abstract class Resolution {
|
||||
Parsing get parsing;
|
||||
|
@ -145,6 +408,9 @@ abstract class Resolution {
|
|||
void resolveMetadataAnnotation(MetadataAnnotation metadataAnnotation);
|
||||
FunctionSignature resolveSignature(FunctionElement function);
|
||||
DartType resolveTypeAnnotation(Element element, TypeAnnotation node);
|
||||
|
||||
bool hasBeenResolved(Element element);
|
||||
ResolutionWorldImpact analyzeElement(Element element);
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Rename to `Parser` or `ParsingContext`.
|
||||
|
|
|
@ -1265,10 +1265,9 @@ class ErroneousAstConstant extends AstConstant {
|
|||
new ErroneousConstantExpression(), new NullConstantValue());
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Avoid the need for this hack.
|
||||
// TODO(johnniwinther): Clean this up.
|
||||
TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) {
|
||||
WorldImpact worldImpact = compiler.analyzeElement(element.declaration);
|
||||
compiler.enqueuer.resolution.applyImpact(element.declaration, worldImpact);
|
||||
compiler.resolution.analyzeElement(element.declaration);
|
||||
return element.resolvedAst.elements;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ import 'common/registry.dart' show
|
|||
import 'common/resolution.dart' show
|
||||
Parsing,
|
||||
Resolution,
|
||||
ResolutionWorkItem;
|
||||
ResolutionWorkItem,
|
||||
ResolutionWorldImpact;
|
||||
import 'common/tasks.dart' show
|
||||
CompilerTask,
|
||||
GenericTask;
|
||||
|
@ -769,7 +770,7 @@ abstract class Compiler {
|
|||
bool isProxyConstant(ConstantValue value) {
|
||||
FieldElement field = coreLibrary.find('proxy');
|
||||
if (field == null) return false;
|
||||
if (!enqueuer.resolution.hasBeenResolved(field)) return false;
|
||||
if (!resolution.hasBeenResolved(field)) return false;
|
||||
if (proxyConstant == null) {
|
||||
proxyConstant =
|
||||
constants.getConstantValue(
|
||||
|
@ -1160,7 +1161,7 @@ abstract class Compiler {
|
|||
});
|
||||
}
|
||||
if (!REPORT_EXCESS_RESOLUTION) return;
|
||||
var resolved = new Set.from(enqueuer.resolution.resolvedElements);
|
||||
var resolved = new Set.from(enqueuer.resolution.processedElements);
|
||||
for (Element e in enqueuer.codegen.generatedCode.keys) {
|
||||
resolved.remove(e);
|
||||
}
|
||||
|
@ -1187,7 +1188,7 @@ abstract class Compiler {
|
|||
}
|
||||
}
|
||||
|
||||
WorldImpact analyzeElement(Element element) {
|
||||
ResolutionWorldImpact analyzeElement(Element element) {
|
||||
assert(invariant(element,
|
||||
element.impliesType ||
|
||||
element.isField ||
|
||||
|
@ -1199,23 +1200,11 @@ abstract class Compiler {
|
|||
assert(invariant(element, element is AnalyzableElement,
|
||||
message: 'Element $element is not analyzable.'));
|
||||
assert(invariant(element, element.isDeclaration));
|
||||
ResolutionEnqueuer world = enqueuer.resolution;
|
||||
if (world.hasBeenResolved(element)) {
|
||||
return const WorldImpact();
|
||||
}
|
||||
assert(parser != null);
|
||||
Node tree = parser.parse(element);
|
||||
assert(invariant(element, !element.isSynthesized || tree == null));
|
||||
WorldImpact worldImpact = resolver.resolve(element);
|
||||
if (tree != null && !analyzeSignaturesOnly && !suppressWarnings) {
|
||||
// Only analyze nodes with a corresponding [TreeElements].
|
||||
checker.check(element);
|
||||
}
|
||||
world.registerResolvedElement(element);
|
||||
return worldImpact;
|
||||
return resolution.analyzeElement(element);
|
||||
}
|
||||
|
||||
WorldImpact analyze(ResolutionWorkItem work, ResolutionEnqueuer world) {
|
||||
ResolutionWorldImpact analyze(ResolutionWorkItem work,
|
||||
ResolutionEnqueuer world) {
|
||||
assert(invariant(work.element, identical(world, enqueuer.resolution)));
|
||||
assert(invariant(work.element, !work.isAnalyzed,
|
||||
message: 'Element ${work.element} has already been analyzed'));
|
||||
|
@ -1223,18 +1212,19 @@ abstract class Compiler {
|
|||
// TODO(ahe): Add structured diagnostics to the compiler API and
|
||||
// use it to separate this from the --verbose option.
|
||||
if (phase == PHASE_RESOLVING) {
|
||||
reporter.log(
|
||||
'Resolved ${enqueuer.resolution.resolvedElements.length} '
|
||||
reporter.log(
|
||||
'Resolved ${enqueuer.resolution.processedElements.length} '
|
||||
'elements.');
|
||||
progress.reset();
|
||||
}
|
||||
}
|
||||
AstElement element = work.element;
|
||||
if (world.hasBeenResolved(element)) {
|
||||
return const WorldImpact();
|
||||
if (world.hasBeenProcessed(element)) {
|
||||
return const ResolutionWorldImpact();
|
||||
}
|
||||
WorldImpact worldImpact = analyzeElement(element);
|
||||
ResolutionWorldImpact worldImpact = analyzeElement(element);
|
||||
backend.onElementResolved(element, element.resolvedAst.elements);
|
||||
world.registerProcessedElement(element);
|
||||
return worldImpact;
|
||||
}
|
||||
|
||||
|
@ -1330,7 +1320,7 @@ abstract class Compiler {
|
|||
void checkLive(member) {
|
||||
if (member.isErroneous) return;
|
||||
if (member.isFunction) {
|
||||
if (!enqueuer.resolution.hasBeenResolved(member)) {
|
||||
if (!enqueuer.resolution.hasBeenProcessed(member)) {
|
||||
reporter.reportHintMessage(
|
||||
member, MessageKind.UNUSED_METHOD, {'name': member.name});
|
||||
}
|
||||
|
@ -1490,28 +1480,47 @@ class _CompilerCoreTypes implements CoreTypes {
|
|||
_CompilerCoreTypes(this.resolution);
|
||||
|
||||
@override
|
||||
InterfaceType get objectType => objectClass.computeType(resolution);
|
||||
InterfaceType get objectType {
|
||||
objectClass.ensureResolved(resolution);
|
||||
return objectClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType get boolType => boolClass.computeType(resolution);
|
||||
InterfaceType get boolType {
|
||||
boolClass.ensureResolved(resolution);
|
||||
return boolClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType get doubleType => doubleClass.computeType(resolution);
|
||||
InterfaceType get doubleType {
|
||||
doubleClass.ensureResolved(resolution);
|
||||
return doubleClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType get functionType => functionClass.computeType(resolution);
|
||||
InterfaceType get functionType {
|
||||
functionClass.ensureResolved(resolution);
|
||||
return functionClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType get intType => intClass.computeType(resolution);
|
||||
InterfaceType get intType {
|
||||
intClass.ensureResolved(resolution);
|
||||
return intClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType get resourceType => resourceClass.computeType(resolution);
|
||||
InterfaceType get resourceType {
|
||||
resourceClass.ensureResolved(resolution);
|
||||
return resourceClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType listType([DartType elementType]) {
|
||||
InterfaceType type = listClass.computeType(resolution);
|
||||
listClass.ensureResolved(resolution);
|
||||
InterfaceType type = listClass.rawType;
|
||||
if (elementType == null) {
|
||||
return listClass.rawType;
|
||||
return type;
|
||||
}
|
||||
return type.createInstantiation([elementType]);
|
||||
}
|
||||
|
@ -1519,9 +1528,10 @@ class _CompilerCoreTypes implements CoreTypes {
|
|||
@override
|
||||
InterfaceType mapType([DartType keyType,
|
||||
DartType valueType]) {
|
||||
InterfaceType type = mapClass.computeType(resolution);
|
||||
mapClass.ensureResolved(resolution);
|
||||
InterfaceType type = mapClass.rawType;
|
||||
if (keyType == null && valueType == null) {
|
||||
return mapClass.rawType;
|
||||
return type;
|
||||
} else if (keyType == null) {
|
||||
keyType = const DynamicType();
|
||||
} else if (valueType == null) {
|
||||
|
@ -1531,43 +1541,61 @@ class _CompilerCoreTypes implements CoreTypes {
|
|||
}
|
||||
|
||||
@override
|
||||
InterfaceType get nullType => nullClass.computeType(resolution);
|
||||
InterfaceType get nullType {
|
||||
nullClass.ensureResolved(resolution);
|
||||
return nullClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType get numType => numClass.computeType(resolution);
|
||||
InterfaceType get numType {
|
||||
numClass.ensureResolved(resolution);
|
||||
return numClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType get stringType => stringClass.computeType(resolution);
|
||||
InterfaceType get stringType {
|
||||
stringClass.ensureResolved(resolution);
|
||||
return stringClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType get symbolType => symbolClass.computeType(resolution);
|
||||
InterfaceType get symbolType {
|
||||
symbolClass.ensureResolved(resolution);
|
||||
return symbolClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType get typeType => typeClass.computeType(resolution);
|
||||
InterfaceType get typeType {
|
||||
typeClass.ensureResolved(resolution);
|
||||
return typeClass.rawType;
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType iterableType([DartType elementType]) {
|
||||
InterfaceType type = iterableClass.computeType(resolution);
|
||||
iterableClass.ensureResolved(resolution);
|
||||
InterfaceType type = iterableClass.rawType;
|
||||
if (elementType == null) {
|
||||
return iterableClass.rawType;
|
||||
return type;
|
||||
}
|
||||
return type.createInstantiation([elementType]);
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType futureType([DartType elementType]) {
|
||||
InterfaceType type = futureClass.computeType(resolution);
|
||||
futureClass.ensureResolved(resolution);
|
||||
InterfaceType type = futureClass.rawType;
|
||||
if (elementType == null) {
|
||||
return futureClass.rawType;
|
||||
return type;
|
||||
}
|
||||
return type.createInstantiation([elementType]);
|
||||
}
|
||||
|
||||
@override
|
||||
InterfaceType streamType([DartType elementType]) {
|
||||
InterfaceType type = streamClass.computeType(resolution);
|
||||
streamClass.ensureResolved(resolution);
|
||||
InterfaceType type = streamClass.rawType;
|
||||
if (elementType == null) {
|
||||
return streamClass.rawType;
|
||||
return type;
|
||||
}
|
||||
return type.createInstantiation([elementType]);
|
||||
}
|
||||
|
@ -1920,6 +1948,8 @@ class _CompilerDiagnosticReporter extends DiagnosticReporter {
|
|||
// TODO(johnniwinther): Move [ResolverTask] here.
|
||||
class _CompilerResolution implements Resolution {
|
||||
final Compiler compiler;
|
||||
final Map<Element, ResolutionWorldImpact> _worldImpactCache =
|
||||
<Element, ResolutionWorldImpact>{};
|
||||
|
||||
_CompilerResolution(this.compiler);
|
||||
|
||||
|
@ -1961,6 +1991,27 @@ class _CompilerResolution implements Resolution {
|
|||
DartType resolveTypeAnnotation(Element element, TypeAnnotation node) {
|
||||
return compiler.resolver.resolveTypeAnnotation(element, node);
|
||||
}
|
||||
|
||||
ResolutionWorldImpact analyzeElement(Element element) {
|
||||
return _worldImpactCache.putIfAbsent(element, () {
|
||||
assert(compiler.parser != null);
|
||||
Node tree = compiler.parser.parse(element);
|
||||
assert(invariant(element, !element.isSynthesized || tree == null));
|
||||
ResolutionWorldImpact worldImpact = compiler.resolver.resolve(element);
|
||||
if (tree != null &&
|
||||
!compiler.analyzeSignaturesOnly &&
|
||||
!compiler.suppressWarnings) {
|
||||
// Only analyze nodes with a corresponding [TreeElements].
|
||||
compiler.checker.check(element);
|
||||
}
|
||||
return worldImpact;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
bool hasBeenResolved(Element element) {
|
||||
return _worldImpactCache.containsKey(element);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Move [ParserTask], [PatchParserTask], [DietParserTask]
|
||||
|
|
|
@ -183,7 +183,7 @@ class DartBackend extends Backend {
|
|||
int totalSize = outputter.assembleProgram(
|
||||
libraries: compiler.libraryLoader.libraries,
|
||||
instantiatedClasses: compiler.resolverWorld.directlyInstantiatedClasses,
|
||||
resolvedElements: compiler.enqueuer.resolution.resolvedElements,
|
||||
resolvedElements: compiler.enqueuer.resolution.processedElements,
|
||||
usedTypeLiterals: usedTypeLiterals,
|
||||
postProcessElementAst: postProcessElementAst,
|
||||
computeElementAst: computeElementAst,
|
||||
|
@ -346,6 +346,24 @@ class DartResolutionCallbacks extends ResolutionCallbacks {
|
|||
|
||||
DartResolutionCallbacks(this.backend);
|
||||
|
||||
@override
|
||||
WorldImpact transformImpact(ResolutionWorldImpact worldImpact) {
|
||||
TransformedWorldImpact transformed =
|
||||
new TransformedWorldImpact(worldImpact);
|
||||
for (DartType typeLiteral in worldImpact.typeLiterals) {
|
||||
onTypeLiteral(typeLiteral, transformed);
|
||||
}
|
||||
for (InterfaceType instantiatedType in worldImpact.instantiatedTypes) {
|
||||
// TODO(johnniwinther): Remove this when dependency tracking is done on
|
||||
// the world impact itself.
|
||||
transformed.registerInstantiation(instantiatedType);
|
||||
backend.registerInstantiatedType(
|
||||
instantiatedType, backend.compiler.enqueuer.resolution, transformed);
|
||||
}
|
||||
return transformed;
|
||||
}
|
||||
|
||||
@override
|
||||
void onTypeLiteral(DartType type, Registry registry) {
|
||||
if (type.isInterfaceType) {
|
||||
backend.usedTypeLiterals.add(type.element);
|
||||
|
|
|
@ -20,7 +20,9 @@ import '../common/registry.dart' show
|
|||
Registry;
|
||||
import '../common/resolution.dart' show
|
||||
Resolution,
|
||||
ResolutionCallbacks;
|
||||
ResolutionCallbacks,
|
||||
ResolutionWorldImpact,
|
||||
TransformedWorldImpact;
|
||||
import '../common/tasks.dart' show
|
||||
CompilerTask;
|
||||
import '../compiler.dart' show
|
||||
|
|
|
@ -304,7 +304,7 @@ class DeferredLoadTask extends CompilerTask {
|
|||
// TODO(sigurdm): We want to be more specific about this - need a better
|
||||
// way to query "liveness".
|
||||
if (astElement is! TypedefElement &&
|
||||
!compiler.enqueuer.resolution.hasBeenResolved(astElement)) {
|
||||
!compiler.enqueuer.resolution.hasBeenProcessed(astElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -356,7 +356,7 @@ class DeferredLoadTask extends CompilerTask {
|
|||
// to. Static members are not relevant, unless we are processing
|
||||
// extra dependencies due to mirrors.
|
||||
void addLiveInstanceMember(Element element) {
|
||||
if (!compiler.enqueuer.resolution.hasBeenResolved(element)) return;
|
||||
if (!compiler.enqueuer.resolution.hasBeenProcessed(element)) return;
|
||||
if (!isMirrorUsage && !element.isInstanceMember) return;
|
||||
collectDependencies(element.implementation);
|
||||
}
|
||||
|
|
|
@ -2595,7 +2595,8 @@ abstract class BaseClassElementX extends ElementX
|
|||
* The returned element may not be resolved yet.
|
||||
*/
|
||||
ClassElement get superclass {
|
||||
assert(supertypeLoadState == STATE_DONE);
|
||||
assert(invariant(this, supertypeLoadState == STATE_DONE,
|
||||
message: "Superclass has not been computed for $this."));
|
||||
return supertype == null ? null : supertype.element;
|
||||
}
|
||||
|
||||
|
|
|
@ -112,9 +112,15 @@ class WorldImpact {
|
|||
|
||||
// TODO(johnniwinther): Collect checked types for checked mode separately to
|
||||
// support serialization.
|
||||
Iterable<DartType> get checkedTypes => const <DartType>[];
|
||||
Iterable<DartType> get isChecks => const <DartType>[];
|
||||
|
||||
Iterable<DartType> get checkedModeChecks => const <DartType>[];
|
||||
|
||||
Iterable<DartType> get asCasts => const <DartType>[];
|
||||
|
||||
Iterable<MethodElement> get closurizedFunctions => const <MethodElement>[];
|
||||
|
||||
Iterable<LocalFunctionElement> get closures => const <LocalFunctionElement>[];
|
||||
}
|
||||
|
||||
abstract class Enqueuer {
|
||||
|
@ -161,6 +167,10 @@ abstract class Enqueuer {
|
|||
/// Returns [:true:] if [member] has been processed by this enqueuer.
|
||||
bool isProcessed(Element member);
|
||||
|
||||
bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls);
|
||||
|
||||
Iterable<ClassElement> get processedClasses => _processedClasses;
|
||||
|
||||
/**
|
||||
* Documentation wanted -- johnniwinther
|
||||
*
|
||||
|
@ -190,10 +200,14 @@ abstract class Enqueuer {
|
|||
worldImpact.dynamicGetters.forEach(registerDynamicGetter);
|
||||
worldImpact.dynamicSetters.forEach(registerDynamicSetter);
|
||||
worldImpact.staticUses.forEach(registerStaticUse);
|
||||
// TODO(johnniwinther): Register [worldImpact.instantiatedTypes] when it
|
||||
// doesn't require a [Registry].
|
||||
worldImpact.checkedTypes.forEach(registerIsCheck);
|
||||
worldImpact.instantiatedTypes.forEach(registerInstantiatedType);
|
||||
worldImpact.isChecks.forEach(registerIsCheck);
|
||||
worldImpact.asCasts.forEach(registerIsCheck);
|
||||
if (compiler.enableTypeAssertions) {
|
||||
worldImpact.checkedModeChecks.forEach(registerIsCheck);
|
||||
}
|
||||
worldImpact.closurizedFunctions.forEach(registerGetOfStaticFunction);
|
||||
worldImpact.closures.forEach(registerClosure);
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Remove the need for passing the [registry].
|
||||
|
@ -334,6 +348,15 @@ abstract class Enqueuer {
|
|||
|
||||
void processClass(ClassElement superclass) {
|
||||
if (_processedClasses.contains(superclass)) return;
|
||||
// TODO(johnniwinther): Re-insert this invariant when unittests don't
|
||||
// fail. There is already a similar invariant on the members.
|
||||
/*if (!isResolutionQueue) {
|
||||
assert(invariant(superclass,
|
||||
superclass.isClosure ||
|
||||
compiler.enqueuer.resolution.isClassProcessed(superclass),
|
||||
message: "Class $superclass has not been "
|
||||
"processed in resolution."));
|
||||
}*/
|
||||
|
||||
_processedClasses.add(superclass);
|
||||
recentClasses.add(superclass);
|
||||
|
@ -767,7 +790,7 @@ class ResolutionEnqueuer extends Enqueuer {
|
|||
*
|
||||
* Invariant: Key elements are declaration elements.
|
||||
*/
|
||||
final Set<AstElement> resolvedElements;
|
||||
final Set<AstElement> processedElements;
|
||||
|
||||
final Queue<ResolutionWorkItem> queue;
|
||||
|
||||
|
@ -784,22 +807,22 @@ class ResolutionEnqueuer extends Enqueuer {
|
|||
compiler,
|
||||
itemCompilationContextCreator,
|
||||
strategy),
|
||||
resolvedElements = new Set<AstElement>(),
|
||||
processedElements = new Set<AstElement>(),
|
||||
queue = new Queue<ResolutionWorkItem>(),
|
||||
deferredTaskQueue = new Queue<DeferredTask>();
|
||||
|
||||
bool get isResolutionQueue => true;
|
||||
|
||||
bool isProcessed(Element member) => resolvedElements.contains(member);
|
||||
bool isProcessed(Element member) => processedElements.contains(member);
|
||||
|
||||
/// Returns `true` if [element] has been processed by the resolution enqueuer.
|
||||
bool hasBeenResolved(Element element) {
|
||||
return resolvedElements.contains(element.analyzableElement.declaration);
|
||||
bool hasBeenProcessed(Element element) {
|
||||
return processedElements.contains(element.analyzableElement.declaration);
|
||||
}
|
||||
|
||||
/// Registers [element] as resolved for the resolution enqueuer.
|
||||
void registerResolvedElement(AstElement element) {
|
||||
resolvedElements.add(element);
|
||||
/// Registers [element] as processed by the resolution enqueuer.
|
||||
void registerProcessedElement(AstElement element) {
|
||||
processedElements.add(element);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -820,7 +843,7 @@ class ResolutionEnqueuer extends Enqueuer {
|
|||
|
||||
assert(invariant(element, element is AnalyzableElement,
|
||||
message: 'Element $element is not analyzable.'));
|
||||
if (hasBeenResolved(element)) return false;
|
||||
if (hasBeenProcessed(element)) return false;
|
||||
if (queueIsClosed) {
|
||||
throw new SpannableAssertionFailure(element,
|
||||
"Resolution work list is closed. Trying to add $element.");
|
||||
|
@ -912,12 +935,12 @@ class ResolutionEnqueuer extends Enqueuer {
|
|||
}
|
||||
|
||||
void _logSpecificSummary(log(message)) {
|
||||
log('Resolved ${resolvedElements.length} elements.');
|
||||
log('Resolved ${processedElements.length} elements.');
|
||||
}
|
||||
|
||||
void forgetElement(Element element) {
|
||||
super.forgetElement(element);
|
||||
resolvedElements.remove(element);
|
||||
processedElements.remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -671,6 +671,7 @@ class TypeGraphInferrerEngine
|
|||
compiler.progress.reset();
|
||||
}
|
||||
sortResolvedElements().forEach((Element element) {
|
||||
assert(compiler.enqueuer.resolution.hasBeenProcessed(element));
|
||||
if (compiler.shouldPrintProgress) {
|
||||
reporter.log('Added $addedInGraph elements in inferencing graph.');
|
||||
compiler.progress.reset();
|
||||
|
@ -1220,10 +1221,10 @@ class TypeGraphInferrerEngine
|
|||
Iterable<Element> sortResolvedElements() {
|
||||
int max = 0;
|
||||
Map<int, Setlet<Element>> methodSizes = new Map<int, Setlet<Element>>();
|
||||
compiler.enqueuer.resolution.resolvedElements.forEach((AstElement element) {
|
||||
compiler.enqueuer.resolution.processedElements.forEach((AstElement element) {
|
||||
// TODO(ngeoffray): Not sure why the resolver would put a null
|
||||
// mapping.
|
||||
if (!compiler.enqueuer.resolution.hasBeenResolved(element)) return;
|
||||
if (!compiler.enqueuer.resolution.hasBeenProcessed(element)) return;
|
||||
TreeElementMapping mapping = element.resolvedAst.elements;
|
||||
element = element.implementation;
|
||||
if (element.impliesType) return;
|
||||
|
|
|
@ -1420,7 +1420,7 @@ class JavaScriptBackend extends Backend {
|
|||
}
|
||||
}
|
||||
|
||||
void registerRequiredType(DartType type, Element enclosingElement) {
|
||||
void registerRequiredType(DartType type) {
|
||||
// If [argument] has type variables or is a type variable, this method
|
||||
// registers a RTI dependency between the class where the type variable is
|
||||
// defined (that is the enclosing class of the current element being
|
||||
|
@ -1428,7 +1428,6 @@ class JavaScriptBackend extends Backend {
|
|||
// then the class of the type variable does too.
|
||||
ClassElement contextClass = Types.getClassContext(type);
|
||||
if (contextClass != null) {
|
||||
assert(contextClass == enclosingElement.enclosingClass.declaration);
|
||||
rti.registerRtiDependency(type.element, contextClass);
|
||||
}
|
||||
}
|
||||
|
@ -2427,13 +2426,13 @@ class JavaScriptBackend extends Backend {
|
|||
reflectableMembers.add(cls);
|
||||
// 2) its constructors (if resolved)
|
||||
cls.constructors.forEach((Element constructor) {
|
||||
if (resolution.hasBeenResolved(constructor)) {
|
||||
if (resolution.hasBeenProcessed(constructor)) {
|
||||
reflectableMembers.add(constructor);
|
||||
}
|
||||
});
|
||||
// 3) all members, including fields via getter/setters (if resolved)
|
||||
cls.forEachClassMember((Member member) {
|
||||
if (resolution.hasBeenResolved(member.element)) {
|
||||
if (resolution.hasBeenProcessed(member.element)) {
|
||||
memberNames.add(member.name);
|
||||
reflectableMembers.add(member.element);
|
||||
}
|
||||
|
@ -2445,8 +2444,8 @@ class JavaScriptBackend extends Backend {
|
|||
if (memberNames.contains(member.name)) {
|
||||
// TODO(20993): find out why this assertion fails.
|
||||
// assert(invariant(member.element,
|
||||
// resolution.hasBeenResolved(member.element)));
|
||||
if (resolution.hasBeenResolved(member.element)) {
|
||||
// resolution.hasBeenProcessed(member.element)));
|
||||
if (resolution.hasBeenProcessed(member.element)) {
|
||||
reflectableMembers.add(member.element);
|
||||
}
|
||||
}
|
||||
|
@ -2462,13 +2461,13 @@ class JavaScriptBackend extends Backend {
|
|||
} else {
|
||||
// check members themselves
|
||||
cls.constructors.forEach((ConstructorElement element) {
|
||||
if (!resolution.hasBeenResolved(element)) return;
|
||||
if (!resolution.hasBeenProcessed(element)) return;
|
||||
if (referencedFromMirrorSystem(element, false)) {
|
||||
reflectableMembers.add(element);
|
||||
}
|
||||
});
|
||||
cls.forEachClassMember((Member member) {
|
||||
if (!resolution.hasBeenResolved(member.element)) return;
|
||||
if (!resolution.hasBeenProcessed(member.element)) return;
|
||||
if (referencedFromMirrorSystem(member.element, false)) {
|
||||
reflectableMembers.add(member.element);
|
||||
}
|
||||
|
@ -2493,7 +2492,7 @@ class JavaScriptBackend extends Backend {
|
|||
if (lib.isInternalLibrary) continue;
|
||||
lib.forEachLocalMember((Element member) {
|
||||
if (!member.isClass &&
|
||||
resolution.hasBeenResolved(member) &&
|
||||
resolution.hasBeenProcessed(member) &&
|
||||
referencedFromMirrorSystem(member)) {
|
||||
reflectableMembers.add(member);
|
||||
}
|
||||
|
@ -2652,7 +2651,15 @@ class JavaScriptBackend extends Backend {
|
|||
reporter.log('Retaining metadata.');
|
||||
|
||||
compiler.libraryLoader.libraries.forEach(retainMetadataOf);
|
||||
if (!enqueuer.isResolutionQueue) {
|
||||
if (enqueuer.isResolutionQueue) {
|
||||
for (Dependency dependency in metadataConstants) {
|
||||
registerCompileTimeConstant(
|
||||
dependency.constant,
|
||||
new EagerRegistry(compiler,
|
||||
dependency.annotatedElement.analyzableElement.treeElements),
|
||||
addForEmission: false);
|
||||
}
|
||||
} else {
|
||||
for (Dependency dependency in metadataConstants) {
|
||||
registerCompileTimeConstant(
|
||||
dependency.constant,
|
||||
|
@ -2799,33 +2806,48 @@ class JavaScriptBackend extends Backend {
|
|||
Enqueuer enqueuer,
|
||||
Registry registry) {
|
||||
if (element.asyncMarker == AsyncMarker.ASYNC) {
|
||||
enqueue(enqueuer, getAsyncHelper(), registry);
|
||||
enqueue(enqueuer, getSyncCompleterConstructor(), registry);
|
||||
enqueue(enqueuer, getStreamIteratorConstructor(), registry);
|
||||
enqueue(enqueuer, getWrapBody(), registry);
|
||||
_registerAsync(enqueuer, registry);
|
||||
} else if (element.asyncMarker == AsyncMarker.SYNC_STAR) {
|
||||
ClassElement clsSyncStarIterable = getSyncStarIterable();
|
||||
clsSyncStarIterable.ensureResolved(resolution);
|
||||
registerInstantiatedType(clsSyncStarIterable.rawType, enqueuer, registry);
|
||||
enqueue(enqueuer, getSyncStarIterableConstructor(), registry);
|
||||
enqueue(enqueuer, getEndOfIteration(), registry);
|
||||
enqueue(enqueuer, getYieldStar(), registry);
|
||||
enqueue(enqueuer, getSyncStarUncaughtError(), registry);
|
||||
_registerSyncStar(enqueuer, registry);
|
||||
} else if (element.asyncMarker == AsyncMarker.ASYNC_STAR) {
|
||||
ClassElement clsASyncStarController = getASyncStarController();
|
||||
clsASyncStarController.ensureResolved(resolution);
|
||||
registerInstantiatedType(
|
||||
clsASyncStarController.rawType, enqueuer, registry);
|
||||
enqueue(enqueuer, getAsyncStarHelper(), registry);
|
||||
enqueue(enqueuer, getStreamOfController(), registry);
|
||||
enqueue(enqueuer, getYieldSingle(), registry);
|
||||
enqueue(enqueuer, getYieldStar(), registry);
|
||||
enqueue(enqueuer, getASyncStarControllerConstructor(), registry);
|
||||
enqueue(enqueuer, getStreamIteratorConstructor(), registry);
|
||||
enqueue(enqueuer, getWrapBody(), registry);
|
||||
_registerAsyncStar(enqueuer, registry);
|
||||
}
|
||||
}
|
||||
|
||||
void _registerAsync(Enqueuer enqueuer,
|
||||
Registry registry) {
|
||||
enqueue(enqueuer, getAsyncHelper(), registry);
|
||||
enqueue(enqueuer, getSyncCompleterConstructor(), registry);
|
||||
enqueue(enqueuer, getStreamIteratorConstructor(), registry);
|
||||
enqueue(enqueuer, getWrapBody(), registry);
|
||||
}
|
||||
|
||||
void _registerSyncStar(Enqueuer enqueuer,
|
||||
Registry registry) {
|
||||
ClassElement clsSyncStarIterable = getSyncStarIterable();
|
||||
clsSyncStarIterable.ensureResolved(compiler.resolution);
|
||||
registerInstantiatedType(clsSyncStarIterable.rawType, enqueuer, registry);
|
||||
enqueue(enqueuer, getSyncStarIterableConstructor(), registry);
|
||||
enqueue(enqueuer, getEndOfIteration(), registry);
|
||||
enqueue(enqueuer, getYieldStar(), registry);
|
||||
enqueue(enqueuer, getSyncStarUncaughtError(), registry);
|
||||
}
|
||||
|
||||
void _registerAsyncStar(Enqueuer enqueuer,
|
||||
Registry registry) {
|
||||
ClassElement clsASyncStarController = getASyncStarController();
|
||||
clsASyncStarController.ensureResolved(compiler.resolution);
|
||||
registerInstantiatedType(
|
||||
clsASyncStarController.rawType, enqueuer, registry);
|
||||
enqueue(enqueuer, getAsyncStarHelper(), registry);
|
||||
enqueue(enqueuer, getStreamOfController(), registry);
|
||||
enqueue(enqueuer, getYieldSingle(), registry);
|
||||
enqueue(enqueuer, getYieldStar(), registry);
|
||||
enqueue(enqueuer, getASyncStarControllerConstructor(), registry);
|
||||
enqueue(enqueuer, getStreamIteratorConstructor(), registry);
|
||||
enqueue(enqueuer, getWrapBody(), registry);
|
||||
}
|
||||
|
||||
@override
|
||||
bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) {
|
||||
registerCheckDeferredIsLoaded(registry);
|
||||
|
@ -2984,6 +3006,132 @@ class JavaScriptResolutionCallbacks extends ResolutionCallbacks {
|
|||
|
||||
JavaScriptResolutionCallbacks(this.backend);
|
||||
|
||||
WorldImpact transformImpact(ResolutionWorldImpact worldImpact) {
|
||||
TransformedWorldImpact transformed =
|
||||
new TransformedWorldImpact(worldImpact);
|
||||
for (Feature feature in worldImpact.features) {
|
||||
switch (feature) {
|
||||
case Feature.ABSTRACT_CLASS_INSTANTIATION:
|
||||
onAbstractClassInstantiation(transformed);
|
||||
break;
|
||||
case Feature.ASSERT:
|
||||
onAssert(false, transformed);
|
||||
break;
|
||||
case Feature.ASSERT_WITH_MESSAGE:
|
||||
onAssert(true, transformed);
|
||||
break;
|
||||
case Feature.ASYNC:
|
||||
backend._registerAsync(
|
||||
backend.compiler.enqueuer.resolution, transformed);
|
||||
break;
|
||||
case Feature.ASYNC_FOR_IN:
|
||||
onAsyncForIn(null, transformed);
|
||||
break;
|
||||
case Feature.ASYNC_STAR:
|
||||
backend._registerAsyncStar(
|
||||
backend.compiler.enqueuer.resolution, transformed);
|
||||
break;
|
||||
case Feature.CATCH_STATEMENT:
|
||||
onCatchStatement(transformed);
|
||||
break;
|
||||
case Feature.COMPILE_TIME_ERROR:
|
||||
onCompileTimeError(transformed, null);
|
||||
break;
|
||||
case Feature.FALL_THROUGH_ERROR:
|
||||
onFallThroughError(transformed);
|
||||
break;
|
||||
case Feature.INC_DEC_OPERATION:
|
||||
onIncDecOperation(transformed);
|
||||
break;
|
||||
case Feature.LAZY_FIELD:
|
||||
onLazyField(transformed);
|
||||
break;
|
||||
case Feature.NEW_SYMBOL:
|
||||
backend.registerNewSymbol(transformed);
|
||||
break;
|
||||
case Feature.STACK_TRACE_IN_CATCH:
|
||||
onStackTraceInCatch(transformed);
|
||||
break;
|
||||
case Feature.STRING_INTERPOLATION:
|
||||
onStringInterpolation(transformed);
|
||||
break;
|
||||
case Feature.SUPER_NO_SUCH_METHOD:
|
||||
onSuperNoSuchMethod(transformed);
|
||||
break;
|
||||
case Feature.SYMBOL_CONSTRUCTOR:
|
||||
onSymbolConstructor(transformed);
|
||||
break;
|
||||
case Feature.SYNC_FOR_IN:
|
||||
onSyncForIn(transformed);
|
||||
break;
|
||||
case Feature.SYNC_STAR:
|
||||
backend._registerSyncStar(
|
||||
backend.compiler.enqueuer.resolution, transformed);
|
||||
break;
|
||||
case Feature.THROW_EXPRESSION:
|
||||
onThrowExpression(transformed);
|
||||
break;
|
||||
case Feature.THROW_NO_SUCH_METHOD:
|
||||
onThrowNoSuchMethod(transformed);
|
||||
break;
|
||||
case Feature.THROW_RUNTIME_ERROR:
|
||||
onThrowRuntimeError(transformed);
|
||||
break;
|
||||
case Feature.TYPE_VARIABLE_BOUNDS_CHECK:
|
||||
onTypeVariableBoundCheck(transformed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (DartType type in worldImpact.isChecks) {
|
||||
onIsCheck(type, transformed);
|
||||
}
|
||||
for (DartType type in worldImpact.asCasts) {
|
||||
onIsCheck(type, transformed);
|
||||
onAsCheck(type, transformed);
|
||||
}
|
||||
if (backend.compiler.enableTypeAssertions) {
|
||||
for (DartType type in worldImpact.checkedModeChecks) {
|
||||
onIsCheck(type, transformed);
|
||||
}
|
||||
}
|
||||
for (DartType requiredType in worldImpact.requiredTypes) {
|
||||
backend.registerRequiredType(requiredType);
|
||||
}
|
||||
for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) {
|
||||
// TODO(johnniwinther): Use the [isEmpty] property when factory
|
||||
// constructors are registered directly.
|
||||
onMapLiteral(transformed, mapLiteralUse.type, mapLiteralUse.isConstant);
|
||||
}
|
||||
for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) {
|
||||
// TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when
|
||||
// factory constructors are registered directly.
|
||||
transformed.registerInstantiation(listLiteralUse.type);
|
||||
}
|
||||
for (DartType typeLiteral in worldImpact.typeLiterals) {
|
||||
onTypeLiteral(typeLiteral, transformed);
|
||||
transformed.registerInstantiation(backend.compiler.coreTypes.typeType);
|
||||
if (typeLiteral.isTypeVariable) {
|
||||
onTypeVariableExpression(transformed, typeLiteral.element);
|
||||
}
|
||||
}
|
||||
for (String constSymbolName in worldImpact.constSymbolNames) {
|
||||
backend.registerConstSymbol(constSymbolName, transformed);
|
||||
}
|
||||
for (LocalFunctionElement closure in worldImpact.closures) {
|
||||
if (closure.computeType(backend.resolution).containsTypeVariables) {
|
||||
backend.registerClosureWithFreeTypeVariables(
|
||||
closure, backend.compiler.enqueuer.resolution, transformed);
|
||||
}
|
||||
}
|
||||
// TODO(johnniwinther): Remove this when dependency tracking is done on
|
||||
// the world impact itself.
|
||||
for (InterfaceType instantiatedType in worldImpact.instantiatedTypes) {
|
||||
transformed.registerInstantiation(instantiatedType);
|
||||
}
|
||||
|
||||
return transformed;
|
||||
}
|
||||
|
||||
void registerBackendStaticInvocation(Element element, Registry registry) {
|
||||
registry.registerStaticInvocation(backend.registerBackendUse(element));
|
||||
}
|
||||
|
@ -3189,7 +3337,7 @@ class JavaScriptResolutionCallbacks extends ResolutionCallbacks {
|
|||
'Needed to encode the name of super.noSuchMethod.');
|
||||
}
|
||||
|
||||
void onMapLiteral(ResolutionRegistry registry,
|
||||
void onMapLiteral(Registry registry,
|
||||
DartType type,
|
||||
bool isConstant) {
|
||||
assert(registry.isForResolution);
|
||||
|
@ -3204,7 +3352,7 @@ class JavaScriptResolutionCallbacks extends ResolutionCallbacks {
|
|||
enqueue(JavaScriptMapConstant.DART_STRING_CLASS);
|
||||
enqueue(JavaScriptMapConstant.DART_GENERAL_CLASS);
|
||||
} else {
|
||||
registry.registerInstantiatedType(type);
|
||||
registry.registerInstantiation(type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,13 @@ import '../common/registry.dart' show
|
|||
import '../common/tasks.dart' show
|
||||
CompilerTask;
|
||||
import '../common/resolution.dart' show
|
||||
Feature,
|
||||
ListLiteralUse,
|
||||
MapLiteralUse,
|
||||
Resolution,
|
||||
ResolutionCallbacks;
|
||||
ResolutionCallbacks,
|
||||
ResolutionWorldImpact,
|
||||
TransformedWorldImpact;
|
||||
import '../common/work.dart' show
|
||||
ItemCompilationContext;
|
||||
import '../compiler.dart' show
|
||||
|
@ -77,7 +82,7 @@ import '../js_emitter/js_emitter.dart' show
|
|||
import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
|
||||
import '../native/native.dart' as native;
|
||||
import '../resolution/registry.dart' show
|
||||
ResolutionRegistry;
|
||||
EagerRegistry;
|
||||
import '../resolution/tree_elements.dart' show
|
||||
TreeElements;
|
||||
import '../ssa/ssa.dart';
|
||||
|
|
|
@ -853,6 +853,7 @@ abstract class ClassMemberMixin implements ClassElement {
|
|||
/// this class.
|
||||
MembersCreator _prepareCreator(Compiler compiler) {
|
||||
if (classMembers == null) {
|
||||
ensureResolved(compiler.resolution);
|
||||
classMembers = new Map<Name, Member>();
|
||||
|
||||
if (interfaceMembersAreClassMembers) {
|
||||
|
|
|
@ -414,7 +414,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
TypeResult visitTypeAnnotation(TypeAnnotation node) {
|
||||
DartType type = resolveTypeAnnotation(node);
|
||||
if (inCheckContext) {
|
||||
registry.registerIsCheck(type);
|
||||
registry.registerCheckedModeCheck(type);
|
||||
}
|
||||
return new TypeResult(type);
|
||||
}
|
||||
|
@ -500,7 +500,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
});
|
||||
if (inCheckContext) {
|
||||
functionParameters.forEachParameter((ParameterElement element) {
|
||||
registry.registerIsCheck(element.type);
|
||||
registry.registerCheckedModeCheck(element.type);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1190,7 +1190,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
|
||||
Node typeNode = node.arguments.head;
|
||||
DartType type = resolveTypeAnnotation(typeNode);
|
||||
registry.registerAsCheck(type);
|
||||
registry.registerAsCast(type);
|
||||
registry.registerSendStructure(node, new AsStructure(type));
|
||||
return const NoneResult();
|
||||
}
|
||||
|
@ -1952,7 +1952,6 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
} else {
|
||||
semantics = new StaticAccess.typeParameterTypeLiteral(element);
|
||||
}
|
||||
registry.registerTypeVariableExpression(element);
|
||||
|
||||
registry.useElement(node, element);
|
||||
registry.registerTypeLiteral(node, element.type);
|
||||
|
@ -2005,14 +2004,10 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
MessageKind.ASSIGNING_TYPE, const {});
|
||||
}
|
||||
|
||||
if (node.isComplex) {
|
||||
// We read the type variable before trying write to it.
|
||||
registry.registerTypeVariableExpression(element);
|
||||
}
|
||||
|
||||
// TODO(23998): Remove this when all information goes through
|
||||
// the [SendStructure].
|
||||
registry.useElement(node, error);
|
||||
// TODO(johnniwinther): Register only on read?
|
||||
registry.registerTypeLiteral(node, element.type);
|
||||
registry.registerThrowNoSuchMethod();
|
||||
semantics = new StaticAccess.typeParameterTypeLiteral(element);
|
||||
|
@ -4008,7 +4003,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
this, node, malformedIsError: malformedIsError,
|
||||
deferredIsMalformed: deferredIsMalformed);
|
||||
if (inCheckContext) {
|
||||
registry.registerIsCheck(type);
|
||||
registry.registerCheckedModeCheck(type);
|
||||
registry.registerRequiredType(type, enclosingElement);
|
||||
}
|
||||
return type;
|
||||
|
@ -4048,8 +4043,11 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
} else {
|
||||
listType = coreTypes.listType();
|
||||
}
|
||||
registry.setType(node, listType);
|
||||
registry.registerInstantiatedType(listType);
|
||||
registry.registerLiteralList(
|
||||
node,
|
||||
listType,
|
||||
isConstant: node.isConst,
|
||||
isEmpty: node.elements.isEmpty);
|
||||
registry.registerRequiredType(listType, enclosingElement);
|
||||
if (node.isConst) {
|
||||
List<ConstantExpression> constantExpressions = <ConstantExpression>[];
|
||||
|
@ -4369,7 +4367,11 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
MessageKind.TYPE_VARIABLE_IN_CONSTANT);
|
||||
isValidAsConstant = false;
|
||||
}
|
||||
registry.registerMapLiteral(node, mapType, node.isConst);
|
||||
registry.registerMapLiteral(
|
||||
node,
|
||||
mapType,
|
||||
isConstant: node.isConst,
|
||||
isEmpty: node.entries.isEmpty);
|
||||
registry.registerRequiredType(mapType, enclosingElement);
|
||||
if (node.isConst) {
|
||||
|
||||
|
|
|
@ -7,6 +7,11 @@ library dart2js.resolution.registry;
|
|||
import '../common/backend_api.dart' show
|
||||
Backend,
|
||||
ForeignResolver;
|
||||
import '../common/resolution.dart' show
|
||||
Feature,
|
||||
ListLiteralUse,
|
||||
MapLiteralUse,
|
||||
ResolutionWorldImpact;
|
||||
import '../common/registry.dart' show
|
||||
Registry;
|
||||
import '../compiler.dart' show
|
||||
|
@ -16,9 +21,9 @@ import '../dart_types.dart';
|
|||
import '../diagnostics/invariant.dart' show
|
||||
invariant;
|
||||
import '../enqueue.dart' show
|
||||
ResolutionEnqueuer,
|
||||
WorldImpact;
|
||||
ResolutionEnqueuer;
|
||||
import '../elements/elements.dart';
|
||||
import '../helpers/helpers.dart';
|
||||
import '../tree/tree.dart';
|
||||
import '../util/util.dart' show
|
||||
Setlet;
|
||||
|
@ -37,11 +42,7 @@ import 'members.dart' show
|
|||
import 'tree_elements.dart' show
|
||||
TreeElementMapping;
|
||||
|
||||
/// [ResolutionRegistry] collects all resolution information. It stores node
|
||||
/// related information in a [TreeElements] mapping and registers calls with
|
||||
/// [Backend], [World] and [Enqueuer].
|
||||
// TODO(johnniwinther): Split this into an interface and implementation class.
|
||||
|
||||
// TODO(johnniwinther): Remove this.
|
||||
class EagerRegistry implements Registry {
|
||||
final Compiler compiler;
|
||||
final TreeElementMapping mapping;
|
||||
|
@ -100,19 +101,35 @@ class EagerRegistry implements Registry {
|
|||
String toString() => 'EagerRegistry for ${mapping.analyzedElement}';
|
||||
}
|
||||
|
||||
class ResolutionWorldImpact implements WorldImpact {
|
||||
class _ResolutionWorldImpact implements ResolutionWorldImpact {
|
||||
final Registry registry;
|
||||
// TODO(johnniwinther): Do we benefit from lazy initialization of the
|
||||
// [Setlet]s?
|
||||
Setlet<UniverseSelector> _dynamicInvocations;
|
||||
Setlet<UniverseSelector> _dynamicGetters;
|
||||
Setlet<UniverseSelector> _dynamicSetters;
|
||||
Setlet<InterfaceType> _instantiatedTypes;
|
||||
Setlet<Element> _staticUses;
|
||||
Setlet<DartType> _checkedTypes;
|
||||
Setlet<DartType> _isChecks;
|
||||
Setlet<DartType> _asCasts;
|
||||
Setlet<DartType> _checkedModeChecks;
|
||||
Setlet<MethodElement> _closurizedFunctions;
|
||||
Setlet<LocalFunctionElement> _closures;
|
||||
Setlet<Feature> _features;
|
||||
// TODO(johnniwinther): This seems to be a union of other sets.
|
||||
Setlet<DartType> _requiredTypes;
|
||||
Setlet<MapLiteralUse> _mapLiterals;
|
||||
Setlet<ListLiteralUse> _listLiterals;
|
||||
Setlet<DartType> _typeLiterals;
|
||||
Setlet<String> _constSymbolNames;
|
||||
|
||||
ResolutionWorldImpact(Compiler compiler, TreeElementMapping mapping)
|
||||
_ResolutionWorldImpact(Compiler compiler, TreeElementMapping mapping)
|
||||
: this.registry = new EagerRegistry(compiler, mapping);
|
||||
|
||||
void registerDependency(Element element) {
|
||||
registry.registerDependency(element);
|
||||
}
|
||||
|
||||
void registerDynamicGetter(UniverseSelector selector) {
|
||||
if (_dynamicGetters == null) {
|
||||
_dynamicGetters = new Setlet<UniverseSelector>();
|
||||
|
@ -153,10 +170,6 @@ class ResolutionWorldImpact implements WorldImpact {
|
|||
}
|
||||
|
||||
void registerInstantiatedType(InterfaceType type) {
|
||||
// TODO(johnniwinther): Enable this when registration doesn't require a
|
||||
// [Registry].
|
||||
throw new UnsupportedError(
|
||||
'Lazy registration of instantiated not supported.');
|
||||
if (_instantiatedTypes == null) {
|
||||
_instantiatedTypes = new Setlet<InterfaceType>();
|
||||
}
|
||||
|
@ -169,6 +182,58 @@ class ResolutionWorldImpact implements WorldImpact {
|
|||
? _instantiatedTypes : const <InterfaceType>[];
|
||||
}
|
||||
|
||||
void registerTypeLiteral(DartType type) {
|
||||
if (_typeLiterals == null) {
|
||||
_typeLiterals = new Setlet<DartType>();
|
||||
}
|
||||
_typeLiterals.add(type);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<DartType> get typeLiterals {
|
||||
return _typeLiterals != null
|
||||
? _typeLiterals : const <DartType>[];
|
||||
}
|
||||
|
||||
void registerRequiredType(DartType type) {
|
||||
if (_requiredTypes == null) {
|
||||
_requiredTypes = new Setlet<DartType>();
|
||||
}
|
||||
_requiredTypes.add(type);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<DartType> get requiredTypes {
|
||||
return _requiredTypes != null
|
||||
? _requiredTypes : const <DartType>[];
|
||||
}
|
||||
|
||||
void registerMapLiteral(MapLiteralUse mapLiteralUse) {
|
||||
if (_mapLiterals == null) {
|
||||
_mapLiterals = new Setlet<MapLiteralUse>();
|
||||
}
|
||||
_mapLiterals.add(mapLiteralUse);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<MapLiteralUse> get mapLiterals {
|
||||
return _mapLiterals != null
|
||||
? _mapLiterals : const <MapLiteralUse>[];
|
||||
}
|
||||
|
||||
void registerListLiteral(ListLiteralUse listLiteralUse) {
|
||||
if (_listLiterals == null) {
|
||||
_listLiterals = new Setlet<ListLiteralUse>();
|
||||
}
|
||||
_listLiterals.add(listLiteralUse);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<ListLiteralUse> get listLiterals {
|
||||
return _listLiterals != null
|
||||
? _listLiterals : const <ListLiteralUse>[];
|
||||
}
|
||||
|
||||
void registerStaticUse(Element element) {
|
||||
if (_staticUses == null) {
|
||||
_staticUses = new Setlet<Element>();
|
||||
|
@ -181,17 +246,43 @@ class ResolutionWorldImpact implements WorldImpact {
|
|||
return _staticUses != null ? _staticUses : const <Element>[];
|
||||
}
|
||||
|
||||
void registerCheckedType(DartType type) {
|
||||
if (_checkedTypes == null) {
|
||||
_checkedTypes = new Setlet<DartType>();
|
||||
void registerIsCheck(DartType type) {
|
||||
if (_isChecks == null) {
|
||||
_isChecks = new Setlet<DartType>();
|
||||
}
|
||||
_checkedTypes.add(type);
|
||||
_isChecks.add(type);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<DartType> get checkedTypes {
|
||||
return _checkedTypes != null
|
||||
? _checkedTypes : const <DartType>[];
|
||||
Iterable<DartType> get isChecks {
|
||||
return _isChecks != null
|
||||
? _isChecks : const <DartType>[];
|
||||
}
|
||||
|
||||
void registerAsCast(DartType type) {
|
||||
if (_asCasts == null) {
|
||||
_asCasts = new Setlet<DartType>();
|
||||
}
|
||||
_asCasts.add(type);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<DartType> get asCasts {
|
||||
return _asCasts != null
|
||||
? _asCasts : const <DartType>[];
|
||||
}
|
||||
|
||||
void registerCheckedModeCheckedType(DartType type) {
|
||||
if (_checkedModeChecks == null) {
|
||||
_checkedModeChecks = new Setlet<DartType>();
|
||||
}
|
||||
_checkedModeChecks.add(type);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<DartType> get checkedModeChecks {
|
||||
return _checkedModeChecks != null
|
||||
? _checkedModeChecks : const <DartType>[];
|
||||
}
|
||||
|
||||
void registerClosurizedFunction(MethodElement element) {
|
||||
|
@ -206,17 +297,61 @@ class ResolutionWorldImpact implements WorldImpact {
|
|||
return _closurizedFunctions != null
|
||||
? _closurizedFunctions : const <MethodElement>[];
|
||||
}
|
||||
|
||||
void registerClosure(LocalFunctionElement element) {
|
||||
if (_closures == null) {
|
||||
_closures = new Setlet<LocalFunctionElement>();
|
||||
}
|
||||
_closures.add(element);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<LocalFunctionElement> get closures {
|
||||
return _closures != null
|
||||
? _closures : const <LocalFunctionElement>[];
|
||||
}
|
||||
|
||||
void registerConstSymbolName(String name) {
|
||||
if (_constSymbolNames == null) {
|
||||
_constSymbolNames = new Setlet<String>();
|
||||
}
|
||||
_constSymbolNames.add(name);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<String> get constSymbolNames {
|
||||
return _constSymbolNames != null
|
||||
? _constSymbolNames : const <String>[];
|
||||
}
|
||||
|
||||
void registerFeature(Feature feature) {
|
||||
if (_features == null) {
|
||||
_features = new Setlet<Feature>();
|
||||
}
|
||||
_features.add(feature);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<Feature> get features {
|
||||
return _features != null ? _features : const <Feature>[];
|
||||
}
|
||||
|
||||
String toString() => '$registry';
|
||||
}
|
||||
|
||||
/// [ResolutionRegistry] collects all resolution information. It stores node
|
||||
/// related information in a [TreeElements] mapping and registers calls with
|
||||
/// [Backend], [World] and [Enqueuer].
|
||||
// TODO(johnniwinther): Split this into an interface and implementation class.
|
||||
class ResolutionRegistry implements Registry {
|
||||
final Compiler compiler;
|
||||
final TreeElementMapping mapping;
|
||||
final ResolutionWorldImpact worldImpact;
|
||||
final _ResolutionWorldImpact worldImpact;
|
||||
|
||||
ResolutionRegistry(Compiler compiler, TreeElementMapping mapping)
|
||||
: this.compiler = compiler,
|
||||
this.mapping = mapping,
|
||||
this.worldImpact = new ResolutionWorldImpact(compiler, mapping);
|
||||
this.worldImpact = new _ResolutionWorldImpact(compiler, mapping);
|
||||
|
||||
bool get isForResolution => true;
|
||||
|
||||
|
@ -401,7 +536,7 @@ class ResolutionRegistry implements Registry {
|
|||
}
|
||||
|
||||
void registerImplicitSuperCall(FunctionElement superConstructor) {
|
||||
universe.registerImplicitSuperCall(this, superConstructor);
|
||||
registerDependency(superConstructor);
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Remove this.
|
||||
|
@ -413,47 +548,49 @@ class ResolutionRegistry implements Registry {
|
|||
}
|
||||
|
||||
void registerLazyField() {
|
||||
backend.resolutionCallbacks.onLazyField(this);
|
||||
worldImpact.registerFeature(Feature.LAZY_FIELD);
|
||||
}
|
||||
|
||||
void registerMetadataConstant(MetadataAnnotation metadata,
|
||||
Element annotatedElement) {
|
||||
backend.registerMetadataConstant(metadata, annotatedElement, this);
|
||||
void registerMetadataConstant(MetadataAnnotation metadata) {
|
||||
backend.registerMetadataConstant(metadata, metadata.annotatedElement, this);
|
||||
}
|
||||
|
||||
void registerThrowRuntimeError() {
|
||||
backend.resolutionCallbacks.onThrowRuntimeError(this);
|
||||
worldImpact.registerFeature(Feature.THROW_RUNTIME_ERROR);
|
||||
}
|
||||
|
||||
void registerCompileTimeError(ErroneousElement error) {
|
||||
backend.resolutionCallbacks.onCompileTimeError(this, error);
|
||||
worldImpact.registerFeature(Feature.COMPILE_TIME_ERROR);
|
||||
}
|
||||
|
||||
void registerTypeVariableBoundCheck() {
|
||||
backend.resolutionCallbacks.onTypeVariableBoundCheck(this);
|
||||
worldImpact.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK);
|
||||
}
|
||||
|
||||
void registerThrowNoSuchMethod() {
|
||||
backend.resolutionCallbacks.onThrowNoSuchMethod(this);
|
||||
worldImpact.registerFeature(Feature.THROW_NO_SUCH_METHOD);
|
||||
}
|
||||
|
||||
void registerIsCheck(DartType type) {
|
||||
worldImpact.registerCheckedType(type);
|
||||
backend.resolutionCallbacks.onIsCheck(type, this);
|
||||
/// Register a checked mode check against [type].
|
||||
void registerCheckedModeCheck(DartType type) {
|
||||
worldImpact.registerCheckedModeCheckedType(type);
|
||||
mapping.addRequiredType(type);
|
||||
}
|
||||
|
||||
void registerAsCheck(DartType type) {
|
||||
registerIsCheck(type);
|
||||
backend.resolutionCallbacks.onAsCheck(type, this);
|
||||
/// Register an is-test or is-not-test of [type].
|
||||
void registerIsCheck(DartType type) {
|
||||
worldImpact.registerIsCheck(type);
|
||||
mapping.addRequiredType(type);
|
||||
}
|
||||
|
||||
/// Register an as-cast of [type].
|
||||
void registerAsCast(DartType type) {
|
||||
worldImpact.registerAsCast(type);
|
||||
mapping.addRequiredType(type);
|
||||
}
|
||||
|
||||
void registerClosure(LocalFunctionElement element) {
|
||||
if (element.computeType(compiler.resolution).containsTypeVariables) {
|
||||
backend.registerClosureWithFreeTypeVariables(element, world, this);
|
||||
}
|
||||
world.registerClosure(element);
|
||||
worldImpact.registerClosure(element);
|
||||
}
|
||||
|
||||
void registerSuperUse(Node node) {
|
||||
|
@ -465,22 +602,30 @@ class ResolutionRegistry implements Registry {
|
|||
}
|
||||
|
||||
void registerSuperNoSuchMethod() {
|
||||
backend.resolutionCallbacks.onSuperNoSuchMethod(this);
|
||||
}
|
||||
|
||||
void registerTypeVariableExpression(TypeVariableElement element) {
|
||||
backend.resolutionCallbacks.onTypeVariableExpression(this, element);
|
||||
worldImpact.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
|
||||
}
|
||||
|
||||
void registerTypeLiteral(Send node, DartType type) {
|
||||
mapping.setType(node, type);
|
||||
backend.resolutionCallbacks.onTypeLiteral(type, this);
|
||||
backend.registerInstantiatedType(compiler.coreTypes.typeType, world, this);
|
||||
worldImpact.registerTypeLiteral(type);
|
||||
}
|
||||
|
||||
void registerMapLiteral(Node node, DartType type, bool isConstant) {
|
||||
void registerLiteralList(Node node,
|
||||
InterfaceType type,
|
||||
{bool isConstant,
|
||||
bool isEmpty}) {
|
||||
setType(node, type);
|
||||
backend.resolutionCallbacks.onMapLiteral(this, type, isConstant);
|
||||
worldImpact.registerListLiteral(
|
||||
new ListLiteralUse(type, isConstant: isConstant, isEmpty: isEmpty));
|
||||
}
|
||||
|
||||
void registerMapLiteral(Node node,
|
||||
InterfaceType type,
|
||||
{bool isConstant,
|
||||
bool isEmpty}) {
|
||||
setType(node, type);
|
||||
worldImpact.registerMapLiteral(
|
||||
new MapLiteralUse(type, isConstant: isConstant, isEmpty: isEmpty));
|
||||
}
|
||||
|
||||
void registerForeignCall(Node node,
|
||||
|
@ -507,49 +652,49 @@ class ResolutionRegistry implements Registry {
|
|||
}
|
||||
|
||||
void registerConstSymbol(String name) {
|
||||
backend.registerConstSymbol(name, this);
|
||||
worldImpact.registerConstSymbolName(name);
|
||||
}
|
||||
|
||||
void registerSymbolConstructor() {
|
||||
backend.resolutionCallbacks.onSymbolConstructor(this);
|
||||
worldImpact.registerFeature(Feature.SYMBOL_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
void registerInstantiatedType(InterfaceType type) {
|
||||
backend.registerInstantiatedType(type, world, this);
|
||||
worldImpact.registerInstantiatedType(type);
|
||||
mapping.addRequiredType(type);
|
||||
}
|
||||
|
||||
void registerAbstractClassInstantiation() {
|
||||
backend.resolutionCallbacks.onAbstractClassInstantiation(this);
|
||||
worldImpact.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION);
|
||||
}
|
||||
|
||||
void registerNewSymbol() {
|
||||
backend.registerNewSymbol(this);
|
||||
worldImpact.registerFeature(Feature.NEW_SYMBOL);
|
||||
}
|
||||
|
||||
void registerRequiredType(DartType type, Element enclosingElement) {
|
||||
backend.registerRequiredType(type, enclosingElement);
|
||||
worldImpact.registerRequiredType(type);
|
||||
mapping.addRequiredType(type);
|
||||
}
|
||||
|
||||
void registerStringInterpolation() {
|
||||
backend.resolutionCallbacks.onStringInterpolation(this);
|
||||
worldImpact.registerFeature(Feature.STRING_INTERPOLATION);
|
||||
}
|
||||
|
||||
void registerFallThroughError() {
|
||||
backend.resolutionCallbacks.onFallThroughError(this);
|
||||
worldImpact.registerFeature(Feature.FALL_THROUGH_ERROR);
|
||||
}
|
||||
|
||||
void registerCatchStatement() {
|
||||
backend.resolutionCallbacks.onCatchStatement(this);
|
||||
worldImpact.registerFeature(Feature.CATCH_STATEMENT);
|
||||
}
|
||||
|
||||
void registerStackTraceInCatch() {
|
||||
backend.resolutionCallbacks.onStackTraceInCatch(this);
|
||||
worldImpact.registerFeature(Feature.STACK_TRACE_IN_CATCH);
|
||||
}
|
||||
|
||||
void registerSyncForIn(Node node) {
|
||||
backend.resolutionCallbacks.onSyncForIn(this);
|
||||
worldImpact.registerFeature(Feature.SYNC_FOR_IN);
|
||||
}
|
||||
|
||||
ClassElement defaultSuperclass(ClassElement element) {
|
||||
|
@ -562,7 +707,7 @@ class ResolutionRegistry implements Registry {
|
|||
}
|
||||
|
||||
void registerThrowExpression() {
|
||||
backend.resolutionCallbacks.onThrowExpression(this);
|
||||
worldImpact.registerFeature(Feature.THROW_EXPRESSION);
|
||||
}
|
||||
|
||||
void registerDependency(Element element) {
|
||||
|
@ -580,11 +725,12 @@ class ResolutionRegistry implements Registry {
|
|||
}
|
||||
|
||||
void registerInstantiation(InterfaceType type) {
|
||||
backend.registerInstantiatedType(type, world, this);
|
||||
registerInstantiatedType(type);
|
||||
}
|
||||
|
||||
void registerAssert(bool hasMessage) {
|
||||
backend.resolutionCallbacks.onAssert(hasMessage, this);
|
||||
worldImpact.registerFeature(
|
||||
hasMessage ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT);
|
||||
}
|
||||
|
||||
void registerSendStructure(Send node, SendStructure sendStructure) {
|
||||
|
@ -598,15 +744,27 @@ class ResolutionRegistry implements Registry {
|
|||
}
|
||||
|
||||
void registerAsyncMarker(FunctionElement element) {
|
||||
backend.registerAsyncMarker(element, world, this);
|
||||
switch (element.asyncMarker) {
|
||||
case AsyncMarker.SYNC:
|
||||
break;
|
||||
case AsyncMarker.SYNC_STAR:
|
||||
worldImpact.registerFeature(Feature.SYNC_STAR);
|
||||
break;
|
||||
case AsyncMarker.ASYNC:
|
||||
worldImpact.registerFeature(Feature.ASYNC);
|
||||
break;
|
||||
case AsyncMarker.ASYNC_STAR:
|
||||
worldImpact.registerFeature(Feature.ASYNC_STAR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void registerAsyncForIn(AsyncForIn node) {
|
||||
backend.resolutionCallbacks.onAsyncForIn(node, this);
|
||||
worldImpact.registerFeature(Feature.ASYNC_FOR_IN);
|
||||
}
|
||||
|
||||
void registerIncDecOperation() {
|
||||
backend.resolutionCallbacks.onIncDecOperation(this);
|
||||
worldImpact.registerFeature(Feature.INC_DEC_OPERATION);
|
||||
}
|
||||
|
||||
void registerTryStatement() {
|
||||
|
|
|
@ -10,7 +10,8 @@ import '../common/names.dart' show
|
|||
Identifiers;
|
||||
import '../common/resolution.dart' show
|
||||
Parsing,
|
||||
Resolution;
|
||||
Resolution,
|
||||
ResolutionWorldImpact;
|
||||
import '../common/tasks.dart' show
|
||||
CompilerTask,
|
||||
DeferredAction;
|
||||
|
@ -77,14 +78,14 @@ class ResolverTask extends CompilerTask {
|
|||
|
||||
Parsing get parsing => compiler.parsing;
|
||||
|
||||
WorldImpact resolve(Element element) {
|
||||
ResolutionWorldImpact resolve(Element element) {
|
||||
return measure(() {
|
||||
if (Elements.isErroneous(element)) {
|
||||
// TODO(johnniwinther): Add a predicate for this.
|
||||
assert(invariant(element, element is! ErroneousElement,
|
||||
message: "Element $element expected to have parse errors."));
|
||||
_ensureTreeElements(element);
|
||||
return const WorldImpact();
|
||||
return const ResolutionWorldImpact();
|
||||
}
|
||||
|
||||
WorldImpact processMetadata([WorldImpact result]) {
|
||||
|
@ -108,7 +109,7 @@ class ResolverTask extends CompilerTask {
|
|||
if (element.isClass) {
|
||||
ClassElement cls = element;
|
||||
cls.ensureResolved(resolution);
|
||||
return processMetadata(const WorldImpact());
|
||||
return processMetadata(const ResolutionWorldImpact());
|
||||
} else if (element.isTypedef) {
|
||||
TypedefElement typdef = element;
|
||||
return processMetadata(resolveTypedef(typdef));
|
||||
|
@ -286,13 +287,13 @@ class ResolverTask extends CompilerTask {
|
|||
WorldImpact resolveMethodElement(FunctionElementX element) {
|
||||
assert(invariant(element, element.isDeclaration));
|
||||
return reporter.withCurrentElement(element, () {
|
||||
if (compiler.enqueuer.resolution.hasBeenResolved(element)) {
|
||||
if (compiler.enqueuer.resolution.hasBeenProcessed(element)) {
|
||||
// TODO(karlklose): Remove the check for [isConstructor]. [elememts]
|
||||
// should never be non-null, not even for constructors.
|
||||
assert(invariant(element, element.isConstructor,
|
||||
message: 'Non-constructor element $element '
|
||||
'has already been analyzed.'));
|
||||
return const WorldImpact();
|
||||
return const ResolutionWorldImpact();
|
||||
}
|
||||
if (element.isSynthesized) {
|
||||
if (element.isGenerativeConstructor) {
|
||||
|
@ -312,7 +313,7 @@ class ResolverTask extends CompilerTask {
|
|||
} else {
|
||||
assert(element.isDeferredLoaderGetter || element.isErroneous);
|
||||
_ensureTreeElements(element);
|
||||
return const WorldImpact();
|
||||
return const ResolutionWorldImpact();
|
||||
}
|
||||
} else {
|
||||
element.parseNode(resolution.parsing);
|
||||
|
@ -717,7 +718,7 @@ class ResolverTask extends CompilerTask {
|
|||
// mixin application has been performed.
|
||||
// TODO(johnniwinther): Obtain the [TreeElements] for [member]
|
||||
// differently.
|
||||
if (compiler.enqueuer.resolution.hasBeenResolved(member)) {
|
||||
if (compiler.enqueuer.resolution.hasBeenProcessed(member)) {
|
||||
checkMixinSuperUses(
|
||||
member.resolvedAst.elements,
|
||||
mixinApplication,
|
||||
|
@ -994,7 +995,7 @@ class ResolverTask extends CompilerTask {
|
|||
}
|
||||
|
||||
WorldImpact resolveTypedef(TypedefElementX element) {
|
||||
if (element.isResolved) return const WorldImpact();
|
||||
if (element.isResolved) return const ResolutionWorldImpact();
|
||||
compiler.world.allTypedefs.add(element);
|
||||
return _resolveTypeDeclaration(element, () {
|
||||
ResolutionRegistry registry = new ResolutionRegistry(
|
||||
|
@ -1042,7 +1043,7 @@ class ResolverTask extends CompilerTask {
|
|||
// and the annotated element instead. This will allow the backend to
|
||||
// retrieve the backend constant and only register metadata on the
|
||||
// elements for which it is needed. (Issue 17732).
|
||||
registry.registerMetadataConstant(annotation, annotatedElement);
|
||||
registry.registerMetadataConstant(annotation);
|
||||
annotation.resolutionState = STATE_DONE;
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ class DeserializedResolutionWorkItem implements ResolutionWorkItem {
|
|||
@override
|
||||
WorldImpact run(Compiler compiler, ResolutionEnqueuer world) {
|
||||
_isAnalyzed = true;
|
||||
world.registerResolvedElement(element);
|
||||
world.registerProcessedElement(element);
|
||||
return worldImpact;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -679,11 +679,6 @@ class World implements ClassWorld {
|
|||
return elementsThatCannotThrow.contains(element);
|
||||
}
|
||||
|
||||
void registerImplicitSuperCall(Registry registry,
|
||||
FunctionElement superConstructor) {
|
||||
registry.registerDependency(superConstructor);
|
||||
}
|
||||
|
||||
void registerMightBePassedToApply(Element element) {
|
||||
functionsThatMightBePassedToApply.add(element);
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ bool checkResults(Compiler compiler, CollectingDiagnosticHandler handler) {
|
|||
'pkg/compiler/lib/src/helpers/helpers.dart');
|
||||
void checkLive(member) {
|
||||
if (member.isFunction) {
|
||||
if (compiler.enqueuer.resolution.hasBeenResolved(member)) {
|
||||
if (compiler.enqueuer.resolution.hasBeenProcessed(member)) {
|
||||
compiler.reporter.reportHintMessage(
|
||||
member, MessageKind.GENERIC,
|
||||
{'text': "Helper function in production code '$member'."});
|
||||
|
|
|
@ -245,10 +245,10 @@ Compiler compilerFor(
|
|||
compiler.deferredLibraryClass = cachedCompiler.deferredLibraryClass;
|
||||
|
||||
Iterable cachedTreeElements =
|
||||
cachedCompiler.enqueuer.resolution.resolvedElements;
|
||||
cachedCompiler.enqueuer.resolution.processedElements;
|
||||
cachedTreeElements.forEach((element) {
|
||||
if (element.library.isPlatformLibrary) {
|
||||
compiler.enqueuer.resolution.registerResolvedElement(element);
|
||||
compiler.enqueuer.resolution.registerProcessedElement(element);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:compiler/src/compiler.dart';
|
||||
import 'package:compiler/src/elements/elements.dart';
|
||||
import 'package:compiler/src/enqueue.dart';
|
||||
import 'package:compiler/src/js_backend/js_backend.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
import 'memory_compiler.dart';
|
||||
|
||||
|
@ -13,15 +16,45 @@ main() {
|
|||
asyncTest(() async {
|
||||
await analyze('main() {}');
|
||||
await analyze('main() => proxy;', proxyConstant: true);
|
||||
await analyze('@deprecated main() {}');
|
||||
await analyze('@deprecated main() => deprecated;', deprecatedClass: true);
|
||||
await analyze('main() => deprecated;', deprecatedClass: true);
|
||||
});
|
||||
}
|
||||
|
||||
void checkInstantiated(Compiler compiler, ClassElement cls, bool expected) {
|
||||
ResolutionEnqueuer enqueuer = compiler.enqueuer.resolution;
|
||||
bool isInstantiated =
|
||||
enqueuer.universe.directlyInstantiatedClasses.contains(cls);
|
||||
bool isProcessed = enqueuer.isClassProcessed(cls);
|
||||
Expect.equals(expected, isInstantiated,
|
||||
'Unexpected instantiation state of class $cls.');
|
||||
Expect.equals(expected, isProcessed,
|
||||
'Unexpected processing state of class $cls.');
|
||||
}
|
||||
|
||||
analyze(String code,
|
||||
{bool proxyConstant: false}) async {
|
||||
{bool proxyConstant: false,
|
||||
bool deprecatedClass: false}) async {
|
||||
CompilationResult result = await runCompiler(
|
||||
memorySourceFiles: {'main.dart': code},
|
||||
options: ['--analyze-only']);
|
||||
Expect.isTrue(result.isSuccess);
|
||||
Compiler compiler = result.compiler;
|
||||
Expect.equals(proxyConstant, compiler.proxyConstant != null);
|
||||
Expect.equals(proxyConstant, compiler.proxyConstant != null,
|
||||
"Unexpected computation of proxy constant.");
|
||||
|
||||
checkInstantiated(
|
||||
compiler, compiler.coreLibrary.find('_Proxy'), proxyConstant);
|
||||
checkInstantiated(
|
||||
compiler, compiler.coreLibrary.find('Deprecated'), deprecatedClass);
|
||||
|
||||
LibraryElement jsHelperLibrary =
|
||||
compiler.libraryLoader.lookupLibrary(JavaScriptBackend.DART_JS_HELPER);
|
||||
jsHelperLibrary.forEachLocalMember((Element element) {
|
||||
Uri uri = element.compilationUnit.script.resourceUri;
|
||||
if (element.isClass && uri.path.endsWith('annotations.dart')) {
|
||||
checkInstantiated(compiler, element, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ void checkLibraryElement(Compiler compiler, LibraryElement library) {
|
|||
|
||||
/// Check [member] for unrelated types.
|
||||
void checkMemberElement(Compiler compiler, MemberElement member) {
|
||||
if (!compiler.enqueuer.resolution.hasBeenResolved(member)) return;
|
||||
if (!compiler.resolution.hasBeenResolved(member)) return;
|
||||
|
||||
ResolvedAst resolvedAst = member.resolvedAst;
|
||||
RelatedTypesChecker relatedTypesChecker =
|
||||
|
|
|
@ -1083,7 +1083,7 @@ checkMemberResolved(compiler, className, memberName) {
|
|||
Element memberElement = cls.lookupLocalMember(memberName);
|
||||
Expect.isNotNull(memberElement);
|
||||
Expect.isTrue(
|
||||
compiler.enqueuer.resolution.hasBeenResolved(memberElement));
|
||||
compiler.enqueuer.resolution.hasBeenProcessed(memberElement));
|
||||
}
|
||||
|
||||
testToString() {
|
||||
|
|
Loading…
Reference in a new issue