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.new_js_emitter.model_emitter; | 5 library dart2js.new_js_emitter.model_emitter; |
6 | 6 |
7 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue; | 7 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue; |
8 import '../../dart2jslib.dart' show Compiler; | 8 import '../../dart2jslib.dart' show Compiler; |
9 import '../../elements/elements.dart' show ClassElement, FunctionElement; | 9 import '../../elements/elements.dart' show ClassElement, FunctionElement; |
10 import '../../js/js.dart' as js; | 10 import '../../js/js.dart' as js; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 static const String deferredInitializersGlobal = | 86 static const String deferredInitializersGlobal = |
87 r"$__dart_deferred_initializers__"; | 87 r"$__dart_deferred_initializers__"; |
88 | 88 |
89 static const String deferredExtension = "part.js"; | 89 static const String deferredExtension = "part.js"; |
90 | 90 |
91 static const String typeNameProperty = r"builtin$cls"; | 91 static const String typeNameProperty = r"builtin$cls"; |
92 | 92 |
93 ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter) | 93 ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter) |
94 : this.compiler = compiler, | 94 : this.compiler = compiler, |
95 this.namer = namer { | 95 this.namer = namer { |
96 // TODO(floitsch): remove hard-coded name. | |
97 // TODO(floitsch): there is no harm in caching the template. | |
98 js.Template makeConstantListTemplate = | |
99 js.js.uncachedExpressionTemplate('makeConstList(#)'); | |
100 | 96 |
101 this.constantEmitter = new ConstantEmitter( | 97 this.constantEmitter = new ConstantEmitter( |
102 compiler, namer, this.generateConstantReference, | 98 compiler, namer, this.generateConstantReference, |
103 makeConstantListTemplate); | 99 constantListGenerator); |
| 100 } |
| 101 |
| 102 js.Expression constantListGenerator(js.Expression array) { |
| 103 // TODO(floitsch): remove hard-coded name. |
| 104 return js.js('makeConstList(#)', [array]); |
104 } | 105 } |
105 | 106 |
106 js.Expression generateEmbeddedGlobalAccess(String global) { | 107 js.Expression generateEmbeddedGlobalAccess(String global) { |
107 return js.js(generateEmbeddedGlobalAccessString(global)); | 108 return js.js(generateEmbeddedGlobalAccessString(global)); |
108 } | 109 } |
109 | 110 |
110 String generateEmbeddedGlobalAccessString(String global) { | 111 String generateEmbeddedGlobalAccessString(String global) { |
111 // TODO(floitsch): don't use 'init' as global embedder storage. | 112 // TODO(floitsch): don't use 'init' as global embedder storage. |
112 return 'init.$global'; | 113 return 'init.$global'; |
113 } | 114 } |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 js.Property emitMangledGlobalNames() { | 378 js.Property emitMangledGlobalNames() { |
378 List<js.Property> names = <js.Property>[]; | 379 List<js.Property> names = <js.Property>[]; |
379 | 380 |
380 // We want to keep the original names for the most common core classes when | 381 // We want to keep the original names for the most common core classes when |
381 // calling toString on them. | 382 // calling toString on them. |
382 List<ClassElement> nativeClassesNeedingUnmangledName = | 383 List<ClassElement> nativeClassesNeedingUnmangledName = |
383 [compiler.intClass, compiler.doubleClass, compiler.numClass, | 384 [compiler.intClass, compiler.doubleClass, compiler.numClass, |
384 compiler.stringClass, compiler.boolClass, compiler.nullClass, | 385 compiler.stringClass, compiler.boolClass, compiler.nullClass, |
385 compiler.listClass]; | 386 compiler.listClass]; |
386 nativeClassesNeedingUnmangledName.forEach((element) { | 387 nativeClassesNeedingUnmangledName.forEach((element) { |
387 names.add(new js.Property(js.string(namer.className(element)), | 388 names.add(new js.Property(js.quoteName(namer.className(element)), |
388 js.string(element.name))); | 389 js.string(element.name))); |
389 }); | 390 }); |
390 | 391 |
391 return new js.Property(js.string(MANGLED_GLOBAL_NAMES), | 392 return new js.Property(js.string(MANGLED_GLOBAL_NAMES), |
392 new js.ObjectInitializer(names)); | 393 new js.ObjectInitializer(names)); |
393 } | 394 } |
394 | 395 |
395 js.Statement emitDeferredInitializerGlobal(Map loadMap) { | 396 js.Statement emitDeferredInitializerGlobal(Map loadMap) { |
396 if (loadMap.isEmpty) return new js.Block.empty(); | 397 if (loadMap.isEmpty) return new js.Block.empty(); |
397 | 398 |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 "The array is completely empty if there is no constant at all."; | 573 "The array is completely empty if there is no constant at all."; |
573 | 574 |
574 js.ArrayInitializer emitConstants(List<Constant> constants) { | 575 js.ArrayInitializer emitConstants(List<Constant> constants) { |
575 List<js.Expression> data = <js.Expression>[]; | 576 List<js.Expression> data = <js.Expression>[]; |
576 if (constants.isNotEmpty) { | 577 if (constants.isNotEmpty) { |
577 int holderIndex = constants.first.holder.index; | 578 int holderIndex = constants.first.holder.index; |
578 data.add(js.number(holderIndex)); | 579 data.add(js.number(holderIndex)); |
579 data.addAll(constants.expand((Constant constant) { | 580 data.addAll(constants.expand((Constant constant) { |
580 assert(constant.holder.index == holderIndex); | 581 assert(constant.holder.index == holderIndex); |
581 js.Expression code = constantEmitter.generate(constant.value); | 582 js.Expression code = constantEmitter.generate(constant.value); |
582 return [js.string(constant.name), unparse(compiler, code)]; | 583 return [js.quoteName(constant.name), unparse(compiler, code)]; |
583 })); | 584 })); |
584 } | 585 } |
585 return new js.ArrayInitializer(data); | 586 return new js.ArrayInitializer(data); |
586 } | 587 } |
587 | 588 |
588 js.Block emitStaticNonFinalFields(List<StaticField> fields) { | 589 js.Block emitStaticNonFinalFields(List<StaticField> fields) { |
589 Iterable<js.Statement> statements = fields.map((StaticField field) { | 590 Iterable<js.Statement> statements = fields.map((StaticField field) { |
590 return js.js.statement("#.# = #;", | 591 return js.js.statement("#.# = #;", |
591 [field.holder.name, field.name, field.code]); | 592 [field.holder.name, field.name, field.code]); |
592 }); | 593 }); |
593 return new js.Block(statements.toList()); | 594 return new js.Block(statements.toList()); |
594 } | 595 } |
595 | 596 |
596 js.Expression emitLazilyInitializedStatics(List<StaticField> fields) { | 597 js.Expression emitLazilyInitializedStatics(List<StaticField> fields) { |
597 Iterable fieldDescriptors = fields.expand((field) => | 598 Iterable fieldDescriptors = fields.expand((field) => |
598 [ js.string(field.name), | 599 [ js.quoteName(field.name), |
599 js.string("${namer.getterPrefix}${field.name}"), | 600 js.quoteName(namer.deriveLazyInitializerName(field.name)), |
600 js.number(field.holder.index), | 601 js.number(field.holder.index), |
601 emitLazyInitializer(field) ]); | 602 emitLazyInitializer(field) ]); |
602 return new js.ArrayInitializer(fieldDescriptors.toList(growable: false)); | 603 return new js.ArrayInitializer(fieldDescriptors.toList(growable: false)); |
603 } | 604 } |
604 | 605 |
605 js.Block emitEagerClassInitializations(List<Library> libraries) { | 606 js.Block emitEagerClassInitializations(List<Library> libraries) { |
606 js.Statement createInstantiation(Class cls) { | 607 js.Statement createInstantiation(Class cls) { |
607 return js.js.statement('new #.#()', [cls.holder.name, cls.name]); | 608 return js.js.statement('new #.#()', [cls.holder.name, cls.name]); |
608 } | 609 } |
609 | 610 |
610 List<js.Statement> instantiations = | 611 List<js.Statement> instantiations = |
611 libraries.expand((Library library) => library.classes) | 612 libraries.expand((Library library) => library.classes) |
612 .where((Class cls) => cls.isEager) | 613 .where((Class cls) => cls.isEager) |
613 .map(createInstantiation) | 614 .map(createInstantiation) |
614 .toList(growable: false); | 615 .toList(growable: false); |
615 return new js.Block(instantiations); | 616 return new js.Block(instantiations); |
616 } | 617 } |
617 | 618 |
618 // This string should be referenced wherever JavaScript code makes assumptions | 619 // This string should be referenced wherever JavaScript code makes assumptions |
619 // on the mixin format. | 620 // on the mixin format. |
620 static final String nativeInfoDescription = | 621 static final String nativeInfoDescription = |
621 "A class is encoded as follows:" | 622 "A class is encoded as follows:" |
622 " [name, class-code, holder-index], or " | 623 " [name, class-code, holder-index], or " |
623 " [name, class-code, native-info, holder-index]."; | 624 " [name, class-code, native-info, holder-index]."; |
624 | 625 |
625 js.Expression emitLibrary(Library library) { | 626 js.Expression emitLibrary(Library library) { |
626 Iterable staticDescriptors = library.statics.expand(emitStaticMethod); | 627 Iterable staticDescriptors = library.statics.expand(emitStaticMethod); |
627 | 628 |
628 Iterable classDescriptors = library.classes.expand((Class cls) { | 629 Iterable classDescriptors = library.classes.expand((Class cls) { |
629 js.LiteralString name = js.string(cls.name); | 630 js.Literal name = js.quoteName(cls.name); |
630 js.LiteralNumber holderIndex = js.number(cls.holder.index); | 631 js.LiteralNumber holderIndex = js.number(cls.holder.index); |
631 js.Expression emittedClass = emitClass(cls); | 632 js.Expression emittedClass = emitClass(cls); |
632 if (cls.nativeInfo == null) { | 633 if (cls.nativeInfo == null) { |
633 return [name, emittedClass, holderIndex]; | 634 return [name, emittedClass, holderIndex]; |
634 } else { | 635 } else { |
635 return [name, emittedClass, js.string(cls.nativeInfo), holderIndex]; | 636 return [name, emittedClass, cls.nativeInfo, holderIndex]; |
636 } | 637 } |
637 }); | 638 }); |
638 | 639 |
639 js.Expression staticArray = | 640 js.Expression staticArray = |
640 new js.ArrayInitializer(staticDescriptors.toList(growable: false)); | 641 new js.ArrayInitializer(staticDescriptors.toList(growable: false)); |
641 js.Expression classArray = | 642 js.Expression classArray = |
642 new js.ArrayInitializer(classDescriptors.toList(growable: false)); | 643 new js.ArrayInitializer(classDescriptors.toList(growable: false)); |
643 | 644 |
644 return new js.ArrayInitializer([staticArray, classArray]); | 645 return new js.ArrayInitializer([staticArray, classArray]); |
645 } | 646 } |
646 | 647 |
647 js.Expression _generateConstructor(Class cls) { | 648 js.Expression _generateConstructor(Class cls) { |
648 List<String> fieldNames = <String>[]; | 649 List<js.Name> fieldNames = const <js.Name>[]; |
649 | 650 |
650 // If the class is not directly instantiated we only need it for inheritance | 651 // If the class is not directly instantiated we only need it for inheritance |
651 // or RTI. In either case we don't need its fields. | 652 // or RTI. In either case we don't need its fields. |
652 if (cls.isDirectlyInstantiated && !cls.isNative) { | 653 if (cls.isDirectlyInstantiated && !cls.isNative) { |
653 fieldNames = cls.fields.map((Field field) => field.name).toList(); | 654 fieldNames = cls.fields.map((Field field) => field.name).toList(); |
654 } | 655 } |
655 String name = cls.name; | 656 js.Name name = cls.name; |
656 String parameters = fieldNames.join(', '); | 657 |
657 String assignments = fieldNames | 658 Iterable<js.Name> assignments = fieldNames.map((js.Name field) { |
658 .map((String field) => "this.$field = $field;\n") | 659 return js.js("this.#field = #field", {"field": field}); |
659 .join(); | 660 }); |
660 String code = 'function $name($parameters) { $assignments }'; | 661 |
661 js.Template template = js.js.uncachedExpressionTemplate(code); | 662 return js.js('function #(#) { # }', [name, fieldNames, assignments]); |
662 return template.instantiate(const []); | |
663 } | 663 } |
664 | 664 |
665 Method _generateGetter(Field field) { | 665 Method _generateGetter(Field field) { |
666 String getterTemplateFor(int flags) { | 666 String getterTemplateFor(int flags) { |
667 switch (flags) { | 667 switch (flags) { |
668 case 1: return "function() { return this[#]; }"; | 668 case 1: return "function() { return this[#]; }"; |
669 case 2: return "function(receiver) { return receiver[#]; }"; | 669 case 2: return "function(receiver) { return receiver[#]; }"; |
670 case 3: return "function(receiver) { return this[#]; }"; | 670 case 3: return "function(receiver) { return this[#]; }"; |
671 } | 671 } |
672 return null; | 672 return null; |
673 } | 673 } |
674 | 674 |
675 js.Expression fieldName = js.string(field.name); | 675 js.Expression fieldName = js.quoteName(field.name); |
676 js.Expression code = js.js(getterTemplateFor(field.getterFlags), fieldName); | 676 js.Expression code = js.js(getterTemplateFor(field.getterFlags), fieldName); |
677 String getterName = "${namer.getterPrefix}${field.accessorName}"; | 677 js.Name getterName = namer.deriveGetterName(field.accessorName); |
678 return new StubMethod(getterName, code); | 678 return new StubMethod(getterName, code); |
679 } | 679 } |
680 | 680 |
681 Method _generateSetter(Field field) { | 681 Method _generateSetter(Field field) { |
682 String setterTemplateFor(int flags) { | 682 String setterTemplateFor(int flags) { |
683 switch (flags) { | 683 switch (flags) { |
684 case 1: return "function(val) { return this[#] = val; }"; | 684 case 1: return "function(val) { return this[#] = val; }"; |
685 case 2: return "function(receiver, val) { return receiver[#] = val; }"; | 685 case 2: return "function(receiver, val) { return receiver[#] = val; }"; |
686 case 3: return "function(receiver, val) { return this[#] = val; }"; | 686 case 3: return "function(receiver, val) { return this[#] = val; }"; |
687 } | 687 } |
688 return null; | 688 return null; |
689 } | 689 } |
690 js.Expression fieldName = js.string(field.name); | 690 js.Expression fieldName = js.quoteName(field.name); |
691 js.Expression code = js.js(setterTemplateFor(field.setterFlags), fieldName); | 691 js.Expression code = js.js(setterTemplateFor(field.setterFlags), fieldName); |
692 String setterName = "${namer.setterPrefix}${field.accessorName}"; | 692 js.Name setterName = namer.deriveSetterName(field.accessorName); |
693 return new StubMethod(setterName, code); | 693 return new StubMethod(setterName, code); |
694 } | 694 } |
695 | 695 |
696 Iterable<Method> _generateGettersSetters(Class cls) { | 696 Iterable<Method> _generateGettersSetters(Class cls) { |
697 Iterable<Method> getters = cls.fields | 697 Iterable<Method> getters = cls.fields |
698 .where((Field field) => field.needsGetter) | 698 .where((Field field) => field.needsGetter) |
699 .map(_generateGetter); | 699 .map(_generateGetter); |
700 | 700 |
701 Iterable<Method> setters = cls.fields | 701 Iterable<Method> setters = cls.fields |
702 .where((Field field) => field.needsUncheckedSetter) | 702 .where((Field field) => field.needsUncheckedSetter) |
703 .map(_generateSetter); | 703 .map(_generateSetter); |
704 | 704 |
705 return [getters, setters].expand((x) => x); | 705 return [getters, setters].expand((x) => x); |
706 } | 706 } |
707 | 707 |
708 // This string should be referenced wherever JavaScript code makes assumptions | 708 // This string should be referenced wherever JavaScript code makes assumptions |
709 // on the mixin format. | 709 // on the mixin format. |
710 static final String mixinFormatDescription = | 710 static final String mixinFormatDescription = |
711 "Mixins have a reference to their mixin class at the place of the usual" | 711 "Mixins have a reference to their mixin class at the place of the usual" |
712 "constructor. If they are instantiated the constructor follows the" | 712 "constructor. If they are instantiated the constructor follows the" |
713 "reference."; | 713 "reference."; |
714 | 714 |
715 js.Expression emitClass(Class cls) { | 715 js.Expression emitClass(Class cls) { |
716 List elements = [js.string(cls.superclassName), | 716 List elements = [js.quoteName(cls.superclassName, allowNull: true), |
717 js.number(cls.superclassHolderIndex)]; | 717 js.number(cls.superclassHolderIndex)]; |
718 | 718 |
719 if (cls.isMixinApplication) { | 719 if (cls.isMixinApplication) { |
720 MixinApplication mixin = cls; | 720 MixinApplication mixin = cls; |
721 elements.add(js.string(mixin.mixinClass.name)); | 721 elements.add(js.quoteName(mixin.mixinClass.name)); |
722 elements.add(js.number(mixin.mixinClass.holder.index)); | 722 elements.add(js.number(mixin.mixinClass.holder.index)); |
723 if (cls.isDirectlyInstantiated) { | 723 if (cls.isDirectlyInstantiated) { |
724 elements.add(_generateConstructor(cls)); | 724 elements.add(_generateConstructor(cls)); |
725 } | 725 } |
726 } else { | 726 } else { |
727 elements.add(_generateConstructor(cls)); | 727 elements.add(_generateConstructor(cls)); |
728 } | 728 } |
729 Iterable<Method> methods = cls.methods; | 729 Iterable<Method> methods = cls.methods; |
730 Iterable<Method> isChecks = cls.isChecks; | 730 Iterable<Method> isChecks = cls.isChecks; |
731 Iterable<Method> callStubs = cls.callStubs; | 731 Iterable<Method> callStubs = cls.callStubs; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 properties.add(new js.Property(js.string(name), | 840 properties.add(new js.Property(js.string(name), |
841 generateConstantReference(value))); | 841 generateConstantReference(value))); |
842 }); | 842 }); |
843 return new js.ObjectInitializer(properties); | 843 return new js.ObjectInitializer(properties); |
844 } | 844 } |
845 } | 845 } |
846 | 846 |
847 Iterable<js.Expression> emitInstanceMethod(Method method) { | 847 Iterable<js.Expression> emitInstanceMethod(Method method) { |
848 | 848 |
849 List<js.Expression> makeNameCodePair(Method method) { | 849 List<js.Expression> makeNameCodePair(Method method) { |
850 return [js.string(method.name), method.code]; | 850 return [js.quoteName(method.name), method.code]; |
851 } | 851 } |
852 | 852 |
853 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { | 853 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { |
854 js.Expression callName = stub.callName == null | 854 js.Expression callName = stub.callName == null |
855 ? new js.LiteralNull() | 855 ? new js.LiteralNull() |
856 : js.string(stub.callName); | 856 : js.quoteName(stub.callName); |
857 return [js.string(stub.name), callName, stub.code]; | 857 return [js.quoteName(stub.name), callName, stub.code]; |
858 } | 858 } |
859 | 859 |
860 if (method is InstanceMethod) { | 860 if (method is InstanceMethod) { |
861 if (method.needsTearOff || method.aliasName != null) { | 861 if (method.needsTearOff || method.aliasName != null) { |
862 /// See [parseFunctionDescriptorBoilerplate] for a full description of | 862 /// See [parseFunctionDescriptorBoilerplate] for a full description of |
863 /// the format. | 863 /// the format. |
864 // [name, [aliasName, function, callName, isIntercepted, tearOffName, | 864 // [name, [aliasName, function, callName, isIntercepted, tearOffName, |
865 // functionType, stub1_name, stub1_callName, stub1_code, ...] | 865 // functionType, stub1_name, stub1_callName, stub1_code, ...] |
866 var data = []; | 866 var data = []; |
867 if (method.aliasName != null) { | 867 if (method.aliasName != null) { |
868 data.add(js.string(method.aliasName)); | 868 data.add(js.quoteName(method.aliasName)); |
869 } | 869 } |
870 data.add(method.code); | 870 data.add(method.code); |
871 data.add(js.string(method.callName)); | 871 data.add(js.quoteName(method.callName, allowNull: true)); |
872 | 872 |
873 if (method.needsTearOff) { | 873 if (method.needsTearOff) { |
874 bool isIntercepted = backend.isInterceptedMethod(method.element); | 874 bool isIntercepted = backend.isInterceptedMethod(method.element); |
875 data.add(new js.LiteralBool(isIntercepted)); | 875 data.add(new js.LiteralBool(isIntercepted)); |
876 data.add(js.string(method.tearOffName)); | 876 data.add(js.quoteName(method.tearOffName)); |
877 data.add((method.functionType)); | 877 data.add((method.functionType)); |
878 } | 878 } |
879 | 879 |
880 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); | 880 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); |
881 if (method.canBeApplied) { | 881 if (method.canBeApplied) { |
882 data.add(js.number(method.requiredParameterCount)); | 882 data.add(js.number(method.requiredParameterCount)); |
883 data.add(_encodeOptionalParameterDefaultValues(method)); | 883 data.add(_encodeOptionalParameterDefaultValues(method)); |
884 } | 884 } |
885 return [js.string(method.name), new js.ArrayInitializer(data)]; | 885 return [js.quoteName(method.name), new js.ArrayInitializer(data)]; |
886 } else { | 886 } else { |
887 // TODO(floitsch): not the most efficient way... | 887 // TODO(floitsch): not the most efficient way... |
888 return ([method]..addAll(method.parameterStubs)) | 888 return ([method]..addAll(method.parameterStubs)) |
889 .expand(makeNameCodePair); | 889 .expand(makeNameCodePair); |
890 } | 890 } |
891 } else { | 891 } else { |
892 return makeNameCodePair(method); | 892 return makeNameCodePair(method); |
893 } | 893 } |
894 } | 894 } |
895 | 895 |
896 Iterable<js.Expression> emitStaticMethod(StaticMethod method) { | 896 Iterable<js.Expression> emitStaticMethod(StaticMethod method) { |
897 js.Expression holderIndex = js.number(method.holder.index); | 897 js.Expression holderIndex = js.number(method.holder.index); |
898 List<js.Expression> output = <js.Expression>[]; | 898 List<js.Expression> output = <js.Expression>[]; |
899 | 899 |
900 void _addMethod(Method method) { | 900 void _addMethod(Method method) { |
901 js.Expression unparsed = unparse(compiler, method.code); | 901 js.Expression unparsed = unparse(compiler, method.code); |
902 output.add(js.string(method.name)); | 902 output.add(js.quoteName(method.name)); |
903 output.add(holderIndex); | 903 output.add(holderIndex); |
904 output.add(unparsed); | 904 output.add(unparsed); |
905 } | 905 } |
906 | 906 |
907 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { | 907 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { |
908 js.Expression callName = stub.callName == null | 908 js.Expression callName = stub.callName == null |
909 ? new js.LiteralNull() | 909 ? new js.LiteralNull() |
910 : js.string(stub.callName); | 910 : js.quoteName(stub.callName); |
911 return [js.string(stub.name), callName, unparse(compiler, stub.code)]; | 911 return [js.quoteName(stub.name), callName, unparse(compiler, stub.code)]; |
912 } | 912 } |
913 | 913 |
914 _addMethod(method); | 914 _addMethod(method); |
915 // TODO(floitsch): can there be anything else than a StaticDartMethod? | 915 // TODO(floitsch): can there be anything else than a StaticDartMethod? |
916 if (method is StaticDartMethod) { | 916 if (method is StaticDartMethod) { |
917 if (method.needsTearOff) { | 917 if (method.needsTearOff) { |
918 /// The format emitted is the same as for the parser specified at | 918 /// The format emitted is the same as for the parser specified at |
919 /// [parseFunctionDescriptorBoilerplate] except for the missing | 919 /// [parseFunctionDescriptorBoilerplate] except for the missing |
920 /// field whether the method is intercepted. | 920 /// field whether the method is intercepted. |
921 // [name, [function, callName, tearOffName, functionType, | 921 // [name, [function, callName, tearOffName, functionType, |
922 // stub1_name, stub1_callName, stub1_code, ...] | 922 // stub1_name, stub1_callName, stub1_code, ...] |
923 var data = [unparse(compiler, method.code)]; | 923 var data = [unparse(compiler, method.code)]; |
924 data.add(js.string(method.callName)); | 924 data.add(js.quoteName(method.callName)); |
925 data.add(js.string(method.tearOffName)); | 925 data.add(js.quoteName(method.tearOffName)); |
926 data.add(method.functionType); | 926 data.add(method.functionType); |
927 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); | 927 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); |
928 if (method.canBeApplied) { | 928 if (method.canBeApplied) { |
929 data.add(js.number(method.requiredParameterCount)); | 929 data.add(js.number(method.requiredParameterCount)); |
930 data.add(_encodeOptionalParameterDefaultValues(method)); | 930 data.add(_encodeOptionalParameterDefaultValues(method)); |
931 } | 931 } |
932 return [js.string(method.name), holderIndex, | 932 return [js.quoteName(method.name), holderIndex, |
933 new js.ArrayInitializer(data)]; | 933 new js.ArrayInitializer(data)]; |
934 } else { | 934 } else { |
935 method.parameterStubs.forEach(_addMethod); | 935 method.parameterStubs.forEach(_addMethod); |
936 } | 936 } |
937 } | 937 } |
938 return output; | 938 return output; |
939 } | 939 } |
940 | 940 |
941 static final String setupProgramName = "setupProgram"; | 941 static final String setupProgramName = "setupProgram"; |
942 | 942 |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1276 | 1276 |
1277 var end = Date.now(); | 1277 var end = Date.now(); |
1278 // print('Setup: ' + (end - start) + ' ms.'); | 1278 // print('Setup: ' + (end - start) + ' ms.'); |
1279 | 1279 |
1280 #invokeMain; // Start main. | 1280 #invokeMain; // Start main. |
1281 | 1281 |
1282 })(Date.now(), #code) | 1282 })(Date.now(), #code) |
1283 }"""; | 1283 }"""; |
1284 | 1284 |
1285 } | 1285 } |
OLD | NEW |