Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Unified Diff: pkg/analyzer/lib/src/summary/resynthesize.dart

Issue 1995763003: Build top-level variables and property accessors lazily. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/summary/resynthesize.dart
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index dfcaa983bc0c7b83429038ee4f9822755f2c19b8..64d87b45202c2b7e9f1779dbdb1afe3cde941c04 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -62,8 +62,8 @@ abstract class SummaryResynthesizer extends ElementResynthesizer {
* are the first two elements of the element's location (the library URI and
* the compilation unit URI).
*/
- final Map<String, Map<String, CompilationUnitElement>> _resynthesizedUnits =
- <String, Map<String, CompilationUnitElement>>{};
+ final Map<String, Map<String, CompilationUnitElementImpl>>
+ _resynthesizedUnits = <String, Map<String, CompilationUnitElementImpl>>{};
/**
* Map of top level elements resynthesized from summaries. The three map
@@ -125,18 +125,15 @@ abstract class SummaryResynthesizer extends ElementResynthesizer {
}
return element;
} else if (components.length == 3 || components.length == 4) {
- Map<String, Map<String, Element>> libraryMap =
- _resynthesizedElements[libraryUri];
+ Map<String, CompilationUnitElement> libraryMap =
+ _resynthesizedUnits[libraryUri];
if (libraryMap == null) {
getLibraryElement(libraryUri);
- libraryMap = _resynthesizedElements[libraryUri];
+ libraryMap = _resynthesizedUnits[libraryUri];
assert(libraryMap != null);
}
- Map<String, Element> compilationUnitElements = libraryMap[components[1]];
- Element element;
- if (compilationUnitElements != null) {
- element = compilationUnitElements[components[2]];
- }
+ CompilationUnitElementImpl unitElement = libraryMap[components[1]];
+ Element element = unitElement?.getChildNotImpl(components[2]);
Paul Berry 2016/05/19 11:27:30 I have an efficiency concern here. You're replaci
scheglov 2016/05/19 16:54:57 That's fair. I think that the approach with `getCh
if (element != null && components.length == 4) {
String name = components[3];
Element parentElement = element;
@@ -1025,8 +1022,8 @@ class _LibraryResynthesizer {
* Map of compilation unit elements that have been resynthesized so far. The
* key is the URI of the compilation unit.
*/
- final Map<String, CompilationUnitElement> resynthesizedUnits =
- <String, CompilationUnitElement>{};
+ final Map<String, CompilationUnitElementImpl> resynthesizedUnits =
+ <String, CompilationUnitElementImpl>{};
/**
* Map of top level elements that have been resynthesized so far. The first
@@ -1202,19 +1199,17 @@ class _LibraryResynthesizer {
LibraryElement buildLibrary() {
// Create LibraryElementImpl.
bool hasName = unlinkedUnits[0].libraryName.isNotEmpty;
- library = new LibraryElementImpl(
+ library = new LibraryElementImpl.forSerialized(
summaryResynthesizer.context,
unlinkedUnits[0].libraryName,
hasName ? unlinkedUnits[0].libraryNameOffset : -1,
- unlinkedUnits[0].libraryNameLength);
+ unlinkedUnits[0].libraryNameLength,
+ new _LibraryResynthesizerContext(this),
+ unlinkedUnits[0]);
// Create the defining unit.
_UnitResynthesizer definingUnitResynthesizer =
createUnitResynthesizer(0, librarySource, null);
CompilationUnitElementImpl definingUnit = definingUnitResynthesizer.unit;
- definingUnitResynthesizer.buildDocumentation(
- library, unlinkedUnits[0].libraryDocumentationComment);
- definingUnitResynthesizer.buildAnnotations(
- library, unlinkedUnits[0].libraryAnnotations);
library.definingCompilationUnit = definingUnit;
definingUnit.source = librarySource;
definingUnit.librarySource = librarySource;
@@ -1258,7 +1253,6 @@ class _LibraryResynthesizer {
for (_UnitResynthesizer partResynthesizer in partResynthesizers) {
populateUnit(partResynthesizer);
}
- BuildLibraryElementUtils.patchTopLevelAccessors(library);
// Update delayed Object class references.
if (isCoreLibrary) {
ClassElement objectElement = library.getType('Object');
@@ -1267,18 +1261,6 @@ class _LibraryResynthesizer {
classElement.supertype = objectElement.type;
}
}
- // Compute namespaces.
- library.publicNamespace =
- new NamespaceBuilder().createPublicNamespaceForLibrary(library);
- library.exportNamespace = buildExportNamespace(
- library.publicNamespace, linkedLibrary.exportNames);
- // Find the entry point. Note: we can't use element.isEntryPoint because
- // that will trigger resynthesis of exported libraries.
- Element entryPoint =
- library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME);
- if (entryPoint is FunctionElement) {
- library.entryPoint = entryPoint;
- }
// Create the synthetic element for `loadLibrary`.
// Until the client received dart:core and dart:async, we cannot do this,
// because the TypeProvider is not fully initialized. So, it is up to the
@@ -1370,6 +1352,42 @@ class _LibraryResynthesizer {
}
}
+class _LibraryResynthesizerContext implements LibraryResynthesizerContext {
Paul Berry 2016/05/19 11:27:30 Nit: a doc comment would be helpful here.
scheglov 2016/05/19 16:54:57 Done.
+ final _LibraryResynthesizer resynthesizer;
+
+ _LibraryResynthesizerContext(this.resynthesizer);
+
+ @override
+ Namespace buildExportNamespace() {
+ LibraryElementImpl library = resynthesizer.library;
+ return resynthesizer.buildExportNamespace(
+ library.publicNamespace, resynthesizer.linkedLibrary.exportNames);
+ }
+
+ @override
+ Namespace buildPublicNamespace() {
+ LibraryElementImpl library = resynthesizer.library;
+ return new NamespaceBuilder().createPublicNamespaceForLibrary(library);
+ }
+
+ @override
+ FunctionElement findEntryPoint() {
+ LibraryElementImpl library = resynthesizer.library;
+ Element entryPoint =
+ library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME);
+ if (entryPoint is FunctionElement) {
+ return entryPoint;
+ }
+ return null;
+ }
+
+ @override
+ void patchTopLevelAccessors() {
+ LibraryElementImpl library = resynthesizer.library;
+ BuildLibraryElementUtils.patchTopLevelAccessors(library);
+ }
+}
+
/**
* Data structure used during resynthesis to record all the information that is
* known about how to resynthesize a single entry in [LinkedUnit.references]
@@ -1568,6 +1586,16 @@ class _ResynthesizerContext implements ResynthesizerContext {
}
@override
+ UnitExplicitTopLevelAccessors buildTopLevelAccessors() {
+ return _unitResynthesizer.buildUnitExplicitTopLevelAccessors();
+ }
+
+ @override
+ UnitExplicitTopLevelVariables buildTopLevelVariables() {
+ return _unitResynthesizer.buildUnitExplicitTopLevelVariables();
+ }
+
+ @override
DartType resolveTypeRef(
EntityRef type, TypeParameterizedElementMixin typeParameterContext,
{bool defaultVoid: false, bool instantiateToBoundsAllowed: true}) {
@@ -2074,6 +2102,11 @@ class _UnitResynthesizer {
break;
case UnlinkedExecutableKind.getter:
case UnlinkedExecutableKind.setter:
+ // Top-level accessors are created lazily.
+ if (isTopLevel) {
+ break;
+ }
+ // Class member accessors.
PropertyAccessorElementImpl executableElement =
new PropertyAccessorElementImpl.forSerialized(
serializedExecutable, enclosingElement);
@@ -2085,19 +2118,13 @@ class _UnitResynthesizer {
type = executableElement.parameters[0].type;
}
holder.addAccessor(executableElement);
- PropertyInducingElementImpl implicitVariable;
- if (isTopLevel) {
- implicitVariable = buildImplicitTopLevelVariable(name, kind, holder);
- } else {
- FieldElementImpl field = buildImplicitField(name, type, kind, holder);
- field.static = serializedExecutable.isStatic;
- implicitVariable = field;
- }
- executableElement.variable = implicitVariable;
+ FieldElementImpl field = buildImplicitField(name, type, kind, holder);
+ field.static = serializedExecutable.isStatic;
+ executableElement.variable = field;
if (kind == UnlinkedExecutableKind.getter) {
- implicitVariable.getter = executableElement;
+ field.getter = executableElement;
} else {
- implicitVariable.setter = executableElement;
+ field.setter = executableElement;
}
break;
default:
@@ -2154,33 +2181,12 @@ class _UnitResynthesizer {
String name = element.name;
DartType type = element.type;
PropertyAccessorElementImpl getter =
- new PropertyAccessorElementImpl(name, element.nameOffset);
- getter.getter = true;
- getter.static = element.isStatic;
- getter.synthetic = true;
- getter.returnType = type;
- getter.type = new FunctionTypeImpl(getter);
- getter.variable = element;
- getter.hasImplicitReturnType = element.hasImplicitType;
- holder.addAccessor(getter);
- element.getter = getter;
+ buildImplicitGetter(element, name, type);
+ holder?.addAccessor(getter);
if (!(element.isConst || element.isFinal)) {
PropertyAccessorElementImpl setter =
- new PropertyAccessorElementImpl(name, element.nameOffset);
- setter.setter = true;
- setter.static = element.isStatic;
- setter.synthetic = true;
- setter.parameters = <ParameterElement>[
- new ParameterElementImpl('_$name', element.nameOffset)
- ..synthetic = true
- ..type = type
- ..parameterKind = ParameterKind.REQUIRED
- ];
- setter.returnType = VoidTypeImpl.instance;
- setter.type = new FunctionTypeImpl(setter);
- setter.variable = element;
- holder.addAccessor(setter);
- element.setter = setter;
+ buildImplicitSetter(element, name, type);
+ holder?.addAccessor(setter);
}
}
@@ -2205,24 +2211,39 @@ class _UnitResynthesizer {
}
}
- /**
- * Build the implicit top level variable associated with a getter or setter,
- * and place it in [holder].
- */
- PropertyInducingElementImpl buildImplicitTopLevelVariable(
- String name, UnlinkedExecutableKind kind, ElementHolder holder) {
- TopLevelVariableElementImpl variable = holder.getTopLevelVariable(name);
- if (variable == null) {
- variable = new TopLevelVariableElementImpl(name, -1);
- variable.synthetic = true;
- variable.final2 = kind == UnlinkedExecutableKind.getter;
- holder.addTopLevelVariable(variable);
- return variable;
- } else {
- // TODO(paulberry): what if the getter and setter have a type mismatch?
- variable.final2 = false;
- return variable;
- }
+ PropertyAccessorElementImpl buildImplicitGetter(
Paul Berry 2016/05/19 11:27:30 Please add a doc comment here.
scheglov 2016/05/19 16:54:57 Done.
+ PropertyInducingElementImpl element, String name, DartType type) {
+ PropertyAccessorElementImpl getter =
+ new PropertyAccessorElementImpl(name, element.nameOffset);
+ getter.getter = true;
+ getter.static = element.isStatic;
+ getter.synthetic = true;
+ getter.returnType = type;
+ getter.type = new FunctionTypeImpl(getter);
+ getter.variable = element;
+ getter.hasImplicitReturnType = element.hasImplicitType;
+ element.getter = getter;
+ return getter;
+ }
+
+ PropertyAccessorElementImpl buildImplicitSetter(
Paul Berry 2016/05/19 11:27:30 Ditto.
scheglov 2016/05/19 16:54:57 Done.
+ PropertyInducingElementImpl element, String name, DartType type) {
+ PropertyAccessorElementImpl setter =
+ new PropertyAccessorElementImpl(name, element.nameOffset);
+ setter.setter = true;
+ setter.static = element.isStatic;
+ setter.synthetic = true;
+ setter.parameters = <ParameterElement>[
+ new ParameterElementImpl('_$name', element.nameOffset)
+ ..synthetic = true
+ ..type = type
+ ..parameterKind = ParameterKind.REQUIRED
+ ];
+ setter.returnType = VoidTypeImpl.instance;
+ setter.type = new FunctionTypeImpl(setter);
+ setter.variable = element;
+ element.setter = setter;
+ return setter;
}
/**
@@ -2404,9 +2425,10 @@ class _UnitResynthesizer {
* Handle the parts that are common to top level variables and fields.
*/
void buildPropertyIntroducingElementCommonParts(
- PropertyInducingElementImpl element,
- UnlinkedVariable serializedVariable) {
- buildVariableCommonParts(element, serializedVariable);
+ PropertyInducingElementImpl element, UnlinkedVariable serializedVariable,
+ {bool isLazilyResynthesized: false}) {
+ buildVariableCommonParts(element, serializedVariable,
+ isLazilyResynthesized: isLazilyResynthesized);
element.propagatedType = buildLinkedType(
serializedVariable.propagatedTypeSlot,
_currentTypeParameterizedElement);
@@ -2517,27 +2539,89 @@ class _UnitResynthesizer {
return typeParameters;
}
- /**
- * Resynthesize a [TopLevelVariableElement] or [FieldElement].
- */
- void buildVariable(UnlinkedVariable serializedVariable,
- [ElementHolder holder]) {
- if (holder == null) {
+ UnitExplicitTopLevelAccessors buildUnitExplicitTopLevelAccessors() {
+ HashMap<String, TopLevelVariableElementImpl> implicitVariables =
+ new HashMap<String, TopLevelVariableElementImpl>();
+ UnitExplicitTopLevelAccessors accessorsData =
+ new UnitExplicitTopLevelAccessors();
+ for (UnlinkedExecutable unlinkedExecutable in unlinkedUnit.executables) {
+ UnlinkedExecutableKind kind = unlinkedExecutable.kind;
+ if (kind == UnlinkedExecutableKind.getter ||
+ kind == UnlinkedExecutableKind.setter) {
+ // name
+ String name = unlinkedExecutable.name;
+ if (kind == UnlinkedExecutableKind.setter) {
+ assert(name.endsWith('='));
+ name = name.substring(0, name.length - 1);
+ }
+ // create
+ PropertyAccessorElementImpl accessor =
+ new PropertyAccessorElementImpl.forSerialized(
+ unlinkedExecutable, unit);
+ accessorsData.accessors.add(accessor);
+ buildExecutableCommonParts(accessor, unlinkedExecutable);
+ // implicit variable
+ TopLevelVariableElementImpl variable = implicitVariables[name];
+ if (variable == null) {
+ variable = new TopLevelVariableElementImpl(name, -1);
+ implicitVariables[name] = variable;
+ accessorsData.implicitVariables.add(variable);
+ variable.synthetic = true;
+ variable.final2 = kind == UnlinkedExecutableKind.getter;
+ } else {
+ variable.final2 = false;
+ }
+ accessor.variable = variable;
+ // link
+ if (kind == UnlinkedExecutableKind.getter) {
+ variable.getter = accessor;
+ } else {
+ variable.setter = accessor;
+ }
+ }
+ }
+ return accessorsData;
+ }
+
+ UnitExplicitTopLevelVariables buildUnitExplicitTopLevelVariables() {
+ UnitExplicitTopLevelVariables variablesData =
+ new UnitExplicitTopLevelVariables();
+ for (UnlinkedVariable unlinkedVariable in unlinkedUnit.variables) {
TopLevelVariableElementImpl element;
- if (serializedVariable.constExpr != null && serializedVariable.isConst) {
+ if (unlinkedVariable.constExpr != null && unlinkedVariable.isConst) {
ConstTopLevelVariableElementImpl constElement =
- new ConstTopLevelVariableElementImpl(
- serializedVariable.name, serializedVariable.nameOffset);
+ new ConstTopLevelVariableElementImpl.forSerialized(
+ unlinkedVariable, unit);
element = constElement;
constElement.constantInitializer =
- _buildConstExpression(serializedVariable.constExpr);
+ _buildConstExpression(unlinkedVariable.constExpr);
} else {
- element = new TopLevelVariableElementImpl(
- serializedVariable.name, serializedVariable.nameOffset);
+ element = new TopLevelVariableElementImpl.forSerialized(
+ unlinkedVariable, unit);
}
- buildPropertyIntroducingElementCommonParts(element, serializedVariable);
- unitHolder.addTopLevelVariable(element);
- buildImplicitAccessors(element, unitHolder);
+ buildPropertyIntroducingElementCommonParts(element, unlinkedVariable,
+ isLazilyResynthesized: true);
+ variablesData.variables.add(element);
+ // implicit accessors
+ String name = element.name;
+ DartType type = element.type;
+ variablesData.implicitAccessors
+ .add(buildImplicitGetter(element, name, type));
+ if (!(element.isConst || element.isFinal)) {
+ variablesData.implicitAccessors
+ .add(buildImplicitSetter(element, name, type));
+ }
+ }
+ return variablesData;
+ }
+
+ /**
+ * Resynthesize a [TopLevelVariableElement] or [FieldElement].
+ */
+ void buildVariable(UnlinkedVariable serializedVariable,
+ [ElementHolder holder]) {
+ if (holder == null) {
+ throw new UnimplementedError('Must be lazy');
} else {
FieldElementImpl element;
if (serializedVariable.constExpr != null &&
@@ -2769,8 +2853,6 @@ class _UnitResynthesizer {
unlinkedUnit.enums.forEach(buildEnum);
unlinkedUnit.executables.forEach((e) => buildExecutable(e, unit));
unlinkedUnit.typedefs.forEach(buildTypedef);
- unlinkedUnit.variables.forEach(buildVariable);
- unit.accessors = unitHolder.accessors;
unit.enums = unitHolder.enums;
unit.functions = unitHolder.functions;
List<FunctionTypeAliasElement> typeAliases = unitHolder.typeAliases;
@@ -2781,7 +2863,6 @@ class _UnitResynthesizer {
}
unit.typeAliases = typeAliases.where((e) => !e.isSynthetic).toList();
unit.types = unitHolder.types;
- unit.topLevelVariables = unitHolder.topLevelVariables;
for (ClassElement cls in unit.types) {
elementMap[cls.name] = cls;
}
@@ -2794,9 +2875,6 @@ class _UnitResynthesizer {
for (FunctionElement function in unit.functions) {
elementMap[function.name] = function;
}
- for (PropertyAccessorElementImpl accessor in unit.accessors) {
- elementMap[accessor.identifier] = accessor;
- }
assert(currentTypeParameters.isEmpty);
}

Powered by Google App Engine
This is Rietveld 408576698