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

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

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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) 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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698