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.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 |