Chromium Code Reviews| 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'; |
| 11 import '../js/js.dart' as js; | 11 import '../js/js.dart' as js; |
| 12 | 12 |
| 13 import '../js_backend/js_backend.dart' show | 13 import '../js_backend/js_backend.dart' show |
| 14 Namer, | 14 Namer, |
| 15 JavaScriptBackend, | 15 JavaScriptBackend, |
| 16 JavaScriptConstantCompiler; | 16 JavaScriptConstantCompiler; |
| 17 | 17 |
| 18 import 'js_emitter.dart' show | 18 import 'js_emitter.dart' show |
| 19 ClassStubGenerator, | 19 ClassStubGenerator, |
| 20 CodeEmitterTask, | 20 CodeEmitterTask, |
| 21 InterceptorStubGenerator, | 21 InterceptorStubGenerator, |
| 22 ParameterStubGenerator, | |
| 22 TypeTestGenerator, | 23 TypeTestGenerator, |
| 23 TypeTestProperties; | 24 TypeTestProperties; |
| 24 | 25 |
| 25 import '../universe/universe.dart' show Universe; | 26 import '../universe/universe.dart' show Universe; |
| 26 import '../deferred_load.dart' show DeferredLoadTask, OutputUnit; | 27 import '../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
| 27 | 28 |
| 28 part 'registry.dart'; | 29 part 'registry.dart'; |
| 29 | 30 |
| 30 class ProgramBuilder { | 31 class ProgramBuilder { |
| 31 final Compiler _compiler; | 32 final Compiler _compiler; |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 js.Expression code = backend.generatedCode[element]; | 418 js.Expression code = backend.generatedCode[element]; |
| 418 | 419 |
| 419 // TODO(kasperl): Figure out under which conditions code is null. | 420 // TODO(kasperl): Figure out under which conditions code is null. |
| 420 if (code == null) return null; | 421 if (code == null) return null; |
| 421 | 422 |
| 422 bool canTearOff = false; | 423 bool canTearOff = false; |
| 423 String tearOffName; | 424 String tearOffName; |
| 424 bool isClosure = false; | 425 bool isClosure = false; |
| 425 bool isNotApplyTarget = !element.isFunction || element.isAccessor; | 426 bool isNotApplyTarget = !element.isFunction || element.isAccessor; |
| 426 | 427 |
| 427 final bool needsStubs = _methodNeedsStubs(element); | |
| 428 final bool canBeReflected = _methodCanBeReflected(element); | 428 final bool canBeReflected = _methodCanBeReflected(element); |
| 429 final bool canBeApplied = _methodCanBeApplied(element); | 429 final bool canBeApplied = _methodCanBeApplied(element); |
| 430 final bool hasSuperAlias = backend.isAliasedSuperMember(element); | 430 final bool hasSuperAlias = backend.isAliasedSuperMember(element); |
| 431 | 431 |
| 432 if (isNotApplyTarget) { | 432 if (isNotApplyTarget) { |
| 433 canTearOff = false; | 433 canTearOff = false; |
| 434 } else { | 434 } else { |
| 435 if (element.enclosingClass.isClosure) { | 435 if (element.enclosingClass.isClosure) { |
| 436 canTearOff = false; | 436 canTearOff = false; |
| 437 isClosure = true; | 437 isClosure = true; |
| 438 } else { | 438 } else { |
| 439 // Careful with operators. | 439 // Careful with operators. |
| 440 canTearOff = universe.hasInvokedGetter(element, _compiler.world) || | 440 canTearOff = universe.hasInvokedGetter(element, _compiler.world) || |
| 441 (canBeReflected && !element.isOperator); | 441 (canBeReflected && !element.isOperator); |
| 442 assert(canTearOff || | 442 assert(canTearOff || |
| 443 !universe.methodsNeedingSuperGetter.contains(element)); | 443 !universe.methodsNeedingSuperGetter.contains(element)); |
| 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 return new InstanceMethod(element, name, code, needsTearOff: canTearOff, | 454 return new InstanceMethod(element, name, code, needsTearOff: canTearOff, |
| 455 tearOffName: tearOffName, isClosure: isClosure, | 455 tearOffName: tearOffName, isClosure: isClosure, |
| 456 hasSuperAlias: hasSuperAlias, canBeApplied: canBeApplied, | 456 hasSuperAlias: hasSuperAlias, canBeApplied: canBeApplied, |
| 457 canBeReflected: canBeReflected, needsStubs: needsStubs); | 457 canBeReflected: canBeReflected, |
| 458 parameterStubs: _generateParameterStubs(element, canTearOff)); | |
| 459 } | |
| 460 | |
| 461 List<ParameterStubMethod> _generateParameterStubs(FunctionElement element, | |
| 462 bool canTearOff) { | |
| 463 List<ParameterStubMethod> parameterStubs = <ParameterStubMethod>[]; | |
|
herhut
2015/01/30 10:02:22
How about
if (!_methodNeedsStubs) return const <
zarah
2015/01/30 12:46:39
Done.
| |
| 464 if (_methodNeedsStubs(element)) { | |
| 465 ParameterStubGenerator generator = | |
| 466 new ParameterStubGenerator(_compiler, namer, backend); | |
| 467 Map<Selector, js.Expression> parameterStubsForElement = | |
| 468 generator.generateParameterStubs(element, canTearOff); | |
| 469 parameterStubsForElement.forEach((Selector selector, | |
| 470 js.Expression code) { | |
| 471 String name = namer.invocationName(selector); | |
| 472 parameterStubs.add( | |
| 473 _buildParameterStubMethod(name, code, selector, | |
| 474 element: element)); | |
| 475 }); | |
| 476 } | |
| 477 return parameterStubs; | |
| 458 } | 478 } |
| 459 | 479 |
| 460 /// Builds a stub method. | 480 /// Builds a stub method. |
| 461 /// | 481 /// |
| 462 /// Stub methods may have an element that can be used for code-size | 482 /// Stub methods may have an element that can be used for code-size |
| 463 /// attribution. | 483 /// attribution. |
| 464 Method _buildStubMethod(String name, js.Expression code, | 484 Method _buildStubMethod(String name, js.Expression code, |
| 465 {Element element}) { | 485 {Element element}) { |
| 466 return new StubMethod(name, code, element: element); | 486 return new StubMethod(name, code, element: element); |
| 467 } | 487 } |
| 468 | 488 |
| 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 | |
| 469 // The getInterceptor methods directly access the prototype of classes. | 495 // The getInterceptor methods directly access the prototype of classes. |
| 470 // We must evaluate these classes eagerly so that the prototype is | 496 // We must evaluate these classes eagerly so that the prototype is |
| 471 // accessible. | 497 // accessible. |
| 472 void _markEagerInterceptorClasses() { | 498 void _markEagerInterceptorClasses() { |
| 473 Map<String, Set<ClassElement>> specializedGetInterceptors = | 499 Map<String, Set<ClassElement>> specializedGetInterceptors = |
| 474 backend.specializedGetInterceptors; | 500 backend.specializedGetInterceptors; |
| 475 for (Set<ClassElement> classes in specializedGetInterceptors.values) { | 501 for (Set<ClassElement> classes in specializedGetInterceptors.values) { |
| 476 for (ClassElement element in classes) { | 502 for (ClassElement element in classes) { |
| 477 Class cls = _classes[element]; | 503 Class cls = _classes[element]; |
| 478 if (cls != null) cls.isEager = true; | 504 if (cls != null) cls.isEager = true; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 return new StaticStubMethod(name, holder, code); | 582 return new StaticStubMethod(name, holder, code); |
| 557 }); | 583 }); |
| 558 } | 584 } |
| 559 | 585 |
| 560 StaticDartMethod _buildStaticMethod(FunctionElement element) { | 586 StaticDartMethod _buildStaticMethod(FunctionElement element) { |
| 561 String name = namer.getNameOfMember(element); | 587 String name = namer.getNameOfMember(element); |
| 562 String holder = namer.globalObjectFor(element); | 588 String holder = namer.globalObjectFor(element); |
| 563 js.Expression code = backend.generatedCode[element]; | 589 js.Expression code = backend.generatedCode[element]; |
| 564 | 590 |
| 565 final bool isNotApplyTarget = !element.isConstructor && !element.isAccessor; | 591 final bool isNotApplyTarget = !element.isConstructor && !element.isAccessor; |
| 566 final bool needsStubs = _methodNeedsStubs(element); | |
| 567 final bool canBeApplied = _methodCanBeApplied(element); | 592 final bool canBeApplied = _methodCanBeApplied(element); |
| 568 final bool canBeReflected = _methodCanBeReflected(element); | 593 final bool canBeReflected = _methodCanBeReflected(element); |
| 569 | 594 |
| 570 final bool needsTearOff = isNotApplyTarget && (canBeReflected || | 595 final bool needsTearOff = isNotApplyTarget && (canBeReflected || |
| 571 universe.staticFunctionsNeedingGetter.contains(element)); | 596 universe.staticFunctionsNeedingGetter.contains(element)); |
| 572 | 597 |
| 573 final String tearOffName = | 598 final String tearOffName = |
| 574 needsTearOff ? namer.getStaticClosureName(element) : null; | 599 needsTearOff ? namer.getStaticClosureName(element) : null; |
| 575 | 600 |
| 576 return new StaticDartMethod(element, | 601 return new StaticDartMethod(element, |
| 577 name, _registry.registerHolder(holder), code, | 602 name, _registry.registerHolder(holder), code, |
| 578 needsTearOff: needsTearOff, | 603 needsTearOff: needsTearOff, |
| 579 tearOffName: tearOffName, | 604 tearOffName: tearOffName, |
| 580 canBeApplied: canBeApplied, | 605 canBeApplied: canBeApplied, |
| 581 canBeReflected: canBeReflected, | 606 canBeReflected: canBeReflected, |
| 582 needsStubs: needsStubs); | 607 parameterStubs: |
| 608 _generateParameterStubs(element, | |
| 609 needsTearOff)); | |
| 583 } | 610 } |
| 584 | 611 |
| 585 void _registerConstants(OutputUnit outputUnit, | 612 void _registerConstants(OutputUnit outputUnit, |
| 586 Iterable<ConstantValue> constantValues) { | 613 Iterable<ConstantValue> constantValues) { |
| 587 // `constantValues` is null if an outputUnit doesn't contain any constants. | 614 // `constantValues` is null if an outputUnit doesn't contain any constants. |
| 588 if (constantValues == null) return; | 615 if (constantValues == null) return; |
| 589 for (ConstantValue constantValue in constantValues) { | 616 for (ConstantValue constantValue in constantValues) { |
| 590 _registry.registerConstant(outputUnit, constantValue); | 617 _registry.registerConstant(outputUnit, constantValue); |
| 591 assert(!_constants.containsKey(constantValue)); | 618 assert(!_constants.containsKey(constantValue)); |
| 592 String name = namer.constantName(constantValue); | 619 String name = namer.constantName(constantValue); |
| 593 String constantObject = namer.globalObjectForConstant(constantValue); | 620 String constantObject = namer.globalObjectForConstant(constantValue); |
| 594 Holder holder = _registry.registerHolder(constantObject); | 621 Holder holder = _registry.registerHolder(constantObject); |
| 595 Constant constant = new Constant(name, holder, constantValue); | 622 Constant constant = new Constant(name, holder, constantValue); |
| 596 _constants[constantValue] = constant; | 623 _constants[constantValue] = constant; |
| 597 } | 624 } |
| 598 } | 625 } |
| 599 } | 626 } |
| OLD | NEW |