Avoid late creation of entities.
This changes has been reviewed as part of https://dart-review.googlesource.com/c/sdk/+/55898
Change-Id: I28d41110919a592499ee7b5b7605728638bd5ea2
Reviewed-on: https://dart-review.googlesource.com/56481
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index a62b1a9..b598761 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -418,13 +418,13 @@
phase = PHASE_DONE_RESOLVING;
ClosedWorld closedWorld = resolutionWorldBuilder.closeWorld();
+ OutputUnitData result = deferredLoadTask.run(mainFunction, closedWorld);
ClosedWorldRefiner closedWorldRefiner =
backendStrategy.createClosedWorldRefiner(closedWorld);
// Compute whole-program-knowledge that the backend needs. (This might
// require the information computed in [world.closeWorld].)
backend.onResolutionClosedWorld(closedWorld, closedWorldRefiner);
- OutputUnitData result = deferredLoadTask.run(mainFunction, closedWorld);
backend.onDeferredLoadComplete(result);
// TODO(johnniwinther): Move this after rti computation but before
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index fe02b86..b017937 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -841,6 +841,9 @@
/// Mixin that implements the abstract methods in [KernelToElementMapBase].
abstract class ElementCreatorMixin implements KernelToElementMapBase {
+ /// Set to `true` before creating the J-World from the K-World to assert that
+ /// no entities are created late.
+ bool _envIsClosed = false;
ProgramEnv get _env;
EntityDataEnvMap<IndexedLibrary, LibraryData, LibraryEnv> get _libraries;
EntityDataEnvMap<IndexedClass, ClassData, ClassEnv> get _classes;
@@ -885,6 +888,10 @@
LibraryEntity _getLibrary(ir.Library node, [LibraryEnv libraryEnv]) {
return _libraryMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "library for $node.");
Uri canonicalUri = node.importUri;
String name = node.name;
if (name == null) {
@@ -900,6 +907,10 @@
ClassEntity _getClass(ir.Class node, [ClassEnv classEnv]) {
return _classMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "class for $node.");
KLibrary library = _getLibrary(node.enclosingLibrary);
if (classEnv == null) {
classEnv = _libraries.getEnv(library).lookupClass(node.name);
@@ -913,6 +924,10 @@
TypedefEntity _getTypedef(ir.Typedef node) {
return _typedefMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "typedef for $node.");
IndexedLibrary library = _getLibrary(node.enclosingLibrary);
IndexedTypedef typedef = createTypedef(library, node.name);
TypedefType typedefType = new TypedefType(
@@ -926,6 +941,10 @@
TypeVariableEntity _getTypeVariable(ir.TypeParameter node) {
return _typeVariableMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "type variable for $node.");
if (node.parent is ir.Class) {
ir.Class cls = node.parent;
int index = cls.typeParameters.indexOf(node);
@@ -962,6 +981,10 @@
ConstructorEntity _getConstructor(ir.Member node) {
return _constructorMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "constructor for $node.");
MemberDefinition definition;
ir.FunctionNode functionNode;
ClassEntity enclosingClass = _getClass(node.enclosingClass);
@@ -999,6 +1022,10 @@
FunctionEntity _getMethod(ir.Procedure node) {
return _methodMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "function for $node.");
LibraryEntity library;
ClassEntity enclosingClass;
if (node.enclosingClass != null) {
@@ -1048,6 +1075,10 @@
FieldEntity _getField(ir.Field node) {
return _fieldMap.putIfAbsent(node, () {
+ assert(
+ !_envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "field for $node.");
LibraryEntity library;
ClassEntity enclosingClass;
if (node.enclosingClass != null) {
@@ -2370,6 +2401,11 @@
assert(newTypeVariable.typeVariableIndex ==
oldTypeVariable.typeVariableIndex);
}
+ // TODO(johnniwinther): We should close the environment in the beginning of
+ // this constructor but currently we need the [MemberEntity] to query if the
+ // member is live, thus potentially creating the [MemberEntity] in the
+ // process. Avoid this.
+ _elementMap._envIsClosed = true;
}
@override
diff --git a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
index fa652b4..16a33bd 100644
--- a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
+++ b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
@@ -179,16 +179,18 @@
(ClassEntity cls) {
List<String> expectedLiveMembers =
expectedLiveMembersMap[cls.name] ?? const <String>[];
- elementEnvironment.forEachLocalClassMember(cls, (MemberEntity member) {
+ List<String> actualLiveMembers = <String>[];
+ closedWorld.processedMembers.forEach((MemberEntity member) {
if (member.enclosingClass != cls) return;
- bool expected = expectedLiveMembers.contains(member.name);
- bool live = closedWorld.processedMembers.contains(member);
- Expect.equals(
- expected,
- live,
- "Member $member ${expected ? '' : 'not '}expected to be live "
- "in ${strongMode ? 'Dart 2' : 'Dart 1'}. "
- "Expected members for ${cls.name}: $expectedLiveMembers");
+ if (member.isConstructor) return;
+ actualLiveMembers.add(member.name);
});
+ Expect.setEquals(
+ expectedLiveMembers,
+ actualLiveMembers,
+ "Unexpected live members for $cls "
+ "in ${strongMode ? 'Dart 2' : 'Dart 1'}. \n"
+ "Expected members for ${cls.name}: $expectedLiveMembers\n"
+ "Actual members for ${cls.name} : $actualLiveMembers");
});
}