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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart

Issue 2908153003: It's alive! (Closed)
Patch Set: Updated cf. comments Created 3 years, 6 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart2js.js_emitter.program_builder; 5 part of dart2js.js_emitter.program_builder;
6 6
7 /** 7 /**
8 * [member] is a field (instance, static, or top level). 8 * [member] is a field (instance, static, or top level).
9 * 9 *
10 * [name] is the field name that the [Namer] has picked for this field's 10 * [name] is the field name that the [Namer] has picked for this field's
11 * storage, that is, the JavaScript property name. 11 * storage, that is, the JavaScript property name.
12 * 12 *
13 * [accessorName] is the name of the accessor. For instance fields this is 13 * [accessorName] is the name of the accessor. For instance fields this is
14 * mostly the same as [name] except when [member] is shadowing a field in its 14 * mostly the same as [name] except when [member] is shadowing a field in its
15 * superclass. For other fields, they are rarely the same. 15 * superclass. For other fields, they are rarely the same.
16 * 16 *
17 * [needsGetter] and [needsSetter] represent if a getter or a setter 17 * [needsGetter] and [needsSetter] represent if a getter or a setter
18 * respectively is needed. There are many factors in this, for example, if the 18 * respectively is needed. There are many factors in this, for example, if the
19 * accessor can be inlined. 19 * accessor can be inlined.
20 * 20 *
21 * [needsCheckedSetter] indicates that a checked getter is needed, and in this 21 * [needsCheckedSetter] indicates that a checked getter is needed, and in this
22 * case, [needsSetter] is always false. [needsCheckedSetter] is only true when 22 * case, [needsSetter] is always false. [needsCheckedSetter] is only true when
23 * type assertions are enabled (checked mode). 23 * type assertions are enabled (checked mode).
24 */ 24 */
25 typedef void AcceptField(FieldEntity member, js.Name name, js.Name accessorName, 25 typedef void AcceptField(FieldEntity member, js.Name name, js.Name accessorName,
26 bool needsGetter, bool needsSetter, bool needsCheckedSetter); 26 bool needsGetter, bool needsSetter, bool needsCheckedSetter);
27 27
28 class FieldVisitor { 28 class FieldVisitor {
29 final CompilerOptions _options; 29 final CompilerOptions _options;
30 final ElementEnvironment _elementEnvironment;
30 final CodegenWorldBuilder _codegenWorldBuilder; 31 final CodegenWorldBuilder _codegenWorldBuilder;
31 final NativeData _nativeData; 32 final NativeData _nativeData;
32 final MirrorsData _mirrorsData; 33 final MirrorsData _mirrorsData;
33 final Namer _namer; 34 final Namer _namer;
34 final ClosedWorld _closedWorld; 35 final ClosedWorld _closedWorld;
35 36
36 FieldVisitor(this._options, this._codegenWorldBuilder, this._nativeData, 37 FieldVisitor(
37 this._mirrorsData, this._namer, this._closedWorld); 38 this._options,
39 this._elementEnvironment,
40 this._codegenWorldBuilder,
41 this._nativeData,
42 this._mirrorsData,
43 this._namer,
44 this._closedWorld);
38 45
39 /** 46 /**
40 * Invokes [f] for each of the fields of [element]. 47 * Invokes [f] for each of the fields of [element].
41 * 48 *
42 * [element] must be a [ClassElement] or a [LibraryElement]. 49 * [element] must be a [ClassElement] or a [LibraryElement].
43 * 50 *
44 * If [element] is a [ClassElement], the static fields of the class are 51 * If [element] is a [ClassElement], the static fields of the class are
45 * visited if [visitStatics] is true and the instance fields are visited if 52 * visited if [visitStatics] is true and the instance fields are visited if
46 * [visitStatics] is false. 53 * [visitStatics] is false.
47 * 54 *
48 * If [element] is a [LibraryElement], [visitStatics] must be true. 55 * If [element] is a [LibraryElement], [visitStatics] must be true.
49 * 56 *
50 * When visiting the instance fields of a class, the fields of its superclass 57 * When visiting the instance fields of a class, the fields of its superclass
51 * are also visited if the class is instantiated. 58 * are also visited if the class is instantiated.
52 * 59 *
53 * Invariant: [element] must be a declaration element. 60 * Invariant: [element] must be a declaration element.
54 */ 61 */
55 void visitFields(Element element, bool visitStatics, AcceptField f) { 62 void visitFields(AcceptField f,
56 assert(element.isDeclaration, failedAt(element)); 63 {bool visitStatics: false, LibraryEntity library, ClassEntity cls}) {
64 assert(!(library is LibraryElement && !library.isDeclaration),
65 failedAt(library));
66 assert(!(cls is ClassElement && !cls.isDeclaration), failedAt(cls));
57 67
58 ClassElement cls;
59 bool isNativeClass = false; 68 bool isNativeClass = false;
60 bool isLibrary = false; 69 bool isLibrary = false;
61 bool isInstantiated = false; 70 bool isInstantiated = false;
62 if (element.isClass) { 71 if (cls != null) {
63 cls = element;
64 isNativeClass = _nativeData.isNativeClass(cls); 72 isNativeClass = _nativeData.isNativeClass(cls);
65 73
66 // If the class is never instantiated we still need to set it up for 74 // If the class is never instantiated we still need to set it up for
67 // inheritance purposes, but we can simplify its JavaScript constructor. 75 // inheritance purposes, but we can simplify its JavaScript constructor.
68 isInstantiated = 76 isInstantiated =
69 _codegenWorldBuilder.directlyInstantiatedClasses.contains(cls); 77 _codegenWorldBuilder.directlyInstantiatedClasses.contains(cls);
70 } else if (element.isLibrary) { 78 } else if (library != null) {
71 isLibrary = true; 79 isLibrary = true;
72 assert(visitStatics, failedAt(element)); 80 assert(visitStatics, failedAt(library));
73 } else { 81 } else {
74 throw new SpannableAssertionFailure( 82 throw new SpannableAssertionFailure(NO_LOCATION_SPANNABLE,
75 element, 'Expected a ClassElement or a LibraryElement.'); 83 'Expected a ClassElement or a LibraryElement.');
76 } 84 }
77 85
78 void visitField(Element holder, FieldElement field) { 86 void visitField(FieldElement field, {ClassEntity holder}) {
79 assert(field.isDeclaration, failedAt(element)); 87 assert(field.isDeclaration, failedAt(field));
80 88
81 bool isMixinNativeField = isNativeClass && holder.isMixinApplication; 89 bool isMixinNativeField = isNativeClass &&
90 _elementEnvironment.isUnnamedMixinApplication(holder);
82 91
83 // See if we can dynamically create getters and setters. 92 // See if we can dynamically create getters and setters.
84 // We can only generate getters and setters for [element] since 93 // We can only generate getters and setters for [element] since
85 // the fields of super classes could be overwritten with getters or 94 // the fields of super classes could be overwritten with getters or
86 // setters. 95 // setters.
87 bool needsGetter = false; 96 bool needsGetter = false;
88 bool needsSetter = false; 97 bool needsSetter = false;
89 if (isLibrary || isMixinNativeField || holder == element) { 98 if (isLibrary || isMixinNativeField || holder == cls) {
90 needsGetter = fieldNeedsGetter(field); 99 needsGetter = fieldNeedsGetter(field);
91 needsSetter = fieldNeedsSetter(field); 100 needsSetter = fieldNeedsSetter(field);
92 } 101 }
93 102
94 if ((isInstantiated && !_nativeData.isNativeClass(cls)) || 103 if ((isInstantiated && !_nativeData.isNativeClass(cls)) ||
95 needsGetter || 104 needsGetter ||
96 needsSetter) { 105 needsSetter) {
97 js.Name accessorName = _namer.fieldAccessorName(field); 106 js.Name accessorName = _namer.fieldAccessorName(field);
98 js.Name fieldName = _namer.fieldPropertyName(field); 107 js.Name fieldName = _namer.fieldPropertyName(field);
99 bool needsCheckedSetter = false; 108 bool needsCheckedSetter = false;
100 if (_options.enableTypeAssertions && 109 if (_options.enableTypeAssertions &&
101 needsSetter && 110 needsSetter &&
102 !canAvoidGeneratedCheckedSetter(field)) { 111 !canAvoidGeneratedCheckedSetter(field)) {
103 needsCheckedSetter = true; 112 needsCheckedSetter = true;
104 needsSetter = false; 113 needsSetter = false;
105 } 114 }
106 // Getters and setters with suffixes will be generated dynamically. 115 // Getters and setters with suffixes will be generated dynamically.
107 f(field, fieldName, accessorName, needsGetter, needsSetter, 116 f(field, fieldName, accessorName, needsGetter, needsSetter,
108 needsCheckedSetter); 117 needsCheckedSetter);
109 } 118 }
110 } 119 }
111 120
112 if (isLibrary) { 121 if (isLibrary) {
113 LibraryElement library = element; 122 _elementEnvironment.forEachLibraryMember(library, (MemberEntity member) {
114 library.implementation.forEachLocalMember((Element member) { 123 if (member.isField) visitField(member);
115 if (member.isField) visitField(library, member);
116 }); 124 });
117 } else if (visitStatics) { 125 } else if (visitStatics) {
118 cls.implementation.forEachStaticField(visitField); 126 _elementEnvironment.forEachClassMember(cls,
127 (ClassEntity holder, MemberEntity member) {
128 if (cls == holder && member.isField && member.isStatic) {
129 visitField(member, holder: holder);
130 }
131 });
119 } else { 132 } else {
120 // TODO(kasperl): We should make sure to only emit one version of 133 // TODO(kasperl): We should make sure to only emit one version of
121 // overridden fields. Right now, we rely on the ordering so the 134 // overridden fields. Right now, we rely on the ordering so the
122 // fields pulled in from mixins are replaced with the fields from 135 // fields pulled in from mixins are replaced with the fields from
123 // the class definition. 136 // the class definition.
124 137
125 // If a class is not instantiated then we add the field just so we can 138 // If a class is not instantiated then we add the field just so we can
126 // generate the field getter/setter dynamically. Since this is only 139 // generate the field getter/setter dynamically. Since this is only
127 // allowed on fields that are in [element] we don't need to visit 140 // allowed on fields that are in [element] we don't need to visit
128 // superclasses for non-instantiated classes. 141 // superclasses for non-instantiated classes.
129 cls.implementation.forEachInstanceField(visitField, 142 _elementEnvironment.forEachClassMember(cls,
130 includeSuperAndInjectedMembers: isInstantiated); 143 (ClassEntity holder, MemberEntity member) {
144 if (cls != holder && !isInstantiated) return;
145 if (member.isField && !member.isStatic) {
146 visitField(member, holder: holder);
147 }
148 });
131 } 149 }
132 } 150 }
133 151
134 bool fieldNeedsGetter(FieldElement field) { 152 bool fieldNeedsGetter(FieldElement field) {
135 assert(field.isField); 153 assert(field.isField);
136 if (fieldAccessNeverThrows(field)) return false; 154 if (fieldAccessNeverThrows(field)) return false;
137 if (_mirrorsData.shouldRetainGetter(field)) return true; 155 if (_mirrorsData.shouldRetainGetter(field)) return true;
138 return field.isClassMember && 156 return field.isClassMember &&
139 _codegenWorldBuilder.hasInvokedGetter(field, _closedWorld); 157 _codegenWorldBuilder.hasInvokedGetter(field, _closedWorld);
140 } 158 }
(...skipping 16 matching lines...) Expand all
157 field is ClosureFieldElement; 175 field is ClosureFieldElement;
158 } 176 }
159 177
160 bool canAvoidGeneratedCheckedSetter(VariableElement member) { 178 bool canAvoidGeneratedCheckedSetter(VariableElement member) {
161 // We never generate accessors for top-level/static fields. 179 // We never generate accessors for top-level/static fields.
162 if (!member.isInstanceMember) return true; 180 if (!member.isInstanceMember) return true;
163 ResolutionDartType type = member.type; 181 ResolutionDartType type = member.type;
164 return type.treatAsDynamic || type.isObject; 182 return type.treatAsDynamic || type.isObject;
165 } 183 }
166 } 184 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698