mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
Support caching impacts with the kernel frontend. This is needed by deferred
loading. To make this possible, this CL explicitly models the impact cache and deleter. Change-Id: I444625a7a14155d9c530a390854a42d277055aaa Reviewed-on: https://dart-review.googlesource.com/18463 Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
cfa3a809f0
commit
c53c2f948d
13 changed files with 100 additions and 34 deletions
|
@ -89,6 +89,8 @@ abstract class Compiler {
|
|||
BackendStrategy backendStrategy;
|
||||
CompilerDiagnosticReporter _reporter;
|
||||
CompilerResolution _resolution;
|
||||
Map<Entity, WorldImpact> _impactCache;
|
||||
ImpactCacheDeleter _impactCacheDeleter;
|
||||
ParsingContext _parsingContext;
|
||||
|
||||
ImpactStrategy impactStrategy = const ImpactStrategy();
|
||||
|
@ -122,6 +124,8 @@ abstract class Compiler {
|
|||
|
||||
DiagnosticReporter get reporter => _reporter;
|
||||
Resolution get resolution => _resolution;
|
||||
Map<Entity, WorldImpact> get impactCache => _impactCache;
|
||||
ImpactCacheDeleter get impactCacheDeleter => _impactCacheDeleter;
|
||||
ParsingContext get parsingContext => _parsingContext;
|
||||
|
||||
// TODO(zarah): Remove this map and incorporate compile-time errors
|
||||
|
@ -192,7 +196,14 @@ abstract class Compiler {
|
|||
backendStrategy = options.useKernel
|
||||
? new KernelBackendStrategy(this)
|
||||
: new ElementBackendStrategy(this);
|
||||
_resolution = createResolution();
|
||||
if (options.useKernel) {
|
||||
_impactCache = <Entity, WorldImpact>{};
|
||||
_impactCacheDeleter = new _MapImpactCacheDeleter(_impactCache);
|
||||
} else {
|
||||
_resolution = createResolution();
|
||||
_impactCache = _resolution._worldImpactCache;
|
||||
_impactCacheDeleter = _resolution;
|
||||
}
|
||||
|
||||
if (options.verbose) {
|
||||
progress = new ProgressImpl(_reporter);
|
||||
|
@ -1301,11 +1312,11 @@ class CompilerDiagnosticReporter extends DiagnosticReporter {
|
|||
}
|
||||
|
||||
// TODO(johnniwinther): Move [ResolverTask] here.
|
||||
class CompilerResolution implements Resolution {
|
||||
class CompilerResolution implements Resolution, ImpactCacheDeleter {
|
||||
final Compiler _compiler;
|
||||
final Map<Element, ResolutionImpact> _resolutionImpactCache =
|
||||
<Element, ResolutionImpact>{};
|
||||
final Map<Element, WorldImpact> _worldImpactCache = <Element, WorldImpact>{};
|
||||
final Map<Entity, WorldImpact> _worldImpactCache = <Entity, WorldImpact>{};
|
||||
bool retainCachesForTesting = false;
|
||||
Types _types;
|
||||
|
||||
|
@ -1523,7 +1534,7 @@ class CompilerResolution implements Resolution {
|
|||
}
|
||||
|
||||
@override
|
||||
void uncacheWorldImpact(Element element) {
|
||||
void uncacheWorldImpact(covariant Element element) {
|
||||
assert(element.isDeclaration,
|
||||
failedAt(element, "Element $element must be the declaration."));
|
||||
if (retainCachesForTesting) return;
|
||||
|
@ -1577,6 +1588,23 @@ class CompilerResolution implements Resolution {
|
|||
}
|
||||
}
|
||||
|
||||
class _MapImpactCacheDeleter implements ImpactCacheDeleter {
|
||||
final Map<Entity, WorldImpact> _impactCache;
|
||||
_MapImpactCacheDeleter(this._impactCache);
|
||||
|
||||
bool retainCachesForTesting = false;
|
||||
|
||||
void uncacheWorldImpact(Entity element) {
|
||||
if (retainCachesForTesting) return;
|
||||
_impactCache.remove(element);
|
||||
}
|
||||
|
||||
void emptyCache() {
|
||||
if (retainCachesForTesting) return;
|
||||
_impactCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
class _ScriptLoader implements ScriptLoader {
|
||||
Compiler compiler;
|
||||
_ScriptLoader(this.compiler);
|
||||
|
|
|
@ -335,8 +335,7 @@ class DeferredLoadTask extends CompilerTask {
|
|||
return;
|
||||
}
|
||||
|
||||
WorldImpact worldImpact =
|
||||
compiler.resolution.getWorldImpact(analyzableElement);
|
||||
WorldImpact worldImpact = compiler.impactCache[analyzableElement];
|
||||
compiler.impactStrategy.visitImpact(
|
||||
analyzableElement,
|
||||
worldImpact,
|
||||
|
|
|
@ -88,7 +88,8 @@ abstract class FrontendStrategy {
|
|||
WorkItemBuilder createResolutionWorkItemBuilder(
|
||||
NativeBasicData nativeBasicData,
|
||||
NativeDataBuilder nativeDataBuilder,
|
||||
ImpactTransformer impactTransformer);
|
||||
ImpactTransformer impactTransformer,
|
||||
Map<Entity, WorldImpact> impactCache);
|
||||
|
||||
/// Computes the main function from [mainLibrary] adding additional world
|
||||
/// impact to [impactBuilder].
|
||||
|
@ -141,3 +142,19 @@ abstract class FrontendStrategyBase implements FrontendStrategy {
|
|||
return _nativeBasicData;
|
||||
}
|
||||
}
|
||||
|
||||
/// Class that deletes the contents of an [WorldImpact] cache.
|
||||
// TODO(redemption): this can be deleted when we sunset the old front end and
|
||||
// delete serialization.
|
||||
abstract class ImpactCacheDeleter {
|
||||
bool retainCachesForTesting;
|
||||
|
||||
/// Removes the [WorldImpact] for [element] from the resolution cache. Later
|
||||
/// calls to [getWorldImpact] or [computeWorldImpact] returns an empty impact.
|
||||
void uncacheWorldImpact(Entity element);
|
||||
|
||||
/// Removes the [WorldImpact]s for all [Element]s in the resolution cache. ,
|
||||
/// Later calls to [getWorldImpact] or [computeWorldImpact] returns an empty
|
||||
/// impact.
|
||||
void emptyCache();
|
||||
}
|
||||
|
|
|
@ -462,6 +462,8 @@ class JavaScriptBackend {
|
|||
|
||||
Resolution get resolution => compiler.resolution;
|
||||
|
||||
ImpactCacheDeleter get impactCacheDeleter => compiler.impactCacheDeleter;
|
||||
|
||||
Target get target => _target;
|
||||
|
||||
/// Resolution support for generating table of interceptors and
|
||||
|
@ -760,7 +762,10 @@ class JavaScriptBackend {
|
|||
classHierarchyBuilder,
|
||||
classQueries),
|
||||
compiler.frontendStrategy.createResolutionWorkItemBuilder(
|
||||
nativeBasicData, _nativeDataBuilder, impactTransformer));
|
||||
nativeBasicData,
|
||||
_nativeDataBuilder,
|
||||
impactTransformer,
|
||||
compiler.impactCache));
|
||||
}
|
||||
|
||||
/// Creates an [Enqueuer] for code generation specific to this backend.
|
||||
|
@ -1184,7 +1189,8 @@ class JavaScriptBackend {
|
|||
{bool supportDeferredLoad: true,
|
||||
bool supportDumpInfo: true,
|
||||
bool supportSerialization: true}) {
|
||||
return new JavaScriptImpactStrategy(resolution, compiler.dumpInfoTask,
|
||||
return new JavaScriptImpactStrategy(
|
||||
impactCacheDeleter, compiler.dumpInfoTask,
|
||||
supportDeferredLoad: supportDeferredLoad,
|
||||
supportDumpInfo: supportDumpInfo,
|
||||
supportSerialization: supportSerialization);
|
||||
|
@ -1194,13 +1200,13 @@ class JavaScriptBackend {
|
|||
}
|
||||
|
||||
class JavaScriptImpactStrategy extends ImpactStrategy {
|
||||
final Resolution resolution;
|
||||
final ImpactCacheDeleter impactCacheDeleter;
|
||||
final DumpInfoTask dumpInfoTask;
|
||||
final bool supportDeferredLoad;
|
||||
final bool supportDumpInfo;
|
||||
final bool supportSerialization;
|
||||
|
||||
JavaScriptImpactStrategy(this.resolution, this.dumpInfoTask,
|
||||
JavaScriptImpactStrategy(this.impactCacheDeleter, this.dumpInfoTask,
|
||||
{this.supportDeferredLoad,
|
||||
this.supportDumpInfo,
|
||||
this.supportSerialization});
|
||||
|
@ -1215,7 +1221,7 @@ class JavaScriptImpactStrategy extends ImpactStrategy {
|
|||
} else {
|
||||
impact.apply(visitor);
|
||||
if (impactSource is Element) {
|
||||
resolution.uncacheWorldImpact(impactSource);
|
||||
impactCacheDeleter.uncacheWorldImpact(impactSource);
|
||||
}
|
||||
}
|
||||
} else if (impactUse == DeferredLoadTask.IMPACT_USE) {
|
||||
|
@ -1234,7 +1240,7 @@ class JavaScriptImpactStrategy extends ImpactStrategy {
|
|||
if (impactUse == DeferredLoadTask.IMPACT_USE && !supportSerialization) {
|
||||
// TODO(johnniwinther): Allow emptying when serialization has been
|
||||
// performed.
|
||||
resolution.emptyCache();
|
||||
impactCacheDeleter.emptyCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,12 +143,14 @@ class KernelFrontEndStrategy extends FrontendStrategyBase {
|
|||
classQueries);
|
||||
}
|
||||
|
||||
@override
|
||||
WorkItemBuilder createResolutionWorkItemBuilder(
|
||||
NativeBasicData nativeBasicData,
|
||||
NativeDataBuilder nativeDataBuilder,
|
||||
ImpactTransformer impactTransformer) {
|
||||
ImpactTransformer impactTransformer,
|
||||
Map<Entity, WorldImpact> impactCache) {
|
||||
return new KernelWorkItemBuilder(elementMap, nativeBasicData,
|
||||
nativeDataBuilder, impactTransformer, closureModels);
|
||||
nativeDataBuilder, impactTransformer, closureModels, impactCache);
|
||||
}
|
||||
|
||||
ClassQueries createClassQueries() {
|
||||
|
@ -166,20 +168,22 @@ class KernelWorkItemBuilder implements WorkItemBuilder {
|
|||
final ImpactTransformer _impactTransformer;
|
||||
final NativeMemberResolver _nativeMemberResolver;
|
||||
final Map<MemberEntity, ScopeModel> closureModels;
|
||||
final Map<Entity, WorldImpact> impactCache;
|
||||
|
||||
KernelWorkItemBuilder(
|
||||
this._elementMap,
|
||||
NativeBasicData nativeBasicData,
|
||||
NativeDataBuilder nativeDataBuilder,
|
||||
this._impactTransformer,
|
||||
this.closureModels)
|
||||
this.closureModels,
|
||||
this.impactCache)
|
||||
: _nativeMemberResolver = new KernelNativeMemberResolver(
|
||||
_elementMap, nativeBasicData, nativeDataBuilder);
|
||||
|
||||
@override
|
||||
WorkItem createWorkItem(MemberEntity entity) {
|
||||
return new KernelWorkItem(_elementMap, _impactTransformer,
|
||||
_nativeMemberResolver, entity, closureModels);
|
||||
_nativeMemberResolver, entity, closureModels, impactCache);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,9 +193,15 @@ class KernelWorkItem implements ResolutionWorkItem {
|
|||
final NativeMemberResolver _nativeMemberResolver;
|
||||
final MemberEntity element;
|
||||
final Map<MemberEntity, ScopeModel> closureModels;
|
||||
final Map<Entity, WorldImpact> impactCache;
|
||||
|
||||
KernelWorkItem(this._elementMap, this._impactTransformer,
|
||||
this._nativeMemberResolver, this.element, this.closureModels);
|
||||
KernelWorkItem(
|
||||
this._elementMap,
|
||||
this._impactTransformer,
|
||||
this._nativeMemberResolver,
|
||||
this.element,
|
||||
this.closureModels,
|
||||
this.impactCache);
|
||||
|
||||
@override
|
||||
WorldImpact run() {
|
||||
|
@ -201,7 +211,12 @@ class KernelWorkItem implements ResolutionWorkItem {
|
|||
if (closureModel != null) {
|
||||
closureModels[element] = closureModel;
|
||||
}
|
||||
return _impactTransformer.transformResolutionImpact(impact);
|
||||
WorldImpact worldImpact =
|
||||
_impactTransformer.transformResolutionImpact(impact);
|
||||
if (impactCache != null) {
|
||||
impactCache[element] = impact;
|
||||
}
|
||||
return worldImpact;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -153,7 +153,8 @@ class ResolutionFrontEndStrategy extends FrontendStrategyBase
|
|||
WorkItemBuilder createResolutionWorkItemBuilder(
|
||||
NativeBasicData nativeBasicData,
|
||||
NativeDataBuilder nativeDataBuilder,
|
||||
ImpactTransformer impactTransformer) {
|
||||
ImpactTransformer impactTransformer,
|
||||
Map<Entity, WorldImpact> impactCache) {
|
||||
return new ResolutionWorkItemBuilder(_compiler.resolution);
|
||||
}
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ Future<ResultKind> mainInternal(List<String> args,
|
|||
memorySourceFiles: memorySourceFiles,
|
||||
diagnosticHandler: collector,
|
||||
options: [Flags.analyzeOnly, Flags.enableAssertMessage]);
|
||||
compiler1.resolution.retainCachesForTesting = true;
|
||||
compiler1.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compiler1.run(entryPoint);
|
||||
if (collector.crashes.isNotEmpty) {
|
||||
print('Skipping due to crashes.');
|
||||
|
|
|
@ -118,7 +118,7 @@ Future<ResultKind> mainInternal(List<String> args,
|
|||
diagnosticHandler: collector,
|
||||
options: [Flags.analyzeOnly, Flags.enableAssertMessage]);
|
||||
ElementResolutionWorldBuilder.useInstantiationMap = true;
|
||||
compiler1.resolution.retainCachesForTesting = true;
|
||||
compiler1.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compiler1.run(entryPoint);
|
||||
if (collector.crashes.isNotEmpty) {
|
||||
print('Skipping due to crashes.');
|
||||
|
|
|
@ -395,7 +395,7 @@ Future<ResultKind> runTest(
|
|||
outputProvider: collector1,
|
||||
options: <String>[]..addAll(commonOptions)..addAll(options));
|
||||
ElementResolutionWorldBuilder.useInstantiationMap = true;
|
||||
compiler1.resolution.retainCachesForTesting = true;
|
||||
compiler1.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compiler1.run(entryPoint);
|
||||
if (collector.crashes.isNotEmpty) {
|
||||
print('Skipping due to crashes.');
|
||||
|
|
|
@ -54,7 +54,7 @@ Future<List<CompileFunction>> compileMultiple(List<String> sources) async {
|
|||
Flags.useKernel
|
||||
]);
|
||||
ElementResolutionWorldBuilder.useInstantiationMap = true;
|
||||
compiler.resolution.retainCachesForTesting = true;
|
||||
compiler.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compiler.run(entryPoint);
|
||||
return compiler;
|
||||
});
|
||||
|
@ -75,7 +75,7 @@ Future<Pair<Compiler, Compiler>> analyzeOnly(
|
|||
entryPoint: entryPoint,
|
||||
memorySourceFiles: memorySourceFiles,
|
||||
options: [Flags.analyzeAll, Flags.enableAssertMessage]);
|
||||
compiler.resolution.retainCachesForTesting = true;
|
||||
compiler.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compiler.run(entryPoint);
|
||||
|
||||
if (printSteps) {
|
||||
|
@ -86,7 +86,7 @@ Future<Pair<Compiler, Compiler>> analyzeOnly(
|
|||
memorySourceFiles: memorySourceFiles,
|
||||
options: [Flags.analyzeOnly, Flags.enableAssertMessage, Flags.useKernel]);
|
||||
ElementResolutionWorldBuilder.useInstantiationMap = true;
|
||||
compiler2.resolution.retainCachesForTesting = true;
|
||||
compiler2.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compiler2.run(entryPoint);
|
||||
return new Pair<Compiler, Compiler>(compiler, compiler2);
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ Future<Compiler> compileWithDill(
|
|||
diagnosticHandler: diagnosticHandler,
|
||||
outputProvider: compilerOutput);
|
||||
ElementResolutionWorldBuilder.useInstantiationMap = true;
|
||||
compiler.resolution.retainCachesForTesting = true;
|
||||
compiler.impactCacheDeleter.retainCachesForTesting = true;
|
||||
if (beforeRun != null) {
|
||||
beforeRun(compiler);
|
||||
}
|
||||
|
|
|
@ -34,14 +34,14 @@ Future check(SerializedData serializedData, Uri entryPoint,
|
|||
bool verbose: false}) async {
|
||||
Compiler compilerNormal =
|
||||
compilerFor(memorySourceFiles: sourceFiles, options: [Flags.analyzeAll]);
|
||||
compilerNormal.resolution.retainCachesForTesting = true;
|
||||
compilerNormal.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compilerNormal.run(entryPoint);
|
||||
|
||||
Compiler compilerDeserialized = compilerFor(
|
||||
memorySourceFiles: serializedData.toMemorySourceFiles(sourceFiles),
|
||||
resolutionInputs: serializedData.toUris(),
|
||||
options: [Flags.analyzeAll]);
|
||||
compilerDeserialized.resolution.retainCachesForTesting = true;
|
||||
compilerDeserialized.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compilerDeserialized.run(entryPoint);
|
||||
|
||||
checkAllImpacts(compilerNormal, compilerDeserialized, verbose: verbose);
|
||||
|
|
|
@ -69,7 +69,7 @@ Future checkModels(Uri entryPoint,
|
|||
Compiler compilerNormal = await measure(title, 'compile normal', () async {
|
||||
Compiler compilerNormal = compilerFor(
|
||||
memorySourceFiles: sourceFiles, options: [Flags.analyzeOnly]);
|
||||
compilerNormal.resolution.retainCachesForTesting = true;
|
||||
compilerNormal.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compilerNormal.run(entryPoint);
|
||||
ElementEnvironment elementEnvironment =
|
||||
compilerNormal.frontendStrategy.elementEnvironment;
|
||||
|
@ -83,7 +83,7 @@ Future checkModels(Uri entryPoint,
|
|||
memorySourceFiles: sourceFiles,
|
||||
resolutionInputs: resolutionInputs,
|
||||
options: [Flags.analyzeOnly]);
|
||||
compilerDeserialized.resolution.retainCachesForTesting = true;
|
||||
compilerDeserialized.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compilerDeserialized.run(entryPoint);
|
||||
ElementEnvironment elementEnvironment =
|
||||
compilerDeserialized.frontendStrategy.elementEnvironment;
|
||||
|
|
|
@ -36,14 +36,14 @@ Future check(SerializedData serializedData, Uri entryPoint,
|
|||
[Map<String, String> sourceFiles = const <String, String>{}]) async {
|
||||
Compiler compilerNormal =
|
||||
compilerFor(memorySourceFiles: sourceFiles, options: [Flags.analyzeAll]);
|
||||
compilerNormal.resolution.retainCachesForTesting = true;
|
||||
compilerNormal.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compilerNormal.run(entryPoint);
|
||||
|
||||
Compiler compilerDeserialized = compilerFor(
|
||||
memorySourceFiles: serializedData.toMemorySourceFiles(sourceFiles),
|
||||
resolutionInputs: serializedData.toUris(),
|
||||
options: [Flags.analyzeAll]);
|
||||
compilerDeserialized.resolution.retainCachesForTesting = true;
|
||||
compilerDeserialized.impactCacheDeleter.retainCachesForTesting = true;
|
||||
await compilerDeserialized.run(entryPoint);
|
||||
|
||||
checkAllResolvedAsts(compilerNormal, compilerDeserialized, verbose: true);
|
||||
|
|
Loading…
Reference in a new issue