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

Side by Side Diff: lib/compiler/implementation/js_backend/emitter.dart

Issue 10917285: Stub implementation of patch invariants for the patch refactoring. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments Created 8 years, 3 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 /** 5 /**
6 * A function element that represents a closure call. The signature is copied 6 * A function element that represents a closure call. The signature is copied
7 * from the given element. 7 * from the given element.
8 */ 8 */
9 class ClosureInvocationElement extends FunctionElement { 9 class ClosureInvocationElement extends FunctionElement {
10 ClosureInvocationElement(SourceString name, 10 ClosureInvocationElement(SourceString name,
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 && compiler.codegenWorld.hasInvokedSetter(member, compiler); 491 && compiler.codegenWorld.hasInvokedSetter(member, compiler);
492 } 492 }
493 493
494 String compiledFieldName(Element member) { 494 String compiledFieldName(Element member) {
495 assert(member.isField()); 495 assert(member.isField());
496 return member.isNative() 496 return member.isNative()
497 ? member.name.slowToString() 497 ? member.name.slowToString()
498 : namer.getName(member); 498 : namer.getName(member);
499 } 499 }
500 500
501 /**
502 * Documentation wanted -- johnniwinther
503 *
504 * Invariant: [member] must be a declaration element.
505 */
501 void addInstanceMember(Element member, 506 void addInstanceMember(Element member,
502 DefineMemberFunction defineInstanceMember) { 507 DefineMemberFunction defineInstanceMember) {
508 assert(invariant(member, member.isDeclaration));
503 // TODO(floitsch): we don't need to deal with members of 509 // TODO(floitsch): we don't need to deal with members of
504 // uninstantiated classes, that have been overwritten by subclasses. 510 // uninstantiated classes, that have been overwritten by subclasses.
505 511
506 if (member.isFunction() 512 if (member.isFunction()
507 || member.isGenerativeConstructorBody() 513 || member.isGenerativeConstructorBody()
508 || member.isGetter() 514 || member.isGetter()
509 || member.isSetter()) { 515 || member.isSetter()) {
510 if (member.modifiers !== null && member.modifiers.isAbstract()) return; 516 if (member.modifiers !== null && member.modifiers.isAbstract()) return;
511 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member]; 517 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member];
512 if (codeBuffer == null) return; 518 if (codeBuffer == null) return;
(...skipping 24 matching lines...) Expand all
537 } else { 543 } else {
538 SourceString helper = compiler.backend.getCheckedModeHelper(type); 544 SourceString helper = compiler.backend.getCheckedModeHelper(type);
539 Element helperElement = compiler.findHelper(helper); 545 Element helperElement = compiler.findHelper(helper);
540 String helperName = namer.isolateAccess(helperElement); 546 String helperName = namer.isolateAccess(helperElement);
541 String additionalArgument = namer.operatorIs(type.element); 547 String additionalArgument = namer.operatorIs(type.element);
542 return " set\$$fieldName: function(v) { " 548 return " set\$$fieldName: function(v) { "
543 "this.$fieldName = $helperName(v, '$additionalArgument'); }"; 549 "this.$fieldName = $helperName(v, '$additionalArgument'); }";
544 } 550 }
545 } 551 }
546 552
553 /**
554 * Documentation wanted -- johnniwinther
555 *
556 * Invariant: [classElement] must be a declaration element.
557 */
547 List<String> emitClassFields(ClassElement classElement, CodeBuffer buffer) { 558 List<String> emitClassFields(ClassElement classElement, CodeBuffer buffer) {
559 assert(invariant(classElement, classElement.isDeclaration));
548 // If the class is never instantiated we still need to set it up for 560 // If the class is never instantiated we still need to set it up for
549 // inheritance purposes, but we can simplify its JavaScript constructor. 561 // inheritance purposes, but we can simplify its JavaScript constructor.
550 bool isInstantiated = 562 bool isInstantiated =
551 compiler.codegenWorld.instantiatedClasses.contains(classElement); 563 compiler.codegenWorld.instantiatedClasses.contains(classElement);
552 List<String> checkedSetters = <String>[]; 564 List<String> checkedSetters = <String>[];
553 565
554 bool isFirstField = true; 566 bool isFirstField = true;
555 void addField(ClassElement enclosingClass, Element member) { 567 void addField(ClassElement enclosingClass, Element member) {
556 assert(!member.isNative()); 568 assert(!member.isNative());
569 assert(invariant(classElement, member.isDeclaration));
557 570
558 LibraryElement library = member.getLibrary(); 571 LibraryElement library = member.getLibrary();
559 SourceString name = member.name; 572 SourceString name = member.name;
560 bool isPrivate = name.isPrivate(); 573 bool isPrivate = name.isPrivate();
561 // See if we can dynamically create getters and setters. 574 // See if we can dynamically create getters and setters.
562 // We can only generate getters and setters for [classElement] since 575 // We can only generate getters and setters for [classElement] since
563 // the fields of super classes could be overwritten with getters or 576 // the fields of super classes could be overwritten with getters or
564 // setters. 577 // setters.
565 bool needsDynamicGetter = false; 578 bool needsDynamicGetter = false;
566 bool needsDynamicSetter = false; 579 bool needsDynamicSetter = false;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 // generate the field getter/setter dynamically. Since this is only 624 // generate the field getter/setter dynamically. Since this is only
612 // allowed on fields that are in [classElement] we don't need to visit 625 // allowed on fields that are in [classElement] we don't need to visit
613 // superclasses for non-instantiated classes. 626 // superclasses for non-instantiated classes.
614 classElement.forEachInstanceField( 627 classElement.forEachInstanceField(
615 addField, 628 addField,
616 includeBackendMembers: true, 629 includeBackendMembers: true,
617 includeSuperMembers: isInstantiated && !classElement.isNative()); 630 includeSuperMembers: isInstantiated && !classElement.isNative());
618 return checkedSetters; 631 return checkedSetters;
619 } 632 }
620 633
634 /**
635 * Documentation wanted -- johnniwinther
636 *
637 * Invariant: [classElement] must be a declaration element.
638 */
621 void emitInstanceMembers(ClassElement classElement, 639 void emitInstanceMembers(ClassElement classElement,
622 CodeBuffer buffer, 640 CodeBuffer buffer,
623 bool needsLeadingComma) { 641 bool needsLeadingComma) {
642 assert(invariant(classElement, classElement.isDeclaration));
624 bool needsComma = needsLeadingComma; 643 bool needsComma = needsLeadingComma;
625 void defineInstanceMember(String name, CodeBuffer memberBuffer) { 644 void defineInstanceMember(String name, CodeBuffer memberBuffer) {
626 if (needsComma) buffer.add(','); 645 if (needsComma) buffer.add(',');
627 needsComma = true; 646 needsComma = true;
628 buffer.add('\n'); 647 buffer.add('\n');
629 buffer.add(' $name: '); 648 buffer.add(' $name: ');
630 buffer.add(memberBuffer); 649 buffer.add(memberBuffer);
631 } 650 }
632 651
633 classElement.forEachMember(includeBackendMembers: true, 652 classElement.forEachMember(includeBackendMembers: true,
634 f: (ClassElement enclosing, Element member) { 653 f: (ClassElement enclosing, Element member) {
654 assert(invariant(classElement, member.isDeclaration));
635 if (member.isInstanceMember()) { 655 if (member.isInstanceMember()) {
636 addInstanceMember(member, defineInstanceMember); 656 addInstanceMember(member, defineInstanceMember);
637 } 657 }
638 }); 658 });
639 659
640 generateIsTestsOn(classElement, (Element other) { 660 generateIsTestsOn(classElement, (Element other) {
641 String code; 661 String code;
642 if (nativeEmitter.requiresNativeIsCheck(other)) { 662 if (nativeEmitter.requiresNativeIsCheck(other)) {
643 code = 'function() { return true; }'; 663 code = 'function() { return true; }';
644 } else { 664 } else {
645 code = 'true'; 665 code = 'true';
646 } 666 }
647 CodeBuffer typeTestBuffer = new CodeBuffer(); 667 CodeBuffer typeTestBuffer = new CodeBuffer();
648 typeTestBuffer.add(code); 668 typeTestBuffer.add(code);
649 defineInstanceMember(namer.operatorIs(other), typeTestBuffer); 669 defineInstanceMember(namer.operatorIs(other), typeTestBuffer);
650 }); 670 });
651 671
652 if (classElement === compiler.objectClass && compiler.enabledNoSuchMethod) { 672 if (classElement === compiler.objectClass && compiler.enabledNoSuchMethod) {
653 // Emit the noSuchMethod handlers on the Object prototype now, 673 // Emit the noSuchMethod handlers on the Object prototype now,
654 // so that the code in the dynamicFunction helper can find 674 // so that the code in the dynamicFunction helper can find
655 // them. Note that this helper is invoked before analyzing the 675 // them. Note that this helper is invoked before analyzing the
656 // full JS script. 676 // full JS script.
657 if (!nativeEmitter.handleNoSuchMethod) { 677 if (!nativeEmitter.handleNoSuchMethod) {
658 emitNoSuchMethodHandlers(defineInstanceMember); 678 emitNoSuchMethodHandlers(defineInstanceMember);
659 } 679 }
660 } 680 }
661 } 681 }
662 682
683 /**
684 * Documentation wanted -- johnniwinther
685 *
686 * Invariant: [classElement] must be a declaration element.
687 */
663 void generateClass(ClassElement classElement, CodeBuffer buffer) { 688 void generateClass(ClassElement classElement, CodeBuffer buffer) {
689 assert(invariant(classElement, classElement.isDeclaration));
664 if (classElement.isNative()) { 690 if (classElement.isNative()) {
665 nativeEmitter.generateNativeClass(classElement); 691 nativeEmitter.generateNativeClass(classElement);
666 return; 692 return;
667 } else { 693 } else {
668 // TODO(ngeoffray): Instead of switching between buffer, we 694 // TODO(ngeoffray): Instead of switching between buffer, we
669 // should create code sections, and decide where to emit them at 695 // should create code sections, and decide where to emit them at
670 // the end. 696 // the end.
671 buffer = mainBuffer; 697 buffer = mainBuffer;
672 } 698 }
673 699
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 addParameterStubs(callElement, (String name, CodeBuffer value) { 875 addParameterStubs(callElement, (String name, CodeBuffer value) {
850 buffer.add('$fieldAccess.$name = $value;\n'); 876 buffer.add('$fieldAccess.$name = $value;\n');
851 }); 877 });
852 // If a static function is used as a closure we need to add its name 878 // If a static function is used as a closure we need to add its name
853 // in case it is used in spawnFunction. 879 // in case it is used in spawnFunction.
854 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; 880 String fieldName = namer.STATIC_CLOSURE_NAME_NAME;
855 buffer.add('$fieldAccess.$fieldName = "$staticName";\n'); 881 buffer.add('$fieldAccess.$fieldName = "$staticName";\n');
856 } 882 }
857 } 883 }
858 884
885 /**
886 * Documentation wanted -- johnniwinther
887 *
888 * Invariant: [member] must be a declaration element.
889 */
859 void emitDynamicFunctionGetter(FunctionElement member, 890 void emitDynamicFunctionGetter(FunctionElement member,
860 DefineMemberFunction defineInstanceMember) { 891 DefineMemberFunction defineInstanceMember) {
892 assert(invariant(member, member.isDeclaration));
861 // For every method that has the same name as a property-get we create a 893 // For every method that has the same name as a property-get we create a
862 // getter that returns a bound closure. Say we have a class 'A' with method 894 // getter that returns a bound closure. Say we have a class 'A' with method
863 // 'foo' and somewhere in the code there is a dynamic property get of 895 // 'foo' and somewhere in the code there is a dynamic property get of
864 // 'foo'. Then we generate the following code (in pseudo Dart/JavaScript): 896 // 'foo'. Then we generate the following code (in pseudo Dart/JavaScript):
865 // 897 //
866 // class A { 898 // class A {
867 // foo(x, y, z) { ... } // Original function. 899 // foo(x, y, z) { ... } // Original function.
868 // get foo { return new BoundClosure499(this, "foo"); } 900 // get foo { return new BoundClosure499(this, "foo"); }
869 // } 901 // }
870 // class BoundClosure499 extends Closure { 902 // class BoundClosure499 extends Closure {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 965
934 // And finally the getter. 966 // And finally the getter.
935 String getterName = namer.getterName(member.getLibrary(), member.name); 967 String getterName = namer.getterName(member.getLibrary(), member.name);
936 String targetName = namer.instanceMethodName(member); 968 String targetName = namer.instanceMethodName(member);
937 CodeBuffer getterBuffer = new CodeBuffer(); 969 CodeBuffer getterBuffer = new CodeBuffer();
938 getterBuffer.add( 970 getterBuffer.add(
939 "function() { return new $closureClass(this, '$targetName'); }"); 971 "function() { return new $closureClass(this, '$targetName'); }");
940 defineInstanceMember(getterName, getterBuffer); 972 defineInstanceMember(getterName, getterBuffer);
941 } 973 }
942 974
975 /**
976 * Documentation wanted -- johnniwinther
977 *
978 * Invariant: [member] must be a declaration element.
979 */
943 void emitCallStubForGetter(Element member, 980 void emitCallStubForGetter(Element member,
944 Set<Selector> selectors, 981 Set<Selector> selectors,
945 DefineMemberFunction defineInstanceMember) { 982 DefineMemberFunction defineInstanceMember) {
983 assert(invariant(member, member.isDeclaration));
984 LibraryElement memberLibrary = member.getLibrary();
946 String getter; 985 String getter;
947 if (member.isGetter()) { 986 if (member.isGetter()) {
948 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; 987 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()";
949 } else { 988 } else {
950 String name = namer.instanceFieldName(member.getLibrary(), member.name); 989 String name = namer.instanceFieldName(memberLibrary, member.name);
951 getter = "this.$name"; 990 getter = "this.$name";
952 } 991 }
953 for (Selector selector in selectors) { 992 for (Selector selector in selectors) {
954 if (selector.applies(member, compiler)) { 993 if (selector.applies(member, compiler)) {
955 String invocationName = 994 String invocationName =
956 namer.instanceMethodInvocationName(member.getLibrary(), member.name, 995 namer.instanceMethodInvocationName(memberLibrary, member.name,
957 selector); 996 selector);
958 SourceString callName = Namer.CLOSURE_INVOCATION_NAME; 997 SourceString callName = Namer.CLOSURE_INVOCATION_NAME;
959 String closureCallName = 998 String closureCallName =
960 namer.instanceMethodInvocationName(member.getLibrary(), callName, 999 namer.instanceMethodInvocationName(memberLibrary, callName,
961 selector); 1000 selector);
962 List<String> arguments = <String>[]; 1001 List<String> arguments = <String>[];
963 for (int i = 0; i < selector.argumentCount; i++) { 1002 for (int i = 0; i < selector.argumentCount; i++) {
964 arguments.add("arg$i"); 1003 arguments.add("arg$i");
965 } 1004 }
966 String joined = Strings.join(arguments, ", "); 1005 String joined = Strings.join(arguments, ", ");
967 CodeBuffer getterBuffer = new CodeBuffer(); 1006 CodeBuffer getterBuffer = new CodeBuffer();
968 getterBuffer.add( 1007 getterBuffer.add(
969 "function($joined) { return $getter.$closureCallName($joined); }"); 1008 "function($joined) { return $getter.$closureCallName($joined); }");
970 defineInstanceMember(invocationName, getterBuffer); 1009 defineInstanceMember(invocationName, getterBuffer);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 void emitMakeConstantList(CodeBuffer buffer) { 1081 void emitMakeConstantList(CodeBuffer buffer) {
1043 buffer.add(namer.ISOLATE); 1082 buffer.add(namer.ISOLATE);
1044 buffer.add(@'''.makeConstantList = function(list) { 1083 buffer.add(@'''.makeConstantList = function(list) {
1045 list.immutable$list = true; 1084 list.immutable$list = true;
1046 list.fixed$length = true; 1085 list.fixed$length = true;
1047 return list; 1086 return list;
1048 }; 1087 };
1049 '''); 1088 ''');
1050 } 1089 }
1051 1090
1091 /**
1092 * Documentation wanted -- johnniwinther
1093 *
1094 * Invariant: [member] must be a declaration element.
1095 */
1052 void emitExtraAccessors(Element member, 1096 void emitExtraAccessors(Element member,
1053 DefineMemberFunction defineInstanceMember) { 1097 DefineMemberFunction defineInstanceMember) {
1098 assert(invariant(member, member.isDeclaration));
1054 if (member.isGetter() || member.isField()) { 1099 if (member.isGetter() || member.isField()) {
1055 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; 1100 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name];
1056 if (selectors !== null && !selectors.isEmpty()) { 1101 if (selectors !== null && !selectors.isEmpty()) {
1057 emitCallStubForGetter(member, selectors, defineInstanceMember); 1102 emitCallStubForGetter(member, selectors, defineInstanceMember);
1058 } 1103 }
1059 } else if (member.isFunction()) { 1104 } else if (member.isFunction()) {
1060 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { 1105 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) {
1061 emitDynamicFunctionGetter(member, defineInstanceMember); 1106 emitDynamicFunctionGetter(member, defineInstanceMember);
1062 } 1107 }
1063 } 1108 }
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1377 const String HOOKS_API_USAGE = """ 1422 const String HOOKS_API_USAGE = """
1378 // Generated by dart2js, the Dart to JavaScript compiler. 1423 // Generated by dart2js, the Dart to JavaScript compiler.
1379 // The code supports the following hooks: 1424 // The code supports the following hooks:
1380 // dartPrint(message) - if this function is defined it is called 1425 // dartPrint(message) - if this function is defined it is called
1381 // instead of the Dart [print] method. 1426 // instead of the Dart [print] method.
1382 // dartMainRunner(main) - if this function is defined, the Dart [main] 1427 // dartMainRunner(main) - if this function is defined, the Dart [main]
1383 // method will not be invoked directly. 1428 // method will not be invoked directly.
1384 // Instead, a closure that will invoke [main] is 1429 // Instead, a closure that will invoke [main] is
1385 // passed to [dartMainRunner]. 1430 // passed to [dartMainRunner].
1386 """; 1431 """;
OLDNEW
« no previous file with comments | « lib/compiler/implementation/js_backend/backend.dart ('k') | lib/compiler/implementation/patch_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698