| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.js_emitter.program_builder; | 5 library dart2js.js_emitter.program_builder; |
| 6 | 6 |
| 7 import '../../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 24 matching lines...) Expand all Loading... |
| 35 import '../../js/js.dart' as js; | 35 import '../../js/js.dart' as js; |
| 36 import '../../js_backend/backend.dart' | 36 import '../../js_backend/backend.dart' |
| 37 show | 37 show |
| 38 JavaScriptBackend, | 38 JavaScriptBackend, |
| 39 RuntimeTypesEncoder, | 39 RuntimeTypesEncoder, |
| 40 RuntimeTypesNeed, | 40 RuntimeTypesNeed, |
| 41 SuperMemberData; | 41 SuperMemberData; |
| 42 import '../../js_backend/backend_usage.dart'; | 42 import '../../js_backend/backend_usage.dart'; |
| 43 import '../../js_backend/constant_handler_javascript.dart' | 43 import '../../js_backend/constant_handler_javascript.dart' |
| 44 show JavaScriptConstantCompiler; | 44 show JavaScriptConstantCompiler; |
| 45 import '../../js_backend/custom_elements_analysis.dart'; |
| 45 import '../../js_backend/namer.dart' show Namer, StringBackedName; | 46 import '../../js_backend/namer.dart' show Namer, StringBackedName; |
| 46 import '../../js_backend/native_data.dart'; | 47 import '../../js_backend/native_data.dart'; |
| 47 import '../../js_backend/interceptor_data.dart'; | 48 import '../../js_backend/interceptor_data.dart'; |
| 48 import '../../js_backend/mirrors_data.dart'; | 49 import '../../js_backend/mirrors_data.dart'; |
| 49 import '../../native/enqueue.dart' show NativeCodegenEnqueuer; | 50 import '../../native/enqueue.dart' show NativeCodegenEnqueuer; |
| 50 import '../../options.dart'; | 51 import '../../options.dart'; |
| 51 import '../../universe/selector.dart' show Selector; | 52 import '../../universe/selector.dart' show Selector; |
| 52 import '../../universe/world_builder.dart' | 53 import '../../universe/world_builder.dart' |
| 53 show CodegenWorldBuilder, SelectorConstraints; | 54 show CodegenWorldBuilder, SelectorConstraints; |
| 54 import '../../world.dart' show ClosedWorld; | 55 import '../../world.dart' show ClosedWorld; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 66 import '../model.dart'; | 67 import '../model.dart'; |
| 67 | 68 |
| 68 part 'collector.dart'; | 69 part 'collector.dart'; |
| 69 part 'field_visitor.dart'; | 70 part 'field_visitor.dart'; |
| 70 part 'registry.dart'; | 71 part 'registry.dart'; |
| 71 | 72 |
| 72 /// Builds a self-contained representation of the program that can then be | 73 /// Builds a self-contained representation of the program that can then be |
| 73 /// emitted more easily by the individual emitters. | 74 /// emitted more easily by the individual emitters. |
| 74 class ProgramBuilder { | 75 class ProgramBuilder { |
| 75 final Compiler _compiler; | 76 final Compiler _compiler; |
| 76 final Namer namer; | 77 final Namer _namer; |
| 77 final CodeEmitterTask _task; | 78 final CodeEmitterTask _task; |
| 78 final ClosedWorld closedWorld; | 79 final ClosedWorld _closedWorld; |
| 79 | 80 |
| 80 /// Contains the collected information the program builder used to build | 81 /// Contains the collected information the program builder used to build |
| 81 /// the model. | 82 /// the model. |
| 82 // The collector will be filled on the first call to `buildProgram`. | 83 // The collector will be filled on the first call to `buildProgram`. |
| 83 // It is stored and publicly exposed for backwards compatibility. New code | 84 // It is stored and publicly exposed for backwards compatibility. New code |
| 84 // (and in particular new emitters) should not use it. | 85 // (and in particular new emitters) should not use it. |
| 85 final Collector collector; | 86 final Collector collector; |
| 86 | 87 |
| 87 final Registry _registry; | 88 final Registry _registry; |
| 88 | 89 |
| 89 /// True if the program should store function types in the metadata. | 90 /// True if the program should store function types in the metadata. |
| 90 bool _storeFunctionTypesInMetadata = false; | 91 bool _storeFunctionTypesInMetadata = false; |
| 91 | 92 |
| 92 ProgramBuilder(Compiler compiler, Namer namer, this._task, Emitter emitter, | 93 ProgramBuilder(Compiler compiler, Namer _namer, this._task, Emitter emitter, |
| 93 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses) | 94 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses) |
| 94 : this._compiler = compiler, | 95 : this._compiler = compiler, |
| 95 this.namer = namer, | 96 this._namer = _namer, |
| 96 this.closedWorld = closedWorld, | 97 this._closedWorld = closedWorld, |
| 97 this.collector = new Collector( | 98 this.collector = new Collector( |
| 98 compiler, namer, closedWorld, rtiNeededClasses, emitter), | 99 compiler, _namer, closedWorld, rtiNeededClasses, emitter), |
| 99 this._registry = new Registry(compiler); | 100 this._registry = new Registry(compiler); |
| 100 | 101 |
| 101 JavaScriptBackend get _backend => _compiler.backend; | 102 JavaScriptBackend get _backend => _compiler.backend; |
| 102 CodegenWorldBuilder get _worldBuilder => _compiler.codegenWorldBuilder; | 103 CodegenWorldBuilder get _worldBuilder => _compiler.codegenWorldBuilder; |
| 103 DeferredLoadTask get _deferredLoadTask => _compiler.deferredLoadTask; | 104 DeferredLoadTask get _deferredLoadTask => _compiler.deferredLoadTask; |
| 104 Types get _types => _compiler.types; | 105 Types get _types => _compiler.types; |
| 105 CommonElements get _commonElements => _compiler.commonElements; | 106 CommonElements get _commonElements => _compiler.commonElements; |
| 106 CompilerOptions get _options => _compiler.options; | 107 CompilerOptions get _options => _compiler.options; |
| 107 NativeCodegenEnqueuer get _nativeCodegenEnqueuer => | 108 NativeCodegenEnqueuer get _nativeCodegenEnqueuer => |
| 108 _backend.nativeCodegenEnqueuer; | 109 _backend.nativeCodegenEnqueuer; |
| 109 Namer get _namer => _backend.namer; | |
| 110 BackendUsage get _backendUsage => _backend.backendUsage; | 110 BackendUsage get _backendUsage => _backend.backendUsage; |
| 111 CodeEmitterTask get _emitter => _backend.emitter; | 111 CodeEmitterTask get _emitter => _backend.emitter; |
| 112 JavaScriptConstantCompiler get _constantHandler => _backend.constants; | 112 JavaScriptConstantCompiler get _constantHandler => _backend.constants; |
| 113 NativeData get _nativeData => _backend.nativeData; | 113 NativeData get _nativeData => _backend.nativeData; |
| 114 RuntimeTypesNeed get _rtiNeed => _backend.rtiNeed; | 114 RuntimeTypesNeed get _rtiNeed => _backend.rtiNeed; |
| 115 MirrorsData get _mirrorsData => _backend.mirrorsData; | 115 MirrorsData get _mirrorsData => _backend.mirrorsData; |
| 116 InterceptorData get _interceptorData => _backend.interceptorData; | 116 InterceptorData get _interceptorData => _backend.interceptorData; |
| 117 SuperMemberData get _superMemberData => _backend.superMemberData; | 117 SuperMemberData get _superMemberData => _backend.superMemberData; |
| 118 RuntimeTypesEncoder get _rtiEncoder => _backend.rtiEncoder; | 118 RuntimeTypesEncoder get _rtiEncoder => _backend.rtiEncoder; |
| 119 OneShotInterceptorData get _oneShotInterceptorData => | 119 OneShotInterceptorData get _oneShotInterceptorData => |
| 120 _backend.oneShotInterceptorData; | 120 _backend.oneShotInterceptorData; |
| 121 CustomElementsCodegenAnalysis get _customElementsCodegenAnalysis => |
| 122 _backend.customElementsCodegenAnalysis; |
| 121 | 123 |
| 122 /// Mapping from [ClassElement] to constructed [Class]. We need this to | 124 /// Mapping from [ClassElement] to constructed [Class]. We need this to |
| 123 /// update the superclass in the [Class]. | 125 /// update the superclass in the [Class]. |
| 124 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; | 126 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; |
| 125 | 127 |
| 126 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to | 128 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to |
| 127 /// generate the deferredLoadingMap (to know which hunks to load). | 129 /// generate the deferredLoadingMap (to know which hunks to load). |
| 128 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; | 130 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; |
| 129 | 131 |
| 130 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to | 132 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 _deferredLoadTask.hunksToLoad | 235 _deferredLoadTask.hunksToLoad |
| 234 .forEach((String loadId, List<OutputUnit> outputUnits) { | 236 .forEach((String loadId, List<OutputUnit> outputUnits) { |
| 235 loadMap[loadId] = outputUnits | 237 loadMap[loadId] = outputUnits |
| 236 .map((OutputUnit unit) => _outputs[unit]) | 238 .map((OutputUnit unit) => _outputs[unit]) |
| 237 .toList(growable: false); | 239 .toList(growable: false); |
| 238 }); | 240 }); |
| 239 return loadMap; | 241 return loadMap; |
| 240 } | 242 } |
| 241 | 243 |
| 242 js.Expression _buildTypeToInterceptorMap() { | 244 js.Expression _buildTypeToInterceptorMap() { |
| 243 InterceptorStubGenerator stubGenerator = | 245 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( |
| 244 new InterceptorStubGenerator(_compiler, namer, _backend, closedWorld); | 246 _options, |
| 247 _commonElements, |
| 248 _emitter, |
| 249 _nativeCodegenEnqueuer, |
| 250 _constantHandler, |
| 251 _namer, |
| 252 _nativeData, |
| 253 _interceptorData, |
| 254 _oneShotInterceptorData, |
| 255 _customElementsCodegenAnalysis, |
| 256 _worldBuilder, |
| 257 _closedWorld); |
| 245 return stubGenerator.generateTypeToInterceptorMap(); | 258 return stubGenerator.generateTypeToInterceptorMap(); |
| 246 } | 259 } |
| 247 | 260 |
| 248 MainFragment _buildMainFragment(LibrariesMap librariesMap) { | 261 MainFragment _buildMainFragment(LibrariesMap librariesMap) { |
| 249 // Construct the main output from the libraries and the registered holders. | 262 // Construct the main output from the libraries and the registered holders. |
| 250 MainFragment result = new MainFragment( | 263 MainFragment result = new MainFragment( |
| 251 librariesMap.outputUnit, | 264 librariesMap.outputUnit, |
| 252 "", // The empty string is the name for the main output file. | 265 "", // The empty string is the name for the main output file. |
| 253 _buildInvokeMain(), | 266 _buildInvokeMain(), |
| 254 _buildLibraries(librariesMap), | 267 _buildLibraries(librariesMap), |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 if (staticNonFinalFields == null) return const <StaticField>[]; | 308 if (staticNonFinalFields == null) return const <StaticField>[]; |
| 296 | 309 |
| 297 return staticNonFinalFields.map(_buildStaticField).toList(growable: false); | 310 return staticNonFinalFields.map(_buildStaticField).toList(growable: false); |
| 298 } | 311 } |
| 299 | 312 |
| 300 StaticField _buildStaticField(FieldElement element) { | 313 StaticField _buildStaticField(FieldElement element) { |
| 301 ConstantValue initialValue = | 314 ConstantValue initialValue = |
| 302 _constantHandler.getConstantValue(element.constant); | 315 _constantHandler.getConstantValue(element.constant); |
| 303 // TODO(zarah): The holder should not be registered during building of | 316 // TODO(zarah): The holder should not be registered during building of |
| 304 // a static field. | 317 // a static field. |
| 305 _registry.registerHolder(namer.globalObjectForConstant(initialValue), | 318 _registry.registerHolder(_namer.globalObjectForConstant(initialValue), |
| 306 isConstantsHolder: true); | 319 isConstantsHolder: true); |
| 307 js.Expression code = _task.emitter.constantReference(initialValue); | 320 js.Expression code = _task.emitter.constantReference(initialValue); |
| 308 js.Name name = namer.globalPropertyName(element); | 321 js.Name name = _namer.globalPropertyName(element); |
| 309 bool isFinal = false; | 322 bool isFinal = false; |
| 310 bool isLazy = false; | 323 bool isLazy = false; |
| 311 | 324 |
| 312 // TODO(floitsch): we shouldn't update the registry in the middle of | 325 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 313 // building a static field. (Note that the static-state holder was | 326 // building a static field. (Note that the static-state holder was |
| 314 // already registered earlier, and that we just call the register to get | 327 // already registered earlier, and that we just call the register to get |
| 315 // the holder-instance. | 328 // the holder-instance. |
| 316 return new StaticField( | 329 return new StaticField( |
| 317 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); | 330 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); |
| 318 } | 331 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 331 .toList(growable: false); | 344 .toList(growable: false); |
| 332 } | 345 } |
| 333 | 346 |
| 334 StaticField _buildLazyField(FieldElement element) { | 347 StaticField _buildLazyField(FieldElement element) { |
| 335 js.Expression code = _backend.generatedCode[element]; | 348 js.Expression code = _backend.generatedCode[element]; |
| 336 // The code is null if we ended up not needing the lazily | 349 // The code is null if we ended up not needing the lazily |
| 337 // initialized field after all because of constant folding | 350 // initialized field after all because of constant folding |
| 338 // before code generation. | 351 // before code generation. |
| 339 if (code == null) return null; | 352 if (code == null) return null; |
| 340 | 353 |
| 341 js.Name name = namer.globalPropertyName(element); | 354 js.Name name = _namer.globalPropertyName(element); |
| 342 bool isFinal = element.isFinal; | 355 bool isFinal = element.isFinal; |
| 343 bool isLazy = true; | 356 bool isLazy = true; |
| 344 // TODO(floitsch): we shouldn't update the registry in the middle of | 357 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 345 // building a static field. (Note that the static-state holder was | 358 // building a static field. (Note that the static-state holder was |
| 346 // already registered earlier, and that we just call the register to get | 359 // already registered earlier, and that we just call the register to get |
| 347 // the holder-instance. | 360 // the holder-instance. |
| 348 return new StaticField( | 361 return new StaticField( |
| 349 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); | 362 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); |
| 350 } | 363 } |
| 351 | 364 |
| 352 List<Library> _buildLibraries(LibrariesMap librariesMap) { | 365 List<Library> _buildLibraries(LibrariesMap librariesMap) { |
| 353 List<Library> libraries = new List<Library>(librariesMap.length); | 366 List<Library> libraries = new List<Library>(librariesMap.length); |
| 354 int count = 0; | 367 int count = 0; |
| 355 librariesMap.forEach((LibraryElement library, List<Element> elements) { | 368 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
| 356 libraries[count++] = _buildLibrary(library, elements); | 369 libraries[count++] = _buildLibrary(library, elements); |
| 357 }); | 370 }); |
| 358 return libraries; | 371 return libraries; |
| 359 } | 372 } |
| 360 | 373 |
| 361 void _addJsInteropStubs(LibrariesMap librariesMap) { | 374 void _addJsInteropStubs(LibrariesMap librariesMap) { |
| 362 if (_classes.containsKey(_commonElements.objectClass)) { | 375 if (_classes.containsKey(_commonElements.objectClass)) { |
| 363 var toStringInvocation = namer.invocationName(Selectors.toString_); | 376 var toStringInvocation = _namer.invocationName(Selectors.toString_); |
| 364 // TODO(jacobr): register toString as used so that it is always accessible | 377 // TODO(jacobr): register toString as used so that it is always accessible |
| 365 // from JavaScript. | 378 // from JavaScript. |
| 366 _classes[_commonElements.objectClass].callStubs.add(_buildStubMethod( | 379 _classes[_commonElements.objectClass].callStubs.add(_buildStubMethod( |
| 367 new StringBackedName("toString"), | 380 new StringBackedName("toString"), |
| 368 js.js('function() { return this.#(this) }', toStringInvocation))); | 381 js.js('function() { return this.#(this) }', toStringInvocation))); |
| 369 } | 382 } |
| 370 | 383 |
| 371 // We add all members from classes marked with isJsInterop to the base | 384 // We add all members from classes marked with isJsInterop to the base |
| 372 // Interceptor class with implementations that directly call the | 385 // Interceptor class with implementations that directly call the |
| 373 // corresponding JavaScript member. We do not attempt to bind this when | 386 // corresponding JavaScript member. We do not attempt to bind this when |
| 374 // tearing off JavaScript methods as we cannot distinguish between calling | 387 // tearing off JavaScript methods as we cannot distinguish between calling |
| 375 // a regular getter that returns a JavaScript function and tearing off | 388 // a regular getter that returns a JavaScript function and tearing off |
| 376 // a method in the case where there exist multiple JavaScript classes | 389 // a method in the case where there exist multiple JavaScript classes |
| 377 // that conflict on whether the member is a getter or a method. | 390 // that conflict on whether the member is a getter or a method. |
| 378 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass]; | 391 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass]; |
| 379 var stubNames = new Set<String>(); | 392 var stubNames = new Set<String>(); |
| 380 librariesMap.forEach((LibraryElement library, List<Element> elements) { | 393 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
| 381 for (Element e in elements) { | 394 for (Element e in elements) { |
| 382 if (e is ClassElement && _nativeData.isJsInteropClass(e)) { | 395 if (e is ClassElement && _nativeData.isJsInteropClass(e)) { |
| 383 e.declaration.forEachMember((_, Element member) { | 396 e.declaration.forEachMember((_, Element member) { |
| 384 var jsName = _nativeData.computeUnescapedJSInteropName(member.name); | 397 var jsName = _nativeData.computeUnescapedJSInteropName(member.name); |
| 385 if (!member.isInstanceMember) return; | 398 if (!member.isInstanceMember) return; |
| 386 if (member.isGetter || member.isField || member.isFunction) { | 399 if (member.isGetter || member.isField || member.isFunction) { |
| 387 var selectors = | 400 var selectors = |
| 388 _worldBuilder.getterInvocationsByName(member.name); | 401 _worldBuilder.getterInvocationsByName(member.name); |
| 389 if (selectors != null && !selectors.isEmpty) { | 402 if (selectors != null && !selectors.isEmpty) { |
| 390 for (var selector in selectors.keys) { | 403 for (var selector in selectors.keys) { |
| 391 var stubName = namer.invocationName(selector); | 404 var stubName = _namer.invocationName(selector); |
| 392 if (stubNames.add(stubName.key)) { | 405 if (stubNames.add(stubName.key)) { |
| 393 interceptorClass.callStubs.add(_buildStubMethod(stubName, | 406 interceptorClass.callStubs.add(_buildStubMethod(stubName, |
| 394 js.js('function(obj) { return obj.# }', [jsName]), | 407 js.js('function(obj) { return obj.# }', [jsName]), |
| 395 element: member)); | 408 element: member)); |
| 396 } | 409 } |
| 397 } | 410 } |
| 398 } | 411 } |
| 399 } | 412 } |
| 400 | 413 |
| 401 if (member.isSetter || (member.isField && !member.isConst)) { | 414 if (member.isSetter || (member.isField && !member.isConst)) { |
| 402 var selectors = | 415 var selectors = |
| 403 _worldBuilder.setterInvocationsByName(member.name); | 416 _worldBuilder.setterInvocationsByName(member.name); |
| 404 if (selectors != null && !selectors.isEmpty) { | 417 if (selectors != null && !selectors.isEmpty) { |
| 405 var stubName = namer.setterForElement(member); | 418 var stubName = _namer.setterForElement(member); |
| 406 if (stubNames.add(stubName.key)) { | 419 if (stubNames.add(stubName.key)) { |
| 407 interceptorClass.callStubs.add(_buildStubMethod(stubName, | 420 interceptorClass.callStubs.add(_buildStubMethod(stubName, |
| 408 js.js('function(obj, v) { return obj.# = v }', [jsName]), | 421 js.js('function(obj, v) { return obj.# = v }', [jsName]), |
| 409 element: member)); | 422 element: member)); |
| 410 } | 423 } |
| 411 } | 424 } |
| 412 } | 425 } |
| 413 | 426 |
| 414 // Generating stubs for direct calls and stubs for call-through | 427 // Generating stubs for direct calls and stubs for call-through |
| 415 // of getters that happen to be functions. | 428 // of getters that happen to be functions. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 // may want to map named arguments to an object literal containing | 473 // may want to map named arguments to an object literal containing |
| 461 // all named arguments. | 474 // all named arguments. |
| 462 if (selectors != null && !selectors.isEmpty) { | 475 if (selectors != null && !selectors.isEmpty) { |
| 463 for (var selector in selectors.keys) { | 476 for (var selector in selectors.keys) { |
| 464 // Check whether the arity matches this member. | 477 // Check whether the arity matches this member. |
| 465 var argumentCount = selector.argumentCount; | 478 var argumentCount = selector.argumentCount; |
| 466 // JS interop does not support named arguments. | 479 // JS interop does not support named arguments. |
| 467 if (selector.namedArgumentCount > 0) continue; | 480 if (selector.namedArgumentCount > 0) continue; |
| 468 if (argumentCount < minArgs) continue; | 481 if (argumentCount < minArgs) continue; |
| 469 if (argumentCount > maxArgs) continue; | 482 if (argumentCount > maxArgs) continue; |
| 470 var stubName = namer.invocationName(selector); | 483 var stubName = _namer.invocationName(selector); |
| 471 if (!stubNames.add(stubName.key)) continue; | 484 if (!stubNames.add(stubName.key)) continue; |
| 472 var parameters = | 485 var parameters = |
| 473 new List<String>.generate(argumentCount, (i) => 'p$i'); | 486 new List<String>.generate(argumentCount, (i) => 'p$i'); |
| 474 | 487 |
| 475 // We intentionally generate the same stub method for direct | 488 // We intentionally generate the same stub method for direct |
| 476 // calls and call-throughs of getters so that calling a | 489 // calls and call-throughs of getters so that calling a |
| 477 // getter that returns a function behaves the same as calling | 490 // getter that returns a function behaves the same as calling |
| 478 // a method. This is helpful as many typed JavaScript APIs | 491 // a method. This is helpful as many typed JavaScript APIs |
| 479 // specify member functions with getters that return | 492 // specify member functions with getters that return |
| 480 // functions. The behavior of this solution matches JavaScript | 493 // functions. The behavior of this solution matches JavaScript |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 if (_nativeData.isJsInteropClass(element)) { | 543 if (_nativeData.isJsInteropClass(element)) { |
| 531 // TODO(jacobr): check whether the class has any active static fields | 544 // TODO(jacobr): check whether the class has any active static fields |
| 532 // if it does not we can suppress it completely. | 545 // if it does not we can suppress it completely. |
| 533 onlyForRti = true; | 546 onlyForRti = true; |
| 534 } | 547 } |
| 535 | 548 |
| 536 List<Method> methods = []; | 549 List<Method> methods = []; |
| 537 List<StubMethod> callStubs = <StubMethod>[]; | 550 List<StubMethod> callStubs = <StubMethod>[]; |
| 538 | 551 |
| 539 ClassStubGenerator classStubGenerator = new ClassStubGenerator( | 552 ClassStubGenerator classStubGenerator = new ClassStubGenerator( |
| 540 namer, _backend, _worldBuilder, closedWorld, | 553 _namer, _backend, _worldBuilder, _closedWorld, |
| 541 enableMinification: _options.enableMinification); | 554 enableMinification: _options.enableMinification); |
| 542 RuntimeTypeGenerator runtimeTypeGenerator = | 555 RuntimeTypeGenerator runtimeTypeGenerator = |
| 543 new RuntimeTypeGenerator(_compiler, _task, namer); | 556 new RuntimeTypeGenerator(_compiler, _task, _namer); |
| 544 | 557 |
| 545 void visitMember(ClassElement enclosing, MemberElement member) { | 558 void visitMember(ClassElement enclosing, MemberElement member) { |
| 546 assert(invariant(element, member.isDeclaration)); | 559 assert(invariant(element, member.isDeclaration)); |
| 547 assert(invariant(element, element == enclosing)); | 560 assert(invariant(element, element == enclosing)); |
| 548 | 561 |
| 549 if (Elements.isNonAbstractInstanceMember(member)) { | 562 if (Elements.isNonAbstractInstanceMember(member)) { |
| 550 // TODO(herhut): Remove once _buildMethod can no longer return null. | 563 // TODO(herhut): Remove once _buildMethod can no longer return null. |
| 551 Method method = _buildMethod(member); | 564 Method method = _buildMethod(member); |
| 552 if (method != null) methods.add(method); | 565 if (method != null) methods.add(method); |
| 553 } | 566 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 577 _symbolsMap[name] = selectorName; | 590 _symbolsMap[name] = selectorName; |
| 578 } | 591 } |
| 579 noSuchMethodStubs.add( | 592 noSuchMethodStubs.add( |
| 580 classStubGenerator.generateStubForNoSuchMethod(name, selector)); | 593 classStubGenerator.generateStubForNoSuchMethod(name, selector)); |
| 581 }); | 594 }); |
| 582 } | 595 } |
| 583 | 596 |
| 584 if (element == _commonElements.closureClass) { | 597 if (element == _commonElements.closureClass) { |
| 585 // We add a special getter here to allow for tearing off a closure from | 598 // We add a special getter here to allow for tearing off a closure from |
| 586 // itself. | 599 // itself. |
| 587 js.Name name = namer.getterForMember(Names.call); | 600 js.Name name = _namer.getterForMember(Names.call); |
| 588 js.Fun function = js.js('function() { return this; }'); | 601 js.Fun function = js.js('function() { return this; }'); |
| 589 callStubs.add(_buildStubMethod(name, function)); | 602 callStubs.add(_buildStubMethod(name, function)); |
| 590 } | 603 } |
| 591 | 604 |
| 592 ClassElement implementation = element.implementation; | 605 ClassElement implementation = element.implementation; |
| 593 | 606 |
| 594 // MixinApplications run through the members of their mixin. Here, we are | 607 // MixinApplications run through the members of their mixin. Here, we are |
| 595 // only interested in direct members. | 608 // only interested in direct members. |
| 596 if (!onlyForRti && !element.isMixinApplication) { | 609 if (!onlyForRti && !element.isMixinApplication) { |
| 597 implementation.forEachMember(visitMember, includeBackendMembers: true); | 610 implementation.forEachMember(visitMember, includeBackendMembers: true); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 617 .isChecks | 630 .isChecks |
| 618 .add(_buildStubMethod(name, code)); | 631 .add(_buildStubMethod(name, code)); |
| 619 }); | 632 }); |
| 620 } else { | 633 } else { |
| 621 for (Field field in instanceFields) { | 634 for (Field field in instanceFields) { |
| 622 if (field.needsCheckedSetter) { | 635 if (field.needsCheckedSetter) { |
| 623 assert(!field.needsUncheckedSetter); | 636 assert(!field.needsUncheckedSetter); |
| 624 FieldElement element = field.element; | 637 FieldElement element = field.element; |
| 625 js.Expression code = _backend.generatedCode[element]; | 638 js.Expression code = _backend.generatedCode[element]; |
| 626 assert(code != null); | 639 assert(code != null); |
| 627 js.Name name = namer.deriveSetterName(field.accessorName); | 640 js.Name name = _namer.deriveSetterName(field.accessorName); |
| 628 checkedSetters.add(_buildStubMethod(name, code, element: element)); | 641 checkedSetters.add(_buildStubMethod(name, code, element: element)); |
| 629 } | 642 } |
| 630 } | 643 } |
| 631 | 644 |
| 632 typeTests.properties.forEach((js.Name name, js.Node code) { | 645 typeTests.properties.forEach((js.Name name, js.Node code) { |
| 633 isChecks.add(_buildStubMethod(name, code)); | 646 isChecks.add(_buildStubMethod(name, code)); |
| 634 }); | 647 }); |
| 635 } | 648 } |
| 636 | 649 |
| 637 js.Name name = namer.className(element); | 650 js.Name name = _namer.className(element); |
| 638 String holderName = namer.globalObjectFor(element); | 651 String holderName = _namer.globalObjectFor(element); |
| 639 // TODO(floitsch): we shouldn't update the registry in the middle of | 652 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 640 // building a class. | 653 // building a class. |
| 641 Holder holder = _registry.registerHolder(holderName); | 654 Holder holder = _registry.registerHolder(holderName); |
| 642 bool isInstantiated = !_nativeData.isJsInteropClass(element) && | 655 bool isInstantiated = !_nativeData.isJsInteropClass(element) && |
| 643 _worldBuilder.directlyInstantiatedClasses.contains(element); | 656 _worldBuilder.directlyInstantiatedClasses.contains(element); |
| 644 | 657 |
| 645 Class result; | 658 Class result; |
| 646 if (element.isMixinApplication && !onlyForRti) { | 659 if (element.isMixinApplication && !onlyForRti) { |
| 647 assert(!_nativeData.isNativeClass(element)); | 660 assert(!_nativeData.isNativeClass(element)); |
| 648 assert(methods.isEmpty); | 661 assert(methods.isEmpty); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 bool _methodNeedsStubs(FunctionElement method) { | 698 bool _methodNeedsStubs(FunctionElement method) { |
| 686 return !method.functionSignature.optionalParameters.isEmpty; | 699 return !method.functionSignature.optionalParameters.isEmpty; |
| 687 } | 700 } |
| 688 | 701 |
| 689 bool _methodCanBeReflected(MethodElement method) { | 702 bool _methodCanBeReflected(MethodElement method) { |
| 690 return _mirrorsData.isMemberAccessibleByReflection(method); | 703 return _mirrorsData.isMemberAccessibleByReflection(method); |
| 691 } | 704 } |
| 692 | 705 |
| 693 bool _methodCanBeApplied(FunctionElement method) { | 706 bool _methodCanBeApplied(FunctionElement method) { |
| 694 return _backendUsage.isFunctionApplyUsed && | 707 return _backendUsage.isFunctionApplyUsed && |
| 695 closedWorld.getMightBePassedToApply(method); | 708 _closedWorld.getMightBePassedToApply(method); |
| 696 } | 709 } |
| 697 | 710 |
| 698 /* Map | List */ _computeParameterDefaultValues(FunctionSignature signature) { | 711 /* Map | List */ _computeParameterDefaultValues(FunctionSignature signature) { |
| 699 var /* Map | List */ optionalParameterDefaultValues; | 712 var /* Map | List */ optionalParameterDefaultValues; |
| 700 if (signature.optionalParametersAreNamed) { | 713 if (signature.optionalParametersAreNamed) { |
| 701 optionalParameterDefaultValues = new Map<String, ConstantValue>(); | 714 optionalParameterDefaultValues = new Map<String, ConstantValue>(); |
| 702 signature.forEachOptionalParameter((ParameterElement parameter) { | 715 signature.forEachOptionalParameter((ParameterElement parameter) { |
| 703 ConstantValue def = | 716 ConstantValue def = |
| 704 _constantHandler.getConstantValue(parameter.constant); | 717 _constantHandler.getConstantValue(parameter.constant); |
| 705 optionalParameterDefaultValues[parameter.name] = def; | 718 optionalParameterDefaultValues[parameter.name] = def; |
| 706 }); | 719 }); |
| 707 } else { | 720 } else { |
| 708 optionalParameterDefaultValues = <ConstantValue>[]; | 721 optionalParameterDefaultValues = <ConstantValue>[]; |
| 709 signature.forEachOptionalParameter((ParameterElement parameter) { | 722 signature.forEachOptionalParameter((ParameterElement parameter) { |
| 710 ConstantValue def = | 723 ConstantValue def = |
| 711 _constantHandler.getConstantValue(parameter.constant); | 724 _constantHandler.getConstantValue(parameter.constant); |
| 712 optionalParameterDefaultValues.add(def); | 725 optionalParameterDefaultValues.add(def); |
| 713 }); | 726 }); |
| 714 } | 727 } |
| 715 return optionalParameterDefaultValues; | 728 return optionalParameterDefaultValues; |
| 716 } | 729 } |
| 717 | 730 |
| 718 DartMethod _buildMethod(MethodElement element) { | 731 DartMethod _buildMethod(MethodElement element) { |
| 719 assert(element.isDeclaration); | 732 assert(element.isDeclaration); |
| 720 js.Name name = namer.methodPropertyName(element); | 733 js.Name name = _namer.methodPropertyName(element); |
| 721 js.Expression code = _backend.generatedCode[element]; | 734 js.Expression code = _backend.generatedCode[element]; |
| 722 | 735 |
| 723 // TODO(kasperl): Figure out under which conditions code is null. | 736 // TODO(kasperl): Figure out under which conditions code is null. |
| 724 if (code == null) return null; | 737 if (code == null) return null; |
| 725 | 738 |
| 726 bool canTearOff = false; | 739 bool canTearOff = false; |
| 727 js.Name tearOffName; | 740 js.Name tearOffName; |
| 728 bool isClosureCallMethod = false; | 741 bool isClosureCallMethod = false; |
| 729 bool isNotApplyTarget = !element.isFunction || element.isAccessor; | 742 bool isNotApplyTarget = !element.isFunction || element.isAccessor; |
| 730 | 743 |
| 731 bool canBeReflected = _methodCanBeReflected(element); | 744 bool canBeReflected = _methodCanBeReflected(element); |
| 732 bool canBeApplied = _methodCanBeApplied(element); | 745 bool canBeApplied = _methodCanBeApplied(element); |
| 733 | 746 |
| 734 js.Name aliasName = _superMemberData.isAliasedSuperMember(element) | 747 js.Name aliasName = _superMemberData.isAliasedSuperMember(element) |
| 735 ? namer.aliasedSuperMemberPropertyName(element) | 748 ? _namer.aliasedSuperMemberPropertyName(element) |
| 736 : null; | 749 : null; |
| 737 | 750 |
| 738 if (isNotApplyTarget) { | 751 if (isNotApplyTarget) { |
| 739 canTearOff = false; | 752 canTearOff = false; |
| 740 } else { | 753 } else { |
| 741 if (element.enclosingClass.isClosure) { | 754 if (element.enclosingClass.isClosure) { |
| 742 canTearOff = false; | 755 canTearOff = false; |
| 743 isClosureCallMethod = true; | 756 isClosureCallMethod = true; |
| 744 } else { | 757 } else { |
| 745 // Careful with operators. | 758 // Careful with operators. |
| 746 canTearOff = _worldBuilder.hasInvokedGetter(element, closedWorld) || | 759 canTearOff = _worldBuilder.hasInvokedGetter(element, _closedWorld) || |
| 747 (canBeReflected && !element.isOperator); | 760 (canBeReflected && !element.isOperator); |
| 748 assert(canTearOff || | 761 assert(canTearOff || |
| 749 !_worldBuilder.methodsNeedingSuperGetter.contains(element)); | 762 !_worldBuilder.methodsNeedingSuperGetter.contains(element)); |
| 750 tearOffName = namer.getterForElement(element); | 763 tearOffName = _namer.getterForElement(element); |
| 751 } | 764 } |
| 752 } | 765 } |
| 753 | 766 |
| 754 if (canTearOff) { | 767 if (canTearOff) { |
| 755 assert(invariant(element, !element.isGenerativeConstructor)); | 768 assert(invariant(element, !element.isGenerativeConstructor)); |
| 756 assert(invariant(element, !element.isGenerativeConstructorBody)); | 769 assert(invariant(element, !element.isGenerativeConstructorBody)); |
| 757 assert(invariant(element, !element.isConstructor)); | 770 assert(invariant(element, !element.isConstructor)); |
| 758 } | 771 } |
| 759 | 772 |
| 760 js.Name callName = null; | 773 js.Name callName = null; |
| 761 if (canTearOff) { | 774 if (canTearOff) { |
| 762 Selector callSelector = | 775 Selector callSelector = |
| 763 new Selector.fromElement(element).toCallSelector(); | 776 new Selector.fromElement(element).toCallSelector(); |
| 764 callName = namer.invocationName(callSelector); | 777 callName = _namer.invocationName(callSelector); |
| 765 } | 778 } |
| 766 | 779 |
| 767 ResolutionDartType memberType; | 780 ResolutionDartType memberType; |
| 768 if (element.isGenerativeConstructorBody) { | 781 if (element.isGenerativeConstructorBody) { |
| 769 // TODO(herhut): Why does this need to be normalized away? We never need | 782 // TODO(herhut): Why does this need to be normalized away? We never need |
| 770 // this information anyway as they cannot be torn off or | 783 // this information anyway as they cannot be torn off or |
| 771 // reflected. | 784 // reflected. |
| 772 var body = element; | 785 var body = element; |
| 773 memberType = body.constructor.type; | 786 memberType = body.constructor.type; |
| 774 } else { | 787 } else { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 return _emitter.metadataCollector | 826 return _emitter.metadataCollector |
| 814 .reifyTypeForOutputUnit(type, outputUnit); | 827 .reifyTypeForOutputUnit(type, outputUnit); |
| 815 } | 828 } |
| 816 } | 829 } |
| 817 | 830 |
| 818 List<ParameterStubMethod> _generateParameterStubs( | 831 List<ParameterStubMethod> _generateParameterStubs( |
| 819 MethodElement element, bool canTearOff) { | 832 MethodElement element, bool canTearOff) { |
| 820 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; | 833 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; |
| 821 | 834 |
| 822 ParameterStubGenerator generator = | 835 ParameterStubGenerator generator = |
| 823 new ParameterStubGenerator(_compiler, namer, _backend, closedWorld); | 836 new ParameterStubGenerator(_compiler, _namer, _backend, _closedWorld); |
| 824 return generator.generateParameterStubs(element, canTearOff: canTearOff); | 837 return generator.generateParameterStubs(element, canTearOff: canTearOff); |
| 825 } | 838 } |
| 826 | 839 |
| 827 /// Builds a stub method. | 840 /// Builds a stub method. |
| 828 /// | 841 /// |
| 829 /// Stub methods may have an element that can be used for code-size | 842 /// Stub methods may have an element that can be used for code-size |
| 830 /// attribution. | 843 /// attribution. |
| 831 Method _buildStubMethod(js.Name name, js.Expression code, | 844 Method _buildStubMethod(js.Name name, js.Expression code, |
| 832 {MemberElement element}) { | 845 {MemberElement element}) { |
| 833 return new StubMethod(name, code, element: element); | 846 return new StubMethod(name, code, element: element); |
| 834 } | 847 } |
| 835 | 848 |
| 836 // The getInterceptor methods directly access the prototype of classes. | 849 // The getInterceptor methods directly access the prototype of classes. |
| 837 // We must evaluate these classes eagerly so that the prototype is | 850 // We must evaluate these classes eagerly so that the prototype is |
| 838 // accessible. | 851 // accessible. |
| 839 void _markEagerInterceptorClasses() { | 852 void _markEagerInterceptorClasses() { |
| 840 Iterable<js.Name> names = | 853 Iterable<js.Name> names = |
| 841 _oneShotInterceptorData.specializedGetInterceptorNames; | 854 _oneShotInterceptorData.specializedGetInterceptorNames; |
| 842 for (js.Name name in names) { | 855 for (js.Name name in names) { |
| 843 for (ClassElement element | 856 for (ClassElement element |
| 844 in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) { | 857 in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) { |
| 845 Class cls = _classes[element]; | 858 Class cls = _classes[element]; |
| 846 if (cls != null) cls.isEager = true; | 859 if (cls != null) cls.isEager = true; |
| 847 } | 860 } |
| 848 } | 861 } |
| 849 } | 862 } |
| 850 | 863 |
| 851 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { | 864 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { |
| 852 InterceptorStubGenerator stubGenerator = | 865 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( |
| 853 new InterceptorStubGenerator(_compiler, namer, _backend, closedWorld); | 866 _options, |
| 867 _commonElements, |
| 868 _emitter, |
| 869 _nativeCodegenEnqueuer, |
| 870 _constantHandler, |
| 871 _namer, |
| 872 _nativeData, |
| 873 _interceptorData, |
| 874 _oneShotInterceptorData, |
| 875 _customElementsCodegenAnalysis, |
| 876 _worldBuilder, |
| 877 _closedWorld); |
| 854 | 878 |
| 855 String holderName = | 879 String holderName = |
| 856 namer.globalObjectForLibrary(_commonElements.interceptorsLibrary); | 880 _namer.globalObjectForLibrary(_commonElements.interceptorsLibrary); |
| 857 // TODO(floitsch): we shouldn't update the registry in the middle of | 881 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 858 // generating the interceptor methods. | 882 // generating the interceptor methods. |
| 859 Holder holder = _registry.registerHolder(holderName); | 883 Holder holder = _registry.registerHolder(holderName); |
| 860 | 884 |
| 861 Iterable<js.Name> names = | 885 Iterable<js.Name> names = |
| 862 _oneShotInterceptorData.specializedGetInterceptorNames; | 886 _oneShotInterceptorData.specializedGetInterceptorNames; |
| 863 return names.map((js.Name name) { | 887 return names.map((js.Name name) { |
| 864 Set<ClassEntity> classes = | 888 Set<ClassEntity> classes = |
| 865 _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name); | 889 _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name); |
| 866 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); | 890 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); |
| 867 return new StaticStubMethod(name, holder, code); | 891 return new StaticStubMethod(name, holder, code); |
| 868 }); | 892 }); |
| 869 } | 893 } |
| 870 | 894 |
| 871 List<Field> _buildFields(Element holder, | 895 List<Field> _buildFields(Element holder, |
| 872 {bool visitStatics, bool isHolderInterceptedClass: false}) { | 896 {bool visitStatics, bool isHolderInterceptedClass: false}) { |
| 873 List<Field> fields = <Field>[]; | 897 List<Field> fields = <Field>[]; |
| 874 new FieldVisitor(_compiler, namer, closedWorld) | 898 new FieldVisitor(_compiler, _namer, _closedWorld) |
| 875 .visitFields(holder, visitStatics, (FieldElement field, | 899 .visitFields(holder, visitStatics, (FieldElement field, |
| 876 js.Name name, | 900 js.Name name, |
| 877 js.Name accessorName, | 901 js.Name accessorName, |
| 878 bool needsGetter, | 902 bool needsGetter, |
| 879 bool needsSetter, | 903 bool needsSetter, |
| 880 bool needsCheckedSetter) { | 904 bool needsCheckedSetter) { |
| 881 assert(invariant(field, field.isDeclaration)); | 905 assert(invariant(field, field.isDeclaration)); |
| 882 | 906 |
| 883 int getterFlags = 0; | 907 int getterFlags = 0; |
| 884 if (needsGetter) { | 908 if (needsGetter) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 910 } | 934 } |
| 911 | 935 |
| 912 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags, | 936 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags, |
| 913 needsCheckedSetter)); | 937 needsCheckedSetter)); |
| 914 }); | 938 }); |
| 915 | 939 |
| 916 return fields; | 940 return fields; |
| 917 } | 941 } |
| 918 | 942 |
| 919 Iterable<StaticStubMethod> _generateOneShotInterceptors() { | 943 Iterable<StaticStubMethod> _generateOneShotInterceptors() { |
| 920 InterceptorStubGenerator stubGenerator = | 944 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( |
| 921 new InterceptorStubGenerator(_compiler, namer, _backend, closedWorld); | 945 _options, |
| 946 _commonElements, |
| 947 _emitter, |
| 948 _nativeCodegenEnqueuer, |
| 949 _constantHandler, |
| 950 _namer, |
| 951 _nativeData, |
| 952 _interceptorData, |
| 953 _oneShotInterceptorData, |
| 954 _customElementsCodegenAnalysis, |
| 955 _worldBuilder, |
| 956 _closedWorld); |
| 922 | 957 |
| 923 String holderName = | 958 String holderName = |
| 924 namer.globalObjectForLibrary(_commonElements.interceptorsLibrary); | 959 _namer.globalObjectForLibrary(_commonElements.interceptorsLibrary); |
| 925 // TODO(floitsch): we shouldn't update the registry in the middle of | 960 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 926 // generating the interceptor methods. | 961 // generating the interceptor methods. |
| 927 Holder holder = _registry.registerHolder(holderName); | 962 Holder holder = _registry.registerHolder(holderName); |
| 928 | 963 |
| 929 List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames; | 964 List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames; |
| 930 return names.map((js.Name name) { | 965 return names.map((js.Name name) { |
| 931 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 966 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
| 932 return new StaticStubMethod(name, holder, code); | 967 return new StaticStubMethod(name, holder, code); |
| 933 }); | 968 }); |
| 934 } | 969 } |
| 935 | 970 |
| 936 StaticDartMethod _buildStaticMethod(MethodElement element) { | 971 StaticDartMethod _buildStaticMethod(MethodElement element) { |
| 937 js.Name name = namer.methodPropertyName(element); | 972 js.Name name = _namer.methodPropertyName(element); |
| 938 String holder = namer.globalObjectFor(element); | 973 String holder = _namer.globalObjectFor(element); |
| 939 js.Expression code = _backend.generatedCode[element]; | 974 js.Expression code = _backend.generatedCode[element]; |
| 940 | 975 |
| 941 bool isApplyTarget = !element.isConstructor && !element.isAccessor; | 976 bool isApplyTarget = !element.isConstructor && !element.isAccessor; |
| 942 bool canBeApplied = _methodCanBeApplied(element); | 977 bool canBeApplied = _methodCanBeApplied(element); |
| 943 bool canBeReflected = _methodCanBeReflected(element); | 978 bool canBeReflected = _methodCanBeReflected(element); |
| 944 | 979 |
| 945 bool needsTearOff = isApplyTarget && | 980 bool needsTearOff = isApplyTarget && |
| 946 (canBeReflected || | 981 (canBeReflected || |
| 947 _worldBuilder.staticFunctionsNeedingGetter.contains(element)); | 982 _worldBuilder.staticFunctionsNeedingGetter.contains(element)); |
| 948 | 983 |
| 949 js.Name tearOffName = | 984 js.Name tearOffName = |
| 950 needsTearOff ? namer.staticClosureName(element) : null; | 985 needsTearOff ? _namer.staticClosureName(element) : null; |
| 951 | 986 |
| 952 js.Name callName = null; | 987 js.Name callName = null; |
| 953 if (needsTearOff) { | 988 if (needsTearOff) { |
| 954 Selector callSelector = | 989 Selector callSelector = |
| 955 new Selector.fromElement(element).toCallSelector(); | 990 new Selector.fromElement(element).toCallSelector(); |
| 956 callName = namer.invocationName(callSelector); | 991 callName = _namer.invocationName(callSelector); |
| 957 } | 992 } |
| 958 js.Expression functionType; | 993 js.Expression functionType; |
| 959 ResolutionDartType type = element.type; | 994 ResolutionDartType type = element.type; |
| 960 if (needsTearOff || canBeReflected) { | 995 if (needsTearOff || canBeReflected) { |
| 961 OutputUnit outputUnit = _deferredLoadTask.outputUnitForElement(element); | 996 OutputUnit outputUnit = _deferredLoadTask.outputUnitForElement(element); |
| 962 functionType = _generateFunctionType(type, outputUnit); | 997 functionType = _generateFunctionType(type, outputUnit); |
| 963 } | 998 } |
| 964 | 999 |
| 965 int requiredParameterCount; | 1000 int requiredParameterCount; |
| 966 var /* List | Map */ optionalParameterDefaultValues; | 1001 var /* List | Map */ optionalParameterDefaultValues; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 984 functionType: functionType); | 1019 functionType: functionType); |
| 985 } | 1020 } |
| 986 | 1021 |
| 987 void _registerConstants( | 1022 void _registerConstants( |
| 988 OutputUnit outputUnit, Iterable<ConstantValue> constantValues) { | 1023 OutputUnit outputUnit, Iterable<ConstantValue> constantValues) { |
| 989 // `constantValues` is null if an outputUnit doesn't contain any constants. | 1024 // `constantValues` is null if an outputUnit doesn't contain any constants. |
| 990 if (constantValues == null) return; | 1025 if (constantValues == null) return; |
| 991 for (ConstantValue constantValue in constantValues) { | 1026 for (ConstantValue constantValue in constantValues) { |
| 992 _registry.registerConstant(outputUnit, constantValue); | 1027 _registry.registerConstant(outputUnit, constantValue); |
| 993 assert(!_constants.containsKey(constantValue)); | 1028 assert(!_constants.containsKey(constantValue)); |
| 994 js.Name name = namer.constantName(constantValue); | 1029 js.Name name = _namer.constantName(constantValue); |
| 995 String constantObject = namer.globalObjectForConstant(constantValue); | 1030 String constantObject = _namer.globalObjectForConstant(constantValue); |
| 996 Holder holder = | 1031 Holder holder = |
| 997 _registry.registerHolder(constantObject, isConstantsHolder: true); | 1032 _registry.registerHolder(constantObject, isConstantsHolder: true); |
| 998 Constant constant = new Constant(name, holder, constantValue); | 1033 Constant constant = new Constant(name, holder, constantValue); |
| 999 _constants[constantValue] = constant; | 1034 _constants[constantValue] = constant; |
| 1000 } | 1035 } |
| 1001 } | 1036 } |
| 1002 | 1037 |
| 1003 Holder _registerStaticStateHolder() { | 1038 Holder _registerStaticStateHolder() { |
| 1004 return _registry.registerHolder(namer.staticStateHolder, | 1039 return _registry.registerHolder(_namer.staticStateHolder, |
| 1005 isStaticStateHolder: true); | 1040 isStaticStateHolder: true); |
| 1006 } | 1041 } |
| 1007 } | 1042 } |
| OLD | NEW |