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

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

Issue 11478050: Revert minification (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years 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 part of js_backend; 5 part of js_backend;
6 6
7 /** 7 /**
8 * A function element that represents a closure call. The signature is copied 8 * A function element that represents a closure call. The signature is copied
9 * from the given element. 9 * from the given element.
10 */ 10 */
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 return constantEmitter.reference(value); 85 return constantEmitter.reference(value);
86 } 86 }
87 87
88 js.Expression constantInitializerExpression(Constant value) { 88 js.Expression constantInitializerExpression(Constant value) {
89 return constantEmitter.initializationExpression(value); 89 return constantEmitter.initializationExpression(value);
90 } 90 }
91 91
92 String get name => 'CodeEmitter'; 92 String get name => 'CodeEmitter';
93 93
94 String get defineClassName 94 String get defineClassName
95 => '${namer.isolateName}.\$defineClass'; 95 => '${namer.ISOLATE}.\$defineClass';
96 String get currentGenerateAccessorName 96 String get currentGenerateAccessorName
97 => '${namer.CURRENT_ISOLATE}.\$generateAccessor'; 97 => '${namer.CURRENT_ISOLATE}.\$generateAccessor';
98 String get generateAccessorHolder 98 String get generateAccessorHolder
99 => '$isolatePropertiesName.\$generateAccessor'; 99 => '$isolatePropertiesName.\$generateAccessor';
100 String get finishClassesName 100 String get finishClassesName
101 => '${namer.isolateName}.\$finishClasses'; 101 => '${namer.ISOLATE}.\$finishClasses';
102 String get finishIsolateConstructorName 102 String get finishIsolateConstructorName
103 => '${namer.isolateName}.\$finishIsolateConstructor'; 103 => '${namer.ISOLATE}.\$finishIsolateConstructor';
104 String get pendingClassesName 104 String get pendingClassesName
105 => '${namer.isolateName}.\$pendingClasses'; 105 => '${namer.ISOLATE}.\$pendingClasses';
106 String get isolatePropertiesName 106 String get isolatePropertiesName
107 => '${namer.isolateName}.${namer.isolatePropertiesName}'; 107 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}';
108 String get supportsProtoName 108 String get supportsProtoName
109 => 'supportsProto'; 109 => 'supportsProto';
110 String get lazyInitializerName 110 String get lazyInitializerName
111 => '${namer.isolateName}.\$lazy'; 111 => '${namer.ISOLATE}.\$lazy';
112 112
113 // Property name suffixes. If the accessors are renaming then the format 113 final String GETTER_SUFFIX = "?";
114 // is <accessorName>:<fieldName><suffix>. We use the suffix to know whether 114 final String SETTER_SUFFIX = "!";
115 // to look for the ':' separator in order to avoid doing the indexOf operation 115 final String GETTER_SETTER_SUFFIX = "=";
116 // on every single property (they are quite rare). None of these characters
117 // are legal in an identifier and they are related by bit patterns.
118 // setter < 0x3c
119 // both = 0x3d
120 // getter > 0x3e
121 // renaming setter | 0x7c
122 // renaming both } 0x7d
123 // renaming getter ~ 0x7e
124 const SUFFIX_MASK = 0x3f;
125 const FIRST_SUFFIX_CODE = 0x3c;
126 const SETTER_CODE = 0x3c;
127 const GETTER_SETTER_CODE = 0x3d;
128 const GETTER_CODE = 0x3e;
129 const RENAMING_FLAG = 0x40;
130 String needsGetterCode(String variable) => '($variable & 3) > 0';
131 String needsSetterCode(String variable) => '($variable & 2) == 0';
132 String isRenaming(String variable) => '($variable & $RENAMING_FLAG) != 0';
133 116
134 String get generateAccessorFunction { 117 String get generateAccessorFunction {
135 return """ 118 return """
136 function generateAccessor(field, prototype) { 119 function generateAccessor(field, prototype) {
137 var len = field.length; 120 var len = field.length;
138 var lastCharCode = field.charCodeAt(len - 1); 121 var lastChar = field[len - 1];
139 var needsAccessor = (lastCharCode & $SUFFIX_MASK) >= $FIRST_SUFFIX_CODE; 122 var needsGetter = lastChar == '$GETTER_SUFFIX' || lastChar == '$GETTER_SETTER_ SUFFIX';
140 if (needsAccessor) { 123 var needsSetter = lastChar == '$SETTER_SUFFIX' || lastChar == '$GETTER_SETTER_ SUFFIX';
141 var needsGetter = ${needsGetterCode('lastCharCode')}; 124 if (needsGetter || needsSetter) field = field.substring(0, len - 1);
142 var needsSetter = ${needsSetterCode('lastCharCode')}; 125 if (needsGetter) {
143 var renaming = ${isRenaming('lastCharCode')}; 126 var getterString = "return this." + field + ";";
144 var accessorName = field = field.substring(0, len - 1); 127 """
145 if (renaming) { 128 /* The supportsProtoCheck below depends on the getter/setter convention.
146 var divider = field.indexOf(":"); 129 When changing here, update the protoCheck too. */
147 accessorName = field.substring(0, divider); 130 """
148 field = field.substring(divider + 1); 131 prototype["get\$" + field] = new Function(getterString);
149 }
150 if (needsGetter) {
151 var getterString = "return this." + field + ";";
152 prototype["get\$" + accessorName] = new Function(getterString);
153 } 132 }
154 if (needsSetter) { 133 if (needsSetter) {
155 var setterString = "this." + field + " = v;"; 134 var setterString = "this." + field + " = v;";
156 prototype["set\$" + accessorName] = new Function("v", setterString); 135 prototype["set\$" + field] = new Function("v", setterString);
157 } 136 }
158 } 137 return field;
159 return field; 138 }""";
160 }""";
161 } 139 }
162 140
163 String get defineClassFunction { 141 String get defineClassFunction {
164 // First the class name, then the field names in an array and the members 142 // First the class name, then the field names in an array and the members
165 // (inside an Object literal). 143 // (inside an Object literal).
166 // The caller can also pass in the constructor as a function if needed. 144 // The caller can also pass in the constructor as a function if needed.
167 // 145 //
168 // Example: 146 // Example:
169 // defineClass("A", ["x", "y"], { 147 // defineClass("A", ["x", "y"], {
170 // foo$1: function(y) { 148 // foo$1: function(y) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes). 186 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes).
209 // If the browser does not support __proto__ we need to instantiate an 187 // If the browser does not support __proto__ we need to instantiate an
210 // object with the correct (internal) prototype set up correctly, and then 188 // object with the correct (internal) prototype set up correctly, and then
211 // copy the members. 189 // copy the members.
212 190
213 return ''' 191 return '''
214 var $supportsProtoName = false; 192 var $supportsProtoName = false;
215 var tmp = $defineClassName('c', ['f?'], {}).prototype; 193 var tmp = $defineClassName('c', ['f?'], {}).prototype;
216 if (tmp.__proto__) { 194 if (tmp.__proto__) {
217 tmp.__proto__ = {}; 195 tmp.__proto__ = {};
218 if (typeof tmp.get\$f !== 'undefined') $supportsProtoName = true; 196 if (typeof tmp.get\$f !== "undefined") $supportsProtoName = true;
219 } 197 }
220 '''; 198 ''';
221 } 199 }
222 200
223 String get finishClassesFunction { 201 String get finishClassesFunction {
224 // 'defineClass' does not require the classes to be constructed in order. 202 // 'defineClass' does not require the classes to be constructed in order.
225 // Classes are initially just stored in the 'pendingClasses' field. 203 // Classes are initially just stored in the 'pendingClasses' field.
226 // 'finishClasses' takes all pending classes and sets up the prototype. 204 // 'finishClasses' takes all pending classes and sets up the prototype.
227 // Once set up, the constructors prototype field satisfy: 205 // Once set up, the constructors prototype field satisfy:
228 // - it contains all (local) members. 206 // - it contains all (local) members.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 newPrototype[member] = prototype[member]; 265 newPrototype[member] = prototype[member];
288 } 266 }
289 } 267 }
290 } 268 }
291 } 269 }
292 for (var cls in pendingClasses) finishClass(cls); 270 for (var cls in pendingClasses) finishClass(cls);
293 }'''; 271 }''';
294 } 272 }
295 273
296 String get finishIsolateConstructorFunction { 274 String get finishIsolateConstructorFunction {
297 String isolate = namer.isolateName; 275 String isolate = namer.ISOLATE;
298 // We replace the old Isolate function with a new one that initializes 276 // We replace the old Isolate function with a new one that initializes
299 // all its field with the initial (and often final) value of all globals. 277 // all its field with the initial (and often final) value of all globals.
300 // This has two advantages: 278 // This has two advantages:
301 // 1. the properties are in the object itself (thus avoiding to go through 279 // 1. the properties are in the object itself (thus avoiding to go through
302 // the prototype when looking up globals. 280 // the prototype when looking up globals.
303 // 2. a new isolate goes through a (usually well optimized) constructor 281 // 2. a new isolate goes through a (usually well optimized) constructor
304 // function of the form: "function() { this.x = ...; this.y = ...; }". 282 // function of the form: "function() { this.x = ...; this.y = ...; }".
305 // 283 //
306 // Example: If [isolateProperties] is an object containing: x = 3 and 284 // Example: If [isolateProperties] is an object containing: x = 3 and
307 // A = function A() { /* constructor of class A. */ }, then we generate: 285 // A = function A() { /* constructor of class A. */ }, then we generate:
308 // str = "{ 286 // str = "{
309 // var isolateProperties = Isolate.$isolateProperties; 287 // var isolateProperties = Isolate.$isolateProperties;
310 // this.x = isolateProperties.x; 288 // this.x = isolateProperties.x;
311 // this.A = isolateProperties.A; 289 // this.A = isolateProperties.A;
312 // }"; 290 // }";
313 // which is then dynamically evaluated: 291 // which is then dynamically evaluated:
314 // var newIsolate = new Function(str); 292 // var newIsolate = new Function(str);
315 // 293 //
316 // We also copy over old values like the prototype, and the 294 // We also copy over old values like the prototype, and the
317 // isolateProperties themselves. 295 // isolateProperties themselves.
318 return """function(oldIsolate) { 296 return """function(oldIsolate) {
319 var isolateProperties = oldIsolate.${namer.isolatePropertiesName}; 297 var isolateProperties = oldIsolate.${namer.ISOLATE_PROPERTIES};
320 var isolatePrototype = oldIsolate.prototype; 298 var isolatePrototype = oldIsolate.prototype;
321 var str = "{\\n"; 299 var str = "{\\n";
322 str += "var properties = $isolate.${namer.isolatePropertiesName};\\n"; 300 str += "var properties = $isolate.${namer.ISOLATE_PROPERTIES};\\n";
323 for (var staticName in isolateProperties) { 301 for (var staticName in isolateProperties) {
324 if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) { 302 if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) {
325 str += "this." + staticName + "= properties." + staticName + ";\\n"; 303 str += "this." + staticName + "= properties." + staticName + ";\\n";
326 } 304 }
327 } 305 }
328 str += "}\\n"; 306 str += "}\\n";
329 var newIsolate = new Function(str); 307 var newIsolate = new Function(str);
330 newIsolate.prototype = isolatePrototype; 308 newIsolate.prototype = isolatePrototype;
331 isolatePrototype.constructor = newIsolate; 309 isolatePrototype.constructor = newIsolate;
332 newIsolate.${namer.isolatePropertiesName} = isolateProperties; 310 newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties;
333 return newIsolate; 311 return newIsolate;
334 }"""; 312 }""";
335 } 313 }
336 314
337 String get lazyInitializerFunction { 315 String get lazyInitializerFunction {
338 String isolate = namer.CURRENT_ISOLATE; 316 String isolate = namer.CURRENT_ISOLATE;
339 return """ 317 return """
340 function(prototype, staticName, fieldName, getterName, lazyValue) { 318 function(prototype, staticName, fieldName, getterName, lazyValue) {
341 var getter = new Function("{ return $isolate." + fieldName + ";}"); 319 var getter = new Function("{ return $isolate." + fieldName + ";}");
342 $lazyInitializerLogic 320 $lazyInitializerLogic
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 } 371 }
394 } 372 }
395 373
396 void emitFinishIsolateConstructor(CodeBuffer buffer) { 374 void emitFinishIsolateConstructor(CodeBuffer buffer) {
397 String name = finishIsolateConstructorName; 375 String name = finishIsolateConstructorName;
398 String value = finishIsolateConstructorFunction; 376 String value = finishIsolateConstructorFunction;
399 buffer.add("$name = $value;\n"); 377 buffer.add("$name = $value;\n");
400 } 378 }
401 379
402 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { 380 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) {
403 String isolate = namer.isolateName; 381 String isolate = namer.ISOLATE;
404 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); 382 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n");
405 } 383 }
406 384
407 /** 385 /**
408 * Generate stubs to handle invocation of methods with optional 386 * Generate stubs to handle invocation of methods with optional
409 * arguments. 387 * arguments.
410 * 388 *
411 * A method like [: foo([x]) :] may be invoked by the following 389 * A method like [: foo([x]) :] may be invoked by the following
412 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this 390 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this
413 * function for detailed examples. 391 * function for detailed examples.
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); 527 // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d);
550 // (4) No stub generated, call is direct. 528 // (4) No stub generated, call is direct.
551 // (5) No stub generated, call is direct. 529 // (5) No stub generated, call is direct.
552 530
553 // Keep a cache of which stubs have already been generated, to 531 // Keep a cache of which stubs have already been generated, to
554 // avoid duplicates. Note that even if selectors are 532 // avoid duplicates. Note that even if selectors are
555 // canonicalized, we would still need this cache: a typed selector 533 // canonicalized, we would still need this cache: a typed selector
556 // on A and a typed selector on B could yield the same stub. 534 // on A and a typed selector on B could yield the same stub.
557 Set<String> generatedStubNames = new Set<String>(); 535 Set<String> generatedStubNames = new Set<String>();
558 if (compiler.enabledFunctionApply 536 if (compiler.enabledFunctionApply
559 && member.name == namer.closureInvocationSelector) { 537 && member.name == Namer.CLOSURE_INVOCATION_NAME) {
560 // If [Function.apply] is called, we pessimistically compile all 538 // If [Function.apply] is called, we pessimistically compile all
561 // possible stubs for this closure. 539 // possible stubs for this closure.
562 FunctionSignature signature = member.computeSignature(compiler); 540 FunctionSignature signature = member.computeSignature(compiler);
563 Set<Selector> selectors = signature.optionalParametersAreNamed 541 Set<Selector> selectors = signature.optionalParametersAreNamed
564 ? computeNamedSelectors(signature, member) 542 ? computeNamedSelectors(signature, member)
565 : computeOptionalSelectors(signature, member); 543 : computeOptionalSelectors(signature, member);
566 for (Selector selector in selectors) { 544 for (Selector selector in selectors) {
567 addParameterStub( 545 addParameterStub(
568 member, selector, defineInstanceMember, generatedStubNames); 546 member, selector, defineInstanceMember, generatedStubNames);
569 } 547 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 622
645 bool instanceFieldNeedsSetter(Element member) { 623 bool instanceFieldNeedsSetter(Element member) {
646 assert(member.isField()); 624 assert(member.isField());
647 return (!member.modifiers.isFinalOrConst()) 625 return (!member.modifiers.isFinalOrConst())
648 && compiler.codegenWorld.hasInvokedSetter(member, compiler); 626 && compiler.codegenWorld.hasInvokedSetter(member, compiler);
649 } 627 }
650 628
651 String compiledFieldName(Element member) { 629 String compiledFieldName(Element member) {
652 assert(member.isField()); 630 assert(member.isField());
653 return member.isNative() 631 return member.isNative()
654 ? member.nativeName() 632 ? member.name.slowToString()
655 : namer.getName(member); 633 : namer.getName(member);
656 } 634 }
657 635
658 /** 636 /**
659 * Documentation wanted -- johnniwinther 637 * Documentation wanted -- johnniwinther
660 * 638 *
661 * Invariant: [member] must be a declaration element. 639 * Invariant: [member] must be a declaration element.
662 */ 640 */
663 void addInstanceMember(Element member, 641 void addInstanceMember(Element member,
664 DefineMemberFunction defineInstanceMember) { 642 DefineMemberFunction defineInstanceMember) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 } 726 }
749 727
750 /** 728 /**
751 * Documentation wanted -- johnniwinther 729 * Documentation wanted -- johnniwinther
752 * 730 *
753 * Invariant: [classElement] must be a declaration element. 731 * Invariant: [classElement] must be a declaration element.
754 */ 732 */
755 void visitClassFields(ClassElement classElement, 733 void visitClassFields(ClassElement classElement,
756 void addField(Element member, 734 void addField(Element member,
757 String name, 735 String name,
758 String accessorName,
759 bool needsGetter, 736 bool needsGetter,
760 bool needsSetter, 737 bool needsSetter,
761 bool needsCheckedSetter)) { 738 bool needsCheckedSetter)) {
762 assert(invariant(classElement, classElement.isDeclaration)); 739 assert(invariant(classElement, classElement.isDeclaration));
763 // If the class is never instantiated we still need to set it up for 740 // If the class is never instantiated we still need to set it up for
764 // inheritance purposes, but we can simplify its JavaScript constructor. 741 // inheritance purposes, but we can simplify its JavaScript constructor.
765 bool isInstantiated = 742 bool isInstantiated =
766 compiler.codegenWorld.instantiatedClasses.contains(classElement); 743 compiler.codegenWorld.instantiatedClasses.contains(classElement);
767 744
768 void visitField(ClassElement enclosingClass, Element member) { 745 void visitField(ClassElement enclosingClass, Element member) {
(...skipping 29 matching lines...) Expand all
798 : accessorName; 775 : accessorName;
799 bool needsCheckedSetter = false; 776 bool needsCheckedSetter = false;
800 if (needsSetter && compiler.enableTypeAssertions 777 if (needsSetter && compiler.enableTypeAssertions
801 && canGenerateCheckedSetter(member)) { 778 && canGenerateCheckedSetter(member)) {
802 needsCheckedSetter = true; 779 needsCheckedSetter = true;
803 needsSetter = false; 780 needsSetter = false;
804 } 781 }
805 // Getters and setters with suffixes will be generated dynamically. 782 // Getters and setters with suffixes will be generated dynamically.
806 addField(member, 783 addField(member,
807 fieldName, 784 fieldName,
808 accessorName,
809 needsGetter, 785 needsGetter,
810 needsSetter, 786 needsSetter,
811 needsCheckedSetter); 787 needsCheckedSetter);
812 } 788 }
813 } 789 }
814 790
815 // If a class is not instantiated then we add the field just so we can 791 // If a class is not instantiated then we add the field just so we can
816 // generate the field getter/setter dynamically. Since this is only 792 // generate the field getter/setter dynamically. Since this is only
817 // allowed on fields that are in [classElement] we don't need to visit 793 // allowed on fields that are in [classElement] we don't need to visit
818 // superclasses for non-instantiated classes. 794 // superclasses for non-instantiated classes.
819 classElement.implementation.forEachInstanceField( 795 classElement.implementation.forEachInstanceField(
820 visitField, 796 visitField,
821 includeBackendMembers: true, 797 includeBackendMembers: true,
822 includeSuperMembers: isInstantiated && !classElement.isNative()); 798 includeSuperMembers: isInstantiated && !classElement.isNative());
823 } 799 }
824 800
801 void generateGetter(Element member, String fieldName, CodeBuffer buffer) {
802 String getterName = namer.getterName(member.getLibrary(), member.name);
803 buffer.add("$getterName: function() { return this.$fieldName; }");
804 }
805
806 void generateSetter(Element member, String fieldName, CodeBuffer buffer) {
807 String setterName = namer.setterName(member.getLibrary(), member.name);
808 buffer.add("$setterName: function(v) { this.$fieldName = v; }");
809 }
810
825 bool canGenerateCheckedSetter(Element member) { 811 bool canGenerateCheckedSetter(Element member) {
826 DartType type = member.computeType(compiler); 812 DartType type = member.computeType(compiler);
827 if (type.element.isTypeVariable() 813 if (type.element.isTypeVariable()
828 || type.element == compiler.dynamicClass 814 || type.element == compiler.dynamicClass
829 || type.element == compiler.objectClass) { 815 || type.element == compiler.objectClass) {
830 // TODO(ngeoffray): Support type checks on type parameters. 816 // TODO(ngeoffray): Support type checks on type parameters.
831 return false; 817 return false;
832 } 818 }
833 return true; 819 return true;
834 } 820 }
835 821
836 void generateCheckedSetter(Element member, 822 void generateCheckedSetter(Element member,
837 String fieldName, 823 String fieldName,
838 String accessorName,
839 CodeBuffer buffer) { 824 CodeBuffer buffer) {
840 assert(canGenerateCheckedSetter(member)); 825 assert(canGenerateCheckedSetter(member));
841 DartType type = member.computeType(compiler); 826 DartType type = member.computeType(compiler);
842 SourceString helper = compiler.backend.getCheckedModeHelper(type); 827 SourceString helper = compiler.backend.getCheckedModeHelper(type);
843 FunctionElement helperElement = compiler.findHelper(helper); 828 FunctionElement helperElement = compiler.findHelper(helper);
844 String helperName = namer.isolateAccess(helperElement); 829 String helperName = namer.isolateAccess(helperElement);
845 String additionalArgument = ''; 830 String additionalArgument = '';
846 if (helperElement.computeSignature(compiler).parameterCount != 1) { 831 if (helperElement.computeSignature(compiler).parameterCount != 1) {
847 additionalArgument = ", '${namer.operatorIs(type.element)}'"; 832 additionalArgument = ", '${namer.operatorIs(type.element)}'";
848 } 833 }
849 String setterName = namer.setterNameFromAccessorName(accessorName); 834 String setterName = namer.setterName(member.getLibrary(), member.name);
850 buffer.add("$setterName: function(v) { " 835 buffer.add("$setterName: function(v) { "
851 "this.$fieldName = $helperName(v$additionalArgument); }"); 836 "this.$fieldName = $helperName(v$additionalArgument); }");
852 } 837 }
853 838
854 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { 839 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) {
855 /* Do nothing. */ 840 /* Do nothing. */
856 } 841 }
857 842
858 void emitSuper(String superName, CodeBuffer buffer) { 843 void emitSuper(String superName, CodeBuffer buffer) {
859 /* Do nothing. */ 844 /* Do nothing. */
860 } 845 }
861 846
862 void emitClassFields(ClassElement classElement, 847 void emitClassFields(ClassElement classElement,
863 CodeBuffer buffer, 848 CodeBuffer buffer,
864 bool emitEndingComma, 849 bool emitEndingComma,
865 { String superClass: "", 850 { String superClass: "",
866 bool isNative: false}) { 851 bool isNative: false}) {
867 bool isFirstField = true; 852 bool isFirstField = true;
868 bool isAnythingOutput = false; 853 bool isAnythingOutput = false;
869 if (!isNative) { 854 if (!isNative) {
870 buffer.add('"":"$superClass;'); 855 buffer.add('"":"$superClass;');
871 isAnythingOutput = true; 856 isAnythingOutput = true;
872 } 857 }
873 visitClassFields(classElement, (Element member, 858 visitClassFields(classElement, (Element member,
874 String name, 859 String name,
875 String accessorName,
876 bool needsGetter, 860 bool needsGetter,
877 bool needsSetter, 861 bool needsSetter,
878 bool needsCheckedSetter) { 862 bool needsCheckedSetter) {
863 if (!getterAndSetterCanBeImplementedByFieldSpec(
864 member, name, needsGetter, needsSetter)) {
865 return;
866 }
879 if (!isNative || needsCheckedSetter || needsGetter || needsSetter) { 867 if (!isNative || needsCheckedSetter || needsGetter || needsSetter) {
880 if (isFirstField) { 868 if (isFirstField) {
881 isFirstField = false; 869 isFirstField = false;
882 if (!isAnythingOutput) { 870 if (!isAnythingOutput) {
883 buffer.add('"":"'); 871 buffer.add('"":"');
884 isAnythingOutput = true; 872 isAnythingOutput = true;
885 } 873 }
886 } else { 874 } else {
887 buffer.add(","); 875 buffer.add(",");
888 } 876 }
889 buffer.add('$accessorName'); 877 buffer.add('$name');
890 int flag = 0;
891 if (name != accessorName) {
892 buffer.add(':$name');
893 assert(needsGetter || needsSetter);
894 flag = RENAMING_FLAG;
895 }
896 if (needsGetter && needsSetter) { 878 if (needsGetter && needsSetter) {
897 buffer.addCharCode(GETTER_SETTER_CODE + flag); 879 buffer.add(GETTER_SETTER_SUFFIX);
898 } else if (needsGetter) { 880 } else if (needsGetter) {
899 buffer.addCharCode(GETTER_CODE + flag); 881 buffer.add(GETTER_SUFFIX);
900 } else if (needsSetter) { 882 } else if (needsSetter) {
901 buffer.addCharCode(SETTER_CODE + flag); 883 buffer.add(SETTER_SUFFIX);
902 } 884 }
903 } 885 }
904 }); 886 });
905 if (isAnythingOutput) { 887 if (isAnythingOutput) {
906 buffer.add('"'); 888 buffer.add('"');
907 if (emitEndingComma) { 889 if (emitEndingComma) {
908 buffer.add(','); 890 buffer.add(',');
909 } 891 }
910 } 892 }
911 } 893 }
912 894
913 /** Each getter/setter must be prefixed with a ",\n ". */ 895 /** Each getter/setter must be prefixed with a ",\n ". */
914 void emitClassGettersSetters(ClassElement classElement, 896 void emitClassGettersSetters(ClassElement classElement,
915 CodeBuffer buffer, 897 CodeBuffer buffer,
916 bool emitLeadingComma) { 898 bool emitLeadingComma) {
917 emitComma() { 899 emitComma() {
918 if (emitLeadingComma) { 900 if (emitLeadingComma) {
919 buffer.add(",\n "); 901 buffer.add(",\n ");
920 } else { 902 } else {
921 emitLeadingComma = true; 903 emitLeadingComma = true;
922 } 904 }
923 } 905 }
924 906
925 visitClassFields(classElement, (Element member, 907 visitClassFields(classElement, (Element member,
926 String name, 908 String name,
927 String accessorName,
928 bool needsGetter, 909 bool needsGetter,
929 bool needsSetter, 910 bool needsSetter,
930 bool needsCheckedSetter) { 911 bool needsCheckedSetter) {
912 if (name == null) throw 123;
913 if (getterAndSetterCanBeImplementedByFieldSpec(
914 member, name, needsGetter, needsSetter)) {
915 needsGetter = false;
916 needsSetter = false;
917 }
918 if (needsGetter) {
919 emitComma();
920 generateGetter(member, name, buffer);
921 }
922 if (needsSetter) {
923 emitComma();
924 generateSetter(member, name, buffer);
925 }
931 if (needsCheckedSetter) { 926 if (needsCheckedSetter) {
932 assert(!needsSetter); 927 assert(!needsSetter);
933 emitComma(); 928 emitComma();
934 generateCheckedSetter(member, name, accessorName, buffer); 929 generateCheckedSetter(member, name, buffer);
935 } 930 }
936 }); 931 });
937 } 932 }
938 933
934 bool getterAndSetterCanBeImplementedByFieldSpec(Element member,
935 String name,
936 bool needsGetter,
937 bool needsSetter) {
938 if (needsGetter) {
939 if (namer.getterName(member.getLibrary(), member.name) != 'get\$$name') {
940 return false;
941 }
942 }
943 if (needsSetter) {
944 if (namer.setterName(member.getLibrary(), member.name) != 'set\$$name') {
945 return false;
946 }
947 }
948 return true;
949 }
950
939 /** 951 /**
940 * Documentation wanted -- johnniwinther 952 * Documentation wanted -- johnniwinther
941 * 953 *
942 * Invariant: [classElement] must be a declaration element. 954 * Invariant: [classElement] must be a declaration element.
943 */ 955 */
944 void generateClass(ClassElement classElement, CodeBuffer buffer) { 956 void generateClass(ClassElement classElement, CodeBuffer buffer) {
945 assert(invariant(classElement, classElement.isDeclaration)); 957 assert(invariant(classElement, classElement.isDeclaration));
946 if (classElement.isNative()) { 958 if (classElement.isNative()) {
947 nativeEmitter.generateNativeClass(classElement); 959 nativeEmitter.generateNativeClass(classElement);
948 return; 960 return;
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 1173
1162 void emitStaticFunctionGetters(CodeBuffer buffer) { 1174 void emitStaticFunctionGetters(CodeBuffer buffer) {
1163 Set<FunctionElement> functionsNeedingGetter = 1175 Set<FunctionElement> functionsNeedingGetter =
1164 compiler.codegenWorld.staticFunctionsNeedingGetter; 1176 compiler.codegenWorld.staticFunctionsNeedingGetter;
1165 for (FunctionElement element in functionsNeedingGetter) { 1177 for (FunctionElement element in functionsNeedingGetter) {
1166 // The static function does not have the correct name. Since 1178 // The static function does not have the correct name. Since
1167 // [addParameterStubs] use the name to create its stubs we simply 1179 // [addParameterStubs] use the name to create its stubs we simply
1168 // create a fake element with the correct name. 1180 // create a fake element with the correct name.
1169 // Note: the callElement will not have any enclosingElement. 1181 // Note: the callElement will not have any enclosingElement.
1170 FunctionElement callElement = 1182 FunctionElement callElement =
1171 new ClosureInvocationElement(namer.closureInvocationSelector, element) ; 1183 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element);
1172 String staticName = namer.getName(element); 1184 String staticName = namer.getName(element);
1173 String invocationName = namer.instanceMethodName(callElement); 1185 String invocationName = namer.instanceMethodName(callElement);
1174 String fieldAccess = '$isolateProperties.$staticName'; 1186 String fieldAccess = '$isolateProperties.$staticName';
1175 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); 1187 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n");
1176 addParameterStubs(callElement, (String name, CodeBuffer value) { 1188 addParameterStubs(callElement, (String name, CodeBuffer value) {
1177 buffer.add('$fieldAccess.$name = $value;\n'); 1189 buffer.add('$fieldAccess.$name = $value;\n');
1178 }); 1190 });
1179 // If a static function is used as a closure we need to add its name 1191 // If a static function is used as a closure we need to add its name
1180 // in case it is used in spawnFunction. 1192 // in case it is used in spawnFunction.
1181 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; 1193 String fieldName = namer.STATIC_CLOSURE_NAME_NAME;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 1268
1257 // Define the constructor with a name so that Object.toString can 1269 // Define the constructor with a name so that Object.toString can
1258 // find the class name of the closure class. 1270 // find the class name of the closure class.
1259 emitBoundClosureClassHeader( 1271 emitBoundClosureClassHeader(
1260 mangledName, superName, fieldNames, boundClosureBuffer); 1272 mangledName, superName, fieldNames, boundClosureBuffer);
1261 // Now add the methods on the closure class. The instance method does not 1273 // Now add the methods on the closure class. The instance method does not
1262 // have the correct name. Since [addParameterStubs] use the name to create 1274 // have the correct name. Since [addParameterStubs] use the name to create
1263 // its stubs we simply create a fake element with the correct name. 1275 // its stubs we simply create a fake element with the correct name.
1264 // Note: the callElement will not have any enclosingElement. 1276 // Note: the callElement will not have any enclosingElement.
1265 FunctionElement callElement = 1277 FunctionElement callElement =
1266 new ClosureInvocationElement(namer.closureInvocationSelector, member); 1278 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member);
1267 1279
1268 String invocationName = namer.instanceMethodName(callElement); 1280 String invocationName = namer.instanceMethodName(callElement);
1269 1281
1270 List<js.Parameter> parameters = <js.Parameter>[]; 1282 List<js.Parameter> parameters = <js.Parameter>[];
1271 List<js.Expression> arguments = <js.Expression>[]; 1283 List<js.Expression> arguments = <js.Expression>[];
1272 if (inInterceptor) { 1284 if (inInterceptor) {
1273 arguments.add(new js.This().dot(fieldNames[2])); 1285 arguments.add(new js.This().dot(fieldNames[2]));
1274 } 1286 }
1275 for (int i = 0; i < parameterCount; i++) { 1287 for (int i = 0; i < parameterCount; i++) {
1276 String name = 'p$i'; 1288 String name = 'p$i';
1277 parameters.add(new js.Parameter(name)); 1289 parameters.add(new js.Parameter(name));
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 : namer.instanceFieldName(memberLibrary, member.name); 1374 : namer.instanceFieldName(memberLibrary, member.name);
1363 return new js.VariableUse('this').dot(fieldName); 1375 return new js.VariableUse('this').dot(fieldName);
1364 } 1376 }
1365 } 1377 }
1366 1378
1367 for (Selector selector in selectors) { 1379 for (Selector selector in selectors) {
1368 if (selector.applies(member, compiler)) { 1380 if (selector.applies(member, compiler)) {
1369 String invocationName = 1381 String invocationName =
1370 namer.instanceMethodInvocationName(memberLibrary, member.name, 1382 namer.instanceMethodInvocationName(memberLibrary, member.name,
1371 selector); 1383 selector);
1372 SourceString callName = namer.closureInvocationSelector; 1384 SourceString callName = Namer.CLOSURE_INVOCATION_NAME;
1373 String closureCallName = 1385 String closureCallName =
1374 namer.instanceMethodInvocationName(memberLibrary, callName, 1386 namer.instanceMethodInvocationName(memberLibrary, callName,
1375 selector); 1387 selector);
1376 1388
1377 List<js.Parameter> parameters = <js.Parameter>[]; 1389 List<js.Parameter> parameters = <js.Parameter>[];
1378 List<js.Expression> arguments = <js.Expression>[]; 1390 List<js.Expression> arguments = <js.Expression>[];
1379 if (isInterceptorClass) { 1391 if (isInterceptorClass) {
1380 parameters.add(new js.Parameter(receiverArgumentName)); 1392 parameters.add(new js.Parameter(receiverArgumentName));
1381 } 1393 }
1382 1394
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1479 new js.PropertyAccess.field( 1491 new js.PropertyAccess.field(
1480 new js.VariableUse(isolateProperties), 1492 new js.VariableUse(isolateProperties),
1481 name), 1493 name),
1482 constantInitializerExpression(constant)); 1494 constantInitializerExpression(constant));
1483 buffer.add(js.prettyPrint(init, compiler)); 1495 buffer.add(js.prettyPrint(init, compiler));
1484 buffer.add(';\n'); 1496 buffer.add(';\n');
1485 } 1497 }
1486 } 1498 }
1487 1499
1488 void emitMakeConstantList(CodeBuffer buffer) { 1500 void emitMakeConstantList(CodeBuffer buffer) {
1489 buffer.add(namer.isolateName); 1501 buffer.add(namer.ISOLATE);
1490 buffer.add(r'''.makeConstantList = function(list) { 1502 buffer.add(r'''.makeConstantList = function(list) {
1491 list.immutable$list = true; 1503 list.immutable$list = true;
1492 list.fixed$length = true; 1504 list.fixed$length = true;
1493 return list; 1505 return list;
1494 }; 1506 };
1495 '''); 1507 ''');
1496 } 1508 }
1497 1509
1498 /** 1510 /**
1499 * Documentation wanted -- johnniwinther 1511 * Documentation wanted -- johnniwinther
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1733 buffer.add(""" 1745 buffer.add("""
1734 var \$globalThis = $currentIsolate; 1746 var \$globalThis = $currentIsolate;
1735 var \$globalState; 1747 var \$globalState;
1736 var \$globals; 1748 var \$globals;
1737 var \$isWorker = false; 1749 var \$isWorker = false;
1738 var \$supportsWorkers = false; 1750 var \$supportsWorkers = false;
1739 var \$thisScriptUrl; 1751 var \$thisScriptUrl;
1740 function \$static_init(){}; 1752 function \$static_init(){};
1741 1753
1742 function \$initGlobals(context) { 1754 function \$initGlobals(context) {
1743 context.isolateStatics = new ${namer.isolateName}(); 1755 context.isolateStatics = new ${namer.ISOLATE}();
1744 } 1756 }
1745 function \$setGlobals(context) { 1757 function \$setGlobals(context) {
1746 $currentIsolate = context.isolateStatics; 1758 $currentIsolate = context.isolateStatics;
1747 \$globalThis = $currentIsolate; 1759 \$globalThis = $currentIsolate;
1748 } 1760 }
1749 $mainEnsureGetter 1761 $mainEnsureGetter
1750 """); 1762 """);
1751 return "${namer.isolateAccess(isolateMain)}($mainAccess)"; 1763 return "${namer.isolateAccess(isolateMain)}($mainAccess)";
1752 } 1764 }
1753 1765
1754 emitMain(CodeBuffer buffer) { 1766 emitMain(CodeBuffer buffer) {
1755 if (compiler.isMockCompilation) return; 1767 if (compiler.isMockCompilation) return;
1756 Element main = compiler.mainApp.find(Compiler.MAIN); 1768 Element main = compiler.mainApp.find(Compiler.MAIN);
1757 String mainCall = null; 1769 String mainCall = null;
1758 if (compiler.isolateLibrary != null) { 1770 if (compiler.isolateLibrary != null) {
1759 Element isolateMain = 1771 Element isolateMain =
1760 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); 1772 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE);
1761 mainCall = buildIsolateSetup(buffer, main, isolateMain); 1773 mainCall = buildIsolateSetup(buffer, main, isolateMain);
1762 } else { 1774 } else {
1763 mainCall = '${namer.isolateAccess(main)}()'; 1775 mainCall = '${namer.isolateAccess(main)}()';
1764 } 1776 }
1765 buffer.add(""" 1777 buffer.add("""
1766 1778
1767 // 1779 //
1768 // BEGIN invoke [main]. 1780 // BEGIN invoke [main].
1769 // 1781 //
1770 if (typeof document !== 'undefined' && document.readyState !== 'complete') { 1782 if (typeof document != 'undefined' && document.readyState != 'complete') {
1771 document.addEventListener('readystatechange', function () { 1783 document.addEventListener('readystatechange', function () {
1772 if (document.readyState == 'complete') { 1784 if (document.readyState == 'complete') {
1773 if (typeof dartMainRunner === 'function') { 1785 if (typeof dartMainRunner == 'function') {
1774 dartMainRunner(function() { ${mainCall}; }); 1786 dartMainRunner(function() { ${mainCall}; });
1775 } else { 1787 } else {
1776 ${mainCall}; 1788 ${mainCall};
1777 } 1789 }
1778 } 1790 }
1779 }, false); 1791 }, false);
1780 } else { 1792 } else {
1781 if (typeof dartMainRunner === 'function') { 1793 if (typeof dartMainRunner == 'function') {
1782 dartMainRunner(function() { ${mainCall}; }); 1794 dartMainRunner(function() { ${mainCall}; });
1783 } else { 1795 } else {
1784 ${mainCall}; 1796 ${mainCall};
1785 } 1797 }
1786 } 1798 }
1787 // 1799 //
1788 // END invoke [main]. 1800 // END invoke [main].
1789 // 1801 //
1790 1802
1791 """); 1803 """);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1834 emitInterceptorCheck(cls, buffer); 1846 emitInterceptorCheck(cls, buffer);
1835 } 1847 }
1836 } 1848 }
1837 buffer.add('\n return $objectName.prototype;\n};\n'); 1849 buffer.add('\n return $objectName.prototype;\n};\n');
1838 }); 1850 });
1839 } 1851 }
1840 1852
1841 String assembleProgram() { 1853 String assembleProgram() {
1842 measure(() { 1854 measure(() {
1843 mainBuffer.add(HOOKS_API_USAGE); 1855 mainBuffer.add(HOOKS_API_USAGE);
1844 mainBuffer.add('function ${namer.isolateName}() {}\n'); 1856 mainBuffer.add('function ${namer.ISOLATE}() {}\n');
1845 mainBuffer.add('init();\n\n'); 1857 mainBuffer.add('init();\n\n');
1846 // Shorten the code by using "$$" as temporary. 1858 // Shorten the code by using "$$" as temporary.
1847 classesCollector = r"$$"; 1859 classesCollector = r"$$";
1848 mainBuffer.add('var $classesCollector = {};\n'); 1860 mainBuffer.add('var $classesCollector = {};\n');
1849 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. 1861 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
1850 isolateProperties = namer.CURRENT_ISOLATE; 1862 isolateProperties = namer.CURRENT_ISOLATE;
1851 mainBuffer.add('var $isolateProperties = $isolatePropertiesName;\n'); 1863 mainBuffer.add('var $isolateProperties = $isolatePropertiesName;\n');
1852 emitClasses(mainBuffer); 1864 emitClasses(mainBuffer);
1853 mainBuffer.add(boundClosureBuffer); 1865 mainBuffer.add(boundClosureBuffer);
1854 // Clear the buffer, so that we can reuse it for the native classes. 1866 // Clear the buffer, so that we can reuse it for the native classes.
(...skipping 15 matching lines...) Expand all
1870 // initialStatics. 1882 // initialStatics.
1871 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); 1883 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n');
1872 mainBuffer.add(boundClosureBuffer); 1884 mainBuffer.add(boundClosureBuffer);
1873 emitFinishClassesInvocationIfNecessary(mainBuffer); 1885 emitFinishClassesInvocationIfNecessary(mainBuffer);
1874 // After this assignment we will produce invalid JavaScript code if we use 1886 // After this assignment we will produce invalid JavaScript code if we use
1875 // the classesCollector variable. 1887 // the classesCollector variable.
1876 classesCollector = 'classesCollector should not be used from now on'; 1888 classesCollector = 'classesCollector should not be used from now on';
1877 1889
1878 emitFinishIsolateConstructorInvocation(mainBuffer); 1890 emitFinishIsolateConstructorInvocation(mainBuffer);
1879 mainBuffer.add( 1891 mainBuffer.add(
1880 'var ${namer.CURRENT_ISOLATE} = new ${namer.isolateName}();\n'); 1892 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n');
1881 1893
1882 nativeEmitter.assembleCode(mainBuffer); 1894 nativeEmitter.assembleCode(mainBuffer);
1883 emitMain(mainBuffer); 1895 emitMain(mainBuffer);
1884 mainBuffer.add('function init() {\n'); 1896 mainBuffer.add('function init() {\n');
1885 mainBuffer.add('$isolateProperties = {};\n'); 1897 mainBuffer.add('$isolateProperties = {};\n');
1886 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); 1898 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer);
1887 addLazyInitializerFunctionIfNecessary(mainBuffer); 1899 addLazyInitializerFunctionIfNecessary(mainBuffer);
1888 emitFinishIsolateConstructor(mainBuffer); 1900 emitFinishIsolateConstructor(mainBuffer);
1889 mainBuffer.add('}\n'); 1901 mainBuffer.add('}\n');
1890 compiler.assembledCode = mainBuffer.toString(); 1902 compiler.assembledCode = mainBuffer.toString();
(...skipping 23 matching lines...) Expand all
1914 const String HOOKS_API_USAGE = """ 1926 const String HOOKS_API_USAGE = """
1915 // Generated by dart2js, the Dart to JavaScript compiler. 1927 // Generated by dart2js, the Dart to JavaScript compiler.
1916 // The code supports the following hooks: 1928 // The code supports the following hooks:
1917 // dartPrint(message) - if this function is defined it is called 1929 // dartPrint(message) - if this function is defined it is called
1918 // instead of the Dart [print] method. 1930 // instead of the Dart [print] method.
1919 // dartMainRunner(main) - if this function is defined, the Dart [main] 1931 // dartMainRunner(main) - if this function is defined, the Dart [main]
1920 // method will not be invoked directly. 1932 // method will not be invoked directly.
1921 // Instead, a closure that will invoke [main] is 1933 // Instead, a closure that will invoke [main] is
1922 // passed to [dartMainRunner]. 1934 // passed to [dartMainRunner].
1923 """; 1935 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698