[dart2js] Remove staticFieldsForReflection

Change-Id: I0ee3ec5528df50e413d861eae495a6440a029602
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/199620
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Mayank Patke <fishythefish@google.com>
This commit is contained in:
Stephen Adams 2021-05-13 16:39:45 +00:00 committed by commit-bot@chromium.org
parent b42c5c77d4
commit 5b93e8d44b
5 changed files with 63 additions and 146 deletions

View file

@ -165,11 +165,7 @@ class Constant {
}
}
abstract class FieldContainer {
List<Field> get staticFieldsForReflection;
}
class Library implements FieldContainer {
class Library {
/// The element should only be used during the transition to the new model.
/// Uses indicate missing information in the model.
final LibraryEntity element;
@ -179,11 +175,8 @@ class Library implements FieldContainer {
final List<Class> classes;
final List<ClassTypeData> classTypeData;
@override
final List<Field> staticFieldsForReflection;
Library(this.element, this.uri, this.statics, this.classes,
this.classTypeData, this.staticFieldsForReflection);
Library(
this.element, this.uri, this.statics, this.classes, this.classTypeData);
@override
String toString() {
@ -233,7 +226,7 @@ class ClassTypeData {
check.cls == commonElements.objectClass || check.cls == element);
}
class Class implements FieldContainer {
class Class {
/// The element should only be used during the transition to the new model.
/// Uses indicate missing information in the model.
final ClassEntity element;
@ -256,8 +249,7 @@ class Class implements FieldContainer {
/// noSuchMethod stubs in the special case that the class is Object.
final List<StubMethod> noSuchMethodStubs;
@override
final List<Field> staticFieldsForReflection;
final bool hasRtiField; // Per-instance runtime type information pseudo-field.
final bool onlyForRti;
final bool onlyForConstructor;
@ -289,7 +281,6 @@ class Class implements FieldContainer {
this.name,
this.methods,
this.fields,
this.staticFieldsForReflection,
this.callStubs,
this.noSuchMethodStubs,
this.checkedSetters,
@ -335,7 +326,6 @@ class MixinApplication extends Class {
ClassTypeData typeData,
js.Name name,
List<Field> instanceFields,
List<Field> staticFieldsForReflection,
List<StubMethod> callStubs,
List<StubMethod> checkedSetters,
List<StubMethod> isChecks,
@ -350,7 +340,6 @@ class MixinApplication extends Class {
name,
const <Method>[],
instanceFields,
staticFieldsForReflection,
callStubs,
const <StubMethod>[],
checkedSetters,

View file

@ -4,7 +4,7 @@
part of dart2js.js_emitter.program_builder;
/// [member] is a field (instance, static, or top level).
/// [member] is an instance field.
///
/// [name] is the field name that the [Namer] has picked for this field's
/// storage, that is, the JavaScript property name.
@ -35,36 +35,18 @@ class FieldVisitor {
/// Invokes [f] for each of the fields of [element].
///
/// [element] must be a [ClassEntity] or a [LibraryEntity].
///
/// If [element] is a [ClassEntity], the static fields of the class are
/// visited if [visitStatics] is true and the instance fields are visited if
/// [visitStatics] is false.
///
/// If [element] is a [LibraryEntity], [visitStatics] must be true.
///
/// When visiting the instance fields of a class, the fields of its superclass
/// are also visited if the class is instantiated.
///
/// Invariant: [element] must be a declaration element.
void visitFields(AcceptField f,
{bool visitStatics: false, LibraryEntity library, ClassEntity cls}) {
bool isNativeClass = false;
bool isLibrary = false;
bool isInstantiated = false;
if (cls != null) {
isNativeClass = _nativeData.isNativeClass(cls);
void visitFields(AcceptField f, ClassEntity cls) {
assert(
cls != null, failedAt(NO_LOCATION_SPANNABLE, 'Expected a ClassEntity'));
// If the class is never instantiated we still need to set it up for
// inheritance purposes, but we can simplify its JavaScript constructor.
isInstantiated = _codegenWorld.directlyInstantiatedClasses.contains(cls);
} else if (library != null) {
isLibrary = true;
assert(visitStatics, failedAt(library));
} else {
failedAt(
NO_LOCATION_SPANNABLE, 'Expected a ClassEntity or a LibraryEntity.');
}
bool isNativeClass = _nativeData.isNativeClass(cls);
// If the class is never instantiated we still need to set it up for
// inheritance purposes, but we can simplify its JavaScript constructor.
bool isInstantiated =
_codegenWorld.directlyInstantiatedClasses.contains(cls);
void visitField(FieldEntity field, {ClassEntity holder}) {
bool isMixinNativeField =
@ -76,7 +58,7 @@ class FieldVisitor {
// setters.
bool needsGetter = false;
bool needsSetter = false;
if (isLibrary || isMixinNativeField || holder == cls) {
if (isMixinNativeField || holder == cls) {
needsGetter = fieldNeedsGetter(field);
needsSetter = fieldNeedsSetter(field);
}
@ -101,34 +83,22 @@ class FieldVisitor {
}
}
if (isLibrary) {
_elementEnvironment.forEachLibraryMember(library, (MemberEntity member) {
if (member.isField) visitField(member);
});
} else if (visitStatics) {
_elementEnvironment.forEachLocalClassMember(cls, (MemberEntity member) {
if (member.isField && member.isStatic) {
visitField(member, holder: cls);
}
});
} else {
// TODO(kasperl): We should make sure to only emit one version of
// overridden fields. Right now, we rely on the ordering so the
// fields pulled in from mixins are replaced with the fields from
// the class definition.
// TODO(kasperl): We should make sure to only emit one version of
// overridden fields. Right now, we rely on the ordering so the
// fields pulled in from mixins are replaced with the fields from
// the class definition.
// If a class is not instantiated then we add the field just so we can
// generate the field getter/setter dynamically. Since this is only
// allowed on fields that are in [element] we don't need to visit
// superclasses for non-instantiated classes.
_elementEnvironment.forEachClassMember(cls,
(ClassEntity holder, MemberEntity member) {
if (cls != holder && !isInstantiated) return;
if (member.isField && !member.isStatic) {
visitField(member, holder: holder);
}
});
}
// If a class is not instantiated then we add the field just so we can
// generate the field getter/setter dynamically. Since this is only
// allowed on fields that are in [element] we don't need to visit
// superclasses for non-instantiated classes.
_elementEnvironment.forEachClassMember(cls,
(ClassEntity holder, MemberEntity member) {
if (cls != holder && !isInstantiated) return;
if (member.isField && !member.isStatic) {
visitField(member, holder: holder);
}
});
}
bool fieldNeedsGetter(FieldEntity field) {

View file

@ -543,12 +543,7 @@ class ProgramBuilder {
.toList();
classTypeData.addAll(classes.map((Class cls) => cls.typeData).toList());
bool visitStatics = true;
List<Field> staticFieldsForReflection =
_buildFields(library: library, visitStatics: visitStatics);
return new Library(library, uri, statics, classes, classTypeData,
staticFieldsForReflection);
return Library(library, uri, statics, classes, classTypeData);
}
Class _buildClass(ClassEntity cls) {
@ -655,16 +650,7 @@ class ProgramBuilder {
bool isInterceptedClass = _interceptorData.isInterceptedClass(cls);
List<Field> instanceFields = onlyForConstructorOrRti
? const []
: _buildFields(
cls: cls,
visitStatics: false,
isHolderInterceptedClass: isInterceptedClass);
List<Field> staticFieldsForReflection = onlyForConstructorOrRti
? const []
: _buildFields(
cls: cls,
visitStatics: true,
isHolderInterceptedClass: isInterceptedClass);
: _buildFields(cls: cls, isHolderInterceptedClass: isInterceptedClass);
TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(
cls, _generatedCode,
@ -717,28 +703,19 @@ class ProgramBuilder {
assert(methods.isEmpty);
assert(!isClosureBaseClass);
result = new MixinApplication(
cls,
typeData,
name,
instanceFields,
staticFieldsForReflection,
callStubs,
checkedSetters,
isChecks,
typeTests.functionTypeIndex,
result = MixinApplication(cls, typeData, name, instanceFields, callStubs,
checkedSetters, isChecks, typeTests.functionTypeIndex,
isDirectlyInstantiated: isInstantiated,
hasRtiField: hasRtiField,
onlyForRti: onlyForRti,
onlyForConstructor: onlyForConstructor);
} else {
result = new Class(
result = Class(
cls,
typeData,
name,
methods,
instanceFields,
staticFieldsForReflection,
callStubs,
noSuchMethodStubs,
checkedSetters,
@ -1009,18 +986,14 @@ class ProgramBuilder {
}
List<Field> _buildFields(
{bool visitStatics: false,
bool isHolderInterceptedClass: false,
LibraryEntity library,
ClassEntity cls}) {
{bool isHolderInterceptedClass: false, ClassEntity cls}) {
List<Field> fields = <Field>[];
void visitField(FieldEntity field, js.Name name, js.Name accessorName,
bool needsGetter, bool needsSetter, bool needsCheckedSetter) {
int getterFlags = 0;
if (needsGetter) {
if (visitStatics ||
!_interceptorData.fieldHasInterceptedGetter(field)) {
if (!_interceptorData.fieldHasInterceptedGetter(field)) {
getterFlags = 1;
} else {
getterFlags += 2;
@ -1035,8 +1008,7 @@ class ProgramBuilder {
int setterFlags = 0;
if (needsSetter) {
if (visitStatics ||
!_interceptorData.fieldHasInterceptedSetter(field)) {
if (!_interceptorData.fieldHasInterceptedSetter(field)) {
setterFlags = 1;
} else {
setterFlags += 2;
@ -1056,7 +1028,7 @@ class ProgramBuilder {
constantValue = fieldData.constantValue;
}
fields.add(new Field(
fields.add(Field(
field,
name,
accessorName,
@ -1068,10 +1040,9 @@ class ProgramBuilder {
fieldData.isElided));
}
FieldVisitor visitor = new FieldVisitor(
FieldVisitor visitor = FieldVisitor(
_elementEnvironment, _codegenWorld, _nativeData, _namer, _closedWorld);
visitor.visitFields(visitField,
visitStatics: visitStatics, library: library, cls: cls);
visitor.visitFields(visitField, cls);
return fields;
}

View file

@ -1039,19 +1039,26 @@ class FragmentEmitter {
Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs;
Iterable<Method> gettersSetters = generateGettersSetters(cls);
Iterable<Method> allMethods = [
methods,
checkedSetters,
isChecks,
callStubs,
noSuchMethodStubs,
gettersSetters
].expand((x) => x);
...methods,
...checkedSetters,
...isChecks,
...callStubs,
...noSuchMethodStubs,
...gettersSetters
];
List<js.Property> properties = [];
if (cls.superclass == null) {
// ie11 might require us to set 'constructor' but we aren't 100% sure.
// This is Dart `Object`. Add properties that are usually added by
// `inherit`.
// TODO(sra): Adding properties here appears to be redundant with the call
// to `inherit(P.Object, null)` in the generated code. See if we can
// remove that.
if (_options.legacyJavaScript) {
// IE11 might require us to set 'constructor' but we aren't 100% sure.
properties
.add(js.Property(js.string("constructor"), classReference(cls)));
}
@ -1147,15 +1154,12 @@ class FragmentEmitter {
/// Generates all getters and setters the given class [cls] needs.
Iterable<Method> generateGettersSetters(Class cls) {
Iterable<Method> getters = cls.fields
.where((Field field) => field.needsGetter)
.map(generateGetter);
Iterable<Method> setters = cls.fields
.where((Field field) => field.needsUncheckedSetter)
.map(generateSetter);
return [getters, setters].expand((x) => x);
return [
for (Field field in cls.fields)
if (field.needsGetter) generateGetter(field),
for (Field field in cls.fields)
if (field.needsUncheckedSetter) generateSetter(field),
];
}
/// Emits the given instance [method].

View file

@ -134,23 +134,6 @@ class LibraryData {
}
}
void addField(Field field) {
ClassEntity enclosingClass = field.element?.enclosingClass;
if (enclosingClass != null) {
ClassData data =
_classMap.putIfAbsent(enclosingClass, () => new ClassData(null));
assert(!data._fieldMap.containsKey(field.element));
data._fieldMap[field.element] = field;
} else if (field.element != null) {
assert(!_fieldMap.containsKey(field.element));
_fieldMap[field.element] = field;
}
}
for (Field field in library.staticFieldsForReflection) {
addField(field);
}
void addStaticField(StaticField field) {
ClassEntity enclosingClass = field.element?.enclosingClass;
if (enclosingClass != null) {