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

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

Issue 2823003003: Remove Compiler and JavaScriptBackend from field_visitor. (Closed)
Patch Set: Created 3 years, 8 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 Compiler compiler; 29 final CompilerOptions _options;
30 final Namer namer; 30 final CodegenWorldBuilder _codegenWorldBuilder;
31 final ClosedWorld closedWorld; 31 final NativeData _nativeData;
32 final MirrorsData _mirrorsData;
33 final Namer _namer;
34 final ClosedWorld _closedWorld;
32 35
33 JavaScriptBackend get backend => compiler.backend; 36 FieldVisitor(this._options, this._codegenWorldBuilder, this._nativeData,
34 37 this._mirrorsData, this._namer, this._closedWorld);
35 FieldVisitor(this.compiler, this.namer, this.closedWorld);
36 38
37 /** 39 /**
38 * Invokes [f] for each of the fields of [element]. 40 * Invokes [f] for each of the fields of [element].
39 * 41 *
40 * [element] must be a [ClassElement] or a [LibraryElement]. 42 * [element] must be a [ClassElement] or a [LibraryElement].
41 * 43 *
42 * If [element] is a [ClassElement], the static fields of the class are 44 * If [element] is a [ClassElement], the static fields of the class are
43 * visited if [visitStatics] is true and the instance fields are visited if 45 * visited if [visitStatics] is true and the instance fields are visited if
44 * [visitStatics] is false. 46 * [visitStatics] is false.
45 * 47 *
46 * If [element] is a [LibraryElement], [visitStatics] must be true. 48 * If [element] is a [LibraryElement], [visitStatics] must be true.
47 * 49 *
48 * When visiting the instance fields of a class, the fields of its superclass 50 * When visiting the instance fields of a class, the fields of its superclass
49 * are also visited if the class is instantiated. 51 * are also visited if the class is instantiated.
50 * 52 *
51 * Invariant: [element] must be a declaration element. 53 * Invariant: [element] must be a declaration element.
52 */ 54 */
53 void visitFields(Element element, bool visitStatics, AcceptField f) { 55 void visitFields(Element element, bool visitStatics, AcceptField f) {
54 assert(invariant(element, element.isDeclaration)); 56 assert(invariant(element, element.isDeclaration));
55 57
56 ClassElement cls; 58 ClassElement cls;
57 bool isNativeClass = false; 59 bool isNativeClass = false;
58 bool isLibrary = false; 60 bool isLibrary = false;
59 bool isInstantiated = false; 61 bool isInstantiated = false;
60 if (element.isClass) { 62 if (element.isClass) {
61 cls = element; 63 cls = element;
62 isNativeClass = backend.nativeData.isNativeClass(cls); 64 isNativeClass = _nativeData.isNativeClass(cls);
63 65
64 // If the class is never instantiated we still need to set it up for 66 // If the class is never instantiated we still need to set it up for
65 // inheritance purposes, but we can simplify its JavaScript constructor. 67 // inheritance purposes, but we can simplify its JavaScript constructor.
66 isInstantiated = compiler.codegenWorldBuilder.directlyInstantiatedClasses 68 isInstantiated =
67 .contains(cls); 69 _codegenWorldBuilder.directlyInstantiatedClasses.contains(cls);
68 } else if (element.isLibrary) { 70 } else if (element.isLibrary) {
69 isLibrary = true; 71 isLibrary = true;
70 assert(invariant(element, visitStatics)); 72 assert(invariant(element, visitStatics));
71 } else { 73 } else {
72 throw new SpannableAssertionFailure( 74 throw new SpannableAssertionFailure(
73 element, 'Expected a ClassElement or a LibraryElement.'); 75 element, 'Expected a ClassElement or a LibraryElement.');
74 } 76 }
75 77
76 void visitField(Element holder, FieldElement field) { 78 void visitField(Element holder, FieldElement field) {
77 assert(invariant(element, field.isDeclaration)); 79 assert(invariant(element, field.isDeclaration));
78 80
79 bool isMixinNativeField = isNativeClass && holder.isMixinApplication; 81 bool isMixinNativeField = isNativeClass && holder.isMixinApplication;
80 82
81 // See if we can dynamically create getters and setters. 83 // See if we can dynamically create getters and setters.
82 // We can only generate getters and setters for [element] since 84 // We can only generate getters and setters for [element] since
83 // the fields of super classes could be overwritten with getters or 85 // the fields of super classes could be overwritten with getters or
84 // setters. 86 // setters.
85 bool needsGetter = false; 87 bool needsGetter = false;
86 bool needsSetter = false; 88 bool needsSetter = false;
87 if (isLibrary || isMixinNativeField || holder == element) { 89 if (isLibrary || isMixinNativeField || holder == element) {
88 needsGetter = fieldNeedsGetter(field); 90 needsGetter = fieldNeedsGetter(field);
89 needsSetter = fieldNeedsSetter(field); 91 needsSetter = fieldNeedsSetter(field);
90 } 92 }
91 93
92 if ((isInstantiated && !backend.nativeData.isNativeClass(cls)) || 94 if ((isInstantiated && !_nativeData.isNativeClass(cls)) ||
93 needsGetter || 95 needsGetter ||
94 needsSetter) { 96 needsSetter) {
95 js.Name accessorName = namer.fieldAccessorName(field); 97 js.Name accessorName = _namer.fieldAccessorName(field);
96 js.Name fieldName = namer.fieldPropertyName(field); 98 js.Name fieldName = _namer.fieldPropertyName(field);
97 bool needsCheckedSetter = false; 99 bool needsCheckedSetter = false;
98 if (compiler.options.enableTypeAssertions && 100 if (_options.enableTypeAssertions &&
99 needsSetter && 101 needsSetter &&
100 !canAvoidGeneratedCheckedSetter(field)) { 102 !canAvoidGeneratedCheckedSetter(field)) {
101 needsCheckedSetter = true; 103 needsCheckedSetter = true;
102 needsSetter = false; 104 needsSetter = false;
103 } 105 }
104 // Getters and setters with suffixes will be generated dynamically. 106 // Getters and setters with suffixes will be generated dynamically.
105 f(field, fieldName, accessorName, needsGetter, needsSetter, 107 f(field, fieldName, accessorName, needsGetter, needsSetter,
106 needsCheckedSetter); 108 needsCheckedSetter);
107 } 109 }
108 } 110 }
(...skipping 16 matching lines...) Expand all
125 // allowed on fields that are in [element] we don't need to visit 127 // allowed on fields that are in [element] we don't need to visit
126 // superclasses for non-instantiated classes. 128 // superclasses for non-instantiated classes.
127 cls.implementation.forEachInstanceField(visitField, 129 cls.implementation.forEachInstanceField(visitField,
128 includeSuperAndInjectedMembers: isInstantiated); 130 includeSuperAndInjectedMembers: isInstantiated);
129 } 131 }
130 } 132 }
131 133
132 bool fieldNeedsGetter(FieldElement field) { 134 bool fieldNeedsGetter(FieldElement field) {
133 assert(field.isField); 135 assert(field.isField);
134 if (fieldAccessNeverThrows(field)) return false; 136 if (fieldAccessNeverThrows(field)) return false;
135 if (backend.mirrorsData.shouldRetainGetter(field)) return true; 137 if (_mirrorsData.shouldRetainGetter(field)) return true;
136 return field.isClassMember && 138 return field.isClassMember &&
137 compiler.codegenWorldBuilder.hasInvokedGetter(field, closedWorld); 139 _codegenWorldBuilder.hasInvokedGetter(field, _closedWorld);
138 } 140 }
139 141
140 bool fieldNeedsSetter(FieldElement field) { 142 bool fieldNeedsSetter(FieldElement field) {
141 assert(field.isField); 143 assert(field.isField);
142 if (fieldAccessNeverThrows(field)) return false; 144 if (fieldAccessNeverThrows(field)) return false;
143 if (field.isFinal || field.isConst) return false; 145 if (field.isFinal || field.isConst) return false;
144 if (backend.mirrorsData.shouldRetainSetter(field)) return true; 146 if (_mirrorsData.shouldRetainSetter(field)) return true;
145 return field.isClassMember && 147 return field.isClassMember &&
146 compiler.codegenWorldBuilder.hasInvokedSetter(field, closedWorld); 148 _codegenWorldBuilder.hasInvokedSetter(field, _closedWorld);
147 } 149 }
148 150
149 static bool fieldAccessNeverThrows(VariableElement field) { 151 static bool fieldAccessNeverThrows(VariableElement field) {
150 return 152 return
151 // We never access a field in a closure (a captured variable) without 153 // We never access a field in a closure (a captured variable) without
152 // knowing that it is there. Therefore we don't need to use a getter 154 // knowing that it is there. Therefore we don't need to use a getter
153 // (that will throw if the getter method is missing), but can always 155 // (that will throw if the getter method is missing), but can always
154 // access the field directly. 156 // access the field directly.
155 field is ClosureFieldElement; 157 field is ClosureFieldElement;
156 } 158 }
157 159
158 bool canAvoidGeneratedCheckedSetter(VariableElement member) { 160 bool canAvoidGeneratedCheckedSetter(VariableElement member) {
159 // We never generate accessors for top-level/static fields. 161 // We never generate accessors for top-level/static fields.
160 if (!member.isInstanceMember) return true; 162 if (!member.isInstanceMember) return true;
161 ResolutionDartType type = member.type; 163 ResolutionDartType type = member.type;
162 return type.treatAsDynamic || type.isObject; 164 return type.treatAsDynamic || type.isObject;
163 } 165 }
164 } 166 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698