| 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 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 tearOffName = namer.getterName(element); | 444 tearOffName = namer.getterName(element); |
| 445 } | 445 } |
| 446 } | 446 } |
| 447 | 447 |
| 448 if (canTearOff) { | 448 if (canTearOff) { |
| 449 assert(invariant(element, !element.isGenerativeConstructor)); | 449 assert(invariant(element, !element.isGenerativeConstructor)); |
| 450 assert(invariant(element, !element.isGenerativeConstructorBody)); | 450 assert(invariant(element, !element.isGenerativeConstructorBody)); |
| 451 assert(invariant(element, !element.isConstructor)); | 451 assert(invariant(element, !element.isConstructor)); |
| 452 } | 452 } |
| 453 | 453 |
| 454 String callName = null; |
| 455 if (canTearOff) { |
| 456 Selector callSelector = |
| 457 new Selector.fromElement(element).toCallSelector(); |
| 458 callName = namer.invocationName(callSelector); |
| 459 } |
| 460 |
| 454 return new InstanceMethod(element, name, code, | 461 return new InstanceMethod(element, name, code, |
| 455 _generateParameterStubs(element, canTearOff), | 462 _generateParameterStubs(element, canTearOff), callName, |
| 456 needsTearOff: canTearOff, tearOffName: tearOffName, | 463 needsTearOff: canTearOff, tearOffName: tearOffName, |
| 457 isClosure: isClosure, hasSuperAlias: hasSuperAlias, | 464 isClosure: isClosure, hasSuperAlias: hasSuperAlias, |
| 458 canBeApplied: canBeApplied, canBeReflected: canBeReflected); | 465 canBeApplied: canBeApplied, canBeReflected: canBeReflected); |
| 459 } | 466 } |
| 460 | 467 |
| 461 List<ParameterStubMethod> _generateParameterStubs(FunctionElement element, | 468 List<ParameterStubMethod> _generateParameterStubs(FunctionElement element, |
| 462 bool canTearOff) { | 469 bool canTearOff) { |
| 463 | 470 |
| 464 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; | 471 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; |
| 465 | 472 |
| 466 List<ParameterStubMethod> parameterStubs = <ParameterStubMethod>[]; | |
| 467 ParameterStubGenerator generator = | 473 ParameterStubGenerator generator = |
| 468 new ParameterStubGenerator(_compiler, namer, backend); | 474 new ParameterStubGenerator(_compiler, namer, backend); |
| 469 Map<Selector, js.Expression> parameterStubsForElement = | 475 return generator.generateParameterStubs(element, canTearOff: canTearOff); |
| 470 generator.generateParameterStubs(element, canTearOff); | |
| 471 parameterStubsForElement.forEach((Selector selector, js.Expression code) { | |
| 472 String name = namer.invocationName(selector); | |
| 473 parameterStubs.add( | |
| 474 _buildParameterStubMethod(name, code, selector, element: element)); | |
| 475 }); | |
| 476 | |
| 477 return parameterStubs; | |
| 478 } | 476 } |
| 479 | 477 |
| 480 /// Builds a stub method. | 478 /// Builds a stub method. |
| 481 /// | 479 /// |
| 482 /// Stub methods may have an element that can be used for code-size | 480 /// Stub methods may have an element that can be used for code-size |
| 483 /// attribution. | 481 /// attribution. |
| 484 Method _buildStubMethod(String name, js.Expression code, | 482 Method _buildStubMethod(String name, js.Expression code, |
| 485 {Element element}) { | 483 {Element element}) { |
| 486 return new StubMethod(name, code, element: element); | 484 return new StubMethod(name, code, element: element); |
| 487 } | 485 } |
| 488 | 486 |
| 489 Method _buildParameterStubMethod(String name, js.Expression code, | |
| 490 Selector selector, | |
| 491 {Element element}) { | |
| 492 return new ParameterStubMethod(name, code, selector, element: element); | |
| 493 } | |
| 494 | |
| 495 // The getInterceptor methods directly access the prototype of classes. | 487 // The getInterceptor methods directly access the prototype of classes. |
| 496 // We must evaluate these classes eagerly so that the prototype is | 488 // We must evaluate these classes eagerly so that the prototype is |
| 497 // accessible. | 489 // accessible. |
| 498 void _markEagerInterceptorClasses() { | 490 void _markEagerInterceptorClasses() { |
| 499 Map<String, Set<ClassElement>> specializedGetInterceptors = | 491 Map<String, Set<ClassElement>> specializedGetInterceptors = |
| 500 backend.specializedGetInterceptors; | 492 backend.specializedGetInterceptors; |
| 501 for (Set<ClassElement> classes in specializedGetInterceptors.values) { | 493 for (Set<ClassElement> classes in specializedGetInterceptors.values) { |
| 502 for (ClassElement element in classes) { | 494 for (ClassElement element in classes) { |
| 503 Class cls = _classes[element]; | 495 Class cls = _classes[element]; |
| 504 if (cls != null) cls.isEager = true; | 496 if (cls != null) cls.isEager = true; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 573 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
| 582 return new StaticStubMethod(name, holder, code); | 574 return new StaticStubMethod(name, holder, code); |
| 583 }); | 575 }); |
| 584 } | 576 } |
| 585 | 577 |
| 586 StaticDartMethod _buildStaticMethod(FunctionElement element) { | 578 StaticDartMethod _buildStaticMethod(FunctionElement element) { |
| 587 String name = namer.getNameOfMember(element); | 579 String name = namer.getNameOfMember(element); |
| 588 String holder = namer.globalObjectFor(element); | 580 String holder = namer.globalObjectFor(element); |
| 589 js.Expression code = backend.generatedCode[element]; | 581 js.Expression code = backend.generatedCode[element]; |
| 590 | 582 |
| 591 final bool isNotApplyTarget = !element.isConstructor && !element.isAccessor; | 583 final bool isApplyTarget = !element.isConstructor && !element.isAccessor; |
| 592 final bool canBeApplied = _methodCanBeApplied(element); | 584 final bool canBeApplied = _methodCanBeApplied(element); |
| 593 final bool canBeReflected = _methodCanBeReflected(element); | 585 final bool canBeReflected = _methodCanBeReflected(element); |
| 594 | 586 |
| 595 final bool needsTearOff = isNotApplyTarget && (canBeReflected || | 587 final bool needsTearOff = isApplyTarget && |
| 596 universe.staticFunctionsNeedingGetter.contains(element)); | 588 (canBeReflected || |
| 589 universe.staticFunctionsNeedingGetter.contains(element)); |
| 597 | 590 |
| 598 final String tearOffName = | 591 final String tearOffName = |
| 599 needsTearOff ? namer.getStaticClosureName(element) : null; | 592 needsTearOff ? namer.getStaticClosureName(element) : null; |
| 600 | 593 |
| 594 String callName = null; |
| 595 if (needsTearOff) { |
| 596 Selector callSelector = |
| 597 new Selector.fromElement(element).toCallSelector(); |
| 598 callName = namer.invocationName(callSelector); |
| 599 } |
| 600 |
| 601 return new StaticDartMethod(element, | 601 return new StaticDartMethod(element, |
| 602 name, _registry.registerHolder(holder), code, | 602 name, _registry.registerHolder(holder), code, |
| 603 _generateParameterStubs(element, needsTearOff), | 603 _generateParameterStubs(element, needsTearOff), |
| 604 callName, |
| 604 needsTearOff: needsTearOff, | 605 needsTearOff: needsTearOff, |
| 605 tearOffName: tearOffName, | 606 tearOffName: tearOffName, |
| 606 canBeApplied: canBeApplied, | 607 canBeApplied: canBeApplied, |
| 607 canBeReflected: canBeReflected); | 608 canBeReflected: canBeReflected); |
| 608 } | 609 } |
| 609 | 610 |
| 610 void _registerConstants(OutputUnit outputUnit, | 611 void _registerConstants(OutputUnit outputUnit, |
| 611 Iterable<ConstantValue> constantValues) { | 612 Iterable<ConstantValue> constantValues) { |
| 612 // `constantValues` is null if an outputUnit doesn't contain any constants. | 613 // `constantValues` is null if an outputUnit doesn't contain any constants. |
| 613 if (constantValues == null) return; | 614 if (constantValues == null) return; |
| 614 for (ConstantValue constantValue in constantValues) { | 615 for (ConstantValue constantValue in constantValues) { |
| 615 _registry.registerConstant(outputUnit, constantValue); | 616 _registry.registerConstant(outputUnit, constantValue); |
| 616 assert(!_constants.containsKey(constantValue)); | 617 assert(!_constants.containsKey(constantValue)); |
| 617 String name = namer.constantName(constantValue); | 618 String name = namer.constantName(constantValue); |
| 618 String constantObject = namer.globalObjectForConstant(constantValue); | 619 String constantObject = namer.globalObjectForConstant(constantValue); |
| 619 Holder holder = _registry.registerHolder(constantObject); | 620 Holder holder = _registry.registerHolder(constantObject); |
| 620 Constant constant = new Constant(name, holder, constantValue); | 621 Constant constant = new Constant(name, holder, constantValue); |
| 621 _constants[constantValue] = constant; | 622 _constants[constantValue] = constant; |
| 622 } | 623 } |
| 623 } | 624 } |
| 624 } | 625 } |
| OLD | NEW |