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

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

Issue 2810183002: Less direct use of JavaScriptBackend in ProgramBuilder (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 '../../closure.dart' show ClosureFieldElement; 7 import '../../closure.dart' show ClosureFieldElement;
8 import '../../common.dart'; 8 import '../../common.dart';
9 import '../../common/names.dart' show Names, Selectors; 9 import '../../common/names.dart' show Names, Selectors;
10 import '../../compiler.dart' show Compiler; 10 import '../../compiler.dart' show Compiler;
(...skipping 12 matching lines...) Expand all
23 FunctionElement, 23 FunctionElement,
24 FunctionSignature, 24 FunctionSignature,
25 GetterElement, 25 GetterElement,
26 LibraryElement, 26 LibraryElement,
27 MemberElement, 27 MemberElement,
28 MethodElement, 28 MethodElement,
29 ParameterElement, 29 ParameterElement,
30 TypedefElement, 30 TypedefElement,
31 VariableElement; 31 VariableElement;
32 import '../../elements/entities.dart'; 32 import '../../elements/entities.dart';
33 import '../../elements/resolution_types.dart' show Types;
33 import '../../elements/types.dart' show DartType; 34 import '../../elements/types.dart' show DartType;
34 import '../../js/js.dart' as js; 35 import '../../js/js.dart' as js;
35 import '../../js_backend/js_backend.dart' 36 import '../../js_backend/backend.dart'
36 show Namer, JavaScriptBackend, JavaScriptConstantCompiler, StringBackedName; 37 show
38 JavaScriptBackend,
39 RuntimeTypesEncoder,
40 RuntimeTypesNeed,
41 SuperMemberData;
42 import '../../js_backend/backend_usage.dart';
43 import '../../js_backend/constant_handler_javascript.dart'
44 show JavaScriptConstantCompiler;
45 import '../../js_backend/namer.dart' show Namer, StringBackedName;
46 import '../../js_backend/native_data.dart';
47 import '../../js_backend/interceptor_data.dart';
48 import '../../js_backend/mirrors_data.dart';
49 import '../../native/enqueue.dart' show NativeCodegenEnqueuer;
50 import '../../options.dart';
37 import '../../universe/selector.dart' show Selector; 51 import '../../universe/selector.dart' show Selector;
38 import '../../universe/world_builder.dart' 52 import '../../universe/world_builder.dart'
39 show CodegenWorldBuilder, SelectorConstraints; 53 show CodegenWorldBuilder, SelectorConstraints;
40 import '../../world.dart' show ClosedWorld; 54 import '../../world.dart' show ClosedWorld;
41 import '../js_emitter.dart' 55 import '../js_emitter.dart'
42 show 56 show
43 ClassStubGenerator, 57 ClassStubGenerator,
44 CodeEmitterTask, 58 CodeEmitterTask,
45 computeMixinClass, 59 computeMixinClass,
46 Emitter, 60 Emitter,
(...skipping 30 matching lines...) Expand all
77 91
78 ProgramBuilder(Compiler compiler, Namer namer, this._task, Emitter emitter, 92 ProgramBuilder(Compiler compiler, Namer namer, this._task, Emitter emitter,
79 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses) 93 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses)
80 : this._compiler = compiler, 94 : this._compiler = compiler,
81 this.namer = namer, 95 this.namer = namer,
82 this.closedWorld = closedWorld, 96 this.closedWorld = closedWorld,
83 this.collector = new Collector( 97 this.collector = new Collector(
84 compiler, namer, closedWorld, rtiNeededClasses, emitter), 98 compiler, namer, closedWorld, rtiNeededClasses, emitter),
85 this._registry = new Registry(compiler); 99 this._registry = new Registry(compiler);
86 100
87 JavaScriptBackend get backend => _compiler.backend; 101 JavaScriptBackend get _backend => _compiler.backend;
88 CodegenWorldBuilder get worldBuilder => _compiler.codegenWorldBuilder; 102 CodegenWorldBuilder get _worldBuilder => _compiler.codegenWorldBuilder;
103 DeferredLoadTask get _deferredLoadTask => _compiler.deferredLoadTask;
104 Types get _types => _compiler.types;
105 CommonElements get _commonElements => _compiler.commonElements;
106 CompilerOptions get _options => _compiler.options;
107 NativeCodegenEnqueuer get _nativeCodegenEnqueuer =>
108 _backend.nativeCodegenEnqueuer;
109 Namer get _namer => _backend.namer;
110 BackendUsage get _backendUsage => _backend.backendUsage;
111 CodeEmitterTask get _emitter => _backend.emitter;
112 JavaScriptConstantCompiler get _constantHandler => _backend.constants;
113 NativeData get _nativeData => _backend.nativeData;
114 RuntimeTypesNeed get _rtiNeed => _backend.rtiNeed;
115 MirrorsData get _mirrorsData => _backend.mirrorsData;
116 InterceptorData get _interceptorData => _backend.interceptorData;
117 SuperMemberData get _superMemberData => _backend.superMemberData;
118 RuntimeTypesEncoder get _rtiEncoder => _backend.rtiEncoder;
119 OneShotInterceptorData get _oneShotInterceptorData =>
120 _backend.oneShotInterceptorData;
89 121
90 /// Mapping from [ClassElement] to constructed [Class]. We need this to 122 /// Mapping from [ClassElement] to constructed [Class]. We need this to
91 /// update the superclass in the [Class]. 123 /// update the superclass in the [Class].
92 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; 124 final Map<ClassElement, Class> _classes = <ClassElement, Class>{};
93 125
94 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to 126 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to
95 /// generate the deferredLoadingMap (to know which hunks to load). 127 /// generate the deferredLoadingMap (to know which hunks to load).
96 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; 128 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{};
97 129
98 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to 130 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to
99 /// update field-initializers to point to the ConstantModel. 131 /// update field-initializers to point to the ConstantModel.
100 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{}; 132 final Map<ConstantValue, Constant> _constants = <ConstantValue, Constant>{};
101 133
102 /// Mapping from names to strings. 134 /// Mapping from names to strings.
103 /// 135 ///
104 /// This mapping is used to support `const Symbol` expressions. 136 /// This mapping is used to support `const Symbol` expressions.
105 /// 137 ///
106 /// This map is filled when building classes. 138 /// This map is filled when building classes.
107 final Map<js.Name, String> _symbolsMap = <js.Name, String>{}; 139 final Map<js.Name, String> _symbolsMap = <js.Name, String>{};
108 140
109 Set<Class> _unneededNativeClasses; 141 Set<Class> _unneededNativeClasses;
110 142
111 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { 143 Program buildProgram({bool storeFunctionTypesInMetadata: false}) {
112 collector.collect(); 144 collector.collect();
113 145
114 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; 146 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata;
115 // Note: In rare cases (mostly tests) output units can be empty. This 147 // Note: In rare cases (mostly tests) output units can be empty. This
116 // happens when the deferred code is dead-code eliminated but we still need 148 // happens when the deferred code is dead-code eliminated but we still need
117 // to check that the library has been loaded. 149 // to check that the library has been loaded.
118 _compiler.deferredLoadTask.allOutputUnits 150 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit);
119 .forEach(_registry.registerOutputUnit);
120 collector.outputClassLists.forEach(_registry.registerElements); 151 collector.outputClassLists.forEach(_registry.registerElements);
121 collector.outputStaticLists.forEach(_registry.registerElements); 152 collector.outputStaticLists.forEach(_registry.registerElements);
122 collector.outputConstantLists.forEach(_registerConstants); 153 collector.outputConstantLists.forEach(_registerConstants);
123 collector.outputStaticNonFinalFieldLists 154 collector.outputStaticNonFinalFieldLists
124 .forEach(_registry.registerElements); 155 .forEach(_registry.registerElements);
125 156
126 // We always add the current isolate holder. 157 // We always add the current isolate holder.
127 _registerStaticStateHolder(); 158 _registerStaticStateHolder();
128 159
129 // We need to run the native-preparation before we build the output. The 160 // We need to run the native-preparation before we build the output. The
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 199
169 List<Fragment> fragments = new List<Fragment>(_registry.librariesMapCount); 200 List<Fragment> fragments = new List<Fragment>(_registry.librariesMapCount);
170 fragments[0] = mainFragment; 201 fragments[0] = mainFragment;
171 fragments.setAll(1, deferredFragments); 202 fragments.setAll(1, deferredFragments);
172 203
173 _markEagerClasses(); 204 _markEagerClasses();
174 205
175 List<Holder> holders = _registry.holders.toList(growable: false); 206 List<Holder> holders = _registry.holders.toList(growable: false);
176 207
177 bool needsNativeSupport = 208 bool needsNativeSupport =
178 backend.nativeCodegenEnqueuer.hasInstantiatedNativeClasses; 209 _nativeCodegenEnqueuer.hasInstantiatedNativeClasses;
179 210
180 assert(!needsNativeSupport || nativeClasses.isNotEmpty); 211 assert(!needsNativeSupport || nativeClasses.isNotEmpty);
181 212
182 List<js.TokenFinalizer> finalizers = [_task.metadataCollector]; 213 List<js.TokenFinalizer> finalizers = [_task.metadataCollector];
183 if (backend.namer is js.TokenFinalizer) { 214 if (_namer is js.TokenFinalizer) {
184 var namingFinalizer = backend.namer; 215 var namingFinalizer = _namer;
185 finalizers.add(namingFinalizer as js.TokenFinalizer); 216 finalizers.add(namingFinalizer as js.TokenFinalizer);
186 } 217 }
187 218
188 return new Program(fragments, holders, _buildLoadMap(), _symbolsMap, 219 return new Program(fragments, holders, _buildLoadMap(), _symbolsMap,
189 _buildTypeToInterceptorMap(), _task.metadataCollector, finalizers, 220 _buildTypeToInterceptorMap(), _task.metadataCollector, finalizers,
190 needsNativeSupport: needsNativeSupport, 221 needsNativeSupport: needsNativeSupport,
191 outputContainsConstantList: collector.outputContainsConstantList, 222 outputContainsConstantList: collector.outputContainsConstantList,
192 hasIsolateSupport: backend.backendUsage.isIsolateInUse); 223 hasIsolateSupport: _backendUsage.isIsolateInUse);
193 } 224 }
194 225
195 void _markEagerClasses() { 226 void _markEagerClasses() {
196 _markEagerInterceptorClasses(); 227 _markEagerInterceptorClasses();
197 } 228 }
198 229
199 /// Builds a map from loadId to outputs-to-load. 230 /// Builds a map from loadId to outputs-to-load.
200 Map<String, List<Fragment>> _buildLoadMap() { 231 Map<String, List<Fragment>> _buildLoadMap() {
201 Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{}; 232 Map<String, List<Fragment>> loadMap = <String, List<Fragment>>{};
202 _compiler.deferredLoadTask.hunksToLoad 233 _deferredLoadTask.hunksToLoad
203 .forEach((String loadId, List<OutputUnit> outputUnits) { 234 .forEach((String loadId, List<OutputUnit> outputUnits) {
204 loadMap[loadId] = outputUnits 235 loadMap[loadId] = outputUnits
205 .map((OutputUnit unit) => _outputs[unit]) 236 .map((OutputUnit unit) => _outputs[unit])
206 .toList(growable: false); 237 .toList(growable: false);
207 }); 238 });
208 return loadMap; 239 return loadMap;
209 } 240 }
210 241
211 js.Expression _buildTypeToInterceptorMap() { 242 js.Expression _buildTypeToInterceptorMap() {
212 InterceptorStubGenerator stubGenerator = 243 InterceptorStubGenerator stubGenerator =
213 new InterceptorStubGenerator(_compiler, namer, backend, closedWorld); 244 new InterceptorStubGenerator(_compiler, namer, _backend, closedWorld);
214 return stubGenerator.generateTypeToInterceptorMap(); 245 return stubGenerator.generateTypeToInterceptorMap();
215 } 246 }
216 247
217 MainFragment _buildMainFragment(LibrariesMap librariesMap) { 248 MainFragment _buildMainFragment(LibrariesMap librariesMap) {
218 // Construct the main output from the libraries and the registered holders. 249 // Construct the main output from the libraries and the registered holders.
219 MainFragment result = new MainFragment( 250 MainFragment result = new MainFragment(
220 librariesMap.outputUnit, 251 librariesMap.outputUnit,
221 "", // The empty string is the name for the main output file. 252 "", // The empty string is the name for the main output file.
222 _buildInvokeMain(), 253 _buildInvokeMain(),
223 _buildLibraries(librariesMap), 254 _buildLibraries(librariesMap),
224 _buildStaticNonFinalFields(librariesMap), 255 _buildStaticNonFinalFields(librariesMap),
225 _buildStaticLazilyInitializedFields(librariesMap), 256 _buildStaticLazilyInitializedFields(librariesMap),
226 _buildConstants(librariesMap)); 257 _buildConstants(librariesMap));
227 _outputs[librariesMap.outputUnit] = result; 258 _outputs[librariesMap.outputUnit] = result;
228 return result; 259 return result;
229 } 260 }
230 261
231 js.Statement _buildInvokeMain() { 262 js.Statement _buildInvokeMain() {
232 if (_compiler.isMockCompilation) return js.js.comment("Mock compilation"); 263 if (_compiler.isMockCompilation) return js.js.comment("Mock compilation");
233 264
234 MainCallStubGenerator generator = 265 MainCallStubGenerator generator =
235 new MainCallStubGenerator(backend, backend.emitter); 266 new MainCallStubGenerator(_backend, _emitter);
236 return generator.generateInvokeMain(_compiler.mainFunction); 267 return generator.generateInvokeMain(_compiler.mainFunction);
237 } 268 }
238 269
239 DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) { 270 DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) {
240 DeferredFragment result = new DeferredFragment( 271 DeferredFragment result = new DeferredFragment(
241 librariesMap.outputUnit, 272 librariesMap.outputUnit,
242 backend.deferredPartFileName(librariesMap.name, addExtension: false), 273 _backend.deferredPartFileName(librariesMap.name, addExtension: false),
243 librariesMap.name, 274 librariesMap.name,
244 _buildLibraries(librariesMap), 275 _buildLibraries(librariesMap),
245 _buildStaticNonFinalFields(librariesMap), 276 _buildStaticNonFinalFields(librariesMap),
246 _buildStaticLazilyInitializedFields(librariesMap), 277 _buildStaticLazilyInitializedFields(librariesMap),
247 _buildConstants(librariesMap)); 278 _buildConstants(librariesMap));
248 _outputs[librariesMap.outputUnit] = result; 279 _outputs[librariesMap.outputUnit] = result;
249 return result; 280 return result;
250 } 281 }
251 282
252 List<Constant> _buildConstants(LibrariesMap librariesMap) { 283 List<Constant> _buildConstants(LibrariesMap librariesMap) {
253 List<ConstantValue> constantValues = 284 List<ConstantValue> constantValues =
254 collector.outputConstantLists[librariesMap.outputUnit]; 285 collector.outputConstantLists[librariesMap.outputUnit];
255 if (constantValues == null) return const <Constant>[]; 286 if (constantValues == null) return const <Constant>[];
256 return constantValues 287 return constantValues
257 .map((ConstantValue value) => _constants[value]) 288 .map((ConstantValue value) => _constants[value])
258 .toList(growable: false); 289 .toList(growable: false);
259 } 290 }
260 291
261 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) { 292 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) {
262 List<VariableElement> staticNonFinalFields = 293 List<VariableElement> staticNonFinalFields =
263 collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit]; 294 collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit];
264 if (staticNonFinalFields == null) return const <StaticField>[]; 295 if (staticNonFinalFields == null) return const <StaticField>[];
265 296
266 return staticNonFinalFields.map(_buildStaticField).toList(growable: false); 297 return staticNonFinalFields.map(_buildStaticField).toList(growable: false);
267 } 298 }
268 299
269 StaticField _buildStaticField(FieldElement element) { 300 StaticField _buildStaticField(FieldElement element) {
270 JavaScriptConstantCompiler handler = backend.constants; 301 ConstantValue initialValue =
271 ConstantValue initialValue = handler.getConstantValue(element.constant); 302 _constantHandler.getConstantValue(element.constant);
272 // TODO(zarah): The holder should not be registered during building of 303 // TODO(zarah): The holder should not be registered during building of
273 // a static field. 304 // a static field.
274 _registry.registerHolder(namer.globalObjectForConstant(initialValue), 305 _registry.registerHolder(namer.globalObjectForConstant(initialValue),
275 isConstantsHolder: true); 306 isConstantsHolder: true);
276 js.Expression code = _task.emitter.constantReference(initialValue); 307 js.Expression code = _task.emitter.constantReference(initialValue);
277 js.Name name = namer.globalPropertyName(element); 308 js.Name name = namer.globalPropertyName(element);
278 bool isFinal = false; 309 bool isFinal = false;
279 bool isLazy = false; 310 bool isLazy = false;
280 311
281 // TODO(floitsch): we shouldn't update the registry in the middle of 312 // TODO(floitsch): we shouldn't update the registry in the middle of
282 // building a static field. (Note that the static-state holder was 313 // building a static field. (Note that the static-state holder was
283 // already registered earlier, and that we just call the register to get 314 // already registered earlier, and that we just call the register to get
284 // the holder-instance. 315 // the holder-instance.
285 return new StaticField( 316 return new StaticField(
286 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); 317 element, name, _registerStaticStateHolder(), code, isFinal, isLazy);
287 } 318 }
288 319
289 List<StaticField> _buildStaticLazilyInitializedFields( 320 List<StaticField> _buildStaticLazilyInitializedFields(
290 LibrariesMap librariesMap) { 321 LibrariesMap librariesMap) {
291 JavaScriptConstantCompiler handler = backend.constants; 322 Iterable<FieldElement> lazyFields = _constantHandler
292 DeferredLoadTask loadTask = _compiler.deferredLoadTask;
293 Iterable<FieldElement> lazyFields = handler
294 .getLazilyInitializedFieldsForEmission() 323 .getLazilyInitializedFieldsForEmission()
295 .where((element) => 324 .where((element) =>
296 loadTask.outputUnitForElement(element) == librariesMap.outputUnit); 325 _deferredLoadTask.outputUnitForElement(element) ==
326 librariesMap.outputUnit);
297 return Elements 327 return Elements
298 .sortedByPosition(lazyFields) 328 .sortedByPosition(lazyFields)
299 .map(_buildLazyField) 329 .map(_buildLazyField)
300 .where((field) => field != null) // Happens when the field was unused. 330 .where((field) => field != null) // Happens when the field was unused.
301 .toList(growable: false); 331 .toList(growable: false);
302 } 332 }
303 333
304 StaticField _buildLazyField(FieldElement element) { 334 StaticField _buildLazyField(FieldElement element) {
305 js.Expression code = backend.generatedCode[element]; 335 js.Expression code = _backend.generatedCode[element];
306 // The code is null if we ended up not needing the lazily 336 // The code is null if we ended up not needing the lazily
307 // initialized field after all because of constant folding 337 // initialized field after all because of constant folding
308 // before code generation. 338 // before code generation.
309 if (code == null) return null; 339 if (code == null) return null;
310 340
311 js.Name name = namer.globalPropertyName(element); 341 js.Name name = namer.globalPropertyName(element);
312 bool isFinal = element.isFinal; 342 bool isFinal = element.isFinal;
313 bool isLazy = true; 343 bool isLazy = true;
314 // TODO(floitsch): we shouldn't update the registry in the middle of 344 // TODO(floitsch): we shouldn't update the registry in the middle of
315 // building a static field. (Note that the static-state holder was 345 // building a static field. (Note that the static-state holder was
316 // already registered earlier, and that we just call the register to get 346 // already registered earlier, and that we just call the register to get
317 // the holder-instance. 347 // the holder-instance.
318 return new StaticField( 348 return new StaticField(
319 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); 349 element, name, _registerStaticStateHolder(), code, isFinal, isLazy);
320 } 350 }
321 351
322 List<Library> _buildLibraries(LibrariesMap librariesMap) { 352 List<Library> _buildLibraries(LibrariesMap librariesMap) {
323 List<Library> libraries = new List<Library>(librariesMap.length); 353 List<Library> libraries = new List<Library>(librariesMap.length);
324 int count = 0; 354 int count = 0;
325 librariesMap.forEach((LibraryElement library, List<Element> elements) { 355 librariesMap.forEach((LibraryElement library, List<Element> elements) {
326 libraries[count++] = _buildLibrary(library, elements); 356 libraries[count++] = _buildLibrary(library, elements);
327 }); 357 });
328 return libraries; 358 return libraries;
329 } 359 }
330 360
331 void _addJsInteropStubs(LibrariesMap librariesMap) { 361 void _addJsInteropStubs(LibrariesMap librariesMap) {
332 if (_classes.containsKey(_compiler.commonElements.objectClass)) { 362 if (_classes.containsKey(_commonElements.objectClass)) {
333 var toStringInvocation = namer.invocationName(Selectors.toString_); 363 var toStringInvocation = namer.invocationName(Selectors.toString_);
334 // TODO(jacobr): register toString as used so that it is always accessible 364 // TODO(jacobr): register toString as used so that it is always accessible
335 // from JavaScript. 365 // from JavaScript.
336 _classes[_compiler.commonElements.objectClass].callStubs.add( 366 _classes[_commonElements.objectClass].callStubs.add(_buildStubMethod(
337 _buildStubMethod(new StringBackedName("toString"), 367 new StringBackedName("toString"),
338 js.js('function() { return this.#(this) }', toStringInvocation))); 368 js.js('function() { return this.#(this) }', toStringInvocation)));
339 } 369 }
340 370
341 // We add all members from classes marked with isJsInterop to the base 371 // We add all members from classes marked with isJsInterop to the base
342 // Interceptor class with implementations that directly call the 372 // Interceptor class with implementations that directly call the
343 // corresponding JavaScript member. We do not attempt to bind this when 373 // corresponding JavaScript member. We do not attempt to bind this when
344 // tearing off JavaScript methods as we cannot distinguish between calling 374 // tearing off JavaScript methods as we cannot distinguish between calling
345 // a regular getter that returns a JavaScript function and tearing off 375 // a regular getter that returns a JavaScript function and tearing off
346 // a method in the case where there exist multiple JavaScript classes 376 // a method in the case where there exist multiple JavaScript classes
347 // that conflict on whether the member is a getter or a method. 377 // that conflict on whether the member is a getter or a method.
348 var interceptorClass = 378 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass];
349 _classes[_compiler.commonElements.jsJavaScriptObjectClass];
350 var stubNames = new Set<String>(); 379 var stubNames = new Set<String>();
351 librariesMap.forEach((LibraryElement library, List<Element> elements) { 380 librariesMap.forEach((LibraryElement library, List<Element> elements) {
352 for (Element e in elements) { 381 for (Element e in elements) {
353 if (e is ClassElement && backend.nativeData.isJsInteropClass(e)) { 382 if (e is ClassElement && _nativeData.isJsInteropClass(e)) {
354 e.declaration.forEachMember((_, Element member) { 383 e.declaration.forEachMember((_, Element member) {
355 var jsName = 384 var jsName = _nativeData.computeUnescapedJSInteropName(member.name);
356 backend.nativeData.computeUnescapedJSInteropName(member.name);
357 if (!member.isInstanceMember) return; 385 if (!member.isInstanceMember) return;
358 if (member.isGetter || member.isField || member.isFunction) { 386 if (member.isGetter || member.isField || member.isFunction) {
359 var selectors = worldBuilder.getterInvocationsByName(member.name); 387 var selectors =
388 _worldBuilder.getterInvocationsByName(member.name);
360 if (selectors != null && !selectors.isEmpty) { 389 if (selectors != null && !selectors.isEmpty) {
361 for (var selector in selectors.keys) { 390 for (var selector in selectors.keys) {
362 var stubName = namer.invocationName(selector); 391 var stubName = namer.invocationName(selector);
363 if (stubNames.add(stubName.key)) { 392 if (stubNames.add(stubName.key)) {
364 interceptorClass.callStubs.add(_buildStubMethod(stubName, 393 interceptorClass.callStubs.add(_buildStubMethod(stubName,
365 js.js('function(obj) { return obj.# }', [jsName]), 394 js.js('function(obj) { return obj.# }', [jsName]),
366 element: member)); 395 element: member));
367 } 396 }
368 } 397 }
369 } 398 }
370 } 399 }
371 400
372 if (member.isSetter || (member.isField && !member.isConst)) { 401 if (member.isSetter || (member.isField && !member.isConst)) {
373 var selectors = worldBuilder.setterInvocationsByName(member.name); 402 var selectors =
403 _worldBuilder.setterInvocationsByName(member.name);
374 if (selectors != null && !selectors.isEmpty) { 404 if (selectors != null && !selectors.isEmpty) {
375 var stubName = namer.setterForElement(member); 405 var stubName = namer.setterForElement(member);
376 if (stubNames.add(stubName.key)) { 406 if (stubNames.add(stubName.key)) {
377 interceptorClass.callStubs.add(_buildStubMethod(stubName, 407 interceptorClass.callStubs.add(_buildStubMethod(stubName,
378 js.js('function(obj, v) { return obj.# = v }', [jsName]), 408 js.js('function(obj, v) { return obj.# = v }', [jsName]),
379 element: member)); 409 element: member));
380 } 410 }
381 } 411 }
382 } 412 }
383 413
384 // Generating stubs for direct calls and stubs for call-through 414 // Generating stubs for direct calls and stubs for call-through
385 // of getters that happen to be functions. 415 // of getters that happen to be functions.
386 bool isFunctionLike = false; 416 bool isFunctionLike = false;
387 ResolutionFunctionType functionType = null; 417 ResolutionFunctionType functionType = null;
388 418
389 if (member.isFunction) { 419 if (member.isFunction) {
390 FunctionElement fn = member; 420 FunctionElement fn = member;
391 functionType = fn.type; 421 functionType = fn.type;
392 } else if (member.isGetter) { 422 } else if (member.isGetter) {
393 if (_compiler.options.trustTypeAnnotations) { 423 if (_options.trustTypeAnnotations) {
394 GetterElement getter = member; 424 GetterElement getter = member;
395 ResolutionDartType returnType = getter.type.returnType; 425 ResolutionDartType returnType = getter.type.returnType;
396 if (returnType.isFunctionType) { 426 if (returnType.isFunctionType) {
397 functionType = returnType; 427 functionType = returnType;
398 } else if (returnType.treatAsDynamic || 428 } else if (returnType.treatAsDynamic ||
399 _compiler.types.isSubtype( 429 _types.isSubtype(
400 returnType, 430 returnType,
401 // ignore: UNNECESSARY_CAST 431 // ignore: UNNECESSARY_CAST
402 backend.commonElements.functionType as DartType)) { 432 _commonElements.functionType as DartType)) {
403 if (returnType.isTypedef) { 433 if (returnType.isTypedef) {
404 ResolutionTypedefType typedef = returnType; 434 ResolutionTypedefType typedef = returnType;
405 // TODO(jacobr): can we just use typdef.unaliased instead? 435 // TODO(jacobr): can we just use typdef.unaliased instead?
406 functionType = typedef.element.functionSignature.type; 436 functionType = typedef.element.functionSignature.type;
407 } else { 437 } else {
408 // Other misc function type such as commonElements.Function. 438 // Other misc function type such as commonElements.Function.
409 // Allow any number of arguments. 439 // Allow any number of arguments.
410 isFunctionLike = true; 440 isFunctionLike = true;
411 } 441 }
412 } 442 }
413 } else { 443 } else {
414 isFunctionLike = true; 444 isFunctionLike = true;
415 } 445 }
416 } // TODO(jacobr): handle field elements. 446 } // TODO(jacobr): handle field elements.
417 447
418 if (isFunctionLike || functionType != null) { 448 if (isFunctionLike || functionType != null) {
419 int minArgs; 449 int minArgs;
420 int maxArgs; 450 int maxArgs;
421 if (functionType != null) { 451 if (functionType != null) {
422 minArgs = functionType.parameterTypes.length; 452 minArgs = functionType.parameterTypes.length;
423 maxArgs = minArgs + functionType.optionalParameterTypes.length; 453 maxArgs = minArgs + functionType.optionalParameterTypes.length;
424 } else { 454 } else {
425 minArgs = 0; 455 minArgs = 0;
426 maxArgs = 32767; 456 maxArgs = 32767;
427 } 457 }
428 var selectors = worldBuilder.invocationsByName(member.name); 458 var selectors = _worldBuilder.invocationsByName(member.name);
429 // Named arguments are not yet supported. In the future we 459 // Named arguments are not yet supported. In the future we
430 // may want to map named arguments to an object literal containing 460 // may want to map named arguments to an object literal containing
431 // all named arguments. 461 // all named arguments.
432 if (selectors != null && !selectors.isEmpty) { 462 if (selectors != null && !selectors.isEmpty) {
433 for (var selector in selectors.keys) { 463 for (var selector in selectors.keys) {
434 // Check whether the arity matches this member. 464 // Check whether the arity matches this member.
435 var argumentCount = selector.argumentCount; 465 var argumentCount = selector.argumentCount;
436 // JS interop does not support named arguments. 466 // JS interop does not support named arguments.
437 if (selector.namedArgumentCount > 0) continue; 467 if (selector.namedArgumentCount > 0) continue;
438 if (argumentCount < minArgs) continue; 468 if (argumentCount < minArgs) continue;
(...skipping 28 matching lines...) Expand all
467 // Note that a library-element may have multiple [Library]s, if it is split 497 // Note that a library-element may have multiple [Library]s, if it is split
468 // into multiple output units. 498 // into multiple output units.
469 Library _buildLibrary(LibraryElement library, List<Element> elements) { 499 Library _buildLibrary(LibraryElement library, List<Element> elements) {
470 String uri = library.canonicalUri.toString(); 500 String uri = library.canonicalUri.toString();
471 501
472 List<StaticMethod> statics = elements 502 List<StaticMethod> statics = elements
473 .where((e) => e is FunctionElement) 503 .where((e) => e is FunctionElement)
474 .map(_buildStaticMethod) 504 .map(_buildStaticMethod)
475 .toList(); 505 .toList();
476 506
477 if (library == _compiler.commonElements.interceptorsLibrary) { 507 if (library == _commonElements.interceptorsLibrary) {
478 statics.addAll(_generateGetInterceptorMethods()); 508 statics.addAll(_generateGetInterceptorMethods());
479 statics.addAll(_generateOneShotInterceptors()); 509 statics.addAll(_generateOneShotInterceptors());
480 } 510 }
481 511
482 List<Class> classes = elements 512 List<Class> classes = elements
483 .where((e) => e is ClassElement) 513 .where((e) => e is ClassElement)
484 .map((ClassElement classElement) => _classes[classElement]) 514 .map((ClassElement classElement) => _classes[classElement])
485 .where((Class cls) => 515 .where((Class cls) =>
486 !cls.isNative || !_unneededNativeClasses.contains(cls)) 516 !cls.isNative || !_unneededNativeClasses.contains(cls))
487 .toList(growable: false); 517 .toList(growable: false);
488 518
489 bool visitStatics = true; 519 bool visitStatics = true;
490 List<Field> staticFieldsForReflection = 520 List<Field> staticFieldsForReflection =
491 _buildFields(library, visitStatics: visitStatics); 521 _buildFields(library, visitStatics: visitStatics);
492 522
493 return new Library( 523 return new Library(
494 library, uri, statics, classes, staticFieldsForReflection); 524 library, uri, statics, classes, staticFieldsForReflection);
495 } 525 }
496 526
497 Class _buildClass(ClassElement element) { 527 Class _buildClass(ClassElement element) {
498 bool onlyForRti = collector.classesOnlyNeededForRti.contains(element); 528 bool onlyForRti = collector.classesOnlyNeededForRti.contains(element);
499 bool hasRtiField = backend.rtiNeed.classNeedsRtiField(element); 529 bool hasRtiField = _rtiNeed.classNeedsRtiField(element);
500 if (backend.nativeData.isJsInteropClass(element)) { 530 if (_nativeData.isJsInteropClass(element)) {
501 // TODO(jacobr): check whether the class has any active static fields 531 // TODO(jacobr): check whether the class has any active static fields
502 // if it does not we can suppress it completely. 532 // if it does not we can suppress it completely.
503 onlyForRti = true; 533 onlyForRti = true;
504 } 534 }
505 535
506 List<Method> methods = []; 536 List<Method> methods = [];
507 List<StubMethod> callStubs = <StubMethod>[]; 537 List<StubMethod> callStubs = <StubMethod>[];
508 538
509 ClassStubGenerator classStubGenerator = new ClassStubGenerator( 539 ClassStubGenerator classStubGenerator = new ClassStubGenerator(
510 namer, backend, worldBuilder, closedWorld, 540 namer, _backend, _worldBuilder, closedWorld,
511 enableMinification: _compiler.options.enableMinification); 541 enableMinification: _options.enableMinification);
512 RuntimeTypeGenerator runtimeTypeGenerator = 542 RuntimeTypeGenerator runtimeTypeGenerator =
513 new RuntimeTypeGenerator(_compiler, _task, namer); 543 new RuntimeTypeGenerator(_compiler, _task, namer);
514 544
515 void visitMember(ClassElement enclosing, MemberElement member) { 545 void visitMember(ClassElement enclosing, MemberElement member) {
516 assert(invariant(element, member.isDeclaration)); 546 assert(invariant(element, member.isDeclaration));
517 assert(invariant(element, element == enclosing)); 547 assert(invariant(element, element == enclosing));
518 548
519 if (Elements.isNonAbstractInstanceMember(member)) { 549 if (Elements.isNonAbstractInstanceMember(member)) {
520 // TODO(herhut): Remove once _buildMethod can no longer return null. 550 // TODO(herhut): Remove once _buildMethod can no longer return null.
521 Method method = _buildMethod(member); 551 Method method = _buildMethod(member);
522 if (method != null) methods.add(method); 552 if (method != null) methods.add(method);
523 } 553 }
524 if (member.isGetter || member.isField) { 554 if (member.isGetter || member.isField) {
525 Map<Selector, SelectorConstraints> selectors = 555 Map<Selector, SelectorConstraints> selectors =
526 worldBuilder.invocationsByName(member.name); 556 _worldBuilder.invocationsByName(member.name);
527 if (selectors != null && !selectors.isEmpty) { 557 if (selectors != null && !selectors.isEmpty) {
528 Map<js.Name, js.Expression> callStubsForMember = 558 Map<js.Name, js.Expression> callStubsForMember =
529 classStubGenerator.generateCallStubsForGetter(member, selectors); 559 classStubGenerator.generateCallStubsForGetter(member, selectors);
530 callStubsForMember.forEach((js.Name name, js.Expression code) { 560 callStubsForMember.forEach((js.Name name, js.Expression code) {
531 callStubs.add(_buildStubMethod(name, code, element: member)); 561 callStubs.add(_buildStubMethod(name, code, element: member));
532 }); 562 });
533 } 563 }
534 } 564 }
535 } 565 }
536 566
537 List<StubMethod> noSuchMethodStubs = <StubMethod>[]; 567 List<StubMethod> noSuchMethodStubs = <StubMethod>[];
538 568
539 if (backend.backendUsage.isNoSuchMethodUsed && element.isObject) { 569 if (_backendUsage.isNoSuchMethodUsed && element.isObject) {
540 Map<js.Name, Selector> selectors = 570 Map<js.Name, Selector> selectors =
541 classStubGenerator.computeSelectorsForNsmHandlers(); 571 classStubGenerator.computeSelectorsForNsmHandlers();
542 selectors.forEach((js.Name name, Selector selector) { 572 selectors.forEach((js.Name name, Selector selector) {
543 // If the program contains `const Symbol` names we have to retain them. 573 // If the program contains `const Symbol` names we have to retain them.
544 String selectorName = selector.name; 574 String selectorName = selector.name;
545 if (selector.isSetter) selectorName = "$selectorName="; 575 if (selector.isSetter) selectorName = "$selectorName=";
546 if (backend.mirrorsData.symbolsUsed.contains(selectorName)) { 576 if (_mirrorsData.symbolsUsed.contains(selectorName)) {
547 _symbolsMap[name] = selectorName; 577 _symbolsMap[name] = selectorName;
548 } 578 }
549 noSuchMethodStubs.add( 579 noSuchMethodStubs.add(
550 classStubGenerator.generateStubForNoSuchMethod(name, selector)); 580 classStubGenerator.generateStubForNoSuchMethod(name, selector));
551 }); 581 });
552 } 582 }
553 583
554 if (element == _compiler.commonElements.closureClass) { 584 if (element == _commonElements.closureClass) {
555 // We add a special getter here to allow for tearing off a closure from 585 // We add a special getter here to allow for tearing off a closure from
556 // itself. 586 // itself.
557 js.Name name = namer.getterForMember(Names.call); 587 js.Name name = namer.getterForMember(Names.call);
558 js.Fun function = js.js('function() { return this; }'); 588 js.Fun function = js.js('function() { return this; }');
559 callStubs.add(_buildStubMethod(name, function)); 589 callStubs.add(_buildStubMethod(name, function));
560 } 590 }
561 591
562 ClassElement implementation = element.implementation; 592 ClassElement implementation = element.implementation;
563 593
564 // MixinApplications run through the members of their mixin. Here, we are 594 // MixinApplications run through the members of their mixin. Here, we are
565 // only interested in direct members. 595 // only interested in direct members.
566 if (!onlyForRti && !element.isMixinApplication) { 596 if (!onlyForRti && !element.isMixinApplication) {
567 implementation.forEachMember(visitMember, includeBackendMembers: true); 597 implementation.forEachMember(visitMember, includeBackendMembers: true);
568 } 598 }
569 bool isInterceptedClass = 599 bool isInterceptedClass = _interceptorData.isInterceptedClass(element);
570 backend.interceptorData.isInterceptedClass(element);
571 List<Field> instanceFields = onlyForRti 600 List<Field> instanceFields = onlyForRti
572 ? const <Field>[] 601 ? const <Field>[]
573 : _buildFields(element, 602 : _buildFields(element,
574 visitStatics: false, isHolderInterceptedClass: isInterceptedClass); 603 visitStatics: false, isHolderInterceptedClass: isInterceptedClass);
575 List<Field> staticFieldsForReflection = onlyForRti 604 List<Field> staticFieldsForReflection = onlyForRti
576 ? const <Field>[] 605 ? const <Field>[]
577 : _buildFields(element, 606 : _buildFields(element,
578 visitStatics: true, isHolderInterceptedClass: isInterceptedClass); 607 visitStatics: true, isHolderInterceptedClass: isInterceptedClass);
579 608
580 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(element, 609 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(element,
581 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); 610 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata);
582 611
583 List<StubMethod> checkedSetters = <StubMethod>[]; 612 List<StubMethod> checkedSetters = <StubMethod>[];
584 List<StubMethod> isChecks = <StubMethod>[]; 613 List<StubMethod> isChecks = <StubMethod>[];
585 if (backend.nativeData.isJsInteropClass(element)) { 614 if (_nativeData.isJsInteropClass(element)) {
586 typeTests.properties.forEach((js.Name name, js.Node code) { 615 typeTests.properties.forEach((js.Name name, js.Node code) {
587 _classes[_compiler.commonElements.jsInterceptorClass] 616 _classes[_commonElements.jsInterceptorClass]
588 .isChecks 617 .isChecks
589 .add(_buildStubMethod(name, code)); 618 .add(_buildStubMethod(name, code));
590 }); 619 });
591 } else { 620 } else {
592 for (Field field in instanceFields) { 621 for (Field field in instanceFields) {
593 if (field.needsCheckedSetter) { 622 if (field.needsCheckedSetter) {
594 assert(!field.needsUncheckedSetter); 623 assert(!field.needsUncheckedSetter);
595 FieldElement element = field.element; 624 FieldElement element = field.element;
596 js.Expression code = backend.generatedCode[element]; 625 js.Expression code = _backend.generatedCode[element];
597 assert(code != null); 626 assert(code != null);
598 js.Name name = namer.deriveSetterName(field.accessorName); 627 js.Name name = namer.deriveSetterName(field.accessorName);
599 checkedSetters.add(_buildStubMethod(name, code, element: element)); 628 checkedSetters.add(_buildStubMethod(name, code, element: element));
600 } 629 }
601 } 630 }
602 631
603 typeTests.properties.forEach((js.Name name, js.Node code) { 632 typeTests.properties.forEach((js.Name name, js.Node code) {
604 isChecks.add(_buildStubMethod(name, code)); 633 isChecks.add(_buildStubMethod(name, code));
605 }); 634 });
606 } 635 }
607 636
608 js.Name name = namer.className(element); 637 js.Name name = namer.className(element);
609 String holderName = namer.globalObjectFor(element); 638 String holderName = namer.globalObjectFor(element);
610 // TODO(floitsch): we shouldn't update the registry in the middle of 639 // TODO(floitsch): we shouldn't update the registry in the middle of
611 // building a class. 640 // building a class.
612 Holder holder = _registry.registerHolder(holderName); 641 Holder holder = _registry.registerHolder(holderName);
613 bool isInstantiated = !backend.nativeData.isJsInteropClass(element) && 642 bool isInstantiated = !_nativeData.isJsInteropClass(element) &&
614 worldBuilder.directlyInstantiatedClasses.contains(element); 643 _worldBuilder.directlyInstantiatedClasses.contains(element);
615 644
616 Class result; 645 Class result;
617 if (element.isMixinApplication && !onlyForRti) { 646 if (element.isMixinApplication && !onlyForRti) {
618 assert(!backend.nativeData.isNativeClass(element)); 647 assert(!_nativeData.isNativeClass(element));
619 assert(methods.isEmpty); 648 assert(methods.isEmpty);
620 649
621 result = new MixinApplication( 650 result = new MixinApplication(
622 element, 651 element,
623 name, 652 name,
624 holder, 653 holder,
625 instanceFields, 654 instanceFields,
626 staticFieldsForReflection, 655 staticFieldsForReflection,
627 callStubs, 656 callStubs,
628 checkedSetters, 657 checkedSetters,
(...skipping 11 matching lines...) Expand all
640 instanceFields, 669 instanceFields,
641 staticFieldsForReflection, 670 staticFieldsForReflection,
642 callStubs, 671 callStubs,
643 noSuchMethodStubs, 672 noSuchMethodStubs,
644 checkedSetters, 673 checkedSetters,
645 isChecks, 674 isChecks,
646 typeTests.functionTypeIndex, 675 typeTests.functionTypeIndex,
647 isDirectlyInstantiated: isInstantiated, 676 isDirectlyInstantiated: isInstantiated,
648 hasRtiField: hasRtiField, 677 hasRtiField: hasRtiField,
649 onlyForRti: onlyForRti, 678 onlyForRti: onlyForRti,
650 isNative: backend.nativeData.isNativeClass(element)); 679 isNative: _nativeData.isNativeClass(element));
651 } 680 }
652 _classes[element] = result; 681 _classes[element] = result;
653 return result; 682 return result;
654 } 683 }
655 684
656 bool _methodNeedsStubs(FunctionElement method) { 685 bool _methodNeedsStubs(FunctionElement method) {
657 return !method.functionSignature.optionalParameters.isEmpty; 686 return !method.functionSignature.optionalParameters.isEmpty;
658 } 687 }
659 688
660 bool _methodCanBeReflected(MethodElement method) { 689 bool _methodCanBeReflected(MethodElement method) {
661 return backend.mirrorsData.isMemberAccessibleByReflection(method); 690 return _mirrorsData.isMemberAccessibleByReflection(method);
662 } 691 }
663 692
664 bool _methodCanBeApplied(FunctionElement method) { 693 bool _methodCanBeApplied(FunctionElement method) {
665 return backend.backendUsage.isFunctionApplyUsed && 694 return _backendUsage.isFunctionApplyUsed &&
666 closedWorld.getMightBePassedToApply(method); 695 closedWorld.getMightBePassedToApply(method);
667 } 696 }
668 697
669 /* Map | List */ _computeParameterDefaultValues(FunctionSignature signature) { 698 /* Map | List */ _computeParameterDefaultValues(FunctionSignature signature) {
670 var /* Map | List */ optionalParameterDefaultValues; 699 var /* Map | List */ optionalParameterDefaultValues;
671 if (signature.optionalParametersAreNamed) { 700 if (signature.optionalParametersAreNamed) {
672 optionalParameterDefaultValues = new Map<String, ConstantValue>(); 701 optionalParameterDefaultValues = new Map<String, ConstantValue>();
673 signature.forEachOptionalParameter((ParameterElement parameter) { 702 signature.forEachOptionalParameter((ParameterElement parameter) {
674 ConstantValue def = 703 ConstantValue def =
675 backend.constants.getConstantValue(parameter.constant); 704 _constantHandler.getConstantValue(parameter.constant);
676 optionalParameterDefaultValues[parameter.name] = def; 705 optionalParameterDefaultValues[parameter.name] = def;
677 }); 706 });
678 } else { 707 } else {
679 optionalParameterDefaultValues = <ConstantValue>[]; 708 optionalParameterDefaultValues = <ConstantValue>[];
680 signature.forEachOptionalParameter((ParameterElement parameter) { 709 signature.forEachOptionalParameter((ParameterElement parameter) {
681 ConstantValue def = 710 ConstantValue def =
682 backend.constants.getConstantValue(parameter.constant); 711 _constantHandler.getConstantValue(parameter.constant);
683 optionalParameterDefaultValues.add(def); 712 optionalParameterDefaultValues.add(def);
684 }); 713 });
685 } 714 }
686 return optionalParameterDefaultValues; 715 return optionalParameterDefaultValues;
687 } 716 }
688 717
689 DartMethod _buildMethod(MethodElement element) { 718 DartMethod _buildMethod(MethodElement element) {
690 assert(element.isDeclaration); 719 assert(element.isDeclaration);
691 js.Name name = namer.methodPropertyName(element); 720 js.Name name = namer.methodPropertyName(element);
692 js.Expression code = backend.generatedCode[element]; 721 js.Expression code = _backend.generatedCode[element];
693 722
694 // TODO(kasperl): Figure out under which conditions code is null. 723 // TODO(kasperl): Figure out under which conditions code is null.
695 if (code == null) return null; 724 if (code == null) return null;
696 725
697 bool canTearOff = false; 726 bool canTearOff = false;
698 js.Name tearOffName; 727 js.Name tearOffName;
699 bool isClosureCallMethod = false; 728 bool isClosureCallMethod = false;
700 bool isNotApplyTarget = !element.isFunction || element.isAccessor; 729 bool isNotApplyTarget = !element.isFunction || element.isAccessor;
701 730
702 bool canBeReflected = _methodCanBeReflected(element); 731 bool canBeReflected = _methodCanBeReflected(element);
703 bool canBeApplied = _methodCanBeApplied(element); 732 bool canBeApplied = _methodCanBeApplied(element);
704 733
705 js.Name aliasName = backend.superMemberData.isAliasedSuperMember(element) 734 js.Name aliasName = _superMemberData.isAliasedSuperMember(element)
706 ? namer.aliasedSuperMemberPropertyName(element) 735 ? namer.aliasedSuperMemberPropertyName(element)
707 : null; 736 : null;
708 737
709 if (isNotApplyTarget) { 738 if (isNotApplyTarget) {
710 canTearOff = false; 739 canTearOff = false;
711 } else { 740 } else {
712 if (element.enclosingClass.isClosure) { 741 if (element.enclosingClass.isClosure) {
713 canTearOff = false; 742 canTearOff = false;
714 isClosureCallMethod = true; 743 isClosureCallMethod = true;
715 } else { 744 } else {
716 // Careful with operators. 745 // Careful with operators.
717 canTearOff = worldBuilder.hasInvokedGetter(element, closedWorld) || 746 canTearOff = _worldBuilder.hasInvokedGetter(element, closedWorld) ||
718 (canBeReflected && !element.isOperator); 747 (canBeReflected && !element.isOperator);
719 assert(canTearOff || 748 assert(canTearOff ||
720 !worldBuilder.methodsNeedingSuperGetter.contains(element)); 749 !_worldBuilder.methodsNeedingSuperGetter.contains(element));
721 tearOffName = namer.getterForElement(element); 750 tearOffName = namer.getterForElement(element);
722 } 751 }
723 } 752 }
724 753
725 if (canTearOff) { 754 if (canTearOff) {
726 assert(invariant(element, !element.isGenerativeConstructor)); 755 assert(invariant(element, !element.isGenerativeConstructor));
727 assert(invariant(element, !element.isGenerativeConstructorBody)); 756 assert(invariant(element, !element.isGenerativeConstructorBody));
728 assert(invariant(element, !element.isConstructor)); 757 assert(invariant(element, !element.isConstructor));
729 } 758 }
730 759
(...skipping 10 matching lines...) Expand all
741 // this information anyway as they cannot be torn off or 770 // this information anyway as they cannot be torn off or
742 // reflected. 771 // reflected.
743 var body = element; 772 var body = element;
744 memberType = body.constructor.type; 773 memberType = body.constructor.type;
745 } else { 774 } else {
746 memberType = element.type; 775 memberType = element.type;
747 } 776 }
748 777
749 js.Expression functionType; 778 js.Expression functionType;
750 if (canTearOff || canBeReflected) { 779 if (canTearOff || canBeReflected) {
751 OutputUnit outputUnit = 780 OutputUnit outputUnit = _deferredLoadTask.outputUnitForElement(element);
752 _compiler.deferredLoadTask.outputUnitForElement(element);
753 functionType = _generateFunctionType(memberType, outputUnit); 781 functionType = _generateFunctionType(memberType, outputUnit);
754 } 782 }
755 783
756 int requiredParameterCount; 784 int requiredParameterCount;
757 var /* List | Map */ optionalParameterDefaultValues; 785 var /* List | Map */ optionalParameterDefaultValues;
758 if (canBeApplied || canBeReflected) { 786 if (canBeApplied || canBeReflected) {
759 FunctionSignature signature = element.functionSignature; 787 FunctionSignature signature = element.functionSignature;
760 requiredParameterCount = signature.requiredParameterCount; 788 requiredParameterCount = signature.requiredParameterCount;
761 optionalParameterDefaultValues = 789 optionalParameterDefaultValues =
762 _computeParameterDefaultValues(signature); 790 _computeParameterDefaultValues(signature);
763 } 791 }
764 792
765 return new InstanceMethod(element, name, code, 793 return new InstanceMethod(element, name, code,
766 _generateParameterStubs(element, canTearOff), callName, 794 _generateParameterStubs(element, canTearOff), callName,
767 needsTearOff: canTearOff, 795 needsTearOff: canTearOff,
768 tearOffName: tearOffName, 796 tearOffName: tearOffName,
769 isClosureCallMethod: isClosureCallMethod, 797 isClosureCallMethod: isClosureCallMethod,
770 aliasName: aliasName, 798 aliasName: aliasName,
771 canBeApplied: canBeApplied, 799 canBeApplied: canBeApplied,
772 canBeReflected: canBeReflected, 800 canBeReflected: canBeReflected,
773 requiredParameterCount: requiredParameterCount, 801 requiredParameterCount: requiredParameterCount,
774 optionalParameterDefaultValues: optionalParameterDefaultValues, 802 optionalParameterDefaultValues: optionalParameterDefaultValues,
775 functionType: functionType); 803 functionType: functionType);
776 } 804 }
777 805
778 js.Expression _generateFunctionType( 806 js.Expression _generateFunctionType(
779 ResolutionDartType type, OutputUnit outputUnit) { 807 ResolutionDartType type, OutputUnit outputUnit) {
780 if (type.containsTypeVariables) { 808 if (type.containsTypeVariables) {
781 js.Expression thisAccess = js.js(r'this.$receiver'); 809 js.Expression thisAccess = js.js(r'this.$receiver');
782 return backend.rtiEncoder 810 return _rtiEncoder.getSignatureEncoding(
783 .getSignatureEncoding(backend.emitter.emitter, type, thisAccess); 811 _emitter.emitter, type, thisAccess);
784 } else { 812 } else {
785 return backend.emitter.metadataCollector 813 return _emitter.metadataCollector
786 .reifyTypeForOutputUnit(type, outputUnit); 814 .reifyTypeForOutputUnit(type, outputUnit);
787 } 815 }
788 } 816 }
789 817
790 List<ParameterStubMethod> _generateParameterStubs( 818 List<ParameterStubMethod> _generateParameterStubs(
791 MethodElement element, bool canTearOff) { 819 MethodElement element, bool canTearOff) {
792 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; 820 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[];
793 821
794 ParameterStubGenerator generator = 822 ParameterStubGenerator generator =
795 new ParameterStubGenerator(_compiler, namer, backend, closedWorld); 823 new ParameterStubGenerator(_compiler, namer, _backend, closedWorld);
796 return generator.generateParameterStubs(element, canTearOff: canTearOff); 824 return generator.generateParameterStubs(element, canTearOff: canTearOff);
797 } 825 }
798 826
799 /// Builds a stub method. 827 /// Builds a stub method.
800 /// 828 ///
801 /// Stub methods may have an element that can be used for code-size 829 /// Stub methods may have an element that can be used for code-size
802 /// attribution. 830 /// attribution.
803 Method _buildStubMethod(js.Name name, js.Expression code, 831 Method _buildStubMethod(js.Name name, js.Expression code,
804 {MemberElement element}) { 832 {MemberElement element}) {
805 return new StubMethod(name, code, element: element); 833 return new StubMethod(name, code, element: element);
806 } 834 }
807 835
808 // The getInterceptor methods directly access the prototype of classes. 836 // The getInterceptor methods directly access the prototype of classes.
809 // We must evaluate these classes eagerly so that the prototype is 837 // We must evaluate these classes eagerly so that the prototype is
810 // accessible. 838 // accessible.
811 void _markEagerInterceptorClasses() { 839 void _markEagerInterceptorClasses() {
812 Iterable<js.Name> names = 840 Iterable<js.Name> names =
813 backend.oneShotInterceptorData.specializedGetInterceptorNames; 841 _oneShotInterceptorData.specializedGetInterceptorNames;
814 for (js.Name name in names) { 842 for (js.Name name in names) {
815 for (ClassElement element in backend.oneShotInterceptorData 843 for (ClassElement element
816 .getSpecializedGetInterceptorsFor(name)) { 844 in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) {
817 Class cls = _classes[element]; 845 Class cls = _classes[element];
818 if (cls != null) cls.isEager = true; 846 if (cls != null) cls.isEager = true;
819 } 847 }
820 } 848 }
821 } 849 }
822 850
823 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { 851 Iterable<StaticStubMethod> _generateGetInterceptorMethods() {
824 InterceptorStubGenerator stubGenerator = 852 InterceptorStubGenerator stubGenerator =
825 new InterceptorStubGenerator(_compiler, namer, backend, closedWorld); 853 new InterceptorStubGenerator(_compiler, namer, _backend, closedWorld);
826 854
827 String holderName = namer 855 String holderName =
828 .globalObjectForLibrary(_compiler.commonElements.interceptorsLibrary); 856 namer.globalObjectForLibrary(_commonElements.interceptorsLibrary);
829 // TODO(floitsch): we shouldn't update the registry in the middle of 857 // TODO(floitsch): we shouldn't update the registry in the middle of
830 // generating the interceptor methods. 858 // generating the interceptor methods.
831 Holder holder = _registry.registerHolder(holderName); 859 Holder holder = _registry.registerHolder(holderName);
832 860
833 Iterable<js.Name> names = 861 Iterable<js.Name> names =
834 backend.oneShotInterceptorData.specializedGetInterceptorNames; 862 _oneShotInterceptorData.specializedGetInterceptorNames;
835 return names.map((js.Name name) { 863 return names.map((js.Name name) {
836 Set<ClassEntity> classes = 864 Set<ClassEntity> classes =
837 backend.oneShotInterceptorData.getSpecializedGetInterceptorsFor(name); 865 _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name);
838 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); 866 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes);
839 return new StaticStubMethod(name, holder, code); 867 return new StaticStubMethod(name, holder, code);
840 }); 868 });
841 } 869 }
842 870
843 List<Field> _buildFields(Element holder, 871 List<Field> _buildFields(Element holder,
844 {bool visitStatics, bool isHolderInterceptedClass: false}) { 872 {bool visitStatics, bool isHolderInterceptedClass: false}) {
845 List<Field> fields = <Field>[]; 873 List<Field> fields = <Field>[];
846 new FieldVisitor(_compiler, namer, closedWorld) 874 new FieldVisitor(_compiler, namer, closedWorld)
847 .visitFields(holder, visitStatics, (FieldElement field, 875 .visitFields(holder, visitStatics, (FieldElement field,
848 js.Name name, 876 js.Name name,
849 js.Name accessorName, 877 js.Name accessorName,
850 bool needsGetter, 878 bool needsGetter,
851 bool needsSetter, 879 bool needsSetter,
852 bool needsCheckedSetter) { 880 bool needsCheckedSetter) {
853 assert(invariant(field, field.isDeclaration)); 881 assert(invariant(field, field.isDeclaration));
854 882
855 int getterFlags = 0; 883 int getterFlags = 0;
856 if (needsGetter) { 884 if (needsGetter) {
857 if (visitStatics || 885 if (visitStatics ||
858 !backend.interceptorData.fieldHasInterceptedGetter(field)) { 886 !_interceptorData.fieldHasInterceptedGetter(field)) {
859 getterFlags = 1; 887 getterFlags = 1;
860 } else { 888 } else {
861 getterFlags += 2; 889 getterFlags += 2;
862 // TODO(sra): 'isInterceptedClass' might not be the correct test 890 // TODO(sra): 'isInterceptedClass' might not be the correct test
863 // for methods forced to use the interceptor convention because 891 // for methods forced to use the interceptor convention because
864 // the method's class was elsewhere mixed-in to an interceptor. 892 // the method's class was elsewhere mixed-in to an interceptor.
865 if (!isHolderInterceptedClass) { 893 if (!isHolderInterceptedClass) {
866 getterFlags += 1; 894 getterFlags += 1;
867 } 895 }
868 } 896 }
869 } 897 }
870 898
871 int setterFlags = 0; 899 int setterFlags = 0;
872 if (needsSetter) { 900 if (needsSetter) {
873 if (visitStatics || 901 if (visitStatics ||
874 !backend.interceptorData.fieldHasInterceptedSetter(field)) { 902 !_interceptorData.fieldHasInterceptedSetter(field)) {
875 setterFlags = 1; 903 setterFlags = 1;
876 } else { 904 } else {
877 setterFlags += 2; 905 setterFlags += 2;
878 if (!isHolderInterceptedClass) { 906 if (!isHolderInterceptedClass) {
879 setterFlags += 1; 907 setterFlags += 1;
880 } 908 }
881 } 909 }
882 } 910 }
883 911
884 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags, 912 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags,
885 needsCheckedSetter)); 913 needsCheckedSetter));
886 }); 914 });
887 915
888 return fields; 916 return fields;
889 } 917 }
890 918
891 Iterable<StaticStubMethod> _generateOneShotInterceptors() { 919 Iterable<StaticStubMethod> _generateOneShotInterceptors() {
892 InterceptorStubGenerator stubGenerator = 920 InterceptorStubGenerator stubGenerator =
893 new InterceptorStubGenerator(_compiler, namer, backend, closedWorld); 921 new InterceptorStubGenerator(_compiler, namer, _backend, closedWorld);
894 922
895 String holderName = namer 923 String holderName =
896 .globalObjectForLibrary(_compiler.commonElements.interceptorsLibrary); 924 namer.globalObjectForLibrary(_commonElements.interceptorsLibrary);
897 // TODO(floitsch): we shouldn't update the registry in the middle of 925 // TODO(floitsch): we shouldn't update the registry in the middle of
898 // generating the interceptor methods. 926 // generating the interceptor methods.
899 Holder holder = _registry.registerHolder(holderName); 927 Holder holder = _registry.registerHolder(holderName);
900 928
901 List<js.Name> names = 929 List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames;
902 backend.oneShotInterceptorData.oneShotInterceptorNames;
903 return names.map((js.Name name) { 930 return names.map((js.Name name) {
904 js.Expression code = stubGenerator.generateOneShotInterceptor(name); 931 js.Expression code = stubGenerator.generateOneShotInterceptor(name);
905 return new StaticStubMethod(name, holder, code); 932 return new StaticStubMethod(name, holder, code);
906 }); 933 });
907 } 934 }
908 935
909 StaticDartMethod _buildStaticMethod(MethodElement element) { 936 StaticDartMethod _buildStaticMethod(MethodElement element) {
910 js.Name name = namer.methodPropertyName(element); 937 js.Name name = namer.methodPropertyName(element);
911 String holder = namer.globalObjectFor(element); 938 String holder = namer.globalObjectFor(element);
912 js.Expression code = backend.generatedCode[element]; 939 js.Expression code = _backend.generatedCode[element];
913 940
914 bool isApplyTarget = !element.isConstructor && !element.isAccessor; 941 bool isApplyTarget = !element.isConstructor && !element.isAccessor;
915 bool canBeApplied = _methodCanBeApplied(element); 942 bool canBeApplied = _methodCanBeApplied(element);
916 bool canBeReflected = _methodCanBeReflected(element); 943 bool canBeReflected = _methodCanBeReflected(element);
917 944
918 bool needsTearOff = isApplyTarget && 945 bool needsTearOff = isApplyTarget &&
919 (canBeReflected || 946 (canBeReflected ||
920 worldBuilder.staticFunctionsNeedingGetter.contains(element)); 947 _worldBuilder.staticFunctionsNeedingGetter.contains(element));
921 948
922 js.Name tearOffName = 949 js.Name tearOffName =
923 needsTearOff ? namer.staticClosureName(element) : null; 950 needsTearOff ? namer.staticClosureName(element) : null;
924 951
925 js.Name callName = null; 952 js.Name callName = null;
926 if (needsTearOff) { 953 if (needsTearOff) {
927 Selector callSelector = 954 Selector callSelector =
928 new Selector.fromElement(element).toCallSelector(); 955 new Selector.fromElement(element).toCallSelector();
929 callName = namer.invocationName(callSelector); 956 callName = namer.invocationName(callSelector);
930 } 957 }
931 js.Expression functionType; 958 js.Expression functionType;
932 ResolutionDartType type = element.type; 959 ResolutionDartType type = element.type;
933 if (needsTearOff || canBeReflected) { 960 if (needsTearOff || canBeReflected) {
934 OutputUnit outputUnit = 961 OutputUnit outputUnit = _deferredLoadTask.outputUnitForElement(element);
935 _compiler.deferredLoadTask.outputUnitForElement(element);
936 functionType = _generateFunctionType(type, outputUnit); 962 functionType = _generateFunctionType(type, outputUnit);
937 } 963 }
938 964
939 int requiredParameterCount; 965 int requiredParameterCount;
940 var /* List | Map */ optionalParameterDefaultValues; 966 var /* List | Map */ optionalParameterDefaultValues;
941 if (canBeApplied || canBeReflected) { 967 if (canBeApplied || canBeReflected) {
942 FunctionSignature signature = element.functionSignature; 968 FunctionSignature signature = element.functionSignature;
943 requiredParameterCount = signature.requiredParameterCount; 969 requiredParameterCount = signature.requiredParameterCount;
944 optionalParameterDefaultValues = 970 optionalParameterDefaultValues =
945 _computeParameterDefaultValues(signature); 971 _computeParameterDefaultValues(signature);
(...skipping 26 matching lines...) Expand all
972 Constant constant = new Constant(name, holder, constantValue); 998 Constant constant = new Constant(name, holder, constantValue);
973 _constants[constantValue] = constant; 999 _constants[constantValue] = constant;
974 } 1000 }
975 } 1001 }
976 1002
977 Holder _registerStaticStateHolder() { 1003 Holder _registerStaticStateHolder() {
978 return _registry.registerHolder(namer.staticStateHolder, 1004 return _registry.registerHolder(namer.staticStateHolder,
979 isStaticStateHolder: true); 1005 isStaticStateHolder: true);
980 } 1006 }
981 } 1007 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698