| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.js_emitter.program_builder; | 5 library dart2js.js_emitter.program_builder; |
| 6 | 6 |
| 7 import 'js_emitter.dart' show computeMixinClass; | 7 import 'js_emitter.dart' show computeMixinClass; |
| 8 import 'model.dart'; | 8 import 'model.dart'; |
| 9 | 9 |
| 10 import '../common.dart'; | 10 import '../common.dart'; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 .toList(growable: false); | 207 .toList(growable: false); |
| 208 } | 208 } |
| 209 | 209 |
| 210 StaticField _buildStaticField(Element element) { | 210 StaticField _buildStaticField(Element element) { |
| 211 JavaScriptConstantCompiler handler = backend.constants; | 211 JavaScriptConstantCompiler handler = backend.constants; |
| 212 ConstantValue initialValue = handler.getInitialValueFor(element); | 212 ConstantValue initialValue = handler.getInitialValueFor(element); |
| 213 // TODO(zarah): The holder should not be registered during building of | 213 // TODO(zarah): The holder should not be registered during building of |
| 214 // a static field. | 214 // a static field. |
| 215 _registry.registerHolder(namer.globalObjectForConstant(initialValue)); | 215 _registry.registerHolder(namer.globalObjectForConstant(initialValue)); |
| 216 js.Expression code = _task.emitter.constantReference(initialValue); | 216 js.Expression code = _task.emitter.constantReference(initialValue); |
| 217 String name = namer.globalPropertyName(element); | 217 js.Name name = namer.globalPropertyName(element); |
| 218 bool isFinal = false; | 218 bool isFinal = false; |
| 219 bool isLazy = false; | 219 bool isLazy = false; |
| 220 | 220 |
| 221 // TODO(floitsch): we shouldn't update the registry in the middle of | 221 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 222 // building a static field. (Note that the $ holder is already registered | 222 // building a static field. (Note that the $ holder is already registered |
| 223 // earlier). | 223 // earlier). |
| 224 return new StaticField(element, | 224 return new StaticField(element, |
| 225 name, _registry.registerHolder(r'$'), code, | 225 name, _registry.registerHolder(r'$'), code, |
| 226 isFinal, isLazy); | 226 isFinal, isLazy); |
| 227 } | 227 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 243 .toList(growable: false); | 243 .toList(growable: false); |
| 244 } | 244 } |
| 245 | 245 |
| 246 StaticField _buildLazyField(Element element) { | 246 StaticField _buildLazyField(Element element) { |
| 247 js.Expression code = backend.generatedCode[element]; | 247 js.Expression code = backend.generatedCode[element]; |
| 248 // The code is null if we ended up not needing the lazily | 248 // The code is null if we ended up not needing the lazily |
| 249 // initialized field after all because of constant folding | 249 // initialized field after all because of constant folding |
| 250 // before code generation. | 250 // before code generation. |
| 251 if (code == null) return null; | 251 if (code == null) return null; |
| 252 | 252 |
| 253 String name = namer.globalPropertyName(element); | 253 js.Name name = namer.globalPropertyName(element); |
| 254 bool isFinal = element.isFinal; | 254 bool isFinal = element.isFinal; |
| 255 bool isLazy = true; | 255 bool isLazy = true; |
| 256 // TODO(floitsch): we shouldn't update the registry in the middle of | 256 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 257 // building a static field. (Note that the $ holder is already registered | 257 // building a static field. (Note that the $ holder is already registered |
| 258 // earlier). | 258 // earlier). |
| 259 return new StaticField(element, | 259 return new StaticField(element, |
| 260 name, _registry.registerHolder(r'$'), code, | 260 name, _registry.registerHolder(r'$'), code, |
| 261 isFinal, isLazy); | 261 isFinal, isLazy); |
| 262 } | 262 } |
| 263 | 263 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 staticFieldsForReflection); | 299 staticFieldsForReflection); |
| 300 } | 300 } |
| 301 | 301 |
| 302 /// HACK for Incremental Compilation. | 302 /// HACK for Incremental Compilation. |
| 303 /// | 303 /// |
| 304 /// Returns a class that contains the fields of a class. | 304 /// Returns a class that contains the fields of a class. |
| 305 Class buildFieldsHackForIncrementalCompilation(ClassElement element) { | 305 Class buildFieldsHackForIncrementalCompilation(ClassElement element) { |
| 306 assert(_compiler.hasIncrementalSupport); | 306 assert(_compiler.hasIncrementalSupport); |
| 307 | 307 |
| 308 List<Field> instanceFields = _buildFields(element, false); | 308 List<Field> instanceFields = _buildFields(element, false); |
| 309 String name = namer.className(element); | 309 js.Name name = namer.className(element); |
| 310 | 310 |
| 311 return new Class( | 311 return new Class( |
| 312 element, name, null, [], instanceFields, [], [], [], [], [], null, | 312 element, name, null, [], instanceFields, [], [], [], [], [], null, |
| 313 isDirectlyInstantiated: true, | 313 isDirectlyInstantiated: true, |
| 314 onlyForRti: false, | 314 onlyForRti: false, |
| 315 isNative: element.isNative); | 315 isNative: element.isNative); |
| 316 } | 316 } |
| 317 | 317 |
| 318 Class _buildClass(ClassElement element) { | 318 Class _buildClass(ClassElement element) { |
| 319 bool onlyForRti = _task.typeTestRegistry.rtiNeededClasses.contains(element); | 319 bool onlyForRti = _task.typeTestRegistry.rtiNeededClasses.contains(element); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 333 if (Elements.isNonAbstractInstanceMember(member)) { | 333 if (Elements.isNonAbstractInstanceMember(member)) { |
| 334 // TODO(herhut): Remove once _buildMethod can no longer return null. | 334 // TODO(herhut): Remove once _buildMethod can no longer return null. |
| 335 Method method = _buildMethod(member); | 335 Method method = _buildMethod(member); |
| 336 if (method != null) methods.add(method); | 336 if (method != null) methods.add(method); |
| 337 } | 337 } |
| 338 if (member.isGetter || member.isField) { | 338 if (member.isGetter || member.isField) { |
| 339 Map<Selector, TypeMaskSet> selectors = | 339 Map<Selector, TypeMaskSet> selectors = |
| 340 _compiler.codegenWorld.invocationsByName(member.name); | 340 _compiler.codegenWorld.invocationsByName(member.name); |
| 341 if (selectors != null && !selectors.isEmpty) { | 341 if (selectors != null && !selectors.isEmpty) { |
| 342 | 342 |
| 343 Map<String, js.Expression> callStubsForMember = | 343 Map<js.Name, js.Expression> callStubsForMember = |
| 344 classStubGenerator.generateCallStubsForGetter(member, selectors); | 344 classStubGenerator.generateCallStubsForGetter(member, selectors); |
| 345 callStubsForMember.forEach((String name, js.Expression code) { | 345 callStubsForMember.forEach((js.Name name, js.Expression code) { |
| 346 callStubs.add(_buildStubMethod(name, code, element: member)); | 346 callStubs.add(_buildStubMethod(name, code, element: member)); |
| 347 }); | 347 }); |
| 348 } | 348 } |
| 349 } | 349 } |
| 350 } | 350 } |
| 351 | 351 |
| 352 List<StubMethod> typeVariableReaderStubs = | 352 List<StubMethod> typeVariableReaderStubs = |
| 353 runtimeTypeGenerator.generateTypeVariableReaderStubs(element); | 353 runtimeTypeGenerator.generateTypeVariableReaderStubs(element); |
| 354 | 354 |
| 355 List<StubMethod> noSuchMethodStubs = <StubMethod>[]; | 355 List<StubMethod> noSuchMethodStubs = <StubMethod>[]; |
| 356 if (backend.enabledNoSuchMethod && element == _compiler.objectClass) { | 356 if (backend.enabledNoSuchMethod && element == _compiler.objectClass) { |
| 357 Map<String, Selector> selectors = | 357 Map<js.Name, Selector> selectors = |
| 358 classStubGenerator.computeSelectorsForNsmHandlers(); | 358 classStubGenerator.computeSelectorsForNsmHandlers(); |
| 359 selectors.forEach((String name, Selector selector) { | 359 selectors.forEach((js.Name name, Selector selector) { |
| 360 noSuchMethodStubs | 360 noSuchMethodStubs |
| 361 .add(classStubGenerator.generateStubForNoSuchMethod(name, | 361 .add(classStubGenerator.generateStubForNoSuchMethod(name, |
| 362 selector)); | 362 selector)); |
| 363 }); | 363 }); |
| 364 } | 364 } |
| 365 | 365 |
| 366 if (element == backend.closureClass) { | 366 if (element == backend.closureClass) { |
| 367 // We add a special getter here to allow for tearing off a closure from | 367 // We add a special getter here to allow for tearing off a closure from |
| 368 // itself. | 368 // itself. |
| 369 String name = namer.getterForMember(Selector.CALL_NAME); | 369 js.Name name = namer.getterForMember(Selector.CALL_NAME); |
| 370 js.Fun function = js.js('function() { return this; }'); | 370 js.Fun function = js.js('function() { return this; }'); |
| 371 callStubs.add(_buildStubMethod(name, function)); | 371 callStubs.add(_buildStubMethod(name, function)); |
| 372 } | 372 } |
| 373 | 373 |
| 374 ClassElement implementation = element.implementation; | 374 ClassElement implementation = element.implementation; |
| 375 | 375 |
| 376 // MixinApplications run through the members of their mixin. Here, we are | 376 // MixinApplications run through the members of their mixin. Here, we are |
| 377 // only interested in direct members. | 377 // only interested in direct members. |
| 378 if (!onlyForRti && !element.isMixinApplication) { | 378 if (!onlyForRti && !element.isMixinApplication) { |
| 379 implementation.forEachMember(visitMember, includeBackendMembers: true); | 379 implementation.forEachMember(visitMember, includeBackendMembers: true); |
| 380 } | 380 } |
| 381 | 381 |
| 382 List<Field> instanceFields = | 382 List<Field> instanceFields = |
| 383 onlyForRti ? const <Field>[] : _buildFields(element, false); | 383 onlyForRti ? const <Field>[] : _buildFields(element, false); |
| 384 List<Field> staticFieldsForReflection = | 384 List<Field> staticFieldsForReflection = |
| 385 onlyForRti ? const <Field>[] : _buildFields(element, true); | 385 onlyForRti ? const <Field>[] : _buildFields(element, true); |
| 386 | 386 |
| 387 TypeTestProperties typeTests = | 387 TypeTestProperties typeTests = |
| 388 runtimeTypeGenerator.generateIsTests( | 388 runtimeTypeGenerator.generateIsTests( |
| 389 element, | 389 element, |
| 390 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); | 390 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); |
| 391 | 391 |
| 392 List<StubMethod> isChecks = <StubMethod>[]; | 392 List<StubMethod> isChecks = <StubMethod>[]; |
| 393 typeTests.properties.forEach((String name, js.Node code) { | 393 typeTests.properties.forEach((js.Name name, js.Node code) { |
| 394 isChecks.add(_buildStubMethod(name, code)); | 394 isChecks.add(_buildStubMethod(name, code)); |
| 395 }); | 395 }); |
| 396 | 396 |
| 397 String name = namer.className(element); | 397 js.Name name = namer.className(element); |
| 398 String holderName = namer.globalObjectFor(element); | 398 String holderName = namer.globalObjectFor(element); |
| 399 // TODO(floitsch): we shouldn't update the registry in the middle of | 399 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 400 // building a class. | 400 // building a class. |
| 401 Holder holder = _registry.registerHolder(holderName); | 401 Holder holder = _registry.registerHolder(holderName); |
| 402 bool isInstantiated = | 402 bool isInstantiated = |
| 403 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); | 403 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); |
| 404 | 404 |
| 405 Class result; | 405 Class result; |
| 406 if (element.isMixinApplication && !onlyForRti) { | 406 if (element.isMixinApplication && !onlyForRti) { |
| 407 assert(!element.isNative); | 407 assert(!element.isNative); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 signature.forEachOptionalParameter((ParameterElement parameter) { | 474 signature.forEachOptionalParameter((ParameterElement parameter) { |
| 475 ConstantValue def = | 475 ConstantValue def = |
| 476 backend.constants.getConstantValueForVariable(parameter); | 476 backend.constants.getConstantValueForVariable(parameter); |
| 477 optionalParameterDefaultValues.add(def); | 477 optionalParameterDefaultValues.add(def); |
| 478 }); | 478 }); |
| 479 } | 479 } |
| 480 return optionalParameterDefaultValues; | 480 return optionalParameterDefaultValues; |
| 481 } | 481 } |
| 482 | 482 |
| 483 DartMethod _buildMethod(MethodElement element) { | 483 DartMethod _buildMethod(MethodElement element) { |
| 484 String name = namer.methodPropertyName(element); | 484 js.Name name = namer.methodPropertyName(element); |
| 485 js.Expression code = backend.generatedCode[element]; | 485 js.Expression code = backend.generatedCode[element]; |
| 486 | 486 |
| 487 // TODO(kasperl): Figure out under which conditions code is null. | 487 // TODO(kasperl): Figure out under which conditions code is null. |
| 488 if (code == null) return null; | 488 if (code == null) return null; |
| 489 | 489 |
| 490 bool canTearOff = false; | 490 bool canTearOff = false; |
| 491 String tearOffName; | 491 js.Name tearOffName; |
| 492 bool isClosure = false; | 492 bool isClosure = false; |
| 493 bool isNotApplyTarget = !element.isFunction || element.isAccessor; | 493 bool isNotApplyTarget = !element.isFunction || element.isAccessor; |
| 494 | 494 |
| 495 bool canBeReflected = _methodCanBeReflected(element); | 495 bool canBeReflected = _methodCanBeReflected(element); |
| 496 bool canBeApplied = _methodCanBeApplied(element); | 496 bool canBeApplied = _methodCanBeApplied(element); |
| 497 | 497 |
| 498 String aliasName = backend.isAliasedSuperMember(element) | 498 js.Name aliasName = backend.isAliasedSuperMember(element) |
| 499 ? namer.aliasedSuperMemberPropertyName(element) | 499 ? namer.aliasedSuperMemberPropertyName(element) |
| 500 : null; | 500 : null; |
| 501 | 501 |
| 502 if (isNotApplyTarget) { | 502 if (isNotApplyTarget) { |
| 503 canTearOff = false; | 503 canTearOff = false; |
| 504 } else { | 504 } else { |
| 505 if (element.enclosingClass.isClosure) { | 505 if (element.enclosingClass.isClosure) { |
| 506 canTearOff = false; | 506 canTearOff = false; |
| 507 isClosure = true; | 507 isClosure = true; |
| 508 } else { | 508 } else { |
| 509 // Careful with operators. | 509 // Careful with operators. |
| 510 canTearOff = universe.hasInvokedGetter(element, _compiler.world) || | 510 canTearOff = universe.hasInvokedGetter(element, _compiler.world) || |
| 511 (canBeReflected && !element.isOperator); | 511 (canBeReflected && !element.isOperator); |
| 512 assert(canTearOff || | 512 assert(canTearOff || |
| 513 !universe.methodsNeedingSuperGetter.contains(element)); | 513 !universe.methodsNeedingSuperGetter.contains(element)); |
| 514 tearOffName = namer.getterForElement(element); | 514 tearOffName = namer.getterForElement(element); |
| 515 } | 515 } |
| 516 } | 516 } |
| 517 | 517 |
| 518 if (canTearOff) { | 518 if (canTearOff) { |
| 519 assert(invariant(element, !element.isGenerativeConstructor)); | 519 assert(invariant(element, !element.isGenerativeConstructor)); |
| 520 assert(invariant(element, !element.isGenerativeConstructorBody)); | 520 assert(invariant(element, !element.isGenerativeConstructorBody)); |
| 521 assert(invariant(element, !element.isConstructor)); | 521 assert(invariant(element, !element.isConstructor)); |
| 522 } | 522 } |
| 523 | 523 |
| 524 String callName = null; | 524 js.Name callName = null; |
| 525 if (canTearOff) { | 525 if (canTearOff) { |
| 526 Selector callSelector = | 526 Selector callSelector = |
| 527 new Selector.fromElement(element).toCallSelector(); | 527 new Selector.fromElement(element).toCallSelector(); |
| 528 callName = namer.invocationName(callSelector); | 528 callName = namer.invocationName(callSelector); |
| 529 } | 529 } |
| 530 | 530 |
| 531 DartType memberType; | 531 DartType memberType; |
| 532 if (element.isGenerativeConstructorBody) { | 532 if (element.isGenerativeConstructorBody) { |
| 533 // TODO(herhut): Why does this need to be normalized away? We never need | 533 // TODO(herhut): Why does this need to be normalized away? We never need |
| 534 // this information anyway as they cannot be torn off or | 534 // this information anyway as they cannot be torn off or |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 | 582 |
| 583 ParameterStubGenerator generator = | 583 ParameterStubGenerator generator = |
| 584 new ParameterStubGenerator(_compiler, namer, backend); | 584 new ParameterStubGenerator(_compiler, namer, backend); |
| 585 return generator.generateParameterStubs(element, canTearOff: canTearOff); | 585 return generator.generateParameterStubs(element, canTearOff: canTearOff); |
| 586 } | 586 } |
| 587 | 587 |
| 588 /// Builds a stub method. | 588 /// Builds a stub method. |
| 589 /// | 589 /// |
| 590 /// Stub methods may have an element that can be used for code-size | 590 /// Stub methods may have an element that can be used for code-size |
| 591 /// attribution. | 591 /// attribution. |
| 592 Method _buildStubMethod(String name, js.Expression code, | 592 Method _buildStubMethod(js.Name name, js.Expression code, |
| 593 {Element element}) { | 593 {Element element}) { |
| 594 return new StubMethod(name, code, element: element); | 594 return new StubMethod(name, code, element: element); |
| 595 } | 595 } |
| 596 | 596 |
| 597 // The getInterceptor methods directly access the prototype of classes. | 597 // The getInterceptor methods directly access the prototype of classes. |
| 598 // We must evaluate these classes eagerly so that the prototype is | 598 // We must evaluate these classes eagerly so that the prototype is |
| 599 // accessible. | 599 // accessible. |
| 600 void _markEagerInterceptorClasses() { | 600 void _markEagerInterceptorClasses() { |
| 601 Map<String, Set<ClassElement>> specializedGetInterceptors = | 601 Map<js.Name, Set<ClassElement>> specializedGetInterceptors = |
| 602 backend.specializedGetInterceptors; | 602 backend.specializedGetInterceptors; |
| 603 for (Set<ClassElement> classes in specializedGetInterceptors.values) { | 603 for (Set<ClassElement> classes in specializedGetInterceptors.values) { |
| 604 for (ClassElement element in classes) { | 604 for (ClassElement element in classes) { |
| 605 Class cls = _classes[element]; | 605 Class cls = _classes[element]; |
| 606 if (cls != null) cls.isEager = true; | 606 if (cls != null) cls.isEager = true; |
| 607 } | 607 } |
| 608 } | 608 } |
| 609 } | 609 } |
| 610 | 610 |
| 611 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { | 611 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { |
| 612 InterceptorStubGenerator stubGenerator = | 612 InterceptorStubGenerator stubGenerator = |
| 613 new InterceptorStubGenerator(_compiler, namer, backend); | 613 new InterceptorStubGenerator(_compiler, namer, backend); |
| 614 | 614 |
| 615 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); | 615 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); |
| 616 // TODO(floitsch): we shouldn't update the registry in the middle of | 616 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 617 // generating the interceptor methods. | 617 // generating the interceptor methods. |
| 618 Holder holder = _registry.registerHolder(holderName); | 618 Holder holder = _registry.registerHolder(holderName); |
| 619 | 619 |
| 620 Map<String, Set<ClassElement>> specializedGetInterceptors = | 620 Map<js.Name, Set<ClassElement>> specializedGetInterceptors = |
| 621 backend.specializedGetInterceptors; | 621 backend.specializedGetInterceptors; |
| 622 List<String> names = specializedGetInterceptors.keys.toList()..sort(); | 622 List<js.Name> names = specializedGetInterceptors.keys.toList()..sort(); |
| 623 return names.map((String name) { | 623 return names.map((js.Name name) { |
| 624 Set<ClassElement> classes = specializedGetInterceptors[name]; | 624 Set<ClassElement> classes = specializedGetInterceptors[name]; |
| 625 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); | 625 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); |
| 626 return new StaticStubMethod(name, holder, code); | 626 return new StaticStubMethod(name, holder, code); |
| 627 }); | 627 }); |
| 628 } | 628 } |
| 629 | 629 |
| 630 List<Field> _buildFields(Element holder, bool visitStatics) { | 630 List<Field> _buildFields(Element holder, bool visitStatics) { |
| 631 List<Field> fields = <Field>[]; | 631 List<Field> fields = <Field>[]; |
| 632 _task.oldEmitter.classEmitter.visitFields( | 632 _task.oldEmitter.classEmitter.visitFields( |
| 633 holder, visitStatics, (VariableElement field, | 633 holder, visitStatics, (VariableElement field, |
| 634 String name, | 634 js.Name name, |
| 635 String accessorName, | 635 js.Name accessorName, |
| 636 bool needsGetter, | 636 bool needsGetter, |
| 637 bool needsSetter, | 637 bool needsSetter, |
| 638 bool needsCheckedSetter) { | 638 bool needsCheckedSetter) { |
| 639 assert(invariant(field, field.isDeclaration)); | 639 assert(invariant(field, field.isDeclaration)); |
| 640 | 640 |
| 641 int getterFlags = 0; | 641 int getterFlags = 0; |
| 642 if (needsGetter) { | 642 if (needsGetter) { |
| 643 if (visitStatics || !backend.fieldHasInterceptedGetter(field)) { | 643 if (visitStatics || !backend.fieldHasInterceptedGetter(field)) { |
| 644 getterFlags = 1; | 644 getterFlags = 1; |
| 645 } else { | 645 } else { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 675 | 675 |
| 676 Iterable<StaticStubMethod> _generateOneShotInterceptors() { | 676 Iterable<StaticStubMethod> _generateOneShotInterceptors() { |
| 677 InterceptorStubGenerator stubGenerator = | 677 InterceptorStubGenerator stubGenerator = |
| 678 new InterceptorStubGenerator(_compiler, namer, backend); | 678 new InterceptorStubGenerator(_compiler, namer, backend); |
| 679 | 679 |
| 680 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); | 680 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); |
| 681 // TODO(floitsch): we shouldn't update the registry in the middle of | 681 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 682 // generating the interceptor methods. | 682 // generating the interceptor methods. |
| 683 Holder holder = _registry.registerHolder(holderName); | 683 Holder holder = _registry.registerHolder(holderName); |
| 684 | 684 |
| 685 List<String> names = backend.oneShotInterceptors.keys.toList()..sort(); | 685 List<js.Name> names = backend.oneShotInterceptors.keys.toList()..sort(); |
| 686 return names.map((String name) { | 686 return names.map((js.Name name) { |
| 687 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 687 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
| 688 return new StaticStubMethod(name, holder, code); | 688 return new StaticStubMethod(name, holder, code); |
| 689 }); | 689 }); |
| 690 } | 690 } |
| 691 | 691 |
| 692 StaticDartMethod _buildStaticMethod(FunctionElement element) { | 692 StaticDartMethod _buildStaticMethod(FunctionElement element) { |
| 693 String name = namer.methodPropertyName(element); | 693 js.Name name = namer.methodPropertyName(element); |
| 694 String holder = namer.globalObjectFor(element); | 694 String holder = namer.globalObjectFor(element); |
| 695 js.Expression code = backend.generatedCode[element]; | 695 js.Expression code = backend.generatedCode[element]; |
| 696 | 696 |
| 697 bool isApplyTarget = !element.isConstructor && !element.isAccessor; | 697 bool isApplyTarget = !element.isConstructor && !element.isAccessor; |
| 698 bool canBeApplied = _methodCanBeApplied(element); | 698 bool canBeApplied = _methodCanBeApplied(element); |
| 699 bool canBeReflected = _methodCanBeReflected(element); | 699 bool canBeReflected = _methodCanBeReflected(element); |
| 700 | 700 |
| 701 bool needsTearOff = isApplyTarget && | 701 bool needsTearOff = isApplyTarget && |
| 702 (canBeReflected || | 702 (canBeReflected || |
| 703 universe.staticFunctionsNeedingGetter.contains(element)); | 703 universe.staticFunctionsNeedingGetter.contains(element)); |
| 704 | 704 |
| 705 String tearOffName = | 705 js.Name tearOffName = |
| 706 needsTearOff ? namer.staticClosureName(element) : null; | 706 needsTearOff ? namer.staticClosureName(element) : null; |
| 707 | 707 |
| 708 | 708 |
| 709 String callName = null; | 709 js.Name callName = null; |
| 710 if (needsTearOff) { | 710 if (needsTearOff) { |
| 711 Selector callSelector = | 711 Selector callSelector = |
| 712 new Selector.fromElement(element).toCallSelector(); | 712 new Selector.fromElement(element).toCallSelector(); |
| 713 callName = namer.invocationName(callSelector); | 713 callName = namer.invocationName(callSelector); |
| 714 } | 714 } |
| 715 js.Expression functionType; | 715 js.Expression functionType; |
| 716 DartType type = element.type; | 716 DartType type = element.type; |
| 717 if (needsTearOff || canBeReflected) { | 717 if (needsTearOff || canBeReflected) { |
| 718 OutputUnit outputUnit = | 718 OutputUnit outputUnit = |
| 719 _compiler.deferredLoadTask.outputUnitForElement(element); | 719 _compiler.deferredLoadTask.outputUnitForElement(element); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 745 functionType: functionType); | 745 functionType: functionType); |
| 746 } | 746 } |
| 747 | 747 |
| 748 void _registerConstants(OutputUnit outputUnit, | 748 void _registerConstants(OutputUnit outputUnit, |
| 749 Iterable<ConstantValue> constantValues) { | 749 Iterable<ConstantValue> constantValues) { |
| 750 // `constantValues` is null if an outputUnit doesn't contain any constants. | 750 // `constantValues` is null if an outputUnit doesn't contain any constants. |
| 751 if (constantValues == null) return; | 751 if (constantValues == null) return; |
| 752 for (ConstantValue constantValue in constantValues) { | 752 for (ConstantValue constantValue in constantValues) { |
| 753 _registry.registerConstant(outputUnit, constantValue); | 753 _registry.registerConstant(outputUnit, constantValue); |
| 754 assert(!_constants.containsKey(constantValue)); | 754 assert(!_constants.containsKey(constantValue)); |
| 755 String name = namer.constantName(constantValue); | 755 js.Name name = namer.constantName(constantValue); |
| 756 String constantObject = namer.globalObjectForConstant(constantValue); | 756 String constantObject = namer.globalObjectForConstant(constantValue); |
| 757 Holder holder = _registry.registerHolder(constantObject); | 757 Holder holder = _registry.registerHolder(constantObject); |
| 758 Constant constant = new Constant(name, holder, constantValue); | 758 Constant constant = new Constant(name, holder, constantValue); |
| 759 _constants[constantValue] = constant; | 759 _constants[constantValue] = constant; |
| 760 } | 760 } |
| 761 } | 761 } |
| 762 } | 762 } |
| OLD | NEW |