Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart

Issue 928203003: Implement Function.apply in the new emitter. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor fix Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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;
7 import '../../dart2jslib.dart' show Compiler; 8 import '../../dart2jslib.dart' show Compiler;
8 import '../../dart_types.dart' show DartType; 9 import '../../dart_types.dart' show DartType;
9 import '../../elements/elements.dart' show ClassElement; 10 import '../../elements/elements.dart' show ClassElement;
10 import '../../js/js.dart' as js; 11 import '../../js/js.dart' as js;
11 import '../../js_backend/js_backend.dart' show 12 import '../../js_backend/js_backend.dart' show
12 JavaScriptBackend, 13 JavaScriptBackend,
13 Namer, 14 Namer,
14 ConstantEmitter; 15 ConstantEmitter;
15 16
16 import '../js_emitter.dart' show 17 import '../js_emitter.dart' show
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 elements.add( 107 elements.add(
107 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); 108 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
108 109
109 js.Expression code = new js.ArrayInitializer(elements); 110 js.Expression code = new js.ArrayInitializer(elements);
110 111
111 Map<String, dynamic> holes = 112 Map<String, dynamic> holes =
112 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), 113 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
113 'holders': emitHolders(program.holders), 114 'holders': emitHolders(program.holders),
114 'tearOff': buildTearOffCode(backend), 115 'tearOff': buildTearOffCode(backend),
115 'parseFunctionDescriptor': 116 'parseFunctionDescriptor':
116 js.js.statement(parseFunctionDescriptorBoilerplate), 117 js.js.statement(parseFunctionDescriptorBoilerplate,
118 {'argCnt': js.string(namer.requiredParameterField),
119 'defArgValues': js.string(namer.defaultValuesField),
120 'callName': js.string(namer.callNameField)}),
121
117 'cyclicThrow': 122 'cyclicThrow':
118 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), 123 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()),
119 'outputContainsConstantList': program.outputContainsConstantList, 124 'outputContainsConstantList': program.outputContainsConstantList,
120 'embeddedGlobals': emitEmbeddedGlobals(program), 125 'embeddedGlobals': emitEmbeddedGlobals(program),
121 'constants': emitConstants(fragment.constants), 126 'constants': emitConstants(fragment.constants),
122 'staticNonFinals': 127 'staticNonFinals':
123 emitStaticNonFinalFields(fragment.staticNonFinalFields), 128 emitStaticNonFinalFields(fragment.staticNonFinalFields),
124 'operatorIsPrefix': js.string(namer.operatorIsPrefix), 129 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
130 'callName': js.string(namer.callNameField),
125 'eagerClasses': emitEagerClassInitializations(fragment.libraries), 131 'eagerClasses': emitEagerClassInitializations(fragment.libraries),
126 'invokeMain': fragment.invokeMain, 132 'invokeMain': fragment.invokeMain,
127 'code': code}; 133 'code': code};
128 134
129 holes.addAll(nativeHoles(program)); 135 holes.addAll(nativeHoles(program));
130 136
131 return js.js.statement(boilerplate, holes); 137 return js.js.statement(boilerplate, holes);
132 } 138 }
133 139
134 Map<String, dynamic> nativeHoles(Program program) { 140 Map<String, dynamic> nativeHoles(Program program) {
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 assert(field.isLazy); 551 assert(field.isLazy);
546 return unparse(compiler, field.code); 552 return unparse(compiler, field.code);
547 } 553 }
548 554
549 /// JavaScript code template that implements parsing of a function descriptor. 555 /// JavaScript code template that implements parsing of a function descriptor.
550 /// Descriptors are used in place of the actual JavaScript function 556 /// Descriptors are used in place of the actual JavaScript function
551 /// definition in the output if additional information needs to be passed to 557 /// definition in the output if additional information needs to be passed to
552 /// facilitate the generation of tearOffs at runtime. The format is an array 558 /// facilitate the generation of tearOffs at runtime. The format is an array
553 /// with the following fields: 559 /// with the following fields:
554 /// 560 ///
555 /// [InstanceMethod.aliasName] (optional). 561 /// * [InstanceMethod.aliasName] (optional).
556 /// [Method.code] 562 /// * [Method.code]
557 /// [DartMethod.callName] 563 /// * [DartMethod.callName]
558 /// isInterceptedMethod (optional, present if [DartMethod.needsTearOff]). 564 /// * isInterceptedMethod (optional, present if [DartMethod.needsTearOff]).
559 /// [DartMethod.tearOffName] (optional, present if [DartMethod.needsTearOff]). 565 /// * [DartMethod.tearOffName] (optional, present if
560 /// functionType (optional, present if [DartMethod.needsTearOff]). 566 /// [DartMethod.needsTearOff]).
567 /// * functionType (optional, present if [DartMethod.needsTearOff]).
561 /// 568 ///
562 /// followed by 569 /// followed by
563 /// 570 ///
564 /// [ParameterStubMethod.name] 571 /// * [ParameterStubMethod.name]
565 /// [ParameterStubMethod.code] 572 /// * [ParameterStubMethod.callName]
573 /// * [ParameterStubMethod.code]
566 /// 574 ///
567 /// for each stub in [DartMethod.parameterStubs]. 575 /// for each stub in [DartMethod.parameterStubs].
576 ///
577 /// If the closure could be used in `Function.apply` (i.e.
578 /// [DartMethod.canBeApplied] is true) then the following fields are appended:
579 ///
580 /// * [DartMethod.requiredParameterCount]
581 /// * [DartMethod.optionalParameterDefaultValues]
568 582
569 static final String parseFunctionDescriptorBoilerplate = r""" 583 static final String parseFunctionDescriptorBoilerplate = r"""
570 function parseFunctionDescriptor(proto, name, descriptor) { 584 function parseFunctionDescriptor(proto, name, descriptor) {
571 if (descriptor instanceof Array) { 585 if (descriptor instanceof Array) {
572 // 'pos' points to the last read entry. 586 // 'pos' points to the last read entry.
573 var f, pos = -1; 587 var f, pos = -1;
574 var aliasOrFunction = descriptor[++pos]; 588 var aliasOrFunction = descriptor[++pos];
575 if (typeof aliasOrFunction == "string") { 589 if (typeof aliasOrFunction == "string") {
576 // Install the alias for super calls on the prototype chain. 590 // Install the alias for super calls on the prototype chain.
577 proto[aliasOrFunction] = f = descriptor[++pos]; 591 proto[aliasOrFunction] = f = descriptor[++pos];
578 } else { 592 } else {
579 f = aliasOrFunction; 593 f = aliasOrFunction;
580 } 594 }
581 595
582 proto[name] = f; 596 proto[name] = f;
583 var funs = [f]; 597 var funs = [f];
584 f.$callName = descriptor[++pos]; 598 f[#callName] = descriptor[++pos];
585 599
586 var isInterceptedOrParameterStubName = descriptor[pos + 1]; 600 var isInterceptedOrParameterStubName = descriptor[pos + 1];
587 var isIntercepted, tearOffName, reflectionInfo; 601 var isIntercepted, tearOffName, reflectionInfo;
588 if (typeof isInterceptedOrParameterStubName == "boolean") { 602 if (typeof isInterceptedOrParameterStubName == "boolean") {
589 isIntercepted = descriptor[++pos]; 603 isIntercepted = descriptor[++pos];
590 tearOffName = descriptor[++pos]; 604 tearOffName = descriptor[++pos];
591 reflectionInfo = descriptor[++pos]; 605 reflectionInfo = descriptor[++pos];
592 } 606 }
593 607
594 for (++pos; pos < descriptor.length; pos += 3) { 608 // We iterate in blocks of 3 but have to stop before we reach the (optional)
609 // two trailing items. To accomplish this, we only iterate until we reach
610 // length - 2.
611 for (++pos; pos < descriptor.length - 2; pos += 3) {
595 var stub = descriptor[pos + 2]; 612 var stub = descriptor[pos + 2];
596 stub.$callName = descriptor[pos + 1]; 613 stub[#callName] = descriptor[pos + 1];
597 proto[descriptor[pos]] = stub; 614 proto[descriptor[pos]] = stub;
598 funs.push(stub); 615 funs.push(stub);
599 } 616 }
600 617
601 if (tearOffName) { 618 if (tearOffName) {
602 proto[tearOffName] = 619 proto[tearOffName] =
603 tearOff(funs, reflectionInfo, false, name, isIntercepted); 620 tearOff(funs, reflectionInfo, false, name, isIntercepted);
604 } 621 }
605 622 if (descriptor[pos] != null) {
623 f[#argCnt] = descriptor[pos];
624 f[#defArgValues] = descriptor[pos + 1];
625 }
606 } else { 626 } else {
607 proto[name] = descriptor; 627 proto[name] = descriptor;
608 } 628 }
609 } 629 }
610 """; 630 """;
611 631
612 js.Expression _generateFunctionType(DartType memberType) { 632 js.Expression _generateFunctionType(DartType memberType) {
613 if (memberType.containsTypeVariables) { 633 if (memberType.containsTypeVariables) {
614 js.Expression thisAccess = js.js(r'this.$receiver'); 634 js.Expression thisAccess = js.js(r'this.$receiver');
615 return backend.rti.getSignatureEncoding(memberType, thisAccess); 635 return backend.rti.getSignatureEncoding(memberType, thisAccess);
616 } else { 636 } else {
617 return js.number(backend.emitter.metadataCollector.reifyType(memberType)); 637 return js.number(backend.emitter.metadataCollector.reifyType(memberType));
618 } 638 }
619 } 639 }
620 640
641 js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) {
642 js.Expression result;
643 // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole].
644 if (method.optionalParameterDefaultValues is List) {
645 List<ConstantValue> defs = method.optionalParameterDefaultValues;
646 Iterable<js.Expression> elements = defs.map(constantEmitter.reference);
647 return new js.ArrayInitializer(elements.toList());
648 } else {
649 Map<String, ConstantValue> defs = method.optionalParameterDefaultValues;
650 List<js.Property> properties = <js.Property>[];
651 defs.forEach((String name, ConstantValue value) {
652 properties.add(new js.Property(js.string(name),
653 constantEmitter.reference(value)));
654 });
655 return new js.ObjectInitializer(properties);
656 }
657 }
658
621 Iterable<js.Expression> emitInstanceMethod(Method method) { 659 Iterable<js.Expression> emitInstanceMethod(Method method) {
622 660
623 List<js.Expression> makeNameCodePair(Method method) { 661 List<js.Expression> makeNameCodePair(Method method) {
624 return [js.string(method.name), method.code]; 662 return [js.string(method.name), method.code];
625 } 663 }
626 664
627 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { 665 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) {
628 js.Expression callName = stub.callName == null 666 js.Expression callName = stub.callName == null
629 ? new js.LiteralNull() 667 ? new js.LiteralNull()
630 : js.string(stub.callName); 668 : js.string(stub.callName);
(...skipping 14 matching lines...) Expand all
645 data.add(js.string(method.callName)); 683 data.add(js.string(method.callName));
646 684
647 if (method.needsTearOff) { 685 if (method.needsTearOff) {
648 bool isIntercepted = backend.isInterceptedMethod(method.element); 686 bool isIntercepted = backend.isInterceptedMethod(method.element);
649 data.add(new js.LiteralBool(isIntercepted)); 687 data.add(new js.LiteralBool(isIntercepted));
650 data.add(js.string(method.tearOffName)); 688 data.add(js.string(method.tearOffName));
651 data.add(_generateFunctionType(method.type)); 689 data.add(_generateFunctionType(method.type));
652 } 690 }
653 691
654 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); 692 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet));
693 if (method.canBeApplied) {
694 data.add(js.number(method.requiredParameterCount));
695 data.add(_encodeOptionalParameterDefaultValues(method));
696 }
655 return [js.string(method.name), new js.ArrayInitializer(data)]; 697 return [js.string(method.name), new js.ArrayInitializer(data)];
656 } else { 698 } else {
657 // TODO(floitsch): not the most efficient way... 699 // TODO(floitsch): not the most efficient way...
658 return ([method]..addAll(method.parameterStubs)) 700 return ([method]..addAll(method.parameterStubs))
659 .expand(makeNameCodePair); 701 .expand(makeNameCodePair);
660 } 702 }
661 } else { 703 } else {
662 return makeNameCodePair(method); 704 return makeNameCodePair(method);
663 } 705 }
664 } 706 }
(...skipping 23 matching lines...) Expand all
688 /// The format emitted is the same as for the parser specified at 730 /// The format emitted is the same as for the parser specified at
689 /// [parseFunctionDescriptorBoilerplate] except for the missing 731 /// [parseFunctionDescriptorBoilerplate] except for the missing
690 /// field whether the method is intercepted. 732 /// field whether the method is intercepted.
691 // [name, [function, callName, tearOffName, functionType, 733 // [name, [function, callName, tearOffName, functionType,
692 // stub1_name, stub1_callName, stub1_code, ...] 734 // stub1_name, stub1_callName, stub1_code, ...]
693 var data = [unparse(compiler, method.code)]; 735 var data = [unparse(compiler, method.code)];
694 data.add(js.string(method.callName)); 736 data.add(js.string(method.callName));
695 data.add(js.string(method.tearOffName)); 737 data.add(js.string(method.tearOffName));
696 data.add(_generateFunctionType(method.type)); 738 data.add(_generateFunctionType(method.type));
697 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); 739 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet));
740 if (method.canBeApplied) {
741 data.add(js.number(method.requiredParameterCount));
742 data.add(_encodeOptionalParameterDefaultValues(method));
743 }
698 return [js.string(method.name), holderIndex, 744 return [js.string(method.name), holderIndex,
699 new js.ArrayInitializer(data)]; 745 new js.ArrayInitializer(data)];
700 } else { 746 } else {
701 method.parameterStubs.forEach(_addMethod); 747 method.parameterStubs.forEach(_addMethod);
702 } 748 }
703 } 749 }
704 return output; 750 return output;
705 } 751 }
706 752
707 static final String setupProgramName = "setupProgram"; 753 static final String setupProgramName = "setupProgram";
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 var method = compile(name, descriptor); 821 var method = compile(name, descriptor);
776 holder[name] = method; 822 holder[name] = method;
777 return method.apply(this, arguments); 823 return method.apply(this, arguments);
778 }; 824 };
779 } else { 825 } else {
780 // Parse the tear off information and generate compile handlers. 826 // Parse the tear off information and generate compile handlers.
781 // TODO(herhut): Share parser with instance methods. 827 // TODO(herhut): Share parser with instance methods.
782 function compileAllStubs() { 828 function compileAllStubs() {
783 var funs; 829 var funs;
784 var fun = compile(name, descriptor[0]); 830 var fun = compile(name, descriptor[0]);
785 fun.\$callName = descriptor[1]; 831 fun[#callName] = descriptor[1];
786 holder[name] = fun; 832 holder[name] = fun;
787 funs = [fun]; 833 funs = [fun];
788 for (var pos = 4; pos < descriptor.length; pos += 3) { 834 for (var pos = 4; pos < descriptor.length; pos += 3) {
789 var stubName = descriptor[pos]; 835 var stubName = descriptor[pos];
790 fun = compile(stubName, descriptor[pos + 2]); 836 fun = compile(stubName, descriptor[pos + 2]);
791 fun.\$callName = descriptor[pos + 1]; 837 fun[#callName] = descriptor[pos + 1];
792 holder[stubName] = fun; 838 holder[stubName] = fun;
793 funs.push(fun); 839 funs.push(fun);
794 } 840 }
795 if (descriptor[2] != null) { // tear-off name. 841 if (descriptor[2] != null) { // tear-off name.
796 // functions, reflectionInfo, isStatic, name, isIntercepted. 842 // functions, reflectionInfo, isStatic, name, isIntercepted.
797 holder[descriptor[2]] = 843 holder[descriptor[2]] =
798 tearOff(funs, descriptor[3], true, name, false); 844 tearOff(funs, descriptor[3], true, name, false);
799 } 845 }
800 } 846 }
801 847
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 1024
979 var end = Date.now(); 1025 var end = Date.now();
980 // print('Setup: ' + (end - start) + ' ms.'); 1026 // print('Setup: ' + (end - start) + ' ms.');
981 1027
982 #invokeMain; // Start main. 1028 #invokeMain; // Start main.
983 1029
984 }(Date.now(), #code) 1030 }(Date.now(), #code)
985 }"""; 1031 }""";
986 1032
987 } 1033 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | pkg/compiler/lib/src/js_emitter/program_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698