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

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

Issue 24267004: Emit CSP code in separate file. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 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 part of js_backend; 5 part of js_backend;
6 6
7 /// Enables debugging of fast/slow objects using V8-specific primitives. 7 /// Enables debugging of fast/slow objects using V8-specific primitives.
8 const DEBUG_FAST_OBJECTS = false; 8 const DEBUG_FAST_OBJECTS = false;
9 9
10 /** 10 /**
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 typedef void FunctionTypeTestEmitter(FunctionType functionType); 83 typedef void FunctionTypeTestEmitter(FunctionType functionType);
84 typedef void SubstitutionEmitter(Element element, {bool emitNull}); 84 typedef void SubstitutionEmitter(Element element, {bool emitNull});
85 85
86 /** 86 /**
87 * Generates the code for all used classes in the program. Static fields (even 87 * Generates the code for all used classes in the program. Static fields (even
88 * in classes) are ignored, since they can be treated as non-class elements. 88 * in classes) are ignored, since they can be treated as non-class elements.
89 * 89 *
90 * The code for the containing (used) methods must exist in the [:universe:]. 90 * The code for the containing (used) methods must exist in the [:universe:].
91 */ 91 */
92 class CodeEmitterTask extends CompilerTask { 92 class CodeEmitterTask extends CompilerTask {
93 bool needsInheritFunction = false;
94 bool needsDefineClass = false; 93 bool needsDefineClass = false;
95 bool needsMixinSupport = false; 94 bool needsMixinSupport = false;
96 bool needsLazyInitializer = false; 95 bool needsLazyInitializer = false;
97 final Namer namer; 96 final Namer namer;
98 ConstantEmitter constantEmitter; 97 ConstantEmitter constantEmitter;
99 NativeEmitter nativeEmitter; 98 NativeEmitter nativeEmitter;
100 CodeBuffer mainBuffer; 99 CodeBuffer mainBuffer;
101 final CodeBuffer deferredLibraries = new CodeBuffer(); 100 final CodeBuffer deferredLibraries = new CodeBuffer();
102 final CodeBuffer deferredConstants = new CodeBuffer(); 101 final CodeBuffer deferredConstants = new CodeBuffer();
103 /** Shorter access to [isolatePropertiesName]. Both here in the code, as 102 /** Shorter access to [isolatePropertiesName]. Both here in the code, as
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 */ 160 */
162 Set<FunctionType> checkedFunctionTypes; 161 Set<FunctionType> checkedFunctionTypes;
163 162
164 Map<ClassElement, Set<FunctionType>> checkedGenericFunctionTypes = 163 Map<ClassElement, Set<FunctionType>> checkedGenericFunctionTypes =
165 new Map<ClassElement, Set<FunctionType>>(); 164 new Map<ClassElement, Set<FunctionType>>();
166 165
167 Set<FunctionType> checkedNonGenericFunctionTypes = 166 Set<FunctionType> checkedNonGenericFunctionTypes =
168 new Set<FunctionType>(); 167 new Set<FunctionType>();
169 168
170 /** 169 /**
170 * List of expressions and statements that will be included in the
171 * precompiled function.
172 *
173 * To save space, dart2js normally generates constructors and accessors
174 * dynamically. This doesn't work in CSP mode, and may impact startup time
175 * negatively. So dart2js will emit these functions to a separate file that
176 * can be optionally included to support CSP mode or for faster startup.
177 */
178 List<jsAst.Node> precompiledFunction = <jsAst.Node>[];
179
180 List<jsAst.Expression> precompiledConstructorNames = <jsAst.Expression>[];
181
182 /**
171 * For classes and libraries, record code for static/top-level members. 183 * For classes and libraries, record code for static/top-level members.
172 * Later, this code is emitted when the class or library is emitted. 184 * Later, this code is emitted when the class or library is emitted.
173 * See [bufferForElement]. 185 * See [bufferForElement].
174 */ 186 */
175 // TODO(ahe): Generate statics with their class, and store only libraries in 187 // TODO(ahe): Generate statics with their class, and store only libraries in
176 // this map. 188 // this map.
177 final Map<Element, List<CodeBuffer>> elementBuffers = 189 final Map<Element, List<CodeBuffer>> elementBuffers =
178 new Map<Element, List<CodeBuffer>>(); 190 new Map<Element, List<CodeBuffer>>();
179 191
180 void registerDynamicFunctionTypeCheck(FunctionType functionType) { 192 void registerDynamicFunctionTypeCheck(FunctionType functionType) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 String get generateAccessorHolder 268 String get generateAccessorHolder
257 => '$isolatePropertiesName.\$generateAccessor'; 269 => '$isolatePropertiesName.\$generateAccessor';
258 String get finishClassesProperty 270 String get finishClassesProperty
259 => r'$finishClasses'; 271 => r'$finishClasses';
260 String get finishClassesName 272 String get finishClassesName
261 => '${namer.isolateName}.$finishClassesProperty'; 273 => '${namer.isolateName}.$finishClassesProperty';
262 String get finishIsolateConstructorName 274 String get finishIsolateConstructorName
263 => '${namer.isolateName}.\$finishIsolateConstructor'; 275 => '${namer.isolateName}.\$finishIsolateConstructor';
264 String get isolatePropertiesName 276 String get isolatePropertiesName
265 => '${namer.isolateName}.${namer.isolatePropertiesName}'; 277 => '${namer.isolateName}.${namer.isolatePropertiesName}';
266 String get supportsProtoName
267 => 'supportsProto';
268 String get lazyInitializerName 278 String get lazyInitializerName
269 => '${namer.isolateName}.\$lazy'; 279 => '${namer.isolateName}.\$lazy';
270 280
271 // Compact field specifications. The format of the field specification is 281 // Compact field specifications. The format of the field specification is
272 // <accessorName>:<fieldName><suffix> where the suffix and accessor name 282 // <accessorName>:<fieldName><suffix> where the suffix and accessor name
273 // prefix are optional. The suffix directs the generation of getter and 283 // prefix are optional. The suffix directs the generation of getter and
274 // setter methods. Each of the getter and setter has two bits to determine 284 // setter methods. Each of the getter and setter has two bits to determine
275 // the calling convention. Setter listed below, getter is similar. 285 // the calling convention. Setter listed below, getter is similar.
276 // 286 //
277 // 00: no setter 287 // 00: no setter
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 // Declare a function called "generateAccessor". This is used in 430 // Declare a function called "generateAccessor". This is used in
421 // defineClassFunction (it's a local declaration in init()). 431 // defineClassFunction (it's a local declaration in init()).
422 return [ 432 return [
423 generateAccessorFunction, 433 generateAccessorFunction,
424 js('$generateAccessorHolder = generateAccessor'), 434 js('$generateAccessorHolder = generateAccessor'),
425 new jsAst.FunctionDeclaration( 435 new jsAst.FunctionDeclaration(
426 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; 436 new jsAst.VariableDeclaration('defineClass'), defineClass) ];
427 } 437 }
428 438
429 /** Needs defineClass to be defined. */ 439 /** Needs defineClass to be defined. */
430 List buildProtoSupportCheck() { 440 List buildInheritFrom() {
431 // On Firefox and Webkit browsers we can manipulate the __proto__
432 // directly. Opera claims to have __proto__ support, but it is buggy.
433 // So we have to do more checks.
434 // Opera bug was filed as DSK-370158, and fixed as CORE-47615
435 // (http://my.opera.com/desktopteam/blog/2012/07/20/more-12-01-fixes).
436 // If the browser does not support __proto__ we need to instantiate an
437 // object with the correct (internal) prototype set up correctly, and then
438 // copy the members.
439 // TODO(8541): Remove this work around.
440
441 return [ 441 return [
442 js('var $supportsProtoName = false'), 442 js('var inheritFrom = #',
443 // js('var tmp = defineClass("c", "c", ["f<"], {}).prototype'), 443 js.fun([], [
444 // 444 new jsAst.FunctionDeclaration(
445 // js.if_(js('tmp.__proto__'), [ 445 new jsAst.VariableDeclaration('tmp'), js.fun([], [])),
446 // js('tmp.__proto__ = {}'), 446 js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
447 // js.if_(js(r'typeof tmp.get$f != "undefined"'), 447 js.return_(js.fun(['constructor', 'superConstructor'], [
448 // js('$supportsProtoName = true')) 448 js('tmp.prototype = superConstructor.prototype'),
449 // ]) 449 js('var object = new tmp()'),
450 ]; 450 js('var properties = constructor.prototype'),
451 js.forIn('member', 'properties',
452 js.if_('hasOwnProperty.call(properties, member)',
453 js('object[member] = properties[member]'))),
454 js('object.constructor = constructor'),
455 js('constructor.prototype = object'),
456 js.return_('object')
457 ]))])())];
451 } 458 }
452 459
453 static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4; 460 static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4;
454 461
455 // If we need fewer than this many noSuchMethod handlers we can save space by 462 // If we need fewer than this many noSuchMethod handlers we can save space by
456 // just emitting them in JS, rather than emitting the JS needed to generate 463 // just emitting them in JS, rather than emitting the JS needed to generate
457 // them at run time. 464 // them at run time.
458 static const VERY_FEW_NO_SUCH_METHOD_HANDLERS = 10; 465 static const VERY_FEW_NO_SUCH_METHOD_HANDLERS = 10;
459 466
460 /** 467 /**
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 // For engines where we have access to the '__proto__' we can manipulate 702 // For engines where we have access to the '__proto__' we can manipulate
696 // the object literal directly. For other engines we have to create a new 703 // the object literal directly. For other engines we have to create a new
697 // object and copy over the members. 704 // object and copy over the members.
698 705
699 String reflectableField = namer.reflectableField; 706 String reflectableField = namer.reflectableField;
700 List<jsAst.Node> statements = [ 707 List<jsAst.Node> statements = [
701 js('var pendingClasses = {}'), 708 js('var pendingClasses = {}'),
702 js.if_('!init.allClasses', js('init.allClasses = {}')), 709 js.if_('!init.allClasses', js('init.allClasses = {}')),
703 js('var allClasses = init.allClasses'), 710 js('var allClasses = init.allClasses'),
704 711
705 js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
706 js('var combinedConstructorFunction = '
707 '"function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"'
708 '+ "var \$desc;\\n"'),
709 js('var constructorsList = []'),
710
711 optional( 712 optional(
712 DEBUG_FAST_OBJECTS, 713 DEBUG_FAST_OBJECTS,
713 js('print("Number of classes: "' 714 js('print("Number of classes: "'
714 r' + Object.getOwnPropertyNames($$).length)')), 715 r' + Object.getOwnPropertyNames($$).length)')),
715 716
717 js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
718
719 js.if_('typeof dart_precompiled == "function"',
720 [js('var constructors = dart_precompiled(collectedClasses)')],
721
722 [js('var combinedConstructorFunction = "function \$reflectable(fn){'
723 'fn.$reflectableField=1;return fn};\\n"+ "var \$desc;\\n"'),
724 js('var constructorsList = []')]),
716 js.forIn('cls', 'collectedClasses', [ 725 js.forIn('cls', 'collectedClasses', [
717 js.if_('hasOwnProperty.call(collectedClasses, cls)', [ 726 js.if_('hasOwnProperty.call(collectedClasses, cls)', [
718 js('var desc = collectedClasses[cls]'), 727 js('var desc = collectedClasses[cls]'),
719 js.if_('desc instanceof Array', js('desc = desc[1]')), 728 js.if_('desc instanceof Array', js('desc = desc[1]')),
720 729
721 /* The 'fields' are either a constructor function or a 730 /* The 'fields' are either a constructor function or a
722 * string encoding fields, constructor and superclass. Get 731 * string encoding fields, constructor and superclass. Get
723 * the superclass and the fields in the format 732 * the superclass and the fields in the format
724 * '[name/]Super;field1,field2' 733 * '[name/]Super;field1,field2'
725 * from the null-string property on the descriptor. 734 * from the null-string property on the descriptor.
726 * The 'name/' is optional and contains the name that should be used 735 * The 'name/' is optional and contains the name that should be used
727 * when printing the runtime type string. It is used, for example, to 736 * when printing the runtime type string. It is used, for example, to
728 * print the runtime type JSInt as 'int'. 737 * print the runtime type JSInt as 'int'.
729 */ 738 */
730 js('var classData = desc[""], supr, name = cls, fields = classData'), 739 js('var classData = desc[""], supr, name = cls, fields = classData'),
731 optional( 740 optional(
732 backend.hasRetainedMetadata, 741 backend.hasRetainedMetadata,
733 js.if_('typeof classData == "object" && ' 742 js.if_('typeof classData == "object" && '
734 'classData instanceof Array', 743 'classData instanceof Array',
735 [js('classData = fields = classData[0]')])), 744 [js('classData = fields = classData[0]')])),
736 745
737 js.if_('typeof classData == "string"', [ 746 js.if_('typeof classData == "string"', [
738 js('var split = classData.split("/")'), 747 js('var split = classData.split("/")'),
739 js.if_('split.length == 2', [ 748 js.if_('split.length == 2', [
740 js('name = split[0]'), 749 js('name = split[0]'),
741 js('fields = split[1]') 750 js('fields = split[1]')
742 ]) 751 ])
743 ]), 752 ]),
744 753
745 js.if_('typeof fields == "string"', [ 754 js('var s = fields.split(";")'),
746 js('var s = fields.split(";")'), 755 js('fields = s[1] == "" ? [] : s[1].split(",")'),
747 js('fields = s[1] == "" ? [] : s[1].split(",")'), 756 js('supr = s[0]'),
748 js('supr = s[0]'),
749 ], /* else */ [
750 js('supr = desc.super'),
751 js.if_(r'!!desc.$name', js(r'name = desc.$name'))
752 ]),
753 757
754 optional(needsMixinSupport, js.if_('supr && supr.indexOf("+") > 0', [ 758 optional(needsMixinSupport, js.if_('supr && supr.indexOf("+") > 0', [
755 js('s = supr.split("+")'), 759 js('s = supr.split("+")'),
756 js('supr = s[0]'), 760 js('supr = s[0]'),
757 js('var mixin = collectedClasses[s[1]]'), 761 js('var mixin = collectedClasses[s[1]]'),
758 js.if_('mixin instanceof Array', js('mixin = mixin[1]')), 762 js.if_('mixin instanceof Array', js('mixin = mixin[1]')),
759 js.forIn('d', 'mixin', [ 763 js.forIn('d', 'mixin', [
760 js.if_('hasOwnProperty.call(mixin, d)' 764 js.if_('hasOwnProperty.call(mixin, d)'
761 '&& !hasOwnProperty.call(desc, d)', 765 '&& !hasOwnProperty.call(desc, d)',
762 js('desc[d] = mixin[d]')) 766 js('desc[d] = mixin[d]'))
763 ]), 767 ]),
764 ])), 768 ])),
765 769
766 js('combinedConstructorFunction += defineClass(name, cls, fields)'), 770 js.if_('typeof dart_precompiled != "function"',
767 js('constructorsList.push(cls)'), 771 [js('combinedConstructorFunction +='
772 ' defineClass(name, cls, fields)'),
773 js('constructorsList.push(cls)')]),
768 js.if_('supr', js('pendingClasses[cls] = supr')) 774 js.if_('supr', js('pendingClasses[cls] = supr'))
769 ]) 775 ])
770 ]), 776 ]),
771 js('combinedConstructorFunction +=' 777 js.if_('typeof dart_precompiled != "function"',
772 ' "return [\\n " + constructorsList.join(",\\n ") + "\\n]"'), 778 [js('combinedConstructorFunction +='
773 js('var constructors =' 779 ' "return [\\n " + constructorsList.join(",\\n ") + "\\n]"'),
774 ' new Function("\$collectedClasses", combinedConstructorFunction)' 780 js('var constructors ='
775 '(collectedClasses)'), 781 ' new Function("\$collectedClasses", combinedConstructorFunction)'
776 js('combinedConstructorFunction = null'), 782 '(collectedClasses)'),
783 js('combinedConstructorFunction = null')]),
777 js.for_('var i = 0', 'i < constructors.length', 'i++', [ 784 js.for_('var i = 0', 'i < constructors.length', 'i++', [
778 js('var constructor = constructors[i]'), 785 js('var constructor = constructors[i]'),
779 js('var cls = constructor.name'), 786 js('var cls = constructor.name'),
780 js('var desc = collectedClasses[cls]'), 787 js('var desc = collectedClasses[cls]'),
781 js('var globalObject = isolateProperties'), 788 js('var globalObject = isolateProperties'),
782 js.if_('desc instanceof Array', [ 789 js.if_('desc instanceof Array', [
783 js('globalObject = desc[0] || isolateProperties'), 790 js('globalObject = desc[0] || isolateProperties'),
784 js('desc = desc[1]') 791 js('desc = desc[1]')
785 ]), 792 ]),
786 optional(backend.isTreeShakingDisabled, 793 optional(backend.isTreeShakingDisabled,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 // we have a string. 841 // we have a string.
835 js.if_('!superclass || typeof superclass != "string"', js.return_()), 842 js.if_('!superclass || typeof superclass != "string"', js.return_()),
836 js('finishClass(superclass)'), 843 js('finishClass(superclass)'),
837 js('var constructor = allClasses[cls]'), 844 js('var constructor = allClasses[cls]'),
838 js('var superConstructor = allClasses[superclass]'), 845 js('var superConstructor = allClasses[superclass]'),
839 846
840 js.if_(js('!superConstructor'), 847 js.if_(js('!superConstructor'),
841 js('superConstructor =' 848 js('superConstructor ='
842 'existingIsolateProperties[superclass]')), 849 'existingIsolateProperties[superclass]')),
843 850
844 js('var prototype = constructor.prototype'), 851 js('prototype = inheritFrom(constructor, superConstructor)'),
845
846 // if ($supportsProtoName) {
847 js.if_(supportsProtoName, [
848 js('prototype.__proto__ = superConstructor.prototype'),
849 js('prototype.constructor = constructor'),
850
851 ], /* else */ [
852 // function tmp() {};
853 new jsAst.FunctionDeclaration(
854 new jsAst.VariableDeclaration('tmp'),
855 js.fun([], [])),
856
857 js('tmp.prototype = superConstructor.prototype'),
858 js('var newPrototype = new tmp()'),
859
860 js('constructor.prototype = newPrototype'),
861 js('newPrototype.constructor = constructor'),
862
863 // for (var member in prototype) {
864 js.forIn('member', 'prototype', [
865 /* Short version of: if (member == '') */
866 // if (!member) continue;
867 js.if_('!member', new jsAst.Continue(null)),
868
869 // if (hasOwnProperty.call(prototype, member)) {
870 js.if_('hasOwnProperty.call(prototype, member)', [
871 js('newPrototype[member] = prototype[member]')
872 ])
873 ])
874
875 ])
876 ]); 852 ]);
877 853
878 return new jsAst.FunctionDeclaration( 854 return new jsAst.FunctionDeclaration(
879 new jsAst.VariableDeclaration('finishClass'), 855 new jsAst.VariableDeclaration('finishClass'),
880 fun); 856 fun);
881 } 857 }
882 858
883 jsAst.Fun get finishIsolateConstructorFunction { 859 jsAst.Fun get finishIsolateConstructorFunction_NO_CSP {
884 String isolate = namer.isolateName; 860 String isolate = namer.isolateName;
885 // We replace the old Isolate function with a new one that initializes 861 // We replace the old Isolate function with a new one that initializes
886 // all its field with the initial (and often final) value of all globals. 862 // all its field with the initial (and often final) value of all globals.
887 // This has two advantages: 863 // This has two advantages:
888 // 1. the properties are in the object itself (thus avoiding to go through 864 // 1. the properties are in the object itself (thus avoiding to go through
889 // the prototype when looking up globals. 865 // the prototype when looking up globals.
890 // 2. a new isolate goes through a (usually well optimized) constructor 866 // 2. a new isolate goes through a (usually well optimized) constructor
891 // function of the form: "function() { this.x = ...; this.y = ...; }". 867 // function of the form: "function() { this.x = ...; this.y = ...; }".
892 // 868 //
893 // Example: If [isolateProperties] is an object containing: x = 3 and 869 // Example: If [isolateProperties] is an object containing: x = 3 and
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 // TODO(ahe): Only copy makeConstantList when it is used. 913 // TODO(ahe): Only copy makeConstantList when it is used.
938 js('newIsolate.makeConstantList = oldIsolate.makeConstantList'), 914 js('newIsolate.makeConstantList = oldIsolate.makeConstantList'),
939 ]..addAll(copyFinishClasses) 915 ]..addAll(copyFinishClasses)
940 ..addAll([ 916 ..addAll([
941 917
942 // return newIsolate; 918 // return newIsolate;
943 js.return_('newIsolate') 919 js.return_('newIsolate')
944 ])); 920 ]));
945 } 921 }
946 922
923 jsAst.Fun get finishIsolateConstructorFunction {
924 // We replace the old Isolate function with a new one that initializes
925 // all its fields with the initial (and often final) value of all globals.
926 //
927 // We also copy over old values like the prototype, and the
928 // isolateProperties themselves.
929 return js.fun('oldIsolate', [
930 js('var isolateProperties = oldIsolate.${namer.isolatePropertiesName}'),
931 new jsAst.FunctionDeclaration(
932 new jsAst.VariableDeclaration('Isolate'),
933 js.fun([], [
934 js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
935 js.forIn('staticName', 'isolateProperties',
936 js.if_('hasOwnProperty.call(isolateProperties, staticName)',
937 js('this[staticName] = isolateProperties[staticName]'))),
938 // Use the newly created object as prototype. In Chrome,
939 // this creates a hidden class for the object and makes
940 // sure it is fast to access.
941 new jsAst.FunctionDeclaration(
kasperl 2013/09/20 13:04:47 Could you use the convertToFast helper?
942 new jsAst.VariableDeclaration('ForceEfficientMap'),
943 js.fun([], [])),
944 js('ForceEfficientMap.prototype = this'),
945 js('new ForceEfficientMap()')])),
946 js('Isolate.prototype = oldIsolate.prototype'),
947 js('Isolate.prototype.constructor = Isolate'),
948 js('Isolate.${namer.isolatePropertiesName} = isolateProperties'),
949 optional(needsDefineClass,
950 js('Isolate.$finishClassesProperty ='
951 ' oldIsolate.$finishClassesProperty')),
952 js.return_('Isolate')]);
953 }
954
955
947 jsAst.Fun get lazyInitializerFunction { 956 jsAst.Fun get lazyInitializerFunction {
948 // function(prototype, staticName, fieldName, getterName, lazyValue) { 957 // function(prototype, staticName, fieldName, getterName, lazyValue) {
949 var parameters = <String>['prototype', 'staticName', 'fieldName', 958 var parameters = <String>['prototype', 'staticName', 'fieldName',
950 'getterName', 'lazyValue']; 959 'getterName', 'lazyValue'];
951 return js.fun(parameters, [ 960 return js.fun(parameters, addLazyInitializerLogic());
952 js('var getter = new Function("{ return this." + fieldName + ";}")'),
953 ]..addAll(addLazyInitializerLogic())
954 );
955 } 961 }
956 962
957 List addLazyInitializerLogic() { 963 List addLazyInitializerLogic() {
958 String isolate = namer.CURRENT_ISOLATE; 964 String isolate = namer.CURRENT_ISOLATE;
959 String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper()); 965 String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper());
960 var lazies = []; 966 var lazies = [];
961 if (backend.rememberLazies) { 967 if (backend.rememberLazies) {
962 lazies = [ 968 lazies = [
963 js.if_('!init.lazies', js('init.lazies = {}')), 969 js.if_('!init.lazies', js('init.lazies = {}')),
964 js('init.lazies[fieldName] = getterName')]; 970 js('init.lazies[fieldName] = getterName')];
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 ], /* else */ [ 1003 ], /* else */ [
998 js.if_('result === sentinelInProgress', 1004 js.if_('result === sentinelInProgress',
999 js('$cyclicThrow(staticName)') 1005 js('$cyclicThrow(staticName)')
1000 ) 1006 )
1001 ]), 1007 ]),
1002 1008
1003 // return result; 1009 // return result;
1004 js.return_('result') 1010 js.return_('result')
1005 1011
1006 ], finallyPart: [ 1012 ], finallyPart: [
1007 js('$isolate[getterName] = getter') 1013 js('$isolate[getterName] = #',
1014 js.fun([], [js.return_('this[fieldName]')]))
kasperl 2013/09/20 13:04:47 It might be worth investigating how much this cost
1008 ]) 1015 ])
1009 ])) 1016 ]))
1010 ]); 1017 ]);
1011 } 1018 }
1012 1019
1013 List buildDefineClassAndFinishClassFunctionsIfNecessary() { 1020 List buildDefineClassAndFinishClassFunctionsIfNecessary() {
1014 if (!needsDefineClass) return []; 1021 if (!needsDefineClass) return [];
1015 return defineClassFunction 1022 return defineClassFunction
1016 ..addAll(buildProtoSupportCheck()) 1023 ..addAll(buildInheritFrom())
1017 ..addAll([ 1024 ..addAll([
1018 js('$finishClassesName = #', finishClassesFunction) 1025 js('$finishClassesName = #', finishClassesFunction)
1019 ]); 1026 ]);
1020 } 1027 }
1021 1028
1022 List buildLazyInitializerFunctionIfNecessary() { 1029 List buildLazyInitializerFunctionIfNecessary() {
1023 if (!needsLazyInitializer) return []; 1030 if (!needsLazyInitializer) return [];
1024 1031
1025 return [js('$lazyInitializerName = #', lazyInitializerFunction)]; 1032 return [js('$lazyInitializerName = #', lazyInitializerFunction)];
1026 } 1033 }
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after
1702 if (reflectionName != null) { 1709 if (reflectionName != null) {
1703 var reflectable = 1710 var reflectable =
1704 js(backend.isAccessibleByReflection(member) ? '1' : '0'); 1711 js(backend.isAccessibleByReflection(member) ? '1' : '0');
1705 builder.addProperty('+$reflectionName', reflectable); 1712 builder.addProperty('+$reflectionName', reflectable);
1706 } 1713 }
1707 } 1714 }
1708 1715
1709 void generateGetter(Element member, String fieldName, String accessorName, 1716 void generateGetter(Element member, String fieldName, String accessorName,
1710 ClassBuilder builder) { 1717 ClassBuilder builder) {
1711 String getterName = namer.getterNameFromAccessorName(accessorName); 1718 String getterName = namer.getterNameFromAccessorName(accessorName);
1712 String receiver = backend.isInterceptorClass(member.getEnclosingClass()) 1719 ClassElement cls = member.getEnclosingClass();
1713 ? 'receiver' : 'this'; 1720 String className = namer.getNameOfClass(cls);
1714 List<String> args = backend.isInterceptedMethod(member) 1721 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this';
1715 ? ['receiver'] 1722 List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : [];
1716 : []; 1723 precompiledFunction.add(
1717 builder.addProperty(getterName, 1724 js('$className.prototype.$getterName = #',
1718 js.fun(args, js.return_(js('$receiver.$fieldName')))); 1725 js.fun(args, js.return_(js('$receiver.$fieldName')))));
1719 generateReflectionDataForFieldGetterOrSetter( 1726 if (backend.isNeededForReflection(member)) {
1720 member, getterName, builder, isGetter: true); 1727 precompiledFunction.add(
1728 js('$className.prototype.$getterName.${namer.reflectableField} = 1'));
1729 }
1721 } 1730 }
1722 1731
1723 void generateSetter(Element member, String fieldName, String accessorName, 1732 void generateSetter(Element member, String fieldName, String accessorName,
1724 ClassBuilder builder) { 1733 ClassBuilder builder) {
1725 String setterName = namer.setterNameFromAccessorName(accessorName); 1734 String setterName = namer.setterNameFromAccessorName(accessorName);
1726 String receiver = backend.isInterceptorClass(member.getEnclosingClass()) 1735 ClassElement cls = member.getEnclosingClass();
1727 ? 'receiver' : 'this'; 1736 String className = namer.getNameOfClass(cls);
1728 List<String> args = backend.isInterceptedMethod(member) 1737 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this';
1729 ? ['receiver', 'v'] 1738 List<String> args =
1730 : ['v']; 1739 backend.isInterceptedMethod(member) ? ['receiver', 'v'] : ['v'];
1731 builder.addProperty(setterName, 1740 precompiledFunction.add(
1732 js.fun(args, js('$receiver.$fieldName = v'))); 1741 js('$className.prototype.$setterName = #',
1733 generateReflectionDataForFieldGetterOrSetter( 1742 js.fun(args, js.return_(js('$receiver.$fieldName = v')))));
1734 member, setterName, builder, isGetter: false); 1743 if (backend.isNeededForReflection(member)) {
1744 precompiledFunction.add(
1745 js('$className.prototype.$setterName.${namer.reflectableField} = 1'));
1746 }
1735 } 1747 }
1736 1748
1737 bool canGenerateCheckedSetter(VariableElement field) { 1749 bool canGenerateCheckedSetter(VariableElement field) {
1738 // We never generate accessors for top-level/static fields. 1750 // We never generate accessors for top-level/static fields.
1739 if (!field.isInstanceMember()) return false; 1751 if (!field.isInstanceMember()) return false;
1740 DartType type = field.computeType(compiler).unalias(compiler); 1752 DartType type = field.computeType(compiler).unalias(compiler);
1741 if (type.element.isTypeVariable() || 1753 if (type.element.isTypeVariable() ||
1742 (type is FunctionType && type.containsTypeVariables) || 1754 (type is FunctionType && type.containsTypeVariables) ||
1743 type.treatAsDynamic || 1755 type.treatAsDynamic ||
1744 type.element == compiler.objectClass) { 1756 type.element == compiler.objectClass) {
(...skipping 29 matching lines...) Expand all
1774 List<String> args = backend.isInterceptedMethod(member) 1786 List<String> args = backend.isInterceptedMethod(member)
1775 ? ['receiver', 'v'] 1787 ? ['receiver', 'v']
1776 : ['v']; 1788 : ['v'];
1777 builder.addProperty(setterName, 1789 builder.addProperty(setterName,
1778 js.fun(args, 1790 js.fun(args,
1779 js('$receiver.$fieldName = #', js(helperName)(arguments)))); 1791 js('$receiver.$fieldName = #', js(helperName)(arguments))));
1780 generateReflectionDataForFieldGetterOrSetter( 1792 generateReflectionDataForFieldGetterOrSetter(
1781 member, setterName, builder, isGetter: false); 1793 member, setterName, builder, isGetter: false);
1782 } 1794 }
1783 1795
1784 void emitClassConstructor(ClassElement classElement, ClassBuilder builder) { 1796 void emitClassConstructor(ClassElement classElement,
1785 /* Do nothing. */ 1797 ClassBuilder builder,
1798 String runtimeName) {
1799 List<String> fields = <String>[];
1800 if (!classElement.isNative()) {
1801 visitFields(classElement, false,
1802 (Element member,
1803 String name,
1804 String accessorName,
1805 bool needsGetter,
1806 bool needsSetter,
1807 bool needsCheckedSetter) {
1808 fields.add(name);
1809 });
1810 }
1811 String constructorName = namer.getNameOfClass(classElement);
1812 precompiledFunction.add(new jsAst.FunctionDeclaration(
1813 new jsAst.VariableDeclaration(constructorName),
1814 js.fun(fields, fields.map(
1815 (name) => js('this.$name = $name')).toList())));
1816 if (runtimeName == null) {
1817 runtimeName = constructorName;
1818 }
1819 precompiledFunction.addAll([
1820 js('$constructorName.builtin\$cls = "$runtimeName"'),
1821 js.if_('!"name" in $constructorName',
1822 js('$constructorName.name = "$constructorName"')),
1823 js('\$desc=\$collectedClasses.$constructorName'),
1824 js.if_('\$desc instanceof Array', js('\$desc = \$desc[1]')),
1825 js('$constructorName.prototype = \$desc'),
1826 ]);
1827
1828 precompiledConstructorNames.add(js(constructorName));
1829 }
1830
1831 jsAst.FunctionDeclaration buildPrecompiledFunction() {
1832 // TODO(ahe): Compute a hash code.
kasperl 2013/09/20 13:04:47 Maybe elaborate on the TODO so others would unders
1833 String name = 'dart_precompiled';
kasperl 2013/09/20 13:04:47 Factor out this constant?
1834
1835 precompiledFunction.add(
1836 js.return_(
1837 new jsAst.ArrayInitializer.from(precompiledConstructorNames)));
1838 precompiledFunction.insert(0, js(r'var $desc'));
1839 return new jsAst.FunctionDeclaration(
1840 new jsAst.VariableDeclaration(name),
1841 js.fun([r'$collectedClasses'], precompiledFunction));
1786 } 1842 }
1787 1843
1788 void emitSuper(String superName, ClassBuilder builder) { 1844 void emitSuper(String superName, ClassBuilder builder) {
1789 /* Do nothing. */ 1845 /* Do nothing. */
1790 } 1846 }
1791 1847
1792 void emitRuntimeName(String runtimeName, ClassBuilder builder) { 1848 void emitRuntimeName(String runtimeName, ClassBuilder builder) {
1793 /* Do nothing. */ 1849 /* Do nothing. */
1794 } 1850 }
1795 1851
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1959 String name, 2015 String name,
1960 String accessorName, 2016 String accessorName,
1961 bool needsGetter, 2017 bool needsGetter,
1962 bool needsSetter, 2018 bool needsSetter,
1963 bool needsCheckedSetter) { 2019 bool needsCheckedSetter) {
1964 compiler.withCurrentElement(member, () { 2020 compiler.withCurrentElement(member, () {
1965 if (needsCheckedSetter) { 2021 if (needsCheckedSetter) {
1966 assert(!needsSetter); 2022 assert(!needsSetter);
1967 generateCheckedSetter(member, name, accessorName, builder); 2023 generateCheckedSetter(member, name, accessorName, builder);
1968 } 2024 }
1969 if (!getterAndSetterCanBeImplementedByFieldSpec) { 2025 if (needsGetter) {
1970 if (needsGetter) { 2026 generateGetter(member, name, accessorName, builder);
1971 generateGetter(member, name, accessorName, builder); 2027 }
1972 } 2028 if (needsSetter) {
1973 if (needsSetter) { 2029 generateSetter(member, name, accessorName, builder);
1974 generateSetter(member, name, accessorName, builder);
1975 }
1976 } 2030 }
1977 }); 2031 });
1978 }); 2032 });
1979 } 2033 }
1980 2034
1981 /** 2035 /**
1982 * Documentation wanted -- johnniwinther 2036 * Documentation wanted -- johnniwinther
1983 * 2037 *
1984 * Invariant: [classElement] must be a declaration element. 2038 * Invariant: [classElement] must be a declaration element.
1985 */ 2039 */
(...skipping 14 matching lines...) Expand all
2000 String runtimeName = 2054 String runtimeName =
2001 namer.getPrimitiveInterceptorRuntimeName(classElement); 2055 namer.getPrimitiveInterceptorRuntimeName(classElement);
2002 2056
2003 if (classElement.isMixinApplication) { 2057 if (classElement.isMixinApplication) {
2004 String mixinName = namer.getNameOfClass(computeMixinClass(classElement)); 2058 String mixinName = namer.getNameOfClass(computeMixinClass(classElement));
2005 superName = '$superName+$mixinName'; 2059 superName = '$superName+$mixinName';
2006 needsMixinSupport = true; 2060 needsMixinSupport = true;
2007 } 2061 }
2008 2062
2009 ClassBuilder builder = new ClassBuilder(); 2063 ClassBuilder builder = new ClassBuilder();
2010 emitClassConstructor(classElement, builder); 2064 emitClassConstructor(classElement, builder, runtimeName);
2011 emitSuper(superName, builder); 2065 emitSuper(superName, builder);
2012 emitRuntimeName(runtimeName, builder); 2066 emitRuntimeName(runtimeName, builder);
2013 emitFields(classElement, builder, superName, onlyForRti: onlyForRti); 2067 emitFields(classElement, builder, superName, onlyForRti: onlyForRti);
2014 emitClassGettersSetters(classElement, builder); 2068 emitClassGettersSetters(classElement, builder);
2015 if (!classElement.isMixinApplication) { 2069 if (!classElement.isMixinApplication) {
2016 emitInstanceMembers(classElement, builder); 2070 emitInstanceMembers(classElement, builder);
2017 } 2071 }
2018 emitIsTests(classElement, builder); 2072 emitIsTests(classElement, builder);
2019 2073
2020 emitClassBuilderWithReflectionData( 2074 emitClassBuilderWithReflectionData(
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2068 String reflectionName = getReflectionName(classElement, className); 2122 String reflectionName = getReflectionName(classElement, className);
2069 if (reflectionName != null) { 2123 if (reflectionName != null) {
2070 List<int> interfaces = <int>[]; 2124 List<int> interfaces = <int>[];
2071 for (DartType interface in classElement.interfaces) { 2125 for (DartType interface in classElement.interfaces) {
2072 interfaces.add(reifyType(interface)); 2126 interfaces.add(reifyType(interface));
2073 } 2127 }
2074 buffer.write(',$n$n"+$reflectionName": $interfaces'); 2128 buffer.write(',$n$n"+$reflectionName": $interfaces');
2075 } 2129 }
2076 } 2130 }
2077 2131
2078 bool get getterAndSetterCanBeImplementedByFieldSpec => true;
2079
2080 /// If this is true then we can generate the noSuchMethod handlers at startup 2132 /// If this is true then we can generate the noSuchMethod handlers at startup
2081 /// time, instead of them being emitted as part of the Object class. 2133 /// time, instead of them being emitted as part of the Object class.
2082 bool get generateTrivialNsmHandlers => true; 2134 bool get generateTrivialNsmHandlers => true;
2083 2135
2084 int _selectorRank(Selector selector) { 2136 int _selectorRank(Selector selector) {
2085 int arity = selector.argumentCount * 3; 2137 int arity = selector.argumentCount * 3;
2086 if (selector.isGetter()) return arity + 2; 2138 if (selector.isGetter()) return arity + 2;
2087 if (selector.isSetter()) return arity + 1; 2139 if (selector.isSetter()) return arity + 1;
2088 return arity; 2140 return arity;
2089 } 2141 }
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
2486 emitFunctionTypeSignature, emitIsFunctionTypeTest); 2538 emitFunctionTypeSignature, emitIsFunctionTypeTest);
2487 } 2539 }
2488 } 2540 }
2489 2541
2490 void emitClosureClassHeader(String mangledName, 2542 void emitClosureClassHeader(String mangledName,
2491 String superName, 2543 String superName,
2492 List<String> fieldNames, 2544 List<String> fieldNames,
2493 ClassBuilder builder) { 2545 ClassBuilder builder) {
2494 builder.addProperty('', 2546 builder.addProperty('',
2495 js.string("$superName;${fieldNames.join(',')}")); 2547 js.string("$superName;${fieldNames.join(',')}"));
2548
2549 List<String> fields = fieldNames;
2550 String constructorName = mangledName;
2551 precompiledFunction.add(new jsAst.FunctionDeclaration(
2552 new jsAst.VariableDeclaration(constructorName),
2553 js.fun(fields, fields.map(
2554 (name) => js('this.$name = $name')).toList())));
2555 precompiledFunction.addAll([
2556 js('$constructorName.builtin\$cls = "$constructorName"'),
2557 js('\$desc=\$collectedClasses.$constructorName'),
2558 js.if_('\$desc instanceof Array', js('\$desc = \$desc[1]')),
2559 js('$constructorName.prototype = \$desc'),
2560 ]);
2561
2562 precompiledConstructorNames.add(js(constructorName));
2496 } 2563 }
2497 2564
2498 /** 2565 /**
2499 * Documentation wanted -- johnniwinther 2566 * Documentation wanted -- johnniwinther
2500 * 2567 *
2501 * Invariant: [member] must be a declaration element. 2568 * Invariant: [member] must be a declaration element.
2502 */ 2569 */
2503 void emitDynamicFunctionGetter(FunctionElement member, 2570 void emitDynamicFunctionGetter(FunctionElement member,
2504 DefineStubFunction defineStub) { 2571 DefineStubFunction defineStub) {
2505 assert(invariant(member, member.isDeclaration)); 2572 assert(invariant(member, member.isDeclaration));
(...skipping 1244 matching lines...) Expand 10 before | Expand all | Expand 10 after
3750 buffer.write(metadata); 3817 buffer.write(metadata);
3751 } 3818 }
3752 } else { 3819 } else {
3753 throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}'; 3820 throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}';
3754 } 3821 }
3755 buffer.write(',$n'); 3822 buffer.write(',$n');
3756 } 3823 }
3757 buffer.write('];$n'); 3824 buffer.write('];$n');
3758 } 3825 }
3759 3826
3760 void emitConvertToFastObjectFunction() { 3827 void emitConvertToFastObjectFunction_NO_CSP() {
3761 mainBuffer.add(r''' 3828 mainBuffer.add(r'''
3762 function convertToFastObject(properties) { 3829 function convertToFastObject(properties) {
kasperl 2013/09/20 13:04:47 Could this go through js ASTs?
3763 function makeConstructor() { 3830 function makeConstructor() {
3764 var str = "{\n"; 3831 var str = "{\n";
3765 var hasOwnProperty = Object.prototype.hasOwnProperty; 3832 var hasOwnProperty = Object.prototype.hasOwnProperty;
3766 for (var property in properties) { 3833 for (var property in properties) {
3767 if (hasOwnProperty.call(properties, property)) { 3834 if (hasOwnProperty.call(properties, property)) {
3768 str += "this." + property + "= properties." + property + ";\n"; 3835 str += "this." + property + "= properties." + property + ";\n";
3769 } 3836 }
3770 } 3837 }
3771 str += "}\n"; 3838 str += "}\n";
3772 return new Function("properties", str); 3839 return new Function("properties", str);
3773 }; 3840 };
3774 var constructor = makeConstructor(); 3841 var constructor = makeConstructor();
3775 return makeConstructor.prototype = new constructor(properties); 3842 return makeConstructor.prototype = new constructor(properties);
3776 } 3843 }
3777 '''); 3844 ''');
3778 } 3845 }
3779 3846
3847 void emitConvertToFastObjectFunction() {
3848 // Create an instance that uses 'properties' as prototype. This should make
3849 // 'properties' a fast object.
3850 mainBuffer.add(r'''function convertToFastObject(properties) {
kasperl 2013/09/20 13:04:47 Could this go through js ASTs?
3851 function MyClass() {};
3852 MyClass.prototype = properties;
3853 new MyClass();
3854 ''');
3855 if (DEBUG_FAST_OBJECTS) {
3856 ClassElement primitives =
3857 compiler.findHelper(const SourceString('Primitives'));
3858 FunctionElement printHelper =
3859 compiler.lookupElementIn(
3860 primitives, const SourceString('printString'));
3861 String printHelperName = namer.isolateAccess(printHelper);
3862 mainBuffer.add('''
3863 // The following only works on V8 when run with option "--allow-natives-syntax".
3864 if (typeof $printHelperName === "function") {
3865 $printHelperName("Size of global object: "
3866 + String(Object.getOwnPropertyNames(properties).length)
3867 + ", fast properties " + %HasFastProperties(properties));
3868 }
3869 ''');
3870 }
3871 mainBuffer.add(r'''
3872 return properties;
3873 }
3874 ''');
3875 }
3876
3877
3780 String assembleProgram() { 3878 String assembleProgram() {
3781 measure(() { 3879 measure(() {
3782 // Compute the required type checks to know which classes need a 3880 // Compute the required type checks to know which classes need a
3783 // 'is$' method. 3881 // 'is$' method.
3784 computeRequiredTypeChecks(); 3882 computeRequiredTypeChecks();
3785 3883
3786 computeNeededClasses(); 3884 computeNeededClasses();
3787 3885
3788 mainBuffer.add(buildGeneratedBy()); 3886 mainBuffer.add(buildGeneratedBy());
3789 addComment(HOOKS_API_USAGE, mainBuffer); 3887 addComment(HOOKS_API_USAGE, mainBuffer);
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
4021 // The following code should not use the short-hand for the 4119 // The following code should not use the short-hand for the
4022 // initialStatics. 4120 // initialStatics.
4023 mainBuffer.add('${namer.CURRENT_ISOLATE}$_=${_}null$N'); 4121 mainBuffer.add('${namer.CURRENT_ISOLATE}$_=${_}null$N');
4024 4122
4025 emitFinishIsolateConstructorInvocation(mainBuffer); 4123 emitFinishIsolateConstructorInvocation(mainBuffer);
4026 mainBuffer.add( 4124 mainBuffer.add(
4027 '${namer.CURRENT_ISOLATE}$_=${_}new ${namer.isolateName}()$N'); 4125 '${namer.CURRENT_ISOLATE}$_=${_}new ${namer.isolateName}()$N');
4028 4126
4029 emitConvertToFastObjectFunction(); 4127 emitConvertToFastObjectFunction();
4030 for (String globalObject in Namer.reservedGlobalObjectNames) { 4128 for (String globalObject in Namer.reservedGlobalObjectNames) {
4031 mainBuffer.add('$globalObject = convertToFastObject($globalObject)$N'); 4129 mainBuffer.add('$globalObject = convertToFastObject($globalObject)$N');
kasperl 2013/09/20 13:04:47 Could this go through js AST?
4032 } 4130 }
4033 if (DEBUG_FAST_OBJECTS) { 4131 if (DEBUG_FAST_OBJECTS) {
4034 ClassElement primitives = 4132 ClassElement primitives =
4035 compiler.findHelper(const SourceString('Primitives')); 4133 compiler.findHelper(const SourceString('Primitives'));
4036 FunctionElement printHelper = 4134 FunctionElement printHelper =
4037 compiler.lookupElementIn( 4135 compiler.lookupElementIn(
4038 primitives, const SourceString('printString')); 4136 primitives, const SourceString('printString'));
4039 String printHelperName = namer.isolateAccess(printHelper); 4137 String printHelperName = namer.isolateAccess(printHelper);
4040 4138
4041 mainBuffer.add(''' 4139 mainBuffer.add('''
(...skipping 25 matching lines...) Expand all
4067 if (typeof $printHelperName === "function") { 4165 if (typeof $printHelperName === "function") {
4068 $printHelperName("Size of $object: " 4166 $printHelperName("Size of $object: "
4069 + String(Object.getOwnPropertyNames($object).length) 4167 + String(Object.getOwnPropertyNames($object).length)
4070 + ", fast properties " + %HasFastProperties($object)); 4168 + ", fast properties " + %HasFastProperties($object));
4071 } 4169 }
4072 '''); 4170 ''');
4073 } 4171 }
4074 } 4172 }
4075 4173
4076 emitMain(mainBuffer); 4174 emitMain(mainBuffer);
4175 jsAst.FunctionDeclaration precompiledFunctionAst =
4176 buildPrecompiledFunction();
4077 emitInitFunction(mainBuffer); 4177 emitInitFunction(mainBuffer);
4078 if (!areAnyElementsDeferred) { 4178 if (!areAnyElementsDeferred) {
4079 mainBuffer.add('})()$n'); 4179 mainBuffer.add('})()$n');
4080 } 4180 }
4081 compiler.assembledCode = mainBuffer.getText(); 4181 compiler.assembledCode = mainBuffer.getText();
4082 outputSourceMap(mainBuffer, compiler.assembledCode, ''); 4182 outputSourceMap(mainBuffer, compiler.assembledCode, '');
4083 4183
4184 mainBuffer.write(
4185 jsAst.prettyPrint(precompiledFunctionAst, compiler).getText());
4186
4187 compiler.outputProvider('precompiled', 'js')
4188 ..add(mainBuffer.getText())
4189 ..close();
4190
4084 emitDeferredCode(); 4191 emitDeferredCode();
4085 4192
4086 }); 4193 });
4087 return compiler.assembledCode; 4194 return compiler.assembledCode;
4088 } 4195 }
4089 4196
4090 CodeBuffer bufferForElement(Element element, CodeBuffer eagerBuffer) { 4197 CodeBuffer bufferForElement(Element element, CodeBuffer eagerBuffer) {
4091 Element owner = element.getLibrary(); 4198 Element owner = element.getLibrary();
4092 if (!element.isTopLevel() && !element.isNative()) { 4199 if (!element.isTopLevel() && !element.isNative()) {
4093 // For static (not top level) elements, record their code in a buffer 4200 // For static (not top level) elements, record their code in a buffer
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
4327 4434
4328 const String HOOKS_API_USAGE = """ 4435 const String HOOKS_API_USAGE = """
4329 // The code supports the following hooks: 4436 // The code supports the following hooks:
4330 // dartPrint(message) - if this function is defined it is called 4437 // dartPrint(message) - if this function is defined it is called
4331 // instead of the Dart [print] method. 4438 // instead of the Dart [print] method.
4332 // dartMainRunner(main) - if this function is defined, the Dart [main] 4439 // dartMainRunner(main) - if this function is defined, the Dart [main]
4333 // method will not be invoked directly. 4440 // method will not be invoked directly.
4334 // Instead, a closure that will invoke [main] is 4441 // Instead, a closure that will invoke [main] is
4335 // passed to [dartMainRunner]. 4442 // passed to [dartMainRunner].
4336 """; 4443 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698