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

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: Make tests pass Created 7 years, 2 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 // True if Isolate.makeConstantList is needed.
183 bool hasMakeConstantList = false;
184
185 /**
171 * For classes and libraries, record code for static/top-level members. 186 * For classes and libraries, record code for static/top-level members.
172 * Later, this code is emitted when the class or library is emitted. 187 * Later, this code is emitted when the class or library is emitted.
173 * See [bufferForElement]. 188 * See [bufferForElement].
174 */ 189 */
175 // TODO(ahe): Generate statics with their class, and store only libraries in 190 // TODO(ahe): Generate statics with their class, and store only libraries in
176 // this map. 191 // this map.
177 final Map<Element, List<CodeBuffer>> elementBuffers = 192 final Map<Element, List<CodeBuffer>> elementBuffers =
178 new Map<Element, List<CodeBuffer>>(); 193 new Map<Element, List<CodeBuffer>>();
179 194
180 void registerDynamicFunctionTypeCheck(FunctionType functionType) { 195 void registerDynamicFunctionTypeCheck(FunctionType functionType) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 String get generateAccessorHolder 271 String get generateAccessorHolder
257 => '$isolatePropertiesName.\$generateAccessor'; 272 => '$isolatePropertiesName.\$generateAccessor';
258 String get finishClassesProperty 273 String get finishClassesProperty
259 => r'$finishClasses'; 274 => r'$finishClasses';
260 String get finishClassesName 275 String get finishClassesName
261 => '${namer.isolateName}.$finishClassesProperty'; 276 => '${namer.isolateName}.$finishClassesProperty';
262 String get finishIsolateConstructorName 277 String get finishIsolateConstructorName
263 => '${namer.isolateName}.\$finishIsolateConstructor'; 278 => '${namer.isolateName}.\$finishIsolateConstructor';
264 String get isolatePropertiesName 279 String get isolatePropertiesName
265 => '${namer.isolateName}.${namer.isolatePropertiesName}'; 280 => '${namer.isolateName}.${namer.isolatePropertiesName}';
266 String get supportsProtoName
267 => 'supportsProto';
268 String get lazyInitializerName 281 String get lazyInitializerName
269 => '${namer.isolateName}.\$lazy'; 282 => '${namer.isolateName}.\$lazy';
270 283
271 // Compact field specifications. The format of the field specification is 284 // Compact field specifications. The format of the field specification is
272 // <accessorName>:<fieldName><suffix> where the suffix and accessor name 285 // <accessorName>:<fieldName><suffix> where the suffix and accessor name
273 // prefix are optional. The suffix directs the generation of getter and 286 // 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 287 // setter methods. Each of the getter and setter has two bits to determine
275 // the calling convention. Setter listed below, getter is similar. 288 // the calling convention. Setter listed below, getter is similar.
276 // 289 //
277 // 00: no setter 290 // 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 433 // Declare a function called "generateAccessor". This is used in
421 // defineClassFunction (it's a local declaration in init()). 434 // defineClassFunction (it's a local declaration in init()).
422 return [ 435 return [
423 generateAccessorFunction, 436 generateAccessorFunction,
424 js('$generateAccessorHolder = generateAccessor'), 437 js('$generateAccessorHolder = generateAccessor'),
425 new jsAst.FunctionDeclaration( 438 new jsAst.FunctionDeclaration(
426 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; 439 new jsAst.VariableDeclaration('defineClass'), defineClass) ];
427 } 440 }
428 441
429 /** Needs defineClass to be defined. */ 442 /** Needs defineClass to be defined. */
430 List buildProtoSupportCheck() { 443 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 [ 444 return [
442 js('var $supportsProtoName = false'), 445 js('var inheritFrom = #',
443 // js('var tmp = defineClass("c", "c", ["f<"], {}).prototype'), 446 js.fun([], [
444 // 447 new jsAst.FunctionDeclaration(
445 // js.if_(js('tmp.__proto__'), [ 448 new jsAst.VariableDeclaration('tmp'), js.fun([], [])),
446 // js('tmp.__proto__ = {}'), 449 js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
447 // js.if_(js(r'typeof tmp.get$f != "undefined"'), 450 js.return_(js.fun(['constructor', 'superConstructor'], [
448 // js('$supportsProtoName = true')) 451 js('tmp.prototype = superConstructor.prototype'),
449 // ]) 452 js('var object = new tmp()'),
450 ]; 453 js('var properties = constructor.prototype'),
454 js.forIn('member', 'properties',
455 js.if_('hasOwnProperty.call(properties, member)',
456 js('object[member] = properties[member]'))),
457 js('object.constructor = constructor'),
458 js('constructor.prototype = object'),
459 js.return_('object')
460 ]))])())];
451 } 461 }
452 462
453 static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4; 463 static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4;
454 464
455 // If we need fewer than this many noSuchMethod handlers we can save space by 465 // 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 466 // just emitting them in JS, rather than emitting the JS needed to generate
457 // them at run time. 467 // them at run time.
458 static const VERY_FEW_NO_SUCH_METHOD_HANDLERS = 10; 468 static const VERY_FEW_NO_SUCH_METHOD_HANDLERS = 10;
459 469
460 /** 470 /**
(...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 705 // 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 706 // the object literal directly. For other engines we have to create a new
697 // object and copy over the members. 707 // object and copy over the members.
698 708
699 String reflectableField = namer.reflectableField; 709 String reflectableField = namer.reflectableField;
700 List<jsAst.Node> statements = [ 710 List<jsAst.Node> statements = [
701 js('var pendingClasses = {}'), 711 js('var pendingClasses = {}'),
702 js.if_('!init.allClasses', js('init.allClasses = {}')), 712 js.if_('!init.allClasses', js('init.allClasses = {}')),
703 js('var allClasses = init.allClasses'), 713 js('var allClasses = init.allClasses'),
704 714
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( 715 optional(
712 DEBUG_FAST_OBJECTS, 716 DEBUG_FAST_OBJECTS,
713 js('print("Number of classes: "' 717 js('print("Number of classes: "'
714 r' + Object.getOwnPropertyNames($$).length)')), 718 r' + Object.getOwnPropertyNames($$).length)')),
715 719
720 js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
721
722 js.if_('typeof dart_precompiled == "function"',
723 [js('var constructors = dart_precompiled(collectedClasses)')],
724
725 [js('var combinedConstructorFunction = "function \$reflectable(fn){'
726 'fn.$reflectableField=1;return fn};\\n"+ "var \$desc;\\n"'),
727 js('var constructorsList = []')]),
716 js.forIn('cls', 'collectedClasses', [ 728 js.forIn('cls', 'collectedClasses', [
717 js.if_('hasOwnProperty.call(collectedClasses, cls)', [ 729 js.if_('hasOwnProperty.call(collectedClasses, cls)', [
718 js('var desc = collectedClasses[cls]'), 730 js('var desc = collectedClasses[cls]'),
719 js.if_('desc instanceof Array', js('desc = desc[1]')), 731 js.if_('desc instanceof Array', js('desc = desc[1]')),
720 732
721 /* The 'fields' are either a constructor function or a 733 /* The 'fields' are either a constructor function or a
722 * string encoding fields, constructor and superclass. Get 734 * string encoding fields, constructor and superclass. Get
723 * the superclass and the fields in the format 735 * the superclass and the fields in the format
724 * '[name/]Super;field1,field2' 736 * '[name/]Super;field1,field2'
725 * from the null-string property on the descriptor. 737 * from the null-string property on the descriptor.
726 * The 'name/' is optional and contains the name that should be used 738 * 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 739 * when printing the runtime type string. It is used, for example, to
728 * print the runtime type JSInt as 'int'. 740 * print the runtime type JSInt as 'int'.
729 */ 741 */
730 js('var classData = desc[""], supr, name = cls, fields = classData'), 742 js('var classData = desc[""], supr, name = cls, fields = classData'),
731 optional( 743 optional(
732 backend.hasRetainedMetadata, 744 backend.hasRetainedMetadata,
733 js.if_('typeof classData == "object" && ' 745 js.if_('typeof classData == "object" && '
734 'classData instanceof Array', 746 'classData instanceof Array',
735 [js('classData = fields = classData[0]')])), 747 [js('classData = fields = classData[0]')])),
736 748
737 js.if_('typeof classData == "string"', [ 749 js.if_('typeof classData == "string"', [
738 js('var split = classData.split("/")'), 750 js('var split = classData.split("/")'),
739 js.if_('split.length == 2', [ 751 js.if_('split.length == 2', [
740 js('name = split[0]'), 752 js('name = split[0]'),
741 js('fields = split[1]') 753 js('fields = split[1]')
742 ]) 754 ])
743 ]), 755 ]),
744 756
745 js.if_('typeof fields == "string"', [ 757 js('var s = fields.split(";")'),
746 js('var s = fields.split(";")'), 758 js('fields = s[1] == "" ? [] : s[1].split(",")'),
747 js('fields = s[1] == "" ? [] : s[1].split(",")'), 759 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 760
754 optional(needsMixinSupport, js.if_('supr && supr.indexOf("+") > 0', [ 761 optional(needsMixinSupport, js.if_('supr && supr.indexOf("+") > 0', [
755 js('s = supr.split("+")'), 762 js('s = supr.split("+")'),
756 js('supr = s[0]'), 763 js('supr = s[0]'),
757 js('var mixin = collectedClasses[s[1]]'), 764 js('var mixin = collectedClasses[s[1]]'),
758 js.if_('mixin instanceof Array', js('mixin = mixin[1]')), 765 js.if_('mixin instanceof Array', js('mixin = mixin[1]')),
759 js.forIn('d', 'mixin', [ 766 js.forIn('d', 'mixin', [
760 js.if_('hasOwnProperty.call(mixin, d)' 767 js.if_('hasOwnProperty.call(mixin, d)'
761 '&& !hasOwnProperty.call(desc, d)', 768 '&& !hasOwnProperty.call(desc, d)',
762 js('desc[d] = mixin[d]')) 769 js('desc[d] = mixin[d]'))
763 ]), 770 ]),
764 ])), 771 ])),
765 772
766 js('combinedConstructorFunction += defineClass(name, cls, fields)'), 773 js.if_('typeof dart_precompiled != "function"',
767 js('constructorsList.push(cls)'), 774 [js('combinedConstructorFunction +='
775 ' defineClass(name, cls, fields)'),
776 js('constructorsList.push(cls)')]),
768 js.if_('supr', js('pendingClasses[cls] = supr')) 777 js.if_('supr', js('pendingClasses[cls] = supr'))
769 ]) 778 ])
770 ]), 779 ]),
771 js('combinedConstructorFunction +=' 780 js.if_('typeof dart_precompiled != "function"',
772 ' "return [\\n " + constructorsList.join(",\\n ") + "\\n]"'), 781 [js('combinedConstructorFunction +='
773 js('var constructors =' 782 ' "return [\\n " + constructorsList.join(",\\n ") + "\\n]"'),
774 ' new Function("\$collectedClasses", combinedConstructorFunction)' 783 js('var constructors ='
775 '(collectedClasses)'), 784 ' new Function("\$collectedClasses", combinedConstructorFunction)'
776 js('combinedConstructorFunction = null'), 785 '(collectedClasses)'),
786 js('combinedConstructorFunction = null')]),
777 js.for_('var i = 0', 'i < constructors.length', 'i++', [ 787 js.for_('var i = 0', 'i < constructors.length', 'i++', [
778 js('var constructor = constructors[i]'), 788 js('var constructor = constructors[i]'),
779 js('var cls = constructor.name'), 789 js('var cls = constructor.name'),
780 js('var desc = collectedClasses[cls]'), 790 js('var desc = collectedClasses[cls]'),
781 js('var globalObject = isolateProperties'), 791 js('var globalObject = isolateProperties'),
782 js.if_('desc instanceof Array', [ 792 js.if_('desc instanceof Array', [
783 js('globalObject = desc[0] || isolateProperties'), 793 js('globalObject = desc[0] || isolateProperties'),
784 js('desc = desc[1]') 794 js('desc = desc[1]')
785 ]), 795 ]),
786 optional(backend.isTreeShakingDisabled, 796 optional(backend.isTreeShakingDisabled,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 // we have a string. 844 // we have a string.
835 js.if_('!superclass || typeof superclass != "string"', js.return_()), 845 js.if_('!superclass || typeof superclass != "string"', js.return_()),
836 js('finishClass(superclass)'), 846 js('finishClass(superclass)'),
837 js('var constructor = allClasses[cls]'), 847 js('var constructor = allClasses[cls]'),
838 js('var superConstructor = allClasses[superclass]'), 848 js('var superConstructor = allClasses[superclass]'),
839 849
840 js.if_(js('!superConstructor'), 850 js.if_(js('!superConstructor'),
841 js('superConstructor =' 851 js('superConstructor ='
842 'existingIsolateProperties[superclass]')), 852 'existingIsolateProperties[superclass]')),
843 853
844 js('var prototype = constructor.prototype'), 854 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 ]); 855 ]);
877 856
878 return new jsAst.FunctionDeclaration( 857 return new jsAst.FunctionDeclaration(
879 new jsAst.VariableDeclaration('finishClass'), 858 new jsAst.VariableDeclaration('finishClass'),
880 fun); 859 fun);
881 } 860 }
882 861
883 jsAst.Fun get finishIsolateConstructorFunction { 862 jsAst.Fun get finishIsolateConstructorFunction_NO_CSP {
ngeoffray 2013/09/24 08:15:29 Is that dead code?
ahe 2013/09/24 14:05:09 Yes, removed in https://codereview.chromium.org/24
884 String isolate = namer.isolateName; 863 String isolate = namer.isolateName;
885 // We replace the old Isolate function with a new one that initializes 864 // 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. 865 // all its field with the initial (and often final) value of all globals.
887 // This has two advantages: 866 // This has two advantages:
888 // 1. the properties are in the object itself (thus avoiding to go through 867 // 1. the properties are in the object itself (thus avoiding to go through
889 // the prototype when looking up globals. 868 // the prototype when looking up globals.
890 // 2. a new isolate goes through a (usually well optimized) constructor 869 // 2. a new isolate goes through a (usually well optimized) constructor
891 // function of the form: "function() { this.x = ...; this.y = ...; }". 870 // function of the form: "function() { this.x = ...; this.y = ...; }".
892 // 871 //
893 // Example: If [isolateProperties] is an object containing: x = 3 and 872 // 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. 916 // TODO(ahe): Only copy makeConstantList when it is used.
938 js('newIsolate.makeConstantList = oldIsolate.makeConstantList'), 917 js('newIsolate.makeConstantList = oldIsolate.makeConstantList'),
939 ]..addAll(copyFinishClasses) 918 ]..addAll(copyFinishClasses)
940 ..addAll([ 919 ..addAll([
941 920
942 // return newIsolate; 921 // return newIsolate;
943 js.return_('newIsolate') 922 js.return_('newIsolate')
944 ])); 923 ]));
945 } 924 }
946 925
926 jsAst.Fun get finishIsolateConstructorFunction {
927 // We replace the old Isolate function with a new one that initializes
928 // all its fields with the initial (and often final) value of all globals.
929 //
930 // We also copy over old values like the prototype, and the
931 // isolateProperties themselves.
932 return js.fun('oldIsolate', [
933 js('var isolateProperties = oldIsolate.${namer.isolatePropertiesName}'),
934 new jsAst.FunctionDeclaration(
935 new jsAst.VariableDeclaration('Isolate'),
936 js.fun([], [
937 js('var hasOwnProperty = Object.prototype.hasOwnProperty'),
938 js.forIn('staticName', 'isolateProperties',
939 js.if_('hasOwnProperty.call(isolateProperties, staticName)',
940 js('this[staticName] = isolateProperties[staticName]'))),
941 // Use the newly created object as prototype. In Chrome,
942 // this creates a hidden class for the object and makes
943 // sure it is fast to access.
944 new jsAst.FunctionDeclaration(
945 new jsAst.VariableDeclaration('ForceEfficientMap'),
946 js.fun([], [])),
947 js('ForceEfficientMap.prototype = this'),
948 js('new ForceEfficientMap()')])),
949 js('Isolate.prototype = oldIsolate.prototype'),
950 js('Isolate.prototype.constructor = Isolate'),
951 js('Isolate.${namer.isolatePropertiesName} = isolateProperties'),
952 optional(needsDefineClass,
953 js('Isolate.$finishClassesProperty ='
954 ' oldIsolate.$finishClassesProperty')),
955 optional(hasMakeConstantList,
956 js('Isolate.makeConstantList = oldIsolate.makeConstantList')),
957 js.return_('Isolate')]);
958 }
959
947 jsAst.Fun get lazyInitializerFunction { 960 jsAst.Fun get lazyInitializerFunction {
948 // function(prototype, staticName, fieldName, getterName, lazyValue) { 961 // function(prototype, staticName, fieldName, getterName, lazyValue) {
949 var parameters = <String>['prototype', 'staticName', 'fieldName', 962 var parameters = <String>['prototype', 'staticName', 'fieldName',
950 'getterName', 'lazyValue']; 963 'getterName', 'lazyValue'];
951 return js.fun(parameters, [ 964 return js.fun(parameters, addLazyInitializerLogic());
952 js('var getter = new Function("{ return this." + fieldName + ";}")'),
953 ]..addAll(addLazyInitializerLogic())
954 );
955 } 965 }
956 966
957 List addLazyInitializerLogic() { 967 List addLazyInitializerLogic() {
958 String isolate = namer.CURRENT_ISOLATE; 968 String isolate = namer.CURRENT_ISOLATE;
959 String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper()); 969 String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper());
960 var lazies = []; 970 var lazies = [];
961 if (backend.rememberLazies) { 971 if (backend.rememberLazies) {
962 lazies = [ 972 lazies = [
963 js.if_('!init.lazies', js('init.lazies = {}')), 973 js.if_('!init.lazies', js('init.lazies = {}')),
964 js('init.lazies[fieldName] = getterName')]; 974 js('init.lazies[fieldName] = getterName')];
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 ], /* else */ [ 1007 ], /* else */ [
998 js.if_('result === sentinelInProgress', 1008 js.if_('result === sentinelInProgress',
999 js('$cyclicThrow(staticName)') 1009 js('$cyclicThrow(staticName)')
1000 ) 1010 )
1001 ]), 1011 ]),
1002 1012
1003 // return result; 1013 // return result;
1004 js.return_('result') 1014 js.return_('result')
1005 1015
1006 ], finallyPart: [ 1016 ], finallyPart: [
1007 js('$isolate[getterName] = getter') 1017 js('$isolate[getterName] = #',
1018 js.fun([], [js.return_('this[fieldName]')]))
1008 ]) 1019 ])
1009 ])) 1020 ]))
1010 ]); 1021 ]);
1011 } 1022 }
1012 1023
1013 List buildDefineClassAndFinishClassFunctionsIfNecessary() { 1024 List buildDefineClassAndFinishClassFunctionsIfNecessary() {
1014 if (!needsDefineClass) return []; 1025 if (!needsDefineClass) return [];
1015 return defineClassFunction 1026 return defineClassFunction
1016 ..addAll(buildProtoSupportCheck()) 1027 ..addAll(buildInheritFrom())
1017 ..addAll([ 1028 ..addAll([
1018 js('$finishClassesName = #', finishClassesFunction) 1029 js('$finishClassesName = #', finishClassesFunction)
1019 ]); 1030 ]);
1020 } 1031 }
1021 1032
1022 List buildLazyInitializerFunctionIfNecessary() { 1033 List buildLazyInitializerFunctionIfNecessary() {
1023 if (!needsLazyInitializer) return []; 1034 if (!needsLazyInitializer) return [];
1024 1035
1025 return [js('$lazyInitializerName = #', lazyInitializerFunction)]; 1036 return [js('$lazyInitializerName = #', lazyInitializerFunction)];
1026 } 1037 }
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after
1702 if (reflectionName != null) { 1713 if (reflectionName != null) {
1703 var reflectable = 1714 var reflectable =
1704 js(backend.isAccessibleByReflection(member) ? '1' : '0'); 1715 js(backend.isAccessibleByReflection(member) ? '1' : '0');
1705 builder.addProperty('+$reflectionName', reflectable); 1716 builder.addProperty('+$reflectionName', reflectable);
1706 } 1717 }
1707 } 1718 }
1708 1719
1709 void generateGetter(Element member, String fieldName, String accessorName, 1720 void generateGetter(Element member, String fieldName, String accessorName,
1710 ClassBuilder builder) { 1721 ClassBuilder builder) {
1711 String getterName = namer.getterNameFromAccessorName(accessorName); 1722 String getterName = namer.getterNameFromAccessorName(accessorName);
1712 String receiver = backend.isInterceptorClass(member.getEnclosingClass()) 1723 ClassElement cls = member.getEnclosingClass();
1713 ? 'receiver' : 'this'; 1724 String className = namer.getNameOfClass(cls);
1714 List<String> args = backend.isInterceptedMethod(member) 1725 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this';
1715 ? ['receiver'] 1726 List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : [];
1716 : []; 1727 precompiledFunction.add(
1717 builder.addProperty(getterName, 1728 js('$className.prototype.$getterName = #',
1718 js.fun(args, js.return_(js('$receiver.$fieldName')))); 1729 js.fun(args, js.return_(js('$receiver.$fieldName')))));
1719 generateReflectionDataForFieldGetterOrSetter( 1730 if (backend.isNeededForReflection(member)) {
1720 member, getterName, builder, isGetter: true); 1731 precompiledFunction.add(
1732 js('$className.prototype.$getterName.${namer.reflectableField} = 1'));
1733 }
1721 } 1734 }
1722 1735
1723 void generateSetter(Element member, String fieldName, String accessorName, 1736 void generateSetter(Element member, String fieldName, String accessorName,
1724 ClassBuilder builder) { 1737 ClassBuilder builder) {
1725 String setterName = namer.setterNameFromAccessorName(accessorName); 1738 String setterName = namer.setterNameFromAccessorName(accessorName);
1726 String receiver = backend.isInterceptorClass(member.getEnclosingClass()) 1739 ClassElement cls = member.getEnclosingClass();
1727 ? 'receiver' : 'this'; 1740 String className = namer.getNameOfClass(cls);
1728 List<String> args = backend.isInterceptedMethod(member) 1741 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this';
1729 ? ['receiver', 'v'] 1742 List<String> args =
1730 : ['v']; 1743 backend.isInterceptedMethod(member) ? ['receiver', 'v'] : ['v'];
1731 builder.addProperty(setterName, 1744 precompiledFunction.add(
1732 js.fun(args, js('$receiver.$fieldName = v'))); 1745 js('$className.prototype.$setterName = #',
1733 generateReflectionDataForFieldGetterOrSetter( 1746 js.fun(args, js.return_(js('$receiver.$fieldName = v')))));
1734 member, setterName, builder, isGetter: false); 1747 if (backend.isNeededForReflection(member)) {
1748 precompiledFunction.add(
1749 js('$className.prototype.$setterName.${namer.reflectableField} = 1'));
1750 }
1735 } 1751 }
1736 1752
1737 bool canGenerateCheckedSetter(VariableElement field) { 1753 bool canGenerateCheckedSetter(VariableElement field) {
1738 // We never generate accessors for top-level/static fields. 1754 // We never generate accessors for top-level/static fields.
1739 if (!field.isInstanceMember()) return false; 1755 if (!field.isInstanceMember()) return false;
1740 DartType type = field.computeType(compiler).unalias(compiler); 1756 DartType type = field.computeType(compiler).unalias(compiler);
1741 if (type.element.isTypeVariable() || 1757 if (type.element.isTypeVariable() ||
1742 (type is FunctionType && type.containsTypeVariables) || 1758 (type is FunctionType && type.containsTypeVariables) ||
1743 type.treatAsDynamic || 1759 type.treatAsDynamic ||
1744 type.element == compiler.objectClass) { 1760 type.element == compiler.objectClass) {
(...skipping 29 matching lines...) Expand all
1774 List<String> args = backend.isInterceptedMethod(member) 1790 List<String> args = backend.isInterceptedMethod(member)
1775 ? ['receiver', 'v'] 1791 ? ['receiver', 'v']
1776 : ['v']; 1792 : ['v'];
1777 builder.addProperty(setterName, 1793 builder.addProperty(setterName,
1778 js.fun(args, 1794 js.fun(args,
1779 js('$receiver.$fieldName = #', js(helperName)(arguments)))); 1795 js('$receiver.$fieldName = #', js(helperName)(arguments))));
1780 generateReflectionDataForFieldGetterOrSetter( 1796 generateReflectionDataForFieldGetterOrSetter(
1781 member, setterName, builder, isGetter: false); 1797 member, setterName, builder, isGetter: false);
1782 } 1798 }
1783 1799
1784 void emitClassConstructor(ClassElement classElement, ClassBuilder builder) { 1800 void emitClassConstructor(ClassElement classElement,
1785 /* Do nothing. */ 1801 ClassBuilder builder,
1802 String runtimeName) {
1803 List<String> fields = <String>[];
1804 if (!classElement.isNative()) {
1805 visitFields(classElement, false,
1806 (Element member,
1807 String name,
1808 String accessorName,
1809 bool needsGetter,
1810 bool needsSetter,
1811 bool needsCheckedSetter) {
1812 fields.add(name);
1813 });
1814 }
1815 String constructorName = namer.getNameOfClass(classElement);
1816 precompiledFunction.add(new jsAst.FunctionDeclaration(
1817 new jsAst.VariableDeclaration(constructorName),
1818 js.fun(fields, fields.map(
1819 (name) => js('this.$name = $name')).toList())));
1820 if (runtimeName == null) {
1821 runtimeName = constructorName;
1822 }
1823 precompiledFunction.addAll([
1824 js('$constructorName.builtin\$cls = "$runtimeName"'),
1825 js.if_('!"name" in $constructorName',
1826 js('$constructorName.name = "$constructorName"')),
1827 js('\$desc=\$collectedClasses.$constructorName'),
1828 js.if_('\$desc instanceof Array', js('\$desc = \$desc[1]')),
1829 js('$constructorName.prototype = \$desc'),
1830 ]);
1831
1832 precompiledConstructorNames.add(js(constructorName));
1833 }
1834
1835 jsAst.FunctionDeclaration buildPrecompiledFunction() {
1836 // TODO(ahe): Compute a hash code.
1837 String name = 'dart_precompiled';
1838
1839 precompiledFunction.add(
1840 js.return_(
1841 new jsAst.ArrayInitializer.from(precompiledConstructorNames)));
1842 precompiledFunction.insert(0, js(r'var $desc'));
1843 return new jsAst.FunctionDeclaration(
1844 new jsAst.VariableDeclaration(name),
1845 js.fun([r'$collectedClasses'], precompiledFunction));
1786 } 1846 }
1787 1847
1788 void emitSuper(String superName, ClassBuilder builder) { 1848 void emitSuper(String superName, ClassBuilder builder) {
1789 /* Do nothing. */ 1849 /* Do nothing. */
1790 } 1850 }
1791 1851
1792 void emitRuntimeName(String runtimeName, ClassBuilder builder) { 1852 void emitRuntimeName(String runtimeName, ClassBuilder builder) {
1793 /* Do nothing. */ 1853 /* Do nothing. */
1794 } 1854 }
1795 1855
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1959 String name, 2019 String name,
1960 String accessorName, 2020 String accessorName,
1961 bool needsGetter, 2021 bool needsGetter,
1962 bool needsSetter, 2022 bool needsSetter,
1963 bool needsCheckedSetter) { 2023 bool needsCheckedSetter) {
1964 compiler.withCurrentElement(member, () { 2024 compiler.withCurrentElement(member, () {
1965 if (needsCheckedSetter) { 2025 if (needsCheckedSetter) {
1966 assert(!needsSetter); 2026 assert(!needsSetter);
1967 generateCheckedSetter(member, name, accessorName, builder); 2027 generateCheckedSetter(member, name, accessorName, builder);
1968 } 2028 }
1969 if (!getterAndSetterCanBeImplementedByFieldSpec) { 2029 if (needsGetter) {
1970 if (needsGetter) { 2030 generateGetter(member, name, accessorName, builder);
1971 generateGetter(member, name, accessorName, builder); 2031 }
1972 } 2032 if (needsSetter) {
1973 if (needsSetter) { 2033 generateSetter(member, name, accessorName, builder);
1974 generateSetter(member, name, accessorName, builder);
1975 }
1976 } 2034 }
1977 }); 2035 });
1978 }); 2036 });
1979 } 2037 }
1980 2038
1981 /** 2039 /**
1982 * Documentation wanted -- johnniwinther 2040 * Documentation wanted -- johnniwinther
1983 * 2041 *
1984 * Invariant: [classElement] must be a declaration element. 2042 * Invariant: [classElement] must be a declaration element.
1985 */ 2043 */
(...skipping 14 matching lines...) Expand all
2000 String runtimeName = 2058 String runtimeName =
2001 namer.getPrimitiveInterceptorRuntimeName(classElement); 2059 namer.getPrimitiveInterceptorRuntimeName(classElement);
2002 2060
2003 if (classElement.isMixinApplication) { 2061 if (classElement.isMixinApplication) {
2004 String mixinName = namer.getNameOfClass(computeMixinClass(classElement)); 2062 String mixinName = namer.getNameOfClass(computeMixinClass(classElement));
2005 superName = '$superName+$mixinName'; 2063 superName = '$superName+$mixinName';
2006 needsMixinSupport = true; 2064 needsMixinSupport = true;
2007 } 2065 }
2008 2066
2009 ClassBuilder builder = new ClassBuilder(); 2067 ClassBuilder builder = new ClassBuilder();
2010 emitClassConstructor(classElement, builder); 2068 emitClassConstructor(classElement, builder, runtimeName);
2011 emitSuper(superName, builder); 2069 emitSuper(superName, builder);
2012 emitRuntimeName(runtimeName, builder); 2070 emitRuntimeName(runtimeName, builder);
2013 emitFields(classElement, builder, superName, onlyForRti: onlyForRti); 2071 emitFields(classElement, builder, superName, onlyForRti: onlyForRti);
2014 emitClassGettersSetters(classElement, builder); 2072 emitClassGettersSetters(classElement, builder);
2015 if (!classElement.isMixinApplication) { 2073 if (!classElement.isMixinApplication) {
2016 emitInstanceMembers(classElement, builder); 2074 emitInstanceMembers(classElement, builder);
2017 } 2075 }
2018 emitIsTests(classElement, builder); 2076 emitIsTests(classElement, builder);
2019 2077
2020 emitClassBuilderWithReflectionData( 2078 emitClassBuilderWithReflectionData(
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2068 String reflectionName = getReflectionName(classElement, className); 2126 String reflectionName = getReflectionName(classElement, className);
2069 if (reflectionName != null) { 2127 if (reflectionName != null) {
2070 List<int> interfaces = <int>[]; 2128 List<int> interfaces = <int>[];
2071 for (DartType interface in classElement.interfaces) { 2129 for (DartType interface in classElement.interfaces) {
2072 interfaces.add(reifyType(interface)); 2130 interfaces.add(reifyType(interface));
2073 } 2131 }
2074 buffer.write(',$n$n"+$reflectionName": $interfaces'); 2132 buffer.write(',$n$n"+$reflectionName": $interfaces');
2075 } 2133 }
2076 } 2134 }
2077 2135
2078 bool get getterAndSetterCanBeImplementedByFieldSpec => true;
2079
2080 /// If this is true then we can generate the noSuchMethod handlers at startup 2136 /// 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. 2137 /// time, instead of them being emitted as part of the Object class.
2082 bool get generateTrivialNsmHandlers => true; 2138 bool get generateTrivialNsmHandlers => true;
2083 2139
2084 int _selectorRank(Selector selector) { 2140 int _selectorRank(Selector selector) {
2085 int arity = selector.argumentCount * 3; 2141 int arity = selector.argumentCount * 3;
2086 if (selector.isGetter()) return arity + 2; 2142 if (selector.isGetter()) return arity + 2;
2087 if (selector.isSetter()) return arity + 1; 2143 if (selector.isSetter()) return arity + 1;
2088 return arity; 2144 return arity;
2089 } 2145 }
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
2486 emitFunctionTypeSignature, emitIsFunctionTypeTest); 2542 emitFunctionTypeSignature, emitIsFunctionTypeTest);
2487 } 2543 }
2488 } 2544 }
2489 2545
2490 void emitClosureClassHeader(String mangledName, 2546 void emitClosureClassHeader(String mangledName,
2491 String superName, 2547 String superName,
2492 List<String> fieldNames, 2548 List<String> fieldNames,
2493 ClassBuilder builder) { 2549 ClassBuilder builder) {
2494 builder.addProperty('', 2550 builder.addProperty('',
2495 js.string("$superName;${fieldNames.join(',')}")); 2551 js.string("$superName;${fieldNames.join(',')}"));
2552
2553 List<String> fields = fieldNames;
2554 String constructorName = mangledName;
2555 precompiledFunction.add(new jsAst.FunctionDeclaration(
2556 new jsAst.VariableDeclaration(constructorName),
2557 js.fun(fields, fields.map(
2558 (name) => js('this.$name = $name')).toList())));
2559 precompiledFunction.addAll([
2560 js('$constructorName.builtin\$cls = "$constructorName"'),
2561 js('\$desc=\$collectedClasses.$constructorName'),
2562 js.if_('\$desc instanceof Array', js('\$desc = \$desc[1]')),
2563 js('$constructorName.prototype = \$desc'),
2564 ]);
2565
2566 precompiledConstructorNames.add(js(constructorName));
2496 } 2567 }
2497 2568
2498 /** 2569 /**
2499 * Documentation wanted -- johnniwinther 2570 * Documentation wanted -- johnniwinther
2500 * 2571 *
2501 * Invariant: [member] must be a declaration element. 2572 * Invariant: [member] must be a declaration element.
2502 */ 2573 */
2503 void emitDynamicFunctionGetter(FunctionElement member, 2574 void emitDynamicFunctionGetter(FunctionElement member,
2504 DefineStubFunction defineStub) { 2575 DefineStubFunction defineStub) {
2505 assert(invariant(member, member.isDeclaration)); 2576 assert(invariant(member, member.isDeclaration));
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
2785 2856
2786 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { 2857 jsAst.Expression buildLazyInitializedGetter(VariableElement element) {
2787 // Nothing to do, the 'lazy' function will create the getter. 2858 // Nothing to do, the 'lazy' function will create the getter.
2788 return null; 2859 return null;
2789 } 2860 }
2790 2861
2791 void emitCompileTimeConstants(CodeBuffer eagerBuffer) { 2862 void emitCompileTimeConstants(CodeBuffer eagerBuffer) {
2792 ConstantHandler handler = compiler.constantHandler; 2863 ConstantHandler handler = compiler.constantHandler;
2793 List<Constant> constants = handler.getConstantsForEmission( 2864 List<Constant> constants = handler.getConstantsForEmission(
2794 compareConstants); 2865 compareConstants);
2795 bool addedMakeConstantList = false;
2796 for (Constant constant in constants) { 2866 for (Constant constant in constants) {
2797 if (isConstantInlinedOrAlreadyEmitted(constant)) continue; 2867 if (isConstantInlinedOrAlreadyEmitted(constant)) continue;
2798 String name = namer.constantName(constant); 2868 String name = namer.constantName(constant);
2799 if (!addedMakeConstantList && constant.isList()) { 2869 if (constant.isList()) emitMakeConstantListIfNotEmitted(eagerBuffer);
2800 addedMakeConstantList = true;
2801 emitMakeConstantList(eagerBuffer);
2802 }
2803 CodeBuffer buffer = bufferForConstant(constant, eagerBuffer); 2870 CodeBuffer buffer = bufferForConstant(constant, eagerBuffer);
2804 jsAst.Expression init = js( 2871 jsAst.Expression init = js(
2805 '${namer.globalObjectForConstant(constant)}.$name = #', 2872 '${namer.globalObjectForConstant(constant)}.$name = #',
2806 constantInitializerExpression(constant)); 2873 constantInitializerExpression(constant));
2807 buffer.write(jsAst.prettyPrint(init, compiler)); 2874 buffer.write(jsAst.prettyPrint(init, compiler));
2808 buffer.write('$N'); 2875 buffer.write('$N');
2809 } 2876 }
2810 } 2877 }
2811 2878
2812 bool isConstantInlinedOrAlreadyEmitted(Constant constant) { 2879 bool isConstantInlinedOrAlreadyEmitted(Constant constant) {
(...skipping 14 matching lines...) Expand all
2827 if (cmp1 + cmp2 < 2) return cmp1 - cmp2; 2894 if (cmp1 + cmp2 < 2) return cmp1 - cmp2;
2828 // Sorting by the long name clusters constants with the same constructor 2895 // Sorting by the long name clusters constants with the same constructor
2829 // which compresses a tiny bit better. 2896 // which compresses a tiny bit better.
2830 int r = namer.constantLongName(a).compareTo(namer.constantLongName(b)); 2897 int r = namer.constantLongName(a).compareTo(namer.constantLongName(b));
2831 if (r != 0) return r; 2898 if (r != 0) return r;
2832 // Resolve collisions in the long name by using the constant name (i.e. JS 2899 // Resolve collisions in the long name by using the constant name (i.e. JS
2833 // name) which is unique. 2900 // name) which is unique.
2834 return namer.constantName(a).compareTo(namer.constantName(b)); 2901 return namer.constantName(a).compareTo(namer.constantName(b));
2835 } 2902 }
2836 2903
2837 void emitMakeConstantList(CodeBuffer buffer) { 2904 void emitMakeConstantListIfNotEmitted(CodeBuffer buffer) {
2838 buffer.write(namer.isolateName); 2905 if (hasMakeConstantList) return;
2839 buffer.write(r'''.makeConstantList = function(list) { 2906 hasMakeConstantList = true;
2907 buffer
2908 ..write(namer.isolateName)
2909 ..write(r'''.makeConstantList = function(list) {
2840 list.immutable$list = true; 2910 list.immutable$list = true;
2841 list.fixed$length = true; 2911 list.fixed$length = true;
2842 return list; 2912 return list;
2843 }; 2913 };
2844 '''); 2914 ''');
2845 } 2915 }
2846 2916
2847 /** 2917 /**
2848 * Documentation wanted -- johnniwinther 2918 * Documentation wanted -- johnniwinther
2849 * 2919 *
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after
3750 buffer.write(metadata); 3820 buffer.write(metadata);
3751 } 3821 }
3752 } else { 3822 } else {
3753 throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}'; 3823 throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}';
3754 } 3824 }
3755 buffer.write(',$n'); 3825 buffer.write(',$n');
3756 } 3826 }
3757 buffer.write('];$n'); 3827 buffer.write('];$n');
3758 } 3828 }
3759 3829
3760 void emitConvertToFastObjectFunction() { 3830 void emitConvertToFastObjectFunction_NO_CSP() {
ngeoffray 2013/09/24 08:15:29 Ditto
3761 mainBuffer.add(r''' 3831 mainBuffer.add(r'''
3762 function convertToFastObject(properties) { 3832 function convertToFastObject(properties) {
3763 function makeConstructor() { 3833 function makeConstructor() {
3764 var str = "{\n"; 3834 var str = "{\n";
3765 var hasOwnProperty = Object.prototype.hasOwnProperty; 3835 var hasOwnProperty = Object.prototype.hasOwnProperty;
3766 for (var property in properties) { 3836 for (var property in properties) {
3767 if (hasOwnProperty.call(properties, property)) { 3837 if (hasOwnProperty.call(properties, property)) {
3768 str += "this." + property + "= properties." + property + ";\n"; 3838 str += "this." + property + "= properties." + property + ";\n";
3769 } 3839 }
3770 } 3840 }
3771 str += "}\n"; 3841 str += "}\n";
3772 return new Function("properties", str); 3842 return new Function("properties", str);
3773 }; 3843 };
3774 var constructor = makeConstructor(); 3844 var constructor = makeConstructor();
3775 return makeConstructor.prototype = new constructor(properties); 3845 return makeConstructor.prototype = new constructor(properties);
3776 } 3846 }
3777 '''); 3847 ''');
3778 } 3848 }
3779 3849
3850 void emitConvertToFastObjectFunction() {
3851 // Create an instance that uses 'properties' as prototype. This should make
3852 // 'properties' a fast object.
3853 mainBuffer.add(r'''function convertToFastObject(properties) {
3854 function MyClass() {};
3855 MyClass.prototype = properties;
3856 new MyClass();
3857 ''');
3858 if (DEBUG_FAST_OBJECTS) {
3859 ClassElement primitives =
3860 compiler.findHelper(const SourceString('Primitives'));
3861 FunctionElement printHelper =
3862 compiler.lookupElementIn(
3863 primitives, const SourceString('printString'));
3864 String printHelperName = namer.isolateAccess(printHelper);
3865 mainBuffer.add('''
3866 // The following only works on V8 when run with option "--allow-natives-syntax".
3867 if (typeof $printHelperName === "function") {
3868 $printHelperName("Size of global object: "
3869 + String(Object.getOwnPropertyNames(properties).length)
3870 + ", fast properties " + %HasFastProperties(properties));
3871 }
3872 ''');
3873 }
3874 mainBuffer.add(r'''
3875 return properties;
3876 }
3877 ''');
3878 }
3879
3880
3780 String assembleProgram() { 3881 String assembleProgram() {
3781 measure(() { 3882 measure(() {
3782 // Compute the required type checks to know which classes need a 3883 // Compute the required type checks to know which classes need a
3783 // 'is$' method. 3884 // 'is$' method.
3784 computeRequiredTypeChecks(); 3885 computeRequiredTypeChecks();
3785 3886
3786 computeNeededClasses(); 3887 computeNeededClasses();
3787 3888
3788 mainBuffer.add(buildGeneratedBy()); 3889 mainBuffer.add(buildGeneratedBy());
3789 addComment(HOOKS_API_USAGE, mainBuffer); 3890 addComment(HOOKS_API_USAGE, mainBuffer);
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
4067 if (typeof $printHelperName === "function") { 4168 if (typeof $printHelperName === "function") {
4068 $printHelperName("Size of $object: " 4169 $printHelperName("Size of $object: "
4069 + String(Object.getOwnPropertyNames($object).length) 4170 + String(Object.getOwnPropertyNames($object).length)
4070 + ", fast properties " + %HasFastProperties($object)); 4171 + ", fast properties " + %HasFastProperties($object));
4071 } 4172 }
4072 '''); 4173 ''');
4073 } 4174 }
4074 } 4175 }
4075 4176
4076 emitMain(mainBuffer); 4177 emitMain(mainBuffer);
4178 jsAst.FunctionDeclaration precompiledFunctionAst =
4179 buildPrecompiledFunction();
4077 emitInitFunction(mainBuffer); 4180 emitInitFunction(mainBuffer);
4078 if (!areAnyElementsDeferred) { 4181 if (!areAnyElementsDeferred) {
4079 mainBuffer.add('})()$n'); 4182 mainBuffer.add('})()$n');
4080 } 4183 }
4081 compiler.assembledCode = mainBuffer.getText(); 4184 compiler.assembledCode = mainBuffer.getText();
4082 outputSourceMap(compiler.assembledCode, ''); 4185 outputSourceMap(compiler.assembledCode, '');
4083 4186
4187 mainBuffer.write(
4188 jsAst.prettyPrint(precompiledFunctionAst, compiler).getText());
4189
4190 compiler.outputProvider('precompiled', 'js')
4191 ..add(mainBuffer.getText())
4192 ..close();
4193
4084 emitDeferredCode(); 4194 emitDeferredCode();
4085 4195
4086 }); 4196 });
4087 return compiler.assembledCode; 4197 return compiler.assembledCode;
4088 } 4198 }
4089 4199
4090 CodeBuffer bufferForElement(Element element, CodeBuffer eagerBuffer) { 4200 CodeBuffer bufferForElement(Element element, CodeBuffer eagerBuffer) {
4091 Element owner = element.getLibrary(); 4201 Element owner = element.getLibrary();
4092 if (!element.isTopLevel() && !element.isNative()) { 4202 if (!element.isTopLevel() && !element.isNative()) {
4093 // For static (not top level) elements, record their code in a buffer 4203 // 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 4437
4328 const String HOOKS_API_USAGE = """ 4438 const String HOOKS_API_USAGE = """
4329 // The code supports the following hooks: 4439 // The code supports the following hooks:
4330 // dartPrint(message) - if this function is defined it is called 4440 // dartPrint(message) - if this function is defined it is called
4331 // instead of the Dart [print] method. 4441 // instead of the Dart [print] method.
4332 // dartMainRunner(main) - if this function is defined, the Dart [main] 4442 // dartMainRunner(main) - if this function is defined, the Dart [main]
4333 // method will not be invoked directly. 4443 // method will not be invoked directly.
4334 // Instead, a closure that will invoke [main] is 4444 // Instead, a closure that will invoke [main] is
4335 // passed to [dartMainRunner]. 4445 // passed to [dartMainRunner].
4336 """; 4446 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698