OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library dart2js.js_emitter.program_builder; | 5 library dart2js.js_emitter.program_builder; |
6 | 6 |
7 import '../js_emitter.dart' show | 7 import '../js_emitter.dart' |
8 ClassStubGenerator, | 8 show |
9 CodeEmitterTask, | 9 ClassStubGenerator, |
10 computeMixinClass, | 10 CodeEmitterTask, |
11 Emitter, | 11 computeMixinClass, |
12 InterceptorStubGenerator, | 12 Emitter, |
13 MainCallStubGenerator, | 13 InterceptorStubGenerator, |
14 ParameterStubGenerator, | 14 MainCallStubGenerator, |
15 RuntimeTypeGenerator, | 15 ParameterStubGenerator, |
16 TypeTestProperties; | 16 RuntimeTypeGenerator, |
| 17 TypeTestProperties; |
17 import '../model.dart'; | 18 import '../model.dart'; |
18 | 19 |
19 import '../../closure.dart' show | 20 import '../../closure.dart' show ClosureFieldElement; |
20 ClosureFieldElement; | |
21 import '../../common.dart'; | 21 import '../../common.dart'; |
22 import '../../common/names.dart' show | 22 import '../../common/names.dart' show Names, Selectors; |
23 Names, | 23 import '../../compiler.dart' show Compiler; |
24 Selectors; | 24 import '../../constants/values.dart' |
25 import '../../compiler.dart' show | 25 show ConstantValue, InterceptorConstantValue; |
26 Compiler; | 26 import '../../core_types.dart' show CoreClasses; |
27 import '../../constants/values.dart' show | 27 import '../../dart_types.dart' show DartType, FunctionType, TypedefType; |
28 ConstantValue, | 28 import '../../elements/elements.dart' |
29 InterceptorConstantValue; | 29 show |
30 import '../../core_types.dart' show | 30 ClassElement, |
31 CoreClasses; | 31 Element, |
32 import '../../dart_types.dart' show | 32 Elements, |
33 DartType, | 33 FieldElement, |
34 FunctionType, | 34 FunctionElement, |
35 TypedefType; | 35 FunctionSignature, |
36 import '../../elements/elements.dart' show | 36 GetterElement, |
37 ClassElement, | 37 LibraryElement, |
38 Element, | 38 MethodElement, |
39 Elements, | 39 Name, |
40 FieldElement, | 40 ParameterElement, |
41 FunctionElement, | 41 TypedefElement, |
42 FunctionSignature, | 42 VariableElement; |
43 GetterElement, | |
44 LibraryElement, | |
45 MethodElement, | |
46 Name, | |
47 ParameterElement, | |
48 TypedefElement, | |
49 VariableElement; | |
50 import '../../js/js.dart' as js; | 43 import '../../js/js.dart' as js; |
51 import '../../js_backend/backend_helpers.dart' show | 44 import '../../js_backend/backend_helpers.dart' show BackendHelpers; |
52 BackendHelpers; | 45 import '../../js_backend/js_backend.dart' |
53 import '../../js_backend/js_backend.dart' show | 46 show Namer, JavaScriptBackend, JavaScriptConstantCompiler, StringBackedName; |
54 Namer, | 47 import '../../universe/selector.dart' show Selector; |
55 JavaScriptBackend, | 48 import '../../universe/universe.dart' show Universe, SelectorConstraints; |
56 JavaScriptConstantCompiler, | 49 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
57 StringBackedName; | |
58 import '../../universe/selector.dart' show | |
59 Selector; | |
60 import '../../universe/universe.dart' show | |
61 Universe, | |
62 SelectorConstraints; | |
63 import '../../deferred_load.dart' show | |
64 DeferredLoadTask, | |
65 OutputUnit; | |
66 | 50 |
67 part 'collector.dart'; | 51 part 'collector.dart'; |
68 part 'registry.dart'; | 52 part 'registry.dart'; |
69 part 'field_visitor.dart'; | 53 part 'field_visitor.dart'; |
70 | 54 |
71 /// Builds a self-contained representation of the program that can then be | 55 /// Builds a self-contained representation of the program that can then be |
72 /// emitted more easily by the individual emitters. | 56 /// emitted more easily by the individual emitters. |
73 class ProgramBuilder { | 57 class ProgramBuilder { |
74 final Compiler _compiler; | 58 final Compiler _compiler; |
75 final Namer namer; | 59 final Namer namer; |
76 final CodeEmitterTask _task; | 60 final CodeEmitterTask _task; |
77 | 61 |
78 /// Contains the collected information the program builder used to build | 62 /// Contains the collected information the program builder used to build |
79 /// the model. | 63 /// the model. |
80 // The collector will be filled on the first call to `buildProgram`. | 64 // The collector will be filled on the first call to `buildProgram`. |
81 // It is stored and publicly exposed for backwards compatibility. New code | 65 // It is stored and publicly exposed for backwards compatibility. New code |
82 // (and in particular new emitters) should not use it. | 66 // (and in particular new emitters) should not use it. |
83 final Collector collector; | 67 final Collector collector; |
84 | 68 |
85 final Registry _registry; | 69 final Registry _registry; |
86 | 70 |
87 /// True if the program should store function types in the metadata. | 71 /// True if the program should store function types in the metadata. |
88 bool _storeFunctionTypesInMetadata = false; | 72 bool _storeFunctionTypesInMetadata = false; |
89 | 73 |
90 ProgramBuilder(Compiler compiler, | 74 ProgramBuilder(Compiler compiler, Namer namer, this._task, Emitter emitter, |
91 Namer namer, | 75 Set<ClassElement> rtiNeededClasses) |
92 this._task, | |
93 Emitter emitter, | |
94 Set<ClassElement> rtiNeededClasses) | |
95 : this._compiler = compiler, | 76 : this._compiler = compiler, |
96 this.namer = namer, | 77 this.namer = namer, |
97 this.collector = | 78 this.collector = |
98 new Collector(compiler, namer, rtiNeededClasses, emitter), | 79 new Collector(compiler, namer, rtiNeededClasses, emitter), |
99 this._registry = new Registry(compiler); | 80 this._registry = new Registry(compiler); |
100 | 81 |
101 JavaScriptBackend get backend => _compiler.backend; | 82 JavaScriptBackend get backend => _compiler.backend; |
102 BackendHelpers get helpers => backend.helpers; | 83 BackendHelpers get helpers => backend.helpers; |
103 Universe get universe => _compiler.codegenWorld; | 84 Universe get universe => _compiler.codegenWorld; |
104 | 85 |
(...skipping 18 matching lines...) Expand all Loading... |
123 | 104 |
124 Set<Class> _unneededNativeClasses; | 105 Set<Class> _unneededNativeClasses; |
125 | 106 |
126 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { | 107 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { |
127 collector.collect(); | 108 collector.collect(); |
128 | 109 |
129 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; | 110 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; |
130 // Note: In rare cases (mostly tests) output units can be empty. This | 111 // Note: In rare cases (mostly tests) output units can be empty. This |
131 // happens when the deferred code is dead-code eliminated but we still need | 112 // happens when the deferred code is dead-code eliminated but we still need |
132 // to check that the library has been loaded. | 113 // to check that the library has been loaded. |
133 _compiler.deferredLoadTask.allOutputUnits.forEach( | 114 _compiler.deferredLoadTask.allOutputUnits |
134 _registry.registerOutputUnit); | 115 .forEach(_registry.registerOutputUnit); |
135 collector.outputClassLists.forEach(_registry.registerElements); | 116 collector.outputClassLists.forEach(_registry.registerElements); |
136 collector.outputStaticLists.forEach(_registry.registerElements); | 117 collector.outputStaticLists.forEach(_registry.registerElements); |
137 collector.outputConstantLists.forEach(_registerConstants); | 118 collector.outputConstantLists.forEach(_registerConstants); |
138 collector.outputStaticNonFinalFieldLists.forEach( | 119 collector.outputStaticNonFinalFieldLists |
139 _registry.registerElements); | 120 .forEach(_registry.registerElements); |
140 | 121 |
141 // We always add the current isolate holder. | 122 // We always add the current isolate holder. |
142 _registerStaticStateHolder(); | 123 _registerStaticStateHolder(); |
143 | 124 |
144 // We need to run the native-preparation before we build the output. The | 125 // We need to run the native-preparation before we build the output. The |
145 // preparation code, in turn needs the classes to be set up. | 126 // preparation code, in turn needs the classes to be set up. |
146 // We thus build the classes before building their containers. | 127 // We thus build the classes before building their containers. |
147 collector.outputClassLists.forEach((OutputUnit _, List<ClassElement> classes
) { | 128 collector.outputClassLists |
| 129 .forEach((OutputUnit _, List<ClassElement> classes) { |
148 classes.forEach(_buildClass); | 130 classes.forEach(_buildClass); |
149 }); | 131 }); |
150 | 132 |
151 // Resolve the superclass references after we've processed all the classes. | 133 // Resolve the superclass references after we've processed all the classes. |
152 _classes.forEach((ClassElement element, Class c) { | 134 _classes.forEach((ClassElement element, Class c) { |
153 if (element.superclass != null) { | 135 if (element.superclass != null) { |
154 c.setSuperclass(_classes[element.superclass]); | 136 c.setSuperclass(_classes[element.superclass]); |
155 assert(c.superclass != null); | 137 assert(c.superclass != null); |
156 } | 138 } |
157 if (c is MixinApplication) { | 139 if (c is MixinApplication) { |
158 c.setMixinClass(_classes[computeMixinClass(element)]); | 140 c.setMixinClass(_classes[computeMixinClass(element)]); |
159 assert(c.mixinClass != null); | 141 assert(c.mixinClass != null); |
160 } | 142 } |
161 }); | 143 }); |
162 | 144 |
163 List<Class> nativeClasses = collector.nativeClassesAndSubclasses | 145 List<Class> nativeClasses = collector.nativeClassesAndSubclasses |
164 .map((ClassElement classElement) => _classes[classElement]) | 146 .map((ClassElement classElement) => _classes[classElement]) |
165 .toList(); | 147 .toList(); |
166 | 148 |
167 Set<ClassElement> interceptorClassesNeededByConstants = | 149 Set<ClassElement> interceptorClassesNeededByConstants = |
168 collector.computeInterceptorsReferencedFromConstants(); | 150 collector.computeInterceptorsReferencedFromConstants(); |
169 Set<ClassElement> classesModifiedByEmitRTISupport = | 151 Set<ClassElement> classesModifiedByEmitRTISupport = |
170 _task.typeTestRegistry.computeClassesModifiedByEmitRuntimeTypeSupport(); | 152 _task.typeTestRegistry.computeClassesModifiedByEmitRuntimeTypeSupport(); |
171 | 153 |
172 | |
173 _unneededNativeClasses = _task.nativeEmitter.prepareNativeClasses( | 154 _unneededNativeClasses = _task.nativeEmitter.prepareNativeClasses( |
174 nativeClasses, interceptorClassesNeededByConstants, | 155 nativeClasses, |
| 156 interceptorClassesNeededByConstants, |
175 classesModifiedByEmitRTISupport); | 157 classesModifiedByEmitRTISupport); |
176 | 158 |
177 _addJsInteropStubs(_registry.mainLibrariesMap); | 159 _addJsInteropStubs(_registry.mainLibrariesMap); |
178 | 160 |
179 MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap); | 161 MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap); |
180 Iterable<Fragment> deferredFragments = | 162 Iterable<Fragment> deferredFragments = |
181 _registry.deferredLibrariesMap.map(_buildDeferredFragment); | 163 _registry.deferredLibrariesMap.map(_buildDeferredFragment); |
182 | 164 |
183 List<Fragment> fragments = new List<Fragment>(_registry.librariesMapCount); | 165 List<Fragment> fragments = new List<Fragment>(_registry.librariesMapCount); |
184 fragments[0] = mainFragment; | 166 fragments[0] = mainFragment; |
185 fragments.setAll(1, deferredFragments); | 167 fragments.setAll(1, deferredFragments); |
186 | 168 |
187 _markEagerClasses(); | 169 _markEagerClasses(); |
188 | 170 |
189 List<Holder> holders = _registry.holders.toList(growable: false); | 171 List<Holder> holders = _registry.holders.toList(growable: false); |
190 | 172 |
191 bool needsNativeSupport = _compiler.enqueuer.codegen.nativeEnqueuer | 173 bool needsNativeSupport = _compiler.enqueuer.codegen.nativeEnqueuer |
192 .hasInstantiatedNativeClasses(); | 174 .hasInstantiatedNativeClasses(); |
193 | 175 |
194 assert(!needsNativeSupport || nativeClasses.isNotEmpty); | 176 assert(!needsNativeSupport || nativeClasses.isNotEmpty); |
195 | 177 |
196 List<js.TokenFinalizer> finalizers = [_task.metadataCollector]; | 178 List<js.TokenFinalizer> finalizers = [_task.metadataCollector]; |
197 if (backend.namer is js.TokenFinalizer) { | 179 if (backend.namer is js.TokenFinalizer) { |
198 var namingFinalizer = backend.namer; | 180 var namingFinalizer = backend.namer; |
199 finalizers.add(namingFinalizer); | 181 finalizers.add(namingFinalizer); |
200 } | 182 } |
201 | 183 |
202 return new Program( | 184 return new Program(fragments, holders, _buildLoadMap(), _symbolsMap, |
203 fragments, | 185 _buildTypeToInterceptorMap(), _task.metadataCollector, finalizers, |
204 holders, | |
205 _buildLoadMap(), | |
206 _symbolsMap, | |
207 _buildTypeToInterceptorMap(), | |
208 _task.metadataCollector, | |
209 finalizers, | |
210 needsNativeSupport: needsNativeSupport, | 186 needsNativeSupport: needsNativeSupport, |
211 outputContainsConstantList: collector.outputContainsConstantList, | 187 outputContainsConstantList: collector.outputContainsConstantList, |
212 hasIsolateSupport: _compiler.hasIsolateSupport); | 188 hasIsolateSupport: _compiler.hasIsolateSupport); |
213 } | 189 } |
214 | 190 |
215 void _markEagerClasses() { | 191 void _markEagerClasses() { |
216 _markEagerInterceptorClasses(); | 192 _markEagerInterceptorClasses(); |
217 } | 193 } |
218 | 194 |
219 /// Builds a map from loadId to outputs-to-load. | 195 /// Builds a map from loadId to outputs-to-load. |
(...skipping 11 matching lines...) Expand all Loading... |
231 js.Expression _buildTypeToInterceptorMap() { | 207 js.Expression _buildTypeToInterceptorMap() { |
232 InterceptorStubGenerator stubGenerator = | 208 InterceptorStubGenerator stubGenerator = |
233 new InterceptorStubGenerator(_compiler, namer, backend); | 209 new InterceptorStubGenerator(_compiler, namer, backend); |
234 return stubGenerator.generateTypeToInterceptorMap(); | 210 return stubGenerator.generateTypeToInterceptorMap(); |
235 } | 211 } |
236 | 212 |
237 MainFragment _buildMainFragment(LibrariesMap librariesMap) { | 213 MainFragment _buildMainFragment(LibrariesMap librariesMap) { |
238 // Construct the main output from the libraries and the registered holders. | 214 // Construct the main output from the libraries and the registered holders. |
239 MainFragment result = new MainFragment( | 215 MainFragment result = new MainFragment( |
240 librariesMap.outputUnit, | 216 librariesMap.outputUnit, |
241 "", // The empty string is the name for the main output file. | 217 "", // The empty string is the name for the main output file. |
242 _buildInvokeMain(), | 218 _buildInvokeMain(), |
243 _buildLibraries(librariesMap), | 219 _buildLibraries(librariesMap), |
244 _buildStaticNonFinalFields(librariesMap), | 220 _buildStaticNonFinalFields(librariesMap), |
245 _buildStaticLazilyInitializedFields(librariesMap), | 221 _buildStaticLazilyInitializedFields(librariesMap), |
246 _buildConstants(librariesMap)); | 222 _buildConstants(librariesMap)); |
247 _outputs[librariesMap.outputUnit] = result; | 223 _outputs[librariesMap.outputUnit] = result; |
248 return result; | 224 return result; |
249 } | 225 } |
250 | 226 |
251 js.Statement _buildInvokeMain() { | 227 js.Statement _buildInvokeMain() { |
252 if (_compiler.isMockCompilation) return js.js.comment("Mock compilation"); | 228 if (_compiler.isMockCompilation) return js.js.comment("Mock compilation"); |
253 | 229 |
254 MainCallStubGenerator generator = | 230 MainCallStubGenerator generator = |
255 new MainCallStubGenerator(_compiler, backend, backend.emitter); | 231 new MainCallStubGenerator(_compiler, backend, backend.emitter); |
256 return generator.generateInvokeMain(); | 232 return generator.generateInvokeMain(); |
257 } | 233 } |
258 | 234 |
259 DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) { | 235 DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) { |
260 DeferredFragment result = new DeferredFragment( | 236 DeferredFragment result = new DeferredFragment( |
261 librariesMap.outputUnit, | 237 librariesMap.outputUnit, |
262 backend.deferredPartFileName(librariesMap.name, addExtension: false), | 238 backend.deferredPartFileName(librariesMap.name, addExtension: false), |
263 librariesMap.name, | 239 librariesMap.name, |
264 _buildLibraries(librariesMap), | 240 _buildLibraries(librariesMap), |
265 _buildStaticNonFinalFields(librariesMap), | 241 _buildStaticNonFinalFields(librariesMap), |
266 _buildStaticLazilyInitializedFields(librariesMap), | 242 _buildStaticLazilyInitializedFields(librariesMap), |
267 _buildConstants(librariesMap)); | 243 _buildConstants(librariesMap)); |
268 _outputs[librariesMap.outputUnit] = result; | 244 _outputs[librariesMap.outputUnit] = result; |
269 return result; | 245 return result; |
270 } | 246 } |
271 | 247 |
272 List<Constant> _buildConstants(LibrariesMap librariesMap) { | 248 List<Constant> _buildConstants(LibrariesMap librariesMap) { |
273 List<ConstantValue> constantValues = | 249 List<ConstantValue> constantValues = |
274 collector.outputConstantLists[librariesMap.outputUnit]; | 250 collector.outputConstantLists[librariesMap.outputUnit]; |
275 if (constantValues == null) return const <Constant>[]; | 251 if (constantValues == null) return const <Constant>[]; |
276 return constantValues.map((ConstantValue value) => _constants[value]) | 252 return constantValues |
| 253 .map((ConstantValue value) => _constants[value]) |
277 .toList(growable: false); | 254 .toList(growable: false); |
278 } | 255 } |
279 | 256 |
280 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) { | 257 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) { |
281 List<VariableElement> staticNonFinalFields = | 258 List<VariableElement> staticNonFinalFields = |
282 collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit]; | 259 collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit]; |
283 if (staticNonFinalFields == null) return const <StaticField>[]; | 260 if (staticNonFinalFields == null) return const <StaticField>[]; |
284 | 261 |
285 return staticNonFinalFields | 262 return staticNonFinalFields.map(_buildStaticField).toList(growable: false); |
286 .map(_buildStaticField) | |
287 .toList(growable: false); | |
288 } | 263 } |
289 | 264 |
290 StaticField _buildStaticField(Element element) { | 265 StaticField _buildStaticField(Element element) { |
291 JavaScriptConstantCompiler handler = backend.constants; | 266 JavaScriptConstantCompiler handler = backend.constants; |
292 ConstantValue initialValue = handler.getInitialValueFor(element); | 267 ConstantValue initialValue = handler.getInitialValueFor(element); |
293 // TODO(zarah): The holder should not be registered during building of | 268 // TODO(zarah): The holder should not be registered during building of |
294 // a static field. | 269 // a static field. |
295 _registry.registerHolder( | 270 _registry.registerHolder(namer.globalObjectForConstant(initialValue), |
296 namer.globalObjectForConstant(initialValue), isConstantsHolder: true); | 271 isConstantsHolder: true); |
297 js.Expression code = _task.emitter.constantReference(initialValue); | 272 js.Expression code = _task.emitter.constantReference(initialValue); |
298 js.Name name = namer.globalPropertyName(element); | 273 js.Name name = namer.globalPropertyName(element); |
299 bool isFinal = false; | 274 bool isFinal = false; |
300 bool isLazy = false; | 275 bool isLazy = false; |
301 | 276 |
302 // TODO(floitsch): we shouldn't update the registry in the middle of | 277 // TODO(floitsch): we shouldn't update the registry in the middle of |
303 // building a static field. (Note that the static-state holder was | 278 // building a static field. (Note that the static-state holder was |
304 // already registered earlier, and that we just call the register to get | 279 // already registered earlier, and that we just call the register to get |
305 // the holder-instance. | 280 // the holder-instance. |
306 return new StaticField(element, | 281 return new StaticField( |
307 name, _registerStaticStateHolder(), code, | 282 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); |
308 isFinal, isLazy); | |
309 } | 283 } |
310 | 284 |
311 List<StaticField> _buildStaticLazilyInitializedFields( | 285 List<StaticField> _buildStaticLazilyInitializedFields( |
312 LibrariesMap librariesMap) { | 286 LibrariesMap librariesMap) { |
313 JavaScriptConstantCompiler handler = backend.constants; | 287 JavaScriptConstantCompiler handler = backend.constants; |
314 DeferredLoadTask loadTask = _compiler.deferredLoadTask; | 288 DeferredLoadTask loadTask = _compiler.deferredLoadTask; |
315 Iterable<VariableElement> lazyFields = handler | 289 Iterable<VariableElement> lazyFields = handler |
316 .getLazilyInitializedFieldsForEmission() | 290 .getLazilyInitializedFieldsForEmission() |
317 .where((element) => | 291 .where((element) => |
318 loadTask.outputUnitForElement(element) == librariesMap.outputUnit); | 292 loadTask.outputUnitForElement(element) == librariesMap.outputUnit); |
319 return Elements.sortedByPosition(lazyFields) | 293 return Elements |
| 294 .sortedByPosition(lazyFields) |
320 .map(_buildLazyField) | 295 .map(_buildLazyField) |
321 .where((field) => field != null) // Happens when the field was unused. | 296 .where((field) => field != null) // Happens when the field was unused. |
322 .toList(growable: false); | 297 .toList(growable: false); |
323 } | 298 } |
324 | 299 |
325 StaticField _buildLazyField(Element element) { | 300 StaticField _buildLazyField(Element element) { |
326 js.Expression code = backend.generatedCode[element]; | 301 js.Expression code = backend.generatedCode[element]; |
327 // The code is null if we ended up not needing the lazily | 302 // The code is null if we ended up not needing the lazily |
328 // initialized field after all because of constant folding | 303 // initialized field after all because of constant folding |
329 // before code generation. | 304 // before code generation. |
330 if (code == null) return null; | 305 if (code == null) return null; |
331 | 306 |
332 js.Name name = namer.globalPropertyName(element); | 307 js.Name name = namer.globalPropertyName(element); |
333 bool isFinal = element.isFinal; | 308 bool isFinal = element.isFinal; |
334 bool isLazy = true; | 309 bool isLazy = true; |
335 // TODO(floitsch): we shouldn't update the registry in the middle of | 310 // TODO(floitsch): we shouldn't update the registry in the middle of |
336 // building a static field. (Note that the static-state holder was | 311 // building a static field. (Note that the static-state holder was |
337 // already registered earlier, and that we just call the register to get | 312 // already registered earlier, and that we just call the register to get |
338 // the holder-instance. | 313 // the holder-instance. |
339 return new StaticField(element, | 314 return new StaticField( |
340 name, _registerStaticStateHolder(), code, | 315 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); |
341 isFinal, isLazy); | |
342 } | 316 } |
343 | 317 |
344 List<Library> _buildLibraries(LibrariesMap librariesMap) { | 318 List<Library> _buildLibraries(LibrariesMap librariesMap) { |
345 List<Library> libraries = new List<Library>(librariesMap.length); | 319 List<Library> libraries = new List<Library>(librariesMap.length); |
346 int count = 0; | 320 int count = 0; |
347 librariesMap.forEach((LibraryElement library, List<Element> elements) { | 321 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
348 libraries[count++] = _buildLibrary(library, elements); | 322 libraries[count++] = _buildLibrary(library, elements); |
349 }); | 323 }); |
350 return libraries; | 324 return libraries; |
351 } | 325 } |
352 | 326 |
353 void _addJsInteropStubs(LibrariesMap librariesMap) { | 327 void _addJsInteropStubs(LibrariesMap librariesMap) { |
354 if (_classes.containsKey(_compiler.coreClasses.objectClass)) { | 328 if (_classes.containsKey(_compiler.coreClasses.objectClass)) { |
355 var toStringInvocation = namer.invocationName(Selectors.toString_); | 329 var toStringInvocation = namer.invocationName(Selectors.toString_); |
356 // TODO(jacobr): register toString as used so that it is always accessible | 330 // TODO(jacobr): register toString as used so that it is always accessible |
357 // from JavaScript. | 331 // from JavaScript. |
358 _classes[_compiler.coreClasses.objectClass].callStubs.add( | 332 _classes[_compiler.coreClasses.objectClass].callStubs.add( |
359 _buildStubMethod( | 333 _buildStubMethod(new StringBackedName("toString"), |
360 new StringBackedName("toString"), | |
361 js.js('function() { return this.#(this) }', toStringInvocation))); | 334 js.js('function() { return this.#(this) }', toStringInvocation))); |
362 } | 335 } |
363 | 336 |
364 // We add all members from classes marked with isJsInterop to the base | 337 // We add all members from classes marked with isJsInterop to the base |
365 // Interceptor class with implementations that directly call the | 338 // Interceptor class with implementations that directly call the |
366 // corresponding JavaScript member. We do not attempt to bind this when | 339 // corresponding JavaScript member. We do not attempt to bind this when |
367 // tearing off JavaScript methods as we cannot distinguish between calling | 340 // tearing off JavaScript methods as we cannot distinguish between calling |
368 // a regular getter that returns a JavaScript function and tearing off | 341 // a regular getter that returns a JavaScript function and tearing off |
369 // a method in the case where there exist multiple JavaScript classes | 342 // a method in the case where there exist multiple JavaScript classes |
370 // that conflict on whether the member is a getter or a method. | 343 // that conflict on whether the member is a getter or a method. |
371 var interceptorClass = _classes[helpers.jsJavaScriptObjectClass]; | 344 var interceptorClass = _classes[helpers.jsJavaScriptObjectClass]; |
372 var stubNames = new Set<String>(); | 345 var stubNames = new Set<String>(); |
373 librariesMap.forEach((LibraryElement library, List<Element> elements) { | 346 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
374 for (Element e in elements) { | 347 for (Element e in elements) { |
375 if (e is ClassElement && backend.isJsInterop(e)) { | 348 if (e is ClassElement && backend.isJsInterop(e)) { |
376 e.declaration.forEachMember((_, Element member) { | 349 e.declaration.forEachMember((_, Element member) { |
377 if (!member.isInstanceMember) return; | 350 if (!member.isInstanceMember) return; |
378 if (member.isGetter || member.isField || member.isFunction) { | 351 if (member.isGetter || member.isField || member.isFunction) { |
379 var selectors = | 352 var selectors = |
380 _compiler.codegenWorld.getterInvocationsByName(member.name); | 353 _compiler.codegenWorld.getterInvocationsByName(member.name); |
381 if (selectors != null && !selectors.isEmpty) { | 354 if (selectors != null && !selectors.isEmpty) { |
382 for (var selector in selectors.keys) { | 355 for (var selector in selectors.keys) { |
383 var stubName = namer.invocationName(selector); | 356 var stubName = namer.invocationName(selector); |
384 if (stubNames.add(stubName.key)) { | 357 if (stubNames.add(stubName.key)) { |
385 interceptorClass.callStubs.add(_buildStubMethod( | 358 interceptorClass.callStubs.add(_buildStubMethod(stubName, |
386 stubName, | 359 js.js('function(obj) { return obj.# }', [member.name]), |
387 js.js( | |
388 'function(obj) { return obj.# }', [member.name]), | |
389 element: member)); | 360 element: member)); |
390 } | 361 } |
391 } | 362 } |
392 } | 363 } |
393 } | 364 } |
394 | 365 |
395 if (member.isSetter || (member.isField && !member.isConst)) { | 366 if (member.isSetter || (member.isField && !member.isConst)) { |
396 var selectors = | 367 var selectors = |
397 _compiler.codegenWorld.setterInvocationsByName(member.name); | 368 _compiler.codegenWorld.setterInvocationsByName(member.name); |
398 if (selectors != null && !selectors.isEmpty) { | 369 if (selectors != null && !selectors.isEmpty) { |
(...skipping 16 matching lines...) Expand all Loading... |
415 if (member.isFunction) { | 386 if (member.isFunction) { |
416 FunctionElement fn = member; | 387 FunctionElement fn = member; |
417 functionType = fn.type; | 388 functionType = fn.type; |
418 } else if (member.isGetter) { | 389 } else if (member.isGetter) { |
419 if (_compiler.options.trustTypeAnnotations) { | 390 if (_compiler.options.trustTypeAnnotations) { |
420 GetterElement getter = member; | 391 GetterElement getter = member; |
421 DartType returnType = getter.type.returnType; | 392 DartType returnType = getter.type.returnType; |
422 if (returnType.isFunctionType) { | 393 if (returnType.isFunctionType) { |
423 functionType = returnType; | 394 functionType = returnType; |
424 } else if (returnType.treatAsDynamic || | 395 } else if (returnType.treatAsDynamic || |
425 _compiler.types.isSubtype(returnType, | 396 _compiler.types.isSubtype( |
426 backend.coreTypes.functionType)) { | 397 returnType, backend.coreTypes.functionType)) { |
427 if (returnType.isTypedef) { | 398 if (returnType.isTypedef) { |
428 TypedefType typedef = returnType; | 399 TypedefType typedef = returnType; |
429 // TODO(jacobr): can we just use typdef.unaliased instead? | 400 // TODO(jacobr): can we just use typdef.unaliased instead? |
430 functionType = typedef.element.functionSignature.type; | 401 functionType = typedef.element.functionSignature.type; |
431 } else { | 402 } else { |
432 // Other misc function type such as coreTypes.Function. | 403 // Other misc function type such as coreTypes.Function. |
433 // Allow any number of arguments. | 404 // Allow any number of arguments. |
434 isFunctionLike = true; | 405 isFunctionLike = true; |
435 } | 406 } |
436 } | 407 } |
(...skipping 20 matching lines...) Expand all Loading... |
457 if (selectors != null && !selectors.isEmpty) { | 428 if (selectors != null && !selectors.isEmpty) { |
458 for (var selector in selectors.keys) { | 429 for (var selector in selectors.keys) { |
459 // Check whether the arity matches this member. | 430 // Check whether the arity matches this member. |
460 var argumentCount = selector.argumentCount; | 431 var argumentCount = selector.argumentCount; |
461 // JS interop does not support named arguments. | 432 // JS interop does not support named arguments. |
462 if (selector.namedArgumentCount > 0) break; | 433 if (selector.namedArgumentCount > 0) break; |
463 if (argumentCount < minArgs) break; | 434 if (argumentCount < minArgs) break; |
464 if (argumentCount > maxArgs) break; | 435 if (argumentCount > maxArgs) break; |
465 var stubName = namer.invocationName(selector); | 436 var stubName = namer.invocationName(selector); |
466 if (!stubNames.add(stubName.key)) break; | 437 if (!stubNames.add(stubName.key)) break; |
467 var parameters = new List<String>.generate(argumentCount, | 438 var parameters = |
468 (i) => 'p$i'); | 439 new List<String>.generate(argumentCount, (i) => 'p$i'); |
469 | 440 |
470 // We intentionally generate the same stub method for direct | 441 // We intentionally generate the same stub method for direct |
471 // calls and call-throughs of getters so that calling a | 442 // calls and call-throughs of getters so that calling a |
472 // getter that returns a function behaves the same as calling | 443 // getter that returns a function behaves the same as calling |
473 // a method. This is helpful as many typed JavaScript APIs | 444 // a method. This is helpful as many typed JavaScript APIs |
474 // specify member functions with getters that return | 445 // specify member functions with getters that return |
475 // functions. The behavior of this solution matches JavaScript | 446 // functions. The behavior of this solution matches JavaScript |
476 // behavior implicitly binding this only when JavaScript | 447 // behavior implicitly binding this only when JavaScript |
477 // would. | 448 // would. |
478 interceptorClass.callStubs.add(_buildStubMethod( | 449 interceptorClass.callStubs.add(_buildStubMethod( |
(...skipping 28 matching lines...) Expand all Loading... |
507 List<Class> classes = elements | 478 List<Class> classes = elements |
508 .where((e) => e is ClassElement) | 479 .where((e) => e is ClassElement) |
509 .map((ClassElement classElement) => _classes[classElement]) | 480 .map((ClassElement classElement) => _classes[classElement]) |
510 .where((Class cls) => | 481 .where((Class cls) => |
511 !cls.isNative || !_unneededNativeClasses.contains(cls)) | 482 !cls.isNative || !_unneededNativeClasses.contains(cls)) |
512 .toList(growable: false); | 483 .toList(growable: false); |
513 | 484 |
514 bool visitStatics = true; | 485 bool visitStatics = true; |
515 List<Field> staticFieldsForReflection = _buildFields(library, visitStatics); | 486 List<Field> staticFieldsForReflection = _buildFields(library, visitStatics); |
516 | 487 |
517 return new Library(library, uri, statics, classes, | 488 return new Library( |
518 staticFieldsForReflection); | 489 library, uri, statics, classes, staticFieldsForReflection); |
519 } | 490 } |
520 | 491 |
521 /// HACK for Incremental Compilation. | 492 /// HACK for Incremental Compilation. |
522 /// | 493 /// |
523 /// Returns a class that contains the fields of a class. | 494 /// Returns a class that contains the fields of a class. |
524 Class buildFieldsHackForIncrementalCompilation(ClassElement element) { | 495 Class buildFieldsHackForIncrementalCompilation(ClassElement element) { |
525 assert(_compiler.options.hasIncrementalSupport); | 496 assert(_compiler.options.hasIncrementalSupport); |
526 | 497 |
527 List<Field> instanceFields = _buildFields(element, false); | 498 List<Field> instanceFields = _buildFields(element, false); |
528 js.Name name = namer.className(element); | 499 js.Name name = namer.className(element); |
(...skipping 27 matching lines...) Expand all Loading... |
556 | 527 |
557 if (Elements.isNonAbstractInstanceMember(member)) { | 528 if (Elements.isNonAbstractInstanceMember(member)) { |
558 // TODO(herhut): Remove once _buildMethod can no longer return null. | 529 // TODO(herhut): Remove once _buildMethod can no longer return null. |
559 Method method = _buildMethod(member); | 530 Method method = _buildMethod(member); |
560 if (method != null) methods.add(method); | 531 if (method != null) methods.add(method); |
561 } | 532 } |
562 if (member.isGetter || member.isField) { | 533 if (member.isGetter || member.isField) { |
563 Map<Selector, SelectorConstraints> selectors = | 534 Map<Selector, SelectorConstraints> selectors = |
564 _compiler.codegenWorld.invocationsByName(member.name); | 535 _compiler.codegenWorld.invocationsByName(member.name); |
565 if (selectors != null && !selectors.isEmpty) { | 536 if (selectors != null && !selectors.isEmpty) { |
566 | |
567 Map<js.Name, js.Expression> callStubsForMember = | 537 Map<js.Name, js.Expression> callStubsForMember = |
568 classStubGenerator.generateCallStubsForGetter(member, selectors); | 538 classStubGenerator.generateCallStubsForGetter(member, selectors); |
569 callStubsForMember.forEach((js.Name name, js.Expression code) { | 539 callStubsForMember.forEach((js.Name name, js.Expression code) { |
570 callStubs.add(_buildStubMethod(name, code, element: member)); | 540 callStubs.add(_buildStubMethod(name, code, element: member)); |
571 }); | 541 }); |
572 } | 542 } |
573 } | 543 } |
574 } | 544 } |
575 | 545 |
576 List<StubMethod> typeVariableReaderStubs = | 546 List<StubMethod> typeVariableReaderStubs = |
577 runtimeTypeGenerator.generateTypeVariableReaderStubs(element); | 547 runtimeTypeGenerator.generateTypeVariableReaderStubs(element); |
578 | 548 |
579 List<StubMethod> noSuchMethodStubs = <StubMethod>[]; | 549 List<StubMethod> noSuchMethodStubs = <StubMethod>[]; |
580 | 550 |
581 if (backend.enabledNoSuchMethod && element.isObject) { | 551 if (backend.enabledNoSuchMethod && element.isObject) { |
582 Map<js.Name, Selector> selectors = | 552 Map<js.Name, Selector> selectors = |
583 classStubGenerator.computeSelectorsForNsmHandlers(); | 553 classStubGenerator.computeSelectorsForNsmHandlers(); |
584 selectors.forEach((js.Name name, Selector selector) { | 554 selectors.forEach((js.Name name, Selector selector) { |
585 // If the program contains `const Symbol` names we have to retain them. | 555 // If the program contains `const Symbol` names we have to retain them. |
586 String selectorName = selector.name; | 556 String selectorName = selector.name; |
587 if (selector.isSetter) selectorName = "$selectorName="; | 557 if (selector.isSetter) selectorName = "$selectorName="; |
588 if (backend.symbolsUsed.contains(selectorName)) { | 558 if (backend.symbolsUsed.contains(selectorName)) { |
589 _symbolsMap[name] = selectorName; | 559 _symbolsMap[name] = selectorName; |
590 } | 560 } |
591 noSuchMethodStubs | 561 noSuchMethodStubs.add( |
592 .add(classStubGenerator.generateStubForNoSuchMethod(name, | 562 classStubGenerator.generateStubForNoSuchMethod(name, selector)); |
593 selector)); | |
594 }); | 563 }); |
595 } | 564 } |
596 | 565 |
597 if (element == helpers.closureClass) { | 566 if (element == helpers.closureClass) { |
598 // We add a special getter here to allow for tearing off a closure from | 567 // We add a special getter here to allow for tearing off a closure from |
599 // itself. | 568 // itself. |
600 js.Name name = namer.getterForMember(Names.call); | 569 js.Name name = namer.getterForMember(Names.call); |
601 js.Fun function = js.js('function() { return this; }'); | 570 js.Fun function = js.js('function() { return this; }'); |
602 callStubs.add(_buildStubMethod(name, function)); | 571 callStubs.add(_buildStubMethod(name, function)); |
603 } | 572 } |
604 | 573 |
605 ClassElement implementation = element.implementation; | 574 ClassElement implementation = element.implementation; |
606 | 575 |
607 // MixinApplications run through the members of their mixin. Here, we are | 576 // MixinApplications run through the members of their mixin. Here, we are |
608 // only interested in direct members. | 577 // only interested in direct members. |
609 if (!onlyForRti && !element.isMixinApplication) { | 578 if (!onlyForRti && !element.isMixinApplication) { |
610 implementation.forEachMember(visitMember, includeBackendMembers: true); | 579 implementation.forEachMember(visitMember, includeBackendMembers: true); |
611 } | 580 } |
612 | 581 |
613 List<Field> instanceFields = | 582 List<Field> instanceFields = |
614 onlyForRti ? const <Field>[] : _buildFields(element, false); | 583 onlyForRti ? const <Field>[] : _buildFields(element, false); |
615 List<Field> staticFieldsForReflection = | 584 List<Field> staticFieldsForReflection = |
616 onlyForRti ? const <Field>[] : _buildFields(element, true); | 585 onlyForRti ? const <Field>[] : _buildFields(element, true); |
617 | 586 |
618 TypeTestProperties typeTests = | 587 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(element, |
619 runtimeTypeGenerator.generateIsTests( | 588 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); |
620 element, | |
621 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); | |
622 | 589 |
623 List<StubMethod> checkedSetters = <StubMethod>[]; | 590 List<StubMethod> checkedSetters = <StubMethod>[]; |
624 List<StubMethod> isChecks = <StubMethod>[]; | 591 List<StubMethod> isChecks = <StubMethod>[]; |
625 if (backend.isJsInterop(element)) { | 592 if (backend.isJsInterop(element)) { |
626 typeTests.properties.forEach((js.Name name, js.Node code) { | 593 typeTests.properties.forEach((js.Name name, js.Node code) { |
627 _classes[helpers.jsInterceptorClass].isChecks.add( | 594 _classes[helpers.jsInterceptorClass] |
628 _buildStubMethod(name, code)); | 595 .isChecks |
| 596 .add(_buildStubMethod(name, code)); |
629 }); | 597 }); |
630 } else { | 598 } else { |
631 for (Field field in instanceFields) { | 599 for (Field field in instanceFields) { |
632 if (field.needsCheckedSetter) { | 600 if (field.needsCheckedSetter) { |
633 assert(!field.needsUncheckedSetter); | 601 assert(!field.needsUncheckedSetter); |
634 Element element = field.element; | 602 Element element = field.element; |
635 js.Expression code = backend.generatedCode[element]; | 603 js.Expression code = backend.generatedCode[element]; |
636 assert(code != null); | 604 assert(code != null); |
637 js.Name name = namer.deriveSetterName(field.accessorName); | 605 js.Name name = namer.deriveSetterName(field.accessorName); |
638 checkedSetters.add(_buildStubMethod(name, code, element: element)); | 606 checkedSetters.add(_buildStubMethod(name, code, element: element)); |
(...skipping 11 matching lines...) Expand all Loading... |
650 // building a class. | 618 // building a class. |
651 Holder holder = _registry.registerHolder(holderName); | 619 Holder holder = _registry.registerHolder(holderName); |
652 bool isInstantiated = !backend.isJsInterop(element) && | 620 bool isInstantiated = !backend.isJsInterop(element) && |
653 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); | 621 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); |
654 | 622 |
655 Class result; | 623 Class result; |
656 if (element.isMixinApplication && !onlyForRti) { | 624 if (element.isMixinApplication && !onlyForRti) { |
657 assert(!backend.isNative(element)); | 625 assert(!backend.isNative(element)); |
658 assert(methods.isEmpty); | 626 assert(methods.isEmpty); |
659 | 627 |
660 result = new MixinApplication(element, | 628 result = new MixinApplication( |
661 name, holder, | 629 element, |
662 instanceFields, | 630 name, |
663 staticFieldsForReflection, | 631 holder, |
664 callStubs, | 632 instanceFields, |
665 typeVariableReaderStubs, | 633 staticFieldsForReflection, |
666 checkedSetters, | 634 callStubs, |
667 isChecks, | 635 typeVariableReaderStubs, |
668 typeTests.functionTypeIndex, | 636 checkedSetters, |
669 isDirectlyInstantiated: isInstantiated, | 637 isChecks, |
670 onlyForRti: onlyForRti); | 638 typeTests.functionTypeIndex, |
| 639 isDirectlyInstantiated: isInstantiated, |
| 640 onlyForRti: onlyForRti); |
671 } else { | 641 } else { |
672 result = new Class(element, | 642 result = new Class( |
673 name, holder, methods, instanceFields, | 643 element, |
674 staticFieldsForReflection, | 644 name, |
675 callStubs, | 645 holder, |
676 typeVariableReaderStubs, | 646 methods, |
677 noSuchMethodStubs, | 647 instanceFields, |
678 checkedSetters, | 648 staticFieldsForReflection, |
679 isChecks, | 649 callStubs, |
680 typeTests.functionTypeIndex, | 650 typeVariableReaderStubs, |
681 isDirectlyInstantiated: isInstantiated, | 651 noSuchMethodStubs, |
682 onlyForRti: onlyForRti, | 652 checkedSetters, |
683 isNative: backend.isNative(element)); | 653 isChecks, |
| 654 typeTests.functionTypeIndex, |
| 655 isDirectlyInstantiated: isInstantiated, |
| 656 onlyForRti: onlyForRti, |
| 657 isNative: backend.isNative(element)); |
684 } | 658 } |
685 _classes[element] = result; | 659 _classes[element] = result; |
686 return result; | 660 return result; |
687 } | 661 } |
688 | 662 |
689 bool _methodNeedsStubs(FunctionElement method) { | 663 bool _methodNeedsStubs(FunctionElement method) { |
690 return !method.functionSignature.optionalParameters.isEmpty; | 664 return !method.functionSignature.optionalParameters.isEmpty; |
691 } | 665 } |
692 | 666 |
693 bool _methodCanBeReflected(FunctionElement method) { | 667 bool _methodCanBeReflected(FunctionElement method) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 canTearOff = false; | 729 canTearOff = false; |
756 } else { | 730 } else { |
757 if (element.enclosingClass.isClosure) { | 731 if (element.enclosingClass.isClosure) { |
758 canTearOff = false; | 732 canTearOff = false; |
759 isClosureCallMethod = true; | 733 isClosureCallMethod = true; |
760 } else { | 734 } else { |
761 // Careful with operators. | 735 // Careful with operators. |
762 canTearOff = universe.hasInvokedGetter(element, _compiler.world) || | 736 canTearOff = universe.hasInvokedGetter(element, _compiler.world) || |
763 (canBeReflected && !element.isOperator); | 737 (canBeReflected && !element.isOperator); |
764 assert(canTearOff || | 738 assert(canTearOff || |
765 !universe.methodsNeedingSuperGetter.contains(element)); | 739 !universe.methodsNeedingSuperGetter.contains(element)); |
766 tearOffName = namer.getterForElement(element); | 740 tearOffName = namer.getterForElement(element); |
767 } | 741 } |
768 } | 742 } |
769 | 743 |
770 if (canTearOff) { | 744 if (canTearOff) { |
771 assert(invariant(element, !element.isGenerativeConstructor)); | 745 assert(invariant(element, !element.isGenerativeConstructor)); |
772 assert(invariant(element, !element.isGenerativeConstructorBody)); | 746 assert(invariant(element, !element.isGenerativeConstructorBody)); |
773 assert(invariant(element, !element.isConstructor)); | 747 assert(invariant(element, !element.isConstructor)); |
774 } | 748 } |
775 | 749 |
(...skipping 26 matching lines...) Expand all Loading... |
802 var /* List | Map */ optionalParameterDefaultValues; | 776 var /* List | Map */ optionalParameterDefaultValues; |
803 if (canBeApplied || canBeReflected) { | 777 if (canBeApplied || canBeReflected) { |
804 FunctionSignature signature = element.functionSignature; | 778 FunctionSignature signature = element.functionSignature; |
805 requiredParameterCount = signature.requiredParameterCount; | 779 requiredParameterCount = signature.requiredParameterCount; |
806 optionalParameterDefaultValues = | 780 optionalParameterDefaultValues = |
807 _computeParameterDefaultValues(signature); | 781 _computeParameterDefaultValues(signature); |
808 } | 782 } |
809 | 783 |
810 return new InstanceMethod(element, name, code, | 784 return new InstanceMethod(element, name, code, |
811 _generateParameterStubs(element, canTearOff), callName, | 785 _generateParameterStubs(element, canTearOff), callName, |
812 needsTearOff: canTearOff, tearOffName: tearOffName, | 786 needsTearOff: canTearOff, |
813 isClosureCallMethod: isClosureCallMethod, aliasName: aliasName, | 787 tearOffName: tearOffName, |
814 canBeApplied: canBeApplied, canBeReflected: canBeReflected, | 788 isClosureCallMethod: isClosureCallMethod, |
| 789 aliasName: aliasName, |
| 790 canBeApplied: canBeApplied, |
| 791 canBeReflected: canBeReflected, |
815 requiredParameterCount: requiredParameterCount, | 792 requiredParameterCount: requiredParameterCount, |
816 optionalParameterDefaultValues: optionalParameterDefaultValues, | 793 optionalParameterDefaultValues: optionalParameterDefaultValues, |
817 functionType: functionType); | 794 functionType: functionType); |
818 } | 795 } |
819 | 796 |
820 js.Expression _generateFunctionType(DartType type, OutputUnit outputUnit) { | 797 js.Expression _generateFunctionType(DartType type, OutputUnit outputUnit) { |
821 if (type.containsTypeVariables) { | 798 if (type.containsTypeVariables) { |
822 js.Expression thisAccess = js.js(r'this.$receiver'); | 799 js.Expression thisAccess = js.js(r'this.$receiver'); |
823 return backend.rtiEncoder.getSignatureEncoding(type, thisAccess); | 800 return backend.rtiEncoder.getSignatureEncoding(type, thisAccess); |
824 } else { | 801 } else { |
825 return backend.emitter.metadataCollector | 802 return backend.emitter.metadataCollector |
826 .reifyTypeForOutputUnit(type, outputUnit); | 803 .reifyTypeForOutputUnit(type, outputUnit); |
827 } | 804 } |
828 } | 805 } |
829 | 806 |
830 List<ParameterStubMethod> _generateParameterStubs(MethodElement element, | 807 List<ParameterStubMethod> _generateParameterStubs( |
831 bool canTearOff) { | 808 MethodElement element, bool canTearOff) { |
832 | |
833 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; | 809 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; |
834 | 810 |
835 ParameterStubGenerator generator = | 811 ParameterStubGenerator generator = |
836 new ParameterStubGenerator(_compiler, namer, backend); | 812 new ParameterStubGenerator(_compiler, namer, backend); |
837 return generator.generateParameterStubs(element, canTearOff: canTearOff); | 813 return generator.generateParameterStubs(element, canTearOff: canTearOff); |
838 } | 814 } |
839 | 815 |
840 /// Builds a stub method. | 816 /// Builds a stub method. |
841 /// | 817 /// |
842 /// Stub methods may have an element that can be used for code-size | 818 /// Stub methods may have an element that can be used for code-size |
843 /// attribution. | 819 /// attribution. |
844 Method _buildStubMethod(js.Name name, js.Expression code, | 820 Method _buildStubMethod(js.Name name, js.Expression code, {Element element}) { |
845 {Element element}) { | |
846 return new StubMethod(name, code, element: element); | 821 return new StubMethod(name, code, element: element); |
847 } | 822 } |
848 | 823 |
849 // The getInterceptor methods directly access the prototype of classes. | 824 // The getInterceptor methods directly access the prototype of classes. |
850 // We must evaluate these classes eagerly so that the prototype is | 825 // We must evaluate these classes eagerly so that the prototype is |
851 // accessible. | 826 // accessible. |
852 void _markEagerInterceptorClasses() { | 827 void _markEagerInterceptorClasses() { |
853 Map<js.Name, Set<ClassElement>> specializedGetInterceptors = | 828 Map<js.Name, Set<ClassElement>> specializedGetInterceptors = |
854 backend.specializedGetInterceptors; | 829 backend.specializedGetInterceptors; |
855 for (Set<ClassElement> classes in specializedGetInterceptors.values) { | 830 for (Set<ClassElement> classes in specializedGetInterceptors.values) { |
(...skipping 18 matching lines...) Expand all Loading... |
874 List<js.Name> names = specializedGetInterceptors.keys.toList()..sort(); | 849 List<js.Name> names = specializedGetInterceptors.keys.toList()..sort(); |
875 return names.map((js.Name name) { | 850 return names.map((js.Name name) { |
876 Set<ClassElement> classes = specializedGetInterceptors[name]; | 851 Set<ClassElement> classes = specializedGetInterceptors[name]; |
877 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); | 852 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); |
878 return new StaticStubMethod(name, holder, code); | 853 return new StaticStubMethod(name, holder, code); |
879 }); | 854 }); |
880 } | 855 } |
881 | 856 |
882 List<Field> _buildFields(Element holder, bool visitStatics) { | 857 List<Field> _buildFields(Element holder, bool visitStatics) { |
883 List<Field> fields = <Field>[]; | 858 List<Field> fields = <Field>[]; |
884 new FieldVisitor(_compiler, namer).visitFields( | 859 new FieldVisitor(_compiler, namer).visitFields(holder, visitStatics, |
885 holder, visitStatics, (VariableElement field, | 860 (VariableElement field, js.Name name, js.Name accessorName, |
886 js.Name name, | 861 bool needsGetter, bool needsSetter, bool needsCheckedSetter) { |
887 js.Name accessorName, | |
888 bool needsGetter, | |
889 bool needsSetter, | |
890 bool needsCheckedSetter) { | |
891 assert(invariant(field, field.isDeclaration)); | 862 assert(invariant(field, field.isDeclaration)); |
892 | 863 |
893 int getterFlags = 0; | 864 int getterFlags = 0; |
894 if (needsGetter) { | 865 if (needsGetter) { |
895 if (visitStatics || !backend.fieldHasInterceptedGetter(field)) { | 866 if (visitStatics || !backend.fieldHasInterceptedGetter(field)) { |
896 getterFlags = 1; | 867 getterFlags = 1; |
897 } else { | 868 } else { |
898 getterFlags += 2; | 869 getterFlags += 2; |
899 // TODO(sra): 'isInterceptorClass' might not be the correct test | 870 // TODO(sra): 'isInterceptorClass' might not be the correct test |
900 // for methods forced to use the interceptor convention because | 871 // for methods forced to use the interceptor convention because |
901 // the method's class was elsewhere mixed-in to an interceptor. | 872 // the method's class was elsewhere mixed-in to an interceptor. |
902 if (!backend.isInterceptorClass(holder)) { | 873 if (!backend.isInterceptorClass(holder)) { |
903 getterFlags += 1; | 874 getterFlags += 1; |
904 } | 875 } |
905 } | 876 } |
906 } | 877 } |
907 | 878 |
908 int setterFlags = 0; | 879 int setterFlags = 0; |
909 if (needsSetter) { | 880 if (needsSetter) { |
910 if (visitStatics || !backend.fieldHasInterceptedSetter(field)) { | 881 if (visitStatics || !backend.fieldHasInterceptedSetter(field)) { |
911 setterFlags = 1; | 882 setterFlags = 1; |
912 } else { | 883 } else { |
913 setterFlags += 2; | 884 setterFlags += 2; |
914 if (!backend.isInterceptorClass(holder)) { | 885 if (!backend.isInterceptorClass(holder)) { |
915 setterFlags += 1; | 886 setterFlags += 1; |
916 } | 887 } |
917 } | 888 } |
918 } | 889 } |
919 | 890 |
920 fields.add(new Field(field, name, accessorName, | 891 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags, |
921 getterFlags, setterFlags, | 892 needsCheckedSetter)); |
922 needsCheckedSetter)); | |
923 }); | 893 }); |
924 | 894 |
925 return fields; | 895 return fields; |
926 } | 896 } |
927 | 897 |
928 Iterable<StaticStubMethod> _generateOneShotInterceptors() { | 898 Iterable<StaticStubMethod> _generateOneShotInterceptors() { |
929 InterceptorStubGenerator stubGenerator = | 899 InterceptorStubGenerator stubGenerator = |
930 new InterceptorStubGenerator(_compiler, namer, backend); | 900 new InterceptorStubGenerator(_compiler, namer, backend); |
931 | 901 |
932 String holderName = namer.globalObjectFor(helpers.interceptorsLibrary); | 902 String holderName = namer.globalObjectFor(helpers.interceptorsLibrary); |
(...skipping 17 matching lines...) Expand all Loading... |
950 bool canBeApplied = _methodCanBeApplied(element); | 920 bool canBeApplied = _methodCanBeApplied(element); |
951 bool canBeReflected = _methodCanBeReflected(element); | 921 bool canBeReflected = _methodCanBeReflected(element); |
952 | 922 |
953 bool needsTearOff = isApplyTarget && | 923 bool needsTearOff = isApplyTarget && |
954 (canBeReflected || | 924 (canBeReflected || |
955 universe.staticFunctionsNeedingGetter.contains(element)); | 925 universe.staticFunctionsNeedingGetter.contains(element)); |
956 | 926 |
957 js.Name tearOffName = | 927 js.Name tearOffName = |
958 needsTearOff ? namer.staticClosureName(element) : null; | 928 needsTearOff ? namer.staticClosureName(element) : null; |
959 | 929 |
960 | |
961 js.Name callName = null; | 930 js.Name callName = null; |
962 if (needsTearOff) { | 931 if (needsTearOff) { |
963 Selector callSelector = | 932 Selector callSelector = |
964 new Selector.fromElement(element).toCallSelector(); | 933 new Selector.fromElement(element).toCallSelector(); |
965 callName = namer.invocationName(callSelector); | 934 callName = namer.invocationName(callSelector); |
966 } | 935 } |
967 js.Expression functionType; | 936 js.Expression functionType; |
968 DartType type = element.type; | 937 DartType type = element.type; |
969 if (needsTearOff || canBeReflected) { | 938 if (needsTearOff || canBeReflected) { |
970 OutputUnit outputUnit = | 939 OutputUnit outputUnit = |
971 _compiler.deferredLoadTask.outputUnitForElement(element); | 940 _compiler.deferredLoadTask.outputUnitForElement(element); |
972 functionType = _generateFunctionType(type, outputUnit); | 941 functionType = _generateFunctionType(type, outputUnit); |
973 } | 942 } |
974 | 943 |
975 int requiredParameterCount; | 944 int requiredParameterCount; |
976 var /* List | Map */ optionalParameterDefaultValues; | 945 var /* List | Map */ optionalParameterDefaultValues; |
977 if (canBeApplied || canBeReflected) { | 946 if (canBeApplied || canBeReflected) { |
978 FunctionSignature signature = element.functionSignature; | 947 FunctionSignature signature = element.functionSignature; |
979 requiredParameterCount = signature.requiredParameterCount; | 948 requiredParameterCount = signature.requiredParameterCount; |
980 optionalParameterDefaultValues = | 949 optionalParameterDefaultValues = |
981 _computeParameterDefaultValues(signature); | 950 _computeParameterDefaultValues(signature); |
982 } | 951 } |
983 | 952 |
984 // TODO(floitsch): we shouldn't update the registry in the middle of | 953 // TODO(floitsch): we shouldn't update the registry in the middle of |
985 // building a static method. | 954 // building a static method. |
986 return new StaticDartMethod(element, | 955 return new StaticDartMethod(element, name, _registry.registerHolder(holder), |
987 name, _registry.registerHolder(holder), code, | 956 code, _generateParameterStubs(element, needsTearOff), callName, |
988 _generateParameterStubs(element, needsTearOff), | 957 needsTearOff: needsTearOff, |
989 callName, | 958 tearOffName: tearOffName, |
990 needsTearOff: needsTearOff, | 959 canBeApplied: canBeApplied, |
991 tearOffName: tearOffName, | 960 canBeReflected: canBeReflected, |
992 canBeApplied: canBeApplied, | 961 requiredParameterCount: requiredParameterCount, |
993 canBeReflected: canBeReflected, | 962 optionalParameterDefaultValues: optionalParameterDefaultValues, |
994 requiredParameterCount: requiredParameterCount, | 963 functionType: functionType); |
995 optionalParameterDefaultValues: | |
996 optionalParameterDefaultValues, | |
997 functionType: functionType); | |
998 } | 964 } |
999 | 965 |
1000 void _registerConstants(OutputUnit outputUnit, | 966 void _registerConstants( |
1001 Iterable<ConstantValue> constantValues) { | 967 OutputUnit outputUnit, Iterable<ConstantValue> constantValues) { |
1002 // `constantValues` is null if an outputUnit doesn't contain any constants. | 968 // `constantValues` is null if an outputUnit doesn't contain any constants. |
1003 if (constantValues == null) return; | 969 if (constantValues == null) return; |
1004 for (ConstantValue constantValue in constantValues) { | 970 for (ConstantValue constantValue in constantValues) { |
1005 _registry.registerConstant(outputUnit, constantValue); | 971 _registry.registerConstant(outputUnit, constantValue); |
1006 assert(!_constants.containsKey(constantValue)); | 972 assert(!_constants.containsKey(constantValue)); |
1007 js.Name name = namer.constantName(constantValue); | 973 js.Name name = namer.constantName(constantValue); |
1008 String constantObject = namer.globalObjectForConstant(constantValue); | 974 String constantObject = namer.globalObjectForConstant(constantValue); |
1009 Holder holder = | 975 Holder holder = |
1010 _registry.registerHolder(constantObject, isConstantsHolder: true); | 976 _registry.registerHolder(constantObject, isConstantsHolder: true); |
1011 Constant constant = new Constant(name, holder, constantValue); | 977 Constant constant = new Constant(name, holder, constantValue); |
1012 _constants[constantValue] = constant; | 978 _constants[constantValue] = constant; |
1013 } | 979 } |
1014 } | 980 } |
1015 | 981 |
1016 Holder _registerStaticStateHolder() { | 982 Holder _registerStaticStateHolder() { |
1017 return _registry.registerHolder( | 983 return _registry.registerHolder(namer.staticStateHolder, |
1018 namer.staticStateHolder, isStaticStateHolder: true); | 984 isStaticStateHolder: true); |
1019 } | 985 } |
1020 } | 986 } |
OLD | NEW |