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; | |
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 Loading... | |
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 | |
117 'cyclicThrow': | 121 'cyclicThrow': |
118 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), | 122 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), |
119 'outputContainsConstantList': program.outputContainsConstantList, | 123 'outputContainsConstantList': program.outputContainsConstantList, |
120 'embeddedGlobals': emitEmbeddedGlobals(program), | 124 'embeddedGlobals': emitEmbeddedGlobals(program), |
121 'constants': emitConstants(fragment.constants), | 125 'constants': emitConstants(fragment.constants), |
122 'staticNonFinals': | 126 'staticNonFinals': |
123 emitStaticNonFinalFields(fragment.staticNonFinalFields), | 127 emitStaticNonFinalFields(fragment.staticNonFinalFields), |
124 'operatorIsPrefix': js.string(namer.operatorIsPrefix), | 128 'operatorIsPrefix': js.string(namer.operatorIsPrefix), |
125 'eagerClasses': emitEagerClassInitializations(fragment.libraries), | 129 'eagerClasses': emitEagerClassInitializations(fragment.libraries), |
126 'invokeMain': fragment.invokeMain, | 130 'invokeMain': fragment.invokeMain, |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
545 assert(field.isLazy); | 549 assert(field.isLazy); |
546 return unparse(compiler, field.code); | 550 return unparse(compiler, field.code); |
547 } | 551 } |
548 | 552 |
549 /// JavaScript code template that implements parsing of a function descriptor. | 553 /// JavaScript code template that implements parsing of a function descriptor. |
550 /// Descriptors are used in place of the actual JavaScript function | 554 /// Descriptors are used in place of the actual JavaScript function |
551 /// definition in the output if additional information needs to be passed to | 555 /// 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 | 556 /// facilitate the generation of tearOffs at runtime. The format is an array |
553 /// with the following fields: | 557 /// with the following fields: |
554 /// | 558 /// |
555 /// [InstanceMethod.aliasName] (optional). | 559 /// [InstanceMethod.aliasName] (optional). |
floitsch
2015/02/16 15:26:03
Since this is dartdoc, writing the fields line per
herhut
2015/02/17 10:25:39
Done.
| |
556 /// [Method.code] | 560 /// [Method.code] |
557 /// [DartMethod.callName] | 561 /// [DartMethod.callName] |
558 /// isInterceptedMethod (optional, present if [DartMethod.needsTearOff]). | 562 /// isInterceptedMethod (optional, present if [DartMethod.needsTearOff]). |
559 /// [DartMethod.tearOffName] (optional, present if [DartMethod.needsTearOff]). | 563 /// [DartMethod.tearOffName] (optional, present if [DartMethod.needsTearOff]). |
560 /// functionType (optional, present if [DartMethod.needsTearOff]). | 564 /// functionType (optional, present if [DartMethod.needsTearOff]). |
561 /// | 565 /// |
562 /// followed by | 566 /// followed by |
563 /// | 567 /// |
564 /// [ParameterStubMethod.name] | 568 /// [ParameterStubMethod.name] |
565 /// [ParameterStubMethod.code] | 569 /// [ParameterStubMethod.code] |
floitsch
2015/02/16 15:26:03
Something seems to be missing here.
herhut
2015/02/17 10:25:39
[ParameterStubMethod.callName] was missing. Fixed.
| |
566 /// | 570 /// |
567 /// for each stub in [DartMethod.parameterStubs]. | 571 /// for each stub in [DartMethod.parameterStubs]. If [DartMethod.canBeApplied] |
floitsch
2015/02/16 15:26:03
Start a new paragraph.
If the closure could be us
herhut
2015/02/17 10:25:39
Done.
| |
572 /// is true | |
573 /// | |
574 /// [DartMethod.requiredParameterCount] | |
575 /// [DartMethod.optionalParameterDefaultValues] | |
576 /// | |
577 /// is also appended. | |
568 | 578 |
569 static final String parseFunctionDescriptorBoilerplate = r""" | 579 static final String parseFunctionDescriptorBoilerplate = r""" |
570 function parseFunctionDescriptor(proto, name, descriptor) { | 580 function parseFunctionDescriptor(proto, name, descriptor) { |
571 if (descriptor instanceof Array) { | 581 if (descriptor instanceof Array) { |
572 // 'pos' points to the last read entry. | 582 // 'pos' points to the last read entry. |
573 var f, pos = -1; | 583 var f, pos = -1; |
574 var aliasOrFunction = descriptor[++pos]; | 584 var aliasOrFunction = descriptor[++pos]; |
575 if (typeof aliasOrFunction == "string") { | 585 if (typeof aliasOrFunction == "string") { |
576 // Install the alias for super calls on the prototype chain. | 586 // Install the alias for super calls on the prototype chain. |
577 proto[aliasOrFunction] = f = descriptor[++pos]; | 587 proto[aliasOrFunction] = f = descriptor[++pos]; |
578 } else { | 588 } else { |
579 f = aliasOrFunction; | 589 f = aliasOrFunction; |
580 } | 590 } |
581 | 591 |
582 proto[name] = f; | 592 proto[name] = f; |
583 var funs = [f]; | 593 var funs = [f]; |
584 f.$callName = descriptor[++pos]; | 594 f.$callName = descriptor[++pos]; |
585 | 595 |
586 var isInterceptedOrParameterStubName = descriptor[pos + 1]; | 596 var isInterceptedOrParameterStubName = descriptor[pos + 1]; |
587 var isIntercepted, tearOffName, reflectionInfo; | 597 var isIntercepted, tearOffName, reflectionInfo; |
588 if (typeof isInterceptedOrParameterStubName == "boolean") { | 598 if (typeof isInterceptedOrParameterStubName == "boolean") { |
589 isIntercepted = descriptor[++pos]; | 599 isIntercepted = descriptor[++pos]; |
590 tearOffName = descriptor[++pos]; | 600 tearOffName = descriptor[++pos]; |
591 reflectionInfo = descriptor[++pos]; | 601 reflectionInfo = descriptor[++pos]; |
592 } | 602 } |
593 | 603 |
594 for (++pos; pos < descriptor.length; pos += 3) { | 604 for (++pos; pos < descriptor.length - 2; pos += 3) { |
floitsch
2015/02/16 15:26:03
add a comment why the "2".
herhut
2015/02/17 10:25:39
Done.
| |
595 var stub = descriptor[pos + 2]; | 605 var stub = descriptor[pos + 2]; |
596 stub.$callName = descriptor[pos + 1]; | 606 stub.$callName = descriptor[pos + 1]; |
floitsch
2015/02/16 15:26:03
This should be a shared variable. (the "$callName"
herhut
2015/02/17 10:25:39
Done.
| |
597 proto[descriptor[pos]] = stub; | 607 proto[descriptor[pos]] = stub; |
598 funs.push(stub); | 608 funs.push(stub); |
599 } | 609 } |
600 | 610 |
601 if (tearOffName) { | 611 if (tearOffName) { |
602 proto[tearOffName] = | 612 proto[tearOffName] = |
603 tearOff(funs, reflectionInfo, false, name, isIntercepted); | 613 tearOff(funs, reflectionInfo, false, name, isIntercepted); |
604 } | 614 } |
605 | 615 if (descriptor[pos] != null) { |
616 f[#argCnt] = descriptor[pos]; | |
617 f[#defArgValues] = descriptor[pos + 1]; | |
618 } | |
606 } else { | 619 } else { |
607 proto[name] = descriptor; | 620 proto[name] = descriptor; |
608 } | 621 } |
609 } | 622 } |
610 """; | 623 """; |
611 | 624 |
612 js.Expression _generateFunctionType(DartType memberType) { | 625 js.Expression _generateFunctionType(DartType memberType) { |
613 if (memberType.containsTypeVariables) { | 626 if (memberType.containsTypeVariables) { |
614 js.Expression thisAccess = js.js(r'this.$receiver'); | 627 js.Expression thisAccess = js.js(r'this.$receiver'); |
615 return backend.rti.getSignatureEncoding(memberType, thisAccess); | 628 return backend.rti.getSignatureEncoding(memberType, thisAccess); |
616 } else { | 629 } else { |
617 return js.number(backend.emitter.metadataCollector.reifyType(memberType)); | 630 return js.number(backend.emitter.metadataCollector.reifyType(memberType)); |
618 } | 631 } |
619 } | 632 } |
620 | 633 |
634 js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) { | |
635 js.Expression result; | |
636 // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole]. | |
637 if (method.optionalParameterDefaultValues is List) { | |
638 List<ConstantValue> defs = method.optionalParameterDefaultValues; | |
639 Iterable<js.Expression> elements = defs.map(constantEmitter.reference); | |
640 return new js.ArrayInitializer(elements.toList()); | |
641 } else { | |
642 Map<String, ConstantValue> defs = method.optionalParameterDefaultValues; | |
643 List<js.Property> properties = <js.Property>[]; | |
644 defs.forEach((String name, ConstantValue value) { | |
645 properties.add(new js.Property(js.string(name), | |
646 constantEmitter.reference(value))); | |
647 }); | |
648 return new js.ObjectInitializer(properties); | |
649 } | |
650 } | |
651 | |
621 Iterable<js.Expression> emitInstanceMethod(Method method) { | 652 Iterable<js.Expression> emitInstanceMethod(Method method) { |
622 | 653 |
623 List<js.Expression> makeNameCodePair(Method method) { | 654 List<js.Expression> makeNameCodePair(Method method) { |
624 return [js.string(method.name), method.code]; | 655 return [js.string(method.name), method.code]; |
625 } | 656 } |
626 | 657 |
627 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { | 658 List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) { |
628 js.Expression callName = stub.callName == null | 659 js.Expression callName = stub.callName == null |
629 ? new js.LiteralNull() | 660 ? new js.LiteralNull() |
630 : js.string(stub.callName); | 661 : js.string(stub.callName); |
(...skipping 14 matching lines...) Expand all Loading... | |
645 data.add(js.string(method.callName)); | 676 data.add(js.string(method.callName)); |
646 | 677 |
647 if (method.needsTearOff) { | 678 if (method.needsTearOff) { |
648 bool isIntercepted = backend.isInterceptedMethod(method.element); | 679 bool isIntercepted = backend.isInterceptedMethod(method.element); |
649 data.add(new js.LiteralBool(isIntercepted)); | 680 data.add(new js.LiteralBool(isIntercepted)); |
650 data.add(js.string(method.tearOffName)); | 681 data.add(js.string(method.tearOffName)); |
651 data.add(_generateFunctionType(method.type)); | 682 data.add(_generateFunctionType(method.type)); |
652 } | 683 } |
653 | 684 |
654 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); | 685 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); |
686 if (method.canBeApplied) { | |
687 data.add(js.number(method.requiredParameterCount)); | |
688 data.add(_encodeOptionalParameterDefaultValues(method)); | |
689 } | |
655 return [js.string(method.name), new js.ArrayInitializer(data)]; | 690 return [js.string(method.name), new js.ArrayInitializer(data)]; |
656 } else { | 691 } else { |
657 // TODO(floitsch): not the most efficient way... | 692 // TODO(floitsch): not the most efficient way... |
658 return ([method]..addAll(method.parameterStubs)) | 693 return ([method]..addAll(method.parameterStubs)) |
659 .expand(makeNameCodePair); | 694 .expand(makeNameCodePair); |
660 } | 695 } |
661 } else { | 696 } else { |
662 return makeNameCodePair(method); | 697 return makeNameCodePair(method); |
663 } | 698 } |
664 } | 699 } |
(...skipping 23 matching lines...) Expand all Loading... | |
688 /// The format emitted is the same as for the parser specified at | 723 /// The format emitted is the same as for the parser specified at |
689 /// [parseFunctionDescriptorBoilerplate] except for the missing | 724 /// [parseFunctionDescriptorBoilerplate] except for the missing |
690 /// field whether the method is intercepted. | 725 /// field whether the method is intercepted. |
691 // [name, [function, callName, tearOffName, functionType, | 726 // [name, [function, callName, tearOffName, functionType, |
692 // stub1_name, stub1_callName, stub1_code, ...] | 727 // stub1_name, stub1_callName, stub1_code, ...] |
693 var data = [unparse(compiler, method.code)]; | 728 var data = [unparse(compiler, method.code)]; |
694 data.add(js.string(method.callName)); | 729 data.add(js.string(method.callName)); |
695 data.add(js.string(method.tearOffName)); | 730 data.add(js.string(method.tearOffName)); |
696 data.add(_generateFunctionType(method.type)); | 731 data.add(_generateFunctionType(method.type)); |
697 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); | 732 data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet)); |
733 if (method.canBeApplied) { | |
734 data.add(js.number(method.requiredParameterCount)); | |
735 data.add(_encodeOptionalParameterDefaultValues(method)); | |
736 } | |
698 return [js.string(method.name), holderIndex, | 737 return [js.string(method.name), holderIndex, |
699 new js.ArrayInitializer(data)]; | 738 new js.ArrayInitializer(data)]; |
700 } else { | 739 } else { |
701 method.parameterStubs.forEach(_addMethod); | 740 method.parameterStubs.forEach(_addMethod); |
702 } | 741 } |
703 } | 742 } |
704 return output; | 743 return output; |
705 } | 744 } |
706 | 745 |
707 static final String setupProgramName = "setupProgram"; | 746 static final String setupProgramName = "setupProgram"; |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
978 | 1017 |
979 var end = Date.now(); | 1018 var end = Date.now(); |
980 // print('Setup: ' + (end - start) + ' ms.'); | 1019 // print('Setup: ' + (end - start) + ' ms.'); |
981 | 1020 |
982 #invokeMain; // Start main. | 1021 #invokeMain; // Start main. |
983 | 1022 |
984 }(Date.now(), #code) | 1023 }(Date.now(), #code) |
985 }"""; | 1024 }"""; |
986 | 1025 |
987 } | 1026 } |
OLD | NEW |