OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 | 7 |
8 class OldEmitter implements Emitter { | 8 class OldEmitter implements Emitter { |
9 final Compiler compiler; | 9 final Compiler compiler; |
10 final CodeEmitterTask task; | 10 final CodeEmitterTask task; |
11 | 11 |
12 final ContainerBuilder containerBuilder = new ContainerBuilder(); | 12 final ContainerBuilder containerBuilder = new ContainerBuilder(); |
13 final ClassEmitter classEmitter = new ClassEmitter(); | 13 final ClassEmitter classEmitter = new ClassEmitter(); |
14 final NsmEmitter nsmEmitter = new NsmEmitter(); | 14 final NsmEmitter nsmEmitter = new NsmEmitter(); |
15 final TypeTestEmitter typeTestEmitter = new TypeTestEmitter(); | 15 final TypeTestEmitter typeTestEmitter = new TypeTestEmitter(); |
16 final InterceptorEmitter interceptorEmitter = new InterceptorEmitter(); | 16 final InterceptorEmitter interceptorEmitter = new InterceptorEmitter(); |
17 final MetadataEmitter metadataEmitter = new MetadataEmitter(); | 17 final MetadataEmitter metadataEmitter = new MetadataEmitter(); |
18 | 18 |
| 19 // TODO(johnniwinther): Wrap these fields in a caching strategy. |
19 final Set<ConstantValue> cachedEmittedConstants; | 20 final Set<ConstantValue> cachedEmittedConstants; |
20 final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer(); | 21 final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer(); |
21 final Map<Element, ClassBuilder> cachedClassBuilders; | 22 final Map<Element, ClassBuilder> cachedClassBuilders; |
22 final Set<Element> cachedElements; | 23 final Set<Element> cachedElements; |
23 | 24 |
24 bool needsClassSupport = false; | 25 bool needsClassSupport = false; |
25 bool needsMixinSupport = false; | 26 bool needsMixinSupport = false; |
26 bool needsLazyInitializer = false; | 27 bool needsLazyInitializer = false; |
27 final Namer namer; | 28 final Namer namer; |
28 ConstantEmitter constantEmitter; | 29 ConstantEmitter constantEmitter; |
29 NativeEmitter get nativeEmitter => task.nativeEmitter; | 30 NativeEmitter get nativeEmitter => task.nativeEmitter; |
30 TypeTestRegistry get typeTestRegistry => task.typeTestRegistry; | 31 TypeTestRegistry get typeTestRegistry => task.typeTestRegistry; |
31 | 32 |
32 // The full code that is written to each hunk part-file. | 33 // The full code that is written to each hunk part-file. |
33 Map<OutputUnit, CodeBuffer> outputBuffers = new Map<OutputUnit, CodeBuffer>(); | 34 Map<OutputUnit, CodeOutput> outputBuffers = new Map<OutputUnit, CodeOutput>(); |
34 final CodeBuffer deferredConstants = new CodeBuffer(); | |
35 | 35 |
36 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | 36 /** Shorter access to [isolatePropertiesName]. Both here in the code, as |
37 well as in the generated code. */ | 37 well as in the generated code. */ |
38 String isolateProperties; | 38 String isolateProperties; |
39 String classesCollector; | 39 String classesCollector; |
40 Set<ClassElement> get neededClasses => task.neededClasses; | 40 Set<ClassElement> get neededClasses => task.neededClasses; |
41 Map<OutputUnit, List<ClassElement>> get outputClassLists | 41 Map<OutputUnit, List<ClassElement>> get outputClassLists |
42 => task.outputClassLists; | 42 => task.outputClassLists; |
43 Map<OutputUnit, List<ConstantValue>> get outputConstantLists | 43 Map<OutputUnit, List<ConstantValue>> get outputConstantLists |
44 => task.outputConstantLists; | 44 => task.outputConstantLists; |
45 List<ClassElement> get nativeClasses => task.nativeClasses; | 45 List<ClassElement> get nativeClasses => task.nativeClasses; |
46 final Map<String, String> mangledFieldNames = <String, String>{}; | 46 final Map<String, String> mangledFieldNames = <String, String>{}; |
47 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; | 47 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; |
48 final Set<String> recordedMangledNames = new Set<String>(); | 48 final Set<String> recordedMangledNames = new Set<String>(); |
49 | 49 |
50 final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties = | 50 final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties = |
51 new Map<ClassElement, Map<String, jsAst.Expression>>(); | 51 new Map<ClassElement, Map<String, jsAst.Expression>>(); |
52 | 52 |
53 List<TypedefElement> get typedefsNeededForReflection => | 53 List<TypedefElement> get typedefsNeededForReflection => |
54 task.typedefsNeededForReflection; | 54 task.typedefsNeededForReflection; |
55 | 55 |
56 JavaScriptBackend get backend => compiler.backend; | 56 JavaScriptBackend get backend => compiler.backend; |
57 TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler; | 57 TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler; |
58 | 58 |
59 String get _ => space; | 59 String get _ => space; |
60 String get space => compiler.enableMinification ? "" : " "; | 60 String get space => compiler.enableMinification ? "" : " "; |
61 String get n => compiler.enableMinification ? "" : "\n"; | 61 String get n => compiler.enableMinification ? "" : "\n"; |
62 String get N => compiler.enableMinification ? "\n" : ";\n"; | 62 String get N => compiler.enableMinification ? "\n" : ";\n"; |
63 | 63 |
64 CodeBuffer getBuffer(OutputUnit outputUnit) { | |
65 return outputBuffers.putIfAbsent(outputUnit, () => new CodeBuffer()); | |
66 } | |
67 | |
68 CodeBuffer get mainBuffer { | |
69 return getBuffer(compiler.deferredLoadTask.mainOutputUnit); | |
70 } | |
71 | |
72 /** | 64 /** |
73 * List of expressions and statements that will be included in the | 65 * List of expressions and statements that will be included in the |
74 * precompiled function. | 66 * precompiled function. |
75 * | 67 * |
76 * To save space, dart2js normally generates constructors and accessors | 68 * To save space, dart2js normally generates constructors and accessors |
77 * dynamically. This doesn't work in CSP mode, so dart2js emits them directly | 69 * dynamically. This doesn't work in CSP mode, so dart2js emits them directly |
78 * when in CSP mode. | 70 * when in CSP mode. |
79 */ | 71 */ |
80 Map<OutputUnit, List<jsAst.Node>> _cspPrecompiledFunctions = | 72 Map<OutputUnit, List<jsAst.Node>> _cspPrecompiledFunctions = |
81 new Map<OutputUnit, List<jsAst.Node>>(); | 73 new Map<OutputUnit, List<jsAst.Node>>(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 () => new List<jsAst.Expression>()); | 118 () => new List<jsAst.Expression>()); |
127 } | 119 } |
128 | 120 |
129 /// Erases the precompiled information for csp mode for all output units. | 121 /// Erases the precompiled information for csp mode for all output units. |
130 /// Used by the incremental compiler. | 122 /// Used by the incremental compiler. |
131 void clearCspPrecompiledNodes() { | 123 void clearCspPrecompiledNodes() { |
132 _cspPrecompiledFunctions.clear(); | 124 _cspPrecompiledFunctions.clear(); |
133 _cspPrecompiledConstructorNames.clear(); | 125 _cspPrecompiledConstructorNames.clear(); |
134 } | 126 } |
135 | 127 |
136 void addComment(String comment, CodeBuffer buffer) { | 128 void addComment(String comment, CodeOutput output) { |
137 buffer.write(jsAst.prettyPrint(js.comment(comment), compiler)); | 129 output.addBuffer(jsAst.prettyPrint(js.comment(comment), compiler)); |
138 } | 130 } |
139 | 131 |
140 @override | 132 @override |
141 jsAst.Expression constantReference(ConstantValue value) { | 133 jsAst.Expression constantReference(ConstantValue value) { |
142 return constantEmitter.reference(value); | 134 return constantEmitter.reference(value); |
143 } | 135 } |
144 | 136 |
145 jsAst.Expression constantInitializerExpression(ConstantValue value) { | 137 jsAst.Expression constantInitializerExpression(ConstantValue value) { |
146 return constantEmitter.initializationExpression(value); | 138 return constantEmitter.initializationExpression(value); |
147 } | 139 } |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 // this.x = t - v; | 315 // this.x = t - v; |
324 // }, | 316 // }, |
325 // }); | 317 // }); |
326 | 318 |
327 bool hasIsolateSupport = compiler.hasIsolateSupport; | 319 bool hasIsolateSupport = compiler.hasIsolateSupport; |
328 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; | 320 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; |
329 | 321 |
330 jsAst.Expression defineClass = js(''' | 322 jsAst.Expression defineClass = js(''' |
331 function(name, fields) { | 323 function(name, fields) { |
332 var accessors = []; | 324 var accessors = []; |
333 | 325 |
334 var str = "function " + name + "("; | 326 var str = "function " + name + "("; |
335 var body = ""; | 327 var body = ""; |
336 if (#hasIsolateSupport) { var fieldNames = ""; } | 328 if (#hasIsolateSupport) { var fieldNames = ""; } |
337 | 329 |
338 for (var i = 0; i < fields.length; i++) { | 330 for (var i = 0; i < fields.length; i++) { |
339 if(i != 0) str += ", "; | 331 if(i != 0) str += ", "; |
340 | 332 |
341 var field = generateAccessor(fields[i], accessors, name); | 333 var field = generateAccessor(fields[i], accessors, name); |
342 if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; } | 334 if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; } |
343 var parameter = "parameter_" + field; | 335 var parameter = "parameter_" + field; |
344 str += parameter; | 336 str += parameter; |
345 body += ("this." + field + " = " + parameter + ";\\n"); | 337 body += ("this." + field + " = " + parameter + ";\\n"); |
346 } | 338 } |
347 str += ") {\\n" + body + "}\\n"; | 339 str += ") {\\n" + body + "}\\n"; |
348 str += name + ".builtin\$cls=\\"" + name + "\\";\\n"; | 340 str += name + ".builtin\$cls=\\"" + name + "\\";\\n"; |
349 str += "\$desc=\$collectedClasses." + name + ";\\n"; | 341 str += "\$desc=\$collectedClasses." + name + ";\\n"; |
350 str += "if(\$desc instanceof Array) \$desc = \$desc[1];\\n"; | 342 str += "if(\$desc instanceof Array) \$desc = \$desc[1];\\n"; |
351 str += name + ".prototype = \$desc;\\n"; | 343 str += name + ".prototype = \$desc;\\n"; |
352 if (typeof defineClass.name != "string") { | 344 if (typeof defineClass.name != "string") { |
353 str += name + ".name=\\"" + name + "\\";\\n"; | 345 str += name + ".name=\\"" + name + "\\";\\n"; |
354 } | 346 } |
355 if (#hasIsolateSupport) { | 347 if (#hasIsolateSupport) { |
356 str += name + ".$fieldNamesProperty=[" + fieldNames + "];\\n"; | 348 str += name + ".$fieldNamesProperty=[" + fieldNames + "];\\n"; |
357 } | 349 } |
358 str += accessors.join(""); | 350 str += accessors.join(""); |
359 | 351 |
360 return str; | 352 return str; |
361 }''', { 'hasIsolateSupport': hasIsolateSupport }); | 353 }''', { 'hasIsolateSupport': hasIsolateSupport }); |
362 | 354 |
363 // Declare a function called "generateAccessor". This is used in | 355 // Declare a function called "generateAccessor". This is used in |
364 // defineClassFunction. | 356 // defineClassFunction. |
365 List result = <jsAst.Node>[ | 357 List result = <jsAst.Node>[ |
366 generateAccessorFunction, | 358 generateAccessorFunction, |
367 new jsAst.FunctionDeclaration( | 359 new jsAst.FunctionDeclaration( |
368 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; | 360 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; |
369 | 361 |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 } | 561 } |
570 }''', {'finishedClassesAccess': finishedClassesAccess, | 562 }''', {'finishedClassesAccess': finishedClassesAccess, |
571 'needsMixinSupport': needsMixinSupport, | 563 'needsMixinSupport': needsMixinSupport, |
572 'hasNativeClasses': nativeClasses.isNotEmpty, | 564 'hasNativeClasses': nativeClasses.isNotEmpty, |
573 'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME, | 565 'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME, |
574 'interceptorsByTagAccess': interceptorsByTagAccess, | 566 'interceptorsByTagAccess': interceptorsByTagAccess, |
575 'leafTagsAccess': leafTagsAccess, | 567 'leafTagsAccess': leafTagsAccess, |
576 'allowNativesSubclassing': true}); | 568 'allowNativesSubclassing': true}); |
577 } | 569 } |
578 | 570 |
579 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 571 void emitFinishIsolateConstructorInvocation(CodeOutput output) { |
580 String isolate = namer.isolateName; | 572 String isolate = namer.isolateName; |
581 buffer.write("$isolate = $finishIsolateConstructorName($isolate)$N"); | 573 output.add("$isolate = $finishIsolateConstructorName($isolate)$N"); |
582 } | 574 } |
583 | 575 |
584 /// In minified mode we want to keep the name for the most common core types. | 576 /// In minified mode we want to keep the name for the most common core types. |
585 bool _isNativeTypeNeedingReflectionName(Element element) { | 577 bool _isNativeTypeNeedingReflectionName(Element element) { |
586 if (!element.isClass) return false; | 578 if (!element.isClass) return false; |
587 return (element == compiler.intClass || | 579 return (element == compiler.intClass || |
588 element == compiler.doubleClass || | 580 element == compiler.doubleClass || |
589 element == compiler.numClass || | 581 element == compiler.numClass || |
590 element == compiler.stringClass || | 582 element == compiler.stringClass || |
591 element == compiler.boolClass || | 583 element == compiler.boolClass || |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 } | 743 } |
752 | 744 |
753 void emitStaticFunctions(List<Element> staticFunctions) { | 745 void emitStaticFunctions(List<Element> staticFunctions) { |
754 for (Element element in staticFunctions) { | 746 for (Element element in staticFunctions) { |
755 ClassBuilder builder = new ClassBuilder(element, namer); | 747 ClassBuilder builder = new ClassBuilder(element, namer); |
756 containerBuilder.addMember(element, builder); | 748 containerBuilder.addMember(element, builder); |
757 getElementDescriptor(element).properties.addAll(builder.properties); | 749 getElementDescriptor(element).properties.addAll(builder.properties); |
758 } | 750 } |
759 } | 751 } |
760 | 752 |
761 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer, | 753 void emitStaticNonFinalFieldInitializations(CodeOutput output, |
762 OutputUnit outputUnit) { | 754 OutputUnit outputUnit) { |
763 JavaScriptConstantCompiler handler = backend.constants; | 755 JavaScriptConstantCompiler handler = backend.constants; |
764 Iterable<VariableElement> staticNonFinalFields = | 756 Iterable<VariableElement> staticNonFinalFields = |
765 handler.getStaticNonFinalFieldsForEmission(); | 757 handler.getStaticNonFinalFieldsForEmission(); |
766 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 758 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
767 // [:interceptedNames:] is handled in [emitInterceptedNames]. | 759 // [:interceptedNames:] is handled in [emitInterceptedNames]. |
768 if (element == backend.interceptedNames) continue; | 760 if (element == backend.interceptedNames) continue; |
769 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. | 761 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. |
770 if (element == backend.mapTypeToInterceptor) continue; | 762 if (element == backend.mapTypeToInterceptor) continue; |
771 compiler.withCurrentElement(element, () { | 763 compiler.withCurrentElement(element, () { |
772 jsAst.Expression initialValue; | 764 jsAst.Expression initialValue; |
773 if (outputUnit != | 765 if (outputUnit != |
774 compiler.deferredLoadTask.outputUnitForElement(element)) { | 766 compiler.deferredLoadTask.outputUnitForElement(element)) { |
775 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { | 767 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { |
776 // In the main output-unit we output a stub initializer for deferred | 768 // In the main output-unit we output a stub initializer for deferred |
777 // variables, such that `isolateProperties` stays a fast object. | 769 // variables, such that `isolateProperties` stays a fast object. |
778 initialValue = jsAst.number(0); | 770 initialValue = jsAst.number(0); |
779 } else { | 771 } else { |
780 // Don't output stubs outside the main output file. | 772 // Don't output stubs outside the main output file. |
781 return; | 773 return; |
782 } | 774 } |
783 } else { | 775 } else { |
784 initialValue = constantEmitter.referenceInInitializationContext( | 776 initialValue = constantEmitter.referenceInInitializationContext( |
785 handler.getInitialValueFor(element).value); | 777 handler.getInitialValueFor(element).value); |
786 | 778 |
787 } | 779 } |
788 jsAst.Expression init = | 780 jsAst.Expression init = |
789 js('$isolateProperties.# = #', | 781 js('$isolateProperties.# = #', |
790 [namer.getNameOfGlobalField(element), initialValue]); | 782 [namer.getNameOfGlobalField(element), initialValue]); |
791 buffer.write(jsAst.prettyPrint(init, compiler, | 783 output.addBuffer(jsAst.prettyPrint(init, compiler, |
792 monitor: compiler.dumpInfoTask)); | 784 monitor: compiler.dumpInfoTask)); |
793 buffer.write('$N'); | 785 output.add('$N'); |
794 }); | 786 }); |
795 } | 787 } |
796 } | 788 } |
797 | 789 |
798 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { | 790 void emitLazilyInitializedStaticFields(CodeOutput output) { |
799 JavaScriptConstantCompiler handler = backend.constants; | 791 JavaScriptConstantCompiler handler = backend.constants; |
800 List<VariableElement> lazyFields = | 792 List<VariableElement> lazyFields = |
801 handler.getLazilyInitializedFieldsForEmission(); | 793 handler.getLazilyInitializedFieldsForEmission(); |
802 if (!lazyFields.isEmpty) { | 794 if (!lazyFields.isEmpty) { |
803 needsLazyInitializer = true; | 795 needsLazyInitializer = true; |
804 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { | 796 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { |
805 jsAst.Expression init = | 797 jsAst.Expression init = |
806 buildLazilyInitializedStaticField(element, isolateProperties); | 798 buildLazilyInitializedStaticField(element, isolateProperties); |
807 if (init == null) continue; | 799 if (init == null) continue; |
808 buffer.write( | 800 output.addBuffer( |
809 jsAst.prettyPrint(init, compiler, monitor: compiler.dumpInfoTask)); | 801 jsAst.prettyPrint(init, compiler, monitor: compiler.dumpInfoTask)); |
810 buffer.write("$N"); | 802 output.add("$N"); |
811 } | 803 } |
812 } | 804 } |
813 } | 805 } |
814 | 806 |
815 jsAst.Expression buildLazilyInitializedStaticField( | 807 jsAst.Expression buildLazilyInitializedStaticField( |
816 VariableElement element, String isolateProperties) { | 808 VariableElement element, String isolateProperties) { |
817 jsAst.Expression code = backend.generatedCode[element]; | 809 jsAst.Expression code = backend.generatedCode[element]; |
818 // The code is null if we ended up not needing the lazily | 810 // The code is null if we ended up not needing the lazily |
819 // initialized field after all because of constant folding | 811 // initialized field after all because of constant folding |
820 // before code generation. | 812 // before code generation. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 | 851 |
860 // Sorting by the long name clusters constants with the same constructor | 852 // Sorting by the long name clusters constants with the same constructor |
861 // which compresses a tiny bit better. | 853 // which compresses a tiny bit better. |
862 int r = namer.constantLongName(a).compareTo(namer.constantLongName(b)); | 854 int r = namer.constantLongName(a).compareTo(namer.constantLongName(b)); |
863 if (r != 0) return r; | 855 if (r != 0) return r; |
864 // Resolve collisions in the long name by using the constant name (i.e. JS | 856 // Resolve collisions in the long name by using the constant name (i.e. JS |
865 // name) which is unique. | 857 // name) which is unique. |
866 return namer.constantName(a).compareTo(namer.constantName(b)); | 858 return namer.constantName(a).compareTo(namer.constantName(b)); |
867 } | 859 } |
868 | 860 |
869 void emitCompileTimeConstants(CodeBuffer buffer, OutputUnit outputUnit) { | 861 void emitCompileTimeConstants(CodeOutput output, OutputUnit outputUnit) { |
870 List<ConstantValue> constants = outputConstantLists[outputUnit]; | 862 List<ConstantValue> constants = outputConstantLists[outputUnit]; |
871 if (constants == null) return; | 863 if (constants == null) return; |
872 bool isMainBuffer = buffer == mainBuffer; | 864 CodeOutput constantOutput = output; |
873 if (compiler.hasIncrementalSupport && isMainBuffer) { | 865 if (compiler.hasIncrementalSupport && outputUnit.isMainOutput) { |
874 buffer = cachedEmittedConstantsBuffer; | 866 constantOutput = cachedEmittedConstantsBuffer; |
875 } | 867 } |
876 for (ConstantValue constant in constants) { | 868 for (ConstantValue constant in constants) { |
877 if (compiler.hasIncrementalSupport && isMainBuffer) { | 869 if (compiler.hasIncrementalSupport && outputUnit.isMainOutput) { |
878 if (cachedEmittedConstants.contains(constant)) continue; | 870 if (cachedEmittedConstants.contains(constant)) continue; |
879 cachedEmittedConstants.add(constant); | 871 cachedEmittedConstants.add(constant); |
880 } | 872 } |
881 jsAst.Expression init = buildConstantInitializer(constant); | 873 jsAst.Expression init = buildConstantInitializer(constant); |
882 buffer.write(jsAst.prettyPrint(init, compiler, | 874 constantOutput.addBuffer(jsAst.prettyPrint(init, compiler, |
883 monitor: compiler.dumpInfoTask)); | 875 monitor: compiler.dumpInfoTask)); |
884 buffer.write('$N'); | 876 constantOutput.add('$N'); |
885 } | 877 } |
886 if (compiler.hasIncrementalSupport && isMainBuffer) { | 878 if (compiler.hasIncrementalSupport && outputUnit.isMainOutput) { |
887 mainBuffer.write(cachedEmittedConstantsBuffer); | 879 output.addBuffer(constantOutput); |
888 } | 880 } |
889 } | 881 } |
890 | 882 |
891 jsAst.Expression buildConstantInitializer(ConstantValue constant) { | 883 jsAst.Expression buildConstantInitializer(ConstantValue constant) { |
892 String name = namer.constantName(constant); | 884 String name = namer.constantName(constant); |
893 return js('#.# = #', | 885 return js('#.# = #', |
894 [namer.globalObjectForConstant(constant), name, | 886 [namer.globalObjectForConstant(constant), name, |
895 constantInitializerExpression(constant)]); | 887 constantInitializerExpression(constant)]); |
896 } | 888 } |
897 | 889 |
898 jsAst.Template get makeConstantListTemplate { | 890 jsAst.Template get makeConstantListTemplate { |
899 // TODO(floitsch): there is no harm in caching the template. | 891 // TODO(floitsch): there is no harm in caching the template. |
900 return jsAst.js.uncachedExpressionTemplate( | 892 return jsAst.js.uncachedExpressionTemplate( |
901 '${namer.isolateName}.$makeConstListProperty(#)'); | 893 '${namer.isolateName}.$makeConstListProperty(#)'); |
902 } | 894 } |
903 | 895 |
904 void emitMakeConstantList(CodeBuffer buffer) { | 896 void emitMakeConstantList(CodeOutput output) { |
905 buffer.write( | 897 output.addBuffer( |
906 jsAst.prettyPrint( | 898 jsAst.prettyPrint( |
907 // Functions are stored in the hidden class and not as properties in | 899 // Functions are stored in the hidden class and not as properties in |
908 // the object. We never actually look at the value, but only want | 900 // the object. We never actually look at the value, but only want |
909 // to know if the property exists. | 901 // to know if the property exists. |
910 js.statement(r'''#.# = function(list) { | 902 js.statement(r'''#.# = function(list) { |
911 list.immutable$list = Array; | 903 list.immutable$list = Array; |
912 list.fixed$length = Array; | 904 list.fixed$length = Array; |
913 return list; | 905 return list; |
914 }''', | 906 }''', |
915 [namer.isolateName, makeConstListProperty]), | 907 [namer.isolateName, makeConstListProperty]), |
916 compiler, monitor: compiler.dumpInfoTask)); | 908 compiler, monitor: compiler.dumpInfoTask)); |
917 buffer.write(N); | 909 output.add(N); |
918 } | 910 } |
919 | 911 |
920 /// Returns the code equivalent to: | 912 /// Returns the code equivalent to: |
921 /// `function(args) { $.startRootIsolate(X.main$closure(), args); }` | 913 /// `function(args) { $.startRootIsolate(X.main$closure(), args); }` |
922 jsAst.Expression buildIsolateSetupClosure(Element appMain, | 914 jsAst.Expression buildIsolateSetupClosure(Element appMain, |
923 Element isolateMain) { | 915 Element isolateMain) { |
924 jsAst.Expression mainAccess = isolateStaticClosureAccess(appMain); | 916 jsAst.Expression mainAccess = isolateStaticClosureAccess(appMain); |
925 // Since we pass the closurized version of the main method to | 917 // Since we pass the closurized version of the main method to |
926 // the isolate method, we must make sure that it exists. | 918 // the isolate method, we must make sure that it exists. |
927 return js('function(a){ #(#, a); }', | 919 return js('function(a){ #(#, a); }', |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 return js('# = #("dispatch_record")', | 972 return js('# = #("dispatch_record")', |
981 [dispatchPropertyNameAccess, | 973 [dispatchPropertyNameAccess, |
982 getIsolateTagAccess]); | 974 getIsolateTagAccess]); |
983 } | 975 } |
984 | 976 |
985 String generateIsolateTagRoot() { | 977 String generateIsolateTagRoot() { |
986 // TODO(sra): MD5 of contributing source code or URIs? | 978 // TODO(sra): MD5 of contributing source code or URIs? |
987 return 'ZxYxX'; | 979 return 'ZxYxX'; |
988 } | 980 } |
989 | 981 |
990 emitMain(CodeBuffer buffer) { | 982 emitMain(CodeOutput output) { |
991 if (compiler.isMockCompilation) return; | 983 if (compiler.isMockCompilation) return; |
992 Element main = compiler.mainFunction; | 984 Element main = compiler.mainFunction; |
993 jsAst.Expression mainCallClosure = null; | 985 jsAst.Expression mainCallClosure = null; |
994 if (compiler.hasIsolateSupport) { | 986 if (compiler.hasIsolateSupport) { |
995 Element isolateMain = | 987 Element isolateMain = |
996 backend.isolateHelperLibrary.find(JavaScriptBackend.START_ROOT_ISOLATE); | 988 backend.isolateHelperLibrary.find(JavaScriptBackend.START_ROOT_ISOLATE); |
997 mainCallClosure = buildIsolateSetupClosure(main, isolateMain); | 989 mainCallClosure = buildIsolateSetupClosure(main, isolateMain); |
998 } else if (compiler.hasIncrementalSupport) { | 990 } else if (compiler.hasIncrementalSupport) { |
999 mainCallClosure = js( | 991 mainCallClosure = js( |
1000 'function() { return #(); }', | 992 'function() { return #(); }', |
1001 backend.emitter.staticFunctionAccess(main)); | 993 backend.emitter.staticFunctionAccess(main)); |
1002 } else { | 994 } else { |
1003 mainCallClosure = backend.emitter.staticFunctionAccess(main); | 995 mainCallClosure = backend.emitter.staticFunctionAccess(main); |
1004 } | 996 } |
1005 | 997 |
1006 if (backend.needToInitializeIsolateAffinityTag) { | 998 if (backend.needToInitializeIsolateAffinityTag) { |
1007 buffer.write( | 999 output.addBuffer( |
1008 jsAst.prettyPrint(generateIsolateAffinityTagInitialization(), | 1000 jsAst.prettyPrint(generateIsolateAffinityTagInitialization(), |
1009 compiler, monitor: compiler.dumpInfoTask)); | 1001 compiler, monitor: compiler.dumpInfoTask)); |
1010 buffer.write(N); | 1002 output.add(N); |
1011 } | 1003 } |
1012 if (backend.needToInitializeDispatchProperty) { | 1004 if (backend.needToInitializeDispatchProperty) { |
1013 assert(backend.needToInitializeIsolateAffinityTag); | 1005 assert(backend.needToInitializeIsolateAffinityTag); |
1014 buffer.write( | 1006 output.addBuffer( |
1015 jsAst.prettyPrint(generateDispatchPropertyNameInitialization(), | 1007 jsAst.prettyPrint(generateDispatchPropertyNameInitialization(), |
1016 compiler, monitor: compiler.dumpInfoTask)); | 1008 compiler, monitor: compiler.dumpInfoTask)); |
1017 buffer.write(N); | 1009 output.add(N); |
1018 } | 1010 } |
1019 | 1011 |
1020 jsAst.Expression currentScriptAccess = | 1012 jsAst.Expression currentScriptAccess = |
1021 generateEmbeddedGlobalAccess(embeddedNames.CURRENT_SCRIPT); | 1013 generateEmbeddedGlobalAccess(embeddedNames.CURRENT_SCRIPT); |
1022 | 1014 |
1023 addComment('BEGIN invoke [main].', buffer); | 1015 addComment('BEGIN invoke [main].', output); |
1024 // This code finds the currently executing script by listening to the | 1016 // This code finds the currently executing script by listening to the |
1025 // onload event of all script tags and getting the first script which | 1017 // onload event of all script tags and getting the first script which |
1026 // finishes. Since onload is called immediately after execution this should | 1018 // finishes. Since onload is called immediately after execution this should |
1027 // not substantially change execution order. | 1019 // not substantially change execution order. |
1028 jsAst.Statement invokeMain = js.statement(''' | 1020 jsAst.Statement invokeMain = js.statement(''' |
1029 (function (callback) { | 1021 (function (callback) { |
1030 if (typeof document === "undefined") { | 1022 if (typeof document === "undefined") { |
1031 callback(null); | 1023 callback(null); |
1032 return; | 1024 return; |
1033 } | 1025 } |
(...skipping 16 matching lines...) Expand all Loading... |
1050 #currentScript = currentScript; | 1042 #currentScript = currentScript; |
1051 | 1043 |
1052 if (typeof dartMainRunner === "function") { | 1044 if (typeof dartMainRunner === "function") { |
1053 dartMainRunner(#mainCallClosure, []); | 1045 dartMainRunner(#mainCallClosure, []); |
1054 } else { | 1046 } else { |
1055 #mainCallClosure([]); | 1047 #mainCallClosure([]); |
1056 } | 1048 } |
1057 })''', {'currentScript': currentScriptAccess, | 1049 })''', {'currentScript': currentScriptAccess, |
1058 'mainCallClosure': mainCallClosure}); | 1050 'mainCallClosure': mainCallClosure}); |
1059 | 1051 |
1060 buffer.write(';'); | 1052 output.add(';'); |
1061 buffer.write(jsAst.prettyPrint(invokeMain, | 1053 output.addBuffer(jsAst.prettyPrint(invokeMain, |
1062 compiler, monitor: compiler.dumpInfoTask)); | 1054 compiler, monitor: compiler.dumpInfoTask)); |
1063 buffer.write(N); | 1055 output.add(N); |
1064 addComment('END invoke [main].', buffer); | 1056 addComment('END invoke [main].', output); |
1065 } | 1057 } |
1066 | 1058 |
1067 void emitInitFunction(CodeBuffer buffer) { | 1059 void emitInitFunction(CodeOutput output) { |
1068 String isolate = namer.currentIsolate; | 1060 String isolate = namer.currentIsolate; |
1069 jsAst.Expression allClassesAccess = | 1061 jsAst.Expression allClassesAccess = |
1070 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); | 1062 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
1071 jsAst.Expression interceptorsByTagAccess = | 1063 jsAst.Expression interceptorsByTagAccess = |
1072 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | 1064 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
1073 jsAst.Expression leafTagsAccess = | 1065 jsAst.Expression leafTagsAccess = |
1074 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | 1066 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
1075 jsAst.Expression finishedClassesAccess = | 1067 jsAst.Expression finishedClassesAccess = |
1076 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | 1068 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
1077 jsAst.Expression cyclicThrow = | 1069 jsAst.Expression cyclicThrow = |
1078 staticFunctionAccess(backend.getCyclicThrowHelper()); | 1070 staticFunctionAccess(backend.getCyclicThrowHelper()); |
1079 jsAst.Expression laziesAccess = | 1071 jsAst.Expression laziesAccess = |
1080 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); | 1072 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); |
1081 | 1073 |
1082 jsAst.FunctionDeclaration decl = js.statement(''' | 1074 jsAst.FunctionDeclaration decl = js.statement(''' |
1083 function init() { | 1075 function init() { |
1084 $isolateProperties = Object.create(null); | 1076 $isolateProperties = Object.create(null); |
1085 (function(){ | 1077 (function(){ |
1086 #allClasses = Object.create(null); | 1078 #allClasses = Object.create(null); |
1087 #interceptorsByTag = Object.create(null); | 1079 #interceptorsByTag = Object.create(null); |
1088 #leafTags = Object.create(null); | 1080 #leafTags = Object.create(null); |
1089 #finishedClasses = Object.create(null); | 1081 #finishedClasses = Object.create(null); |
1090 })(); | 1082 })(); |
1091 | 1083 |
1092 if (#needsLazyInitializer) { | 1084 if (#needsLazyInitializer) { |
1093 $lazyInitializerName = function (prototype, staticName, fieldName, | 1085 $lazyInitializerName = function (prototype, staticName, fieldName, |
1094 getterName, lazyValue) { | 1086 getterName, lazyValue) { |
1095 if (!#lazies) #lazies = Object.create(null); | 1087 if (!#lazies) #lazies = Object.create(null); |
1096 #lazies[fieldName] = getterName; | 1088 #lazies[fieldName] = getterName; |
1097 | 1089 |
1098 var sentinelUndefined = {}; | 1090 var sentinelUndefined = {}; |
1099 var sentinelInProgress = {}; | 1091 var sentinelInProgress = {}; |
1100 prototype[fieldName] = sentinelUndefined; | 1092 prototype[fieldName] = sentinelUndefined; |
1101 | 1093 |
1102 prototype[getterName] = function () { | 1094 prototype[getterName] = function () { |
1103 var result = $isolate[fieldName]; | 1095 var result = $isolate[fieldName]; |
1104 try { | 1096 try { |
1105 if (result === sentinelUndefined) { | 1097 if (result === sentinelUndefined) { |
1106 $isolate[fieldName] = sentinelInProgress; | 1098 $isolate[fieldName] = sentinelInProgress; |
1107 | 1099 |
1108 try { | 1100 try { |
1109 result = $isolate[fieldName] = lazyValue(); | 1101 result = $isolate[fieldName] = lazyValue(); |
1110 } finally { | 1102 } finally { |
1111 // Use try-finally, not try-catch/throw as it destroys the | 1103 // Use try-finally, not try-catch/throw as it destroys the |
1112 // stack trace. | 1104 // stack trace. |
1113 if (result === sentinelUndefined) | 1105 if (result === sentinelUndefined) |
1114 $isolate[fieldName] = null; | 1106 $isolate[fieldName] = null; |
1115 } | 1107 } |
1116 } else { | 1108 } else { |
1117 if (result === sentinelInProgress) | 1109 if (result === sentinelInProgress) |
1118 #cyclicThrow(staticName); | 1110 #cyclicThrow(staticName); |
1119 } | 1111 } |
1120 | 1112 |
1121 return result; | 1113 return result; |
1122 } finally { | 1114 } finally { |
1123 $isolate[getterName] = function() { return this[fieldName]; }; | 1115 $isolate[getterName] = function() { return this[fieldName]; }; |
1124 } | 1116 } |
1125 } | 1117 } |
1126 } | 1118 } |
1127 } | 1119 } |
1128 | 1120 |
1129 // We replace the old Isolate function with a new one that initializes | 1121 // We replace the old Isolate function with a new one that initializes |
1130 // all its fields with the initial (and often final) value of all | 1122 // all its fields with the initial (and often final) value of all |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 Isolate.#isolatePropertiesName = isolateProperties; | 1160 Isolate.#isolatePropertiesName = isolateProperties; |
1169 if (#outputContainsConstantList) { | 1161 if (#outputContainsConstantList) { |
1170 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty; | 1162 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty; |
1171 } | 1163 } |
1172 if (#hasIncrementalSupport) { | 1164 if (#hasIncrementalSupport) { |
1173 Isolate.#lazyInitializerProperty = | 1165 Isolate.#lazyInitializerProperty = |
1174 oldIsolate.#lazyInitializerProperty; | 1166 oldIsolate.#lazyInitializerProperty; |
1175 } | 1167 } |
1176 return Isolate; | 1168 return Isolate; |
1177 } | 1169 } |
1178 | 1170 |
1179 }''', {'allClasses': allClassesAccess, | 1171 }''', {'allClasses': allClassesAccess, |
1180 'interceptorsByTag': interceptorsByTagAccess, | 1172 'interceptorsByTag': interceptorsByTagAccess, |
1181 'leafTags': leafTagsAccess, | 1173 'leafTags': leafTagsAccess, |
1182 'finishedClasses': finishedClassesAccess, | 1174 'finishedClasses': finishedClassesAccess, |
1183 'needsLazyInitializer': needsLazyInitializer, | 1175 'needsLazyInitializer': needsLazyInitializer, |
1184 'lazies': laziesAccess, 'cyclicThrow': cyclicThrow, | 1176 'lazies': laziesAccess, 'cyclicThrow': cyclicThrow, |
1185 'isolatePropertiesName': namer.isolatePropertiesName, | 1177 'isolatePropertiesName': namer.isolatePropertiesName, |
1186 'outputContainsConstantList': task.outputContainsConstantList, | 1178 'outputContainsConstantList': task.outputContainsConstantList, |
1187 'makeConstListProperty': makeConstListProperty, | 1179 'makeConstListProperty': makeConstListProperty, |
1188 'hasIncrementalSupport': compiler.hasIncrementalSupport, | 1180 'hasIncrementalSupport': compiler.hasIncrementalSupport, |
1189 'lazyInitializerProperty': lazyInitializerProperty,}); | 1181 'lazyInitializerProperty': lazyInitializerProperty,}); |
1190 | 1182 |
1191 buffer.write(jsAst.prettyPrint(decl, | 1183 output.addBuffer( |
1192 compiler, monitor: compiler.dumpInfoTask).getText()); | 1184 jsAst.prettyPrint(decl, compiler, monitor: compiler.dumpInfoTask)); |
1193 if (compiler.enableMinification) buffer.write('\n'); | 1185 if (compiler.enableMinification) { |
| 1186 output.add('\n'); |
| 1187 } |
1194 } | 1188 } |
1195 | 1189 |
1196 void emitConvertToFastObjectFunction() { | 1190 void emitConvertToFastObjectFunction(CodeOutput output) { |
1197 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; | 1191 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; |
1198 if (DEBUG_FAST_OBJECTS) { | 1192 if (DEBUG_FAST_OBJECTS) { |
1199 debugCode.add(js.statement(r''' | 1193 debugCode.add(js.statement(r''' |
1200 // The following only works on V8 when run with option | 1194 // The following only works on V8 when run with option |
1201 // "--allow-natives-syntax". We use'new Function' because the | 1195 // "--allow-natives-syntax". We use'new Function' because the |
1202 // miniparser does not understand V8 native syntax. | 1196 // miniparser does not understand V8 native syntax. |
1203 if (typeof print === "function") { | 1197 if (typeof print === "function") { |
1204 var HasFastProperties = | 1198 var HasFastProperties = |
1205 new Function("a", "return %HasFastProperties(a)"); | 1199 new Function("a", "return %HasFastProperties(a)"); |
1206 print("Size of global object: " | 1200 print("Size of global object: " |
1207 + String(Object.getOwnPropertyNames(properties).length) | 1201 + String(Object.getOwnPropertyNames(properties).length) |
1208 + ", fast properties " + HasFastProperties(properties)); | 1202 + ", fast properties " + HasFastProperties(properties)); |
1209 }''')); | 1203 }''')); |
1210 } | 1204 } |
1211 | 1205 |
1212 jsAst.Statement convertToFastObject = js.statement(r''' | 1206 jsAst.Statement convertToFastObject = js.statement(r''' |
1213 function convertToFastObject(properties) { | 1207 function convertToFastObject(properties) { |
1214 // Create an instance that uses 'properties' as prototype. This should | 1208 // Create an instance that uses 'properties' as prototype. This should |
1215 // make 'properties' a fast object. | 1209 // make 'properties' a fast object. |
1216 function MyClass() {}; | 1210 function MyClass() {}; |
1217 MyClass.prototype = properties; | 1211 MyClass.prototype = properties; |
1218 new MyClass(); | 1212 new MyClass(); |
1219 #; | 1213 #; |
1220 return properties; | 1214 return properties; |
1221 }''', [debugCode]); | 1215 }''', [debugCode]); |
1222 | 1216 |
1223 mainBuffer.write(jsAst.prettyPrint(convertToFastObject, compiler)); | 1217 output.addBuffer(jsAst.prettyPrint(convertToFastObject, compiler)); |
1224 mainBuffer.write(N); | 1218 output.add(N); |
1225 } | 1219 } |
1226 | 1220 |
1227 void writeLibraryDescriptors(CodeBuffer buffer, LibraryElement library) { | 1221 void writeLibraryDescriptors(CodeOutput output, LibraryElement library) { |
1228 var uri = ""; | 1222 var uri = ""; |
1229 if (!compiler.enableMinification || backend.mustPreserveUris) { | 1223 if (!compiler.enableMinification || backend.mustPreserveUris) { |
1230 uri = library.canonicalUri; | 1224 uri = library.canonicalUri; |
1231 if (uri.scheme == 'file' && compiler.outputUri != null) { | 1225 if (uri.scheme == 'file' && compiler.outputUri != null) { |
1232 uri = relativize(compiler.outputUri, library.canonicalUri, false); | 1226 uri = relativize(compiler.outputUri, library.canonicalUri, false); |
1233 } | 1227 } |
1234 } | 1228 } |
1235 ClassBuilder descriptor = elementDescriptors[library]; | 1229 ClassBuilder descriptor = elementDescriptors[library]; |
1236 if (descriptor == null) { | 1230 if (descriptor == null) { |
1237 // Nothing of the library was emitted. | 1231 // Nothing of the library was emitted. |
1238 // TODO(floitsch): this should not happen. We currently have an example | 1232 // TODO(floitsch): this should not happen. We currently have an example |
1239 // with language/prefix6_negative_test.dart where we have an instance | 1233 // with language/prefix6_negative_test.dart where we have an instance |
1240 // method without its corresponding class. | 1234 // method without its corresponding class. |
1241 return; | 1235 return; |
1242 } | 1236 } |
1243 | 1237 |
1244 String libraryName = | 1238 String libraryName = |
1245 (!compiler.enableMinification || backend.mustRetainLibraryNames) ? | 1239 (!compiler.enableMinification || backend.mustRetainLibraryNames) ? |
1246 library.getLibraryName() : | 1240 library.getLibraryName() : |
1247 ""; | 1241 ""; |
1248 | 1242 |
1249 jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library); | 1243 jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library); |
1250 | 1244 |
1251 jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer(); | 1245 jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer(); |
1252 | 1246 |
1253 compiler.dumpInfoTask.registerElementAst(library, metadata); | 1247 compiler.dumpInfoTask.registerElementAst(library, metadata); |
1254 compiler.dumpInfoTask.registerElementAst(library, initializers); | 1248 compiler.dumpInfoTask.registerElementAst(library, initializers); |
1255 buffer | 1249 output |
1256 ..write('["$libraryName",$_') | 1250 ..add('["$libraryName",$_') |
1257 ..write('"${uri}",$_') | 1251 ..add('"${uri}",$_'); |
1258 ..write(metadata == null ? "" : jsAst.prettyPrint(metadata, | 1252 if (metadata != null) { |
1259 compiler, | 1253 output.addBuffer(jsAst.prettyPrint(metadata, |
1260 monitor: compiler.dumpInfoTask)) | 1254 compiler, |
1261 ..write(',$_') | 1255 monitor: compiler.dumpInfoTask)); |
1262 ..write(namer.globalObjectFor(library)) | 1256 } |
1263 ..write(',$_') | 1257 output |
1264 ..write(jsAst.prettyPrint(initializers, | 1258 ..add(',$_') |
1265 compiler, | 1259 ..add(namer.globalObjectFor(library)) |
1266 monitor: compiler.dumpInfoTask)) | 1260 ..add(',$_') |
1267 ..write(library == compiler.mainApp ? ',${n}1' : "") | 1261 ..addBuffer(jsAst.prettyPrint(initializers, |
1268 ..write('],$n'); | 1262 compiler, |
| 1263 monitor: compiler.dumpInfoTask)) |
| 1264 ..add(library == compiler.mainApp ? ',${n}1' : "") |
| 1265 ..add('],$n'); |
1269 } | 1266 } |
1270 | 1267 |
1271 void emitPrecompiledConstructor(OutputUnit outputUnit, | 1268 void emitPrecompiledConstructor(OutputUnit outputUnit, |
1272 String constructorName, | 1269 String constructorName, |
1273 jsAst.Expression constructorAst, | 1270 jsAst.Expression constructorAst, |
1274 List<String> fields) { | 1271 List<String> fields) { |
1275 cspPrecompiledFunctionFor(outputUnit).add( | 1272 cspPrecompiledFunctionFor(outputUnit).add( |
1276 new jsAst.FunctionDeclaration( | 1273 new jsAst.FunctionDeclaration( |
1277 new jsAst.VariableDeclaration(constructorName), constructorAst)); | 1274 new jsAst.VariableDeclaration(constructorName), constructorAst)); |
1278 | 1275 |
1279 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; | 1276 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; |
1280 bool hasIsolateSupport = compiler.hasIsolateSupport; | 1277 bool hasIsolateSupport = compiler.hasIsolateSupport; |
1281 jsAst.Node fieldNamesArray = | 1278 jsAst.Node fieldNamesArray = |
1282 hasIsolateSupport ? js.stringArray(fields) : new jsAst.LiteralNull(); | 1279 hasIsolateSupport ? js.stringArray(fields) : new jsAst.LiteralNull(); |
1283 | 1280 |
1284 cspPrecompiledFunctionFor(outputUnit).add(js.statement(r''' | 1281 cspPrecompiledFunctionFor(outputUnit).add(js.statement(r''' |
1285 { | 1282 { |
1286 #constructorName.builtin$cls = #constructorNameString; | 1283 #constructorName.builtin$cls = #constructorNameString; |
1287 if (!"name" in #constructorName) | 1284 if (!"name" in #constructorName) |
1288 #constructorName.name = #constructorNameString; | 1285 #constructorName.name = #constructorNameString; |
1289 $desc = $collectedClasses.#constructorName; | 1286 $desc = $collectedClasses.#constructorName; |
1290 if ($desc instanceof Array) $desc = $desc[1]; | 1287 if ($desc instanceof Array) $desc = $desc[1]; |
1291 #constructorName.prototype = $desc; | 1288 #constructorName.prototype = $desc; |
1292 ''' /* next string is not a raw string */ ''' | 1289 ''' /* next string is not a raw string */ ''' |
1293 if (#hasIsolateSupport) { | 1290 if (#hasIsolateSupport) { |
1294 #constructorName.$fieldNamesProperty = #fieldNamesArray; | 1291 #constructorName.$fieldNamesProperty = #fieldNamesArray; |
1295 } | 1292 } |
1296 }''', | 1293 }''', |
1297 {"constructorName": constructorName, | 1294 {"constructorName": constructorName, |
1298 "constructorNameString": js.string(constructorName), | 1295 "constructorNameString": js.string(constructorName), |
1299 "hasIsolateSupport": hasIsolateSupport, | 1296 "hasIsolateSupport": hasIsolateSupport, |
1300 "fieldNamesArray": fieldNamesArray})); | 1297 "fieldNamesArray": fieldNamesArray})); |
1301 | 1298 |
1302 cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName)); | 1299 cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName)); |
1303 } | 1300 } |
1304 | 1301 |
1305 /// Extracts the output name of the compiler's outputUri. | 1302 /// Extracts the output name of the compiler's outputUri. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1367 String constructorName = mangledName; | 1364 String constructorName = mangledName; |
1368 jsAst.Expression constructorAst = js('function() {}'); | 1365 jsAst.Expression constructorAst = js('function() {}'); |
1369 List<String> fieldNames = []; | 1366 List<String> fieldNames = []; |
1370 emitPrecompiledConstructor(mainOutputUnit, | 1367 emitPrecompiledConstructor(mainOutputUnit, |
1371 constructorName, | 1368 constructorName, |
1372 constructorAst, | 1369 constructorAst, |
1373 fieldNames); | 1370 fieldNames); |
1374 } | 1371 } |
1375 } | 1372 } |
1376 | 1373 |
1377 void emitMangledNames() { | 1374 void emitMangledNames(CodeOutput mainBuffer) { |
1378 if (!mangledFieldNames.isEmpty) { | 1375 if (!mangledFieldNames.isEmpty) { |
1379 var keys = mangledFieldNames.keys.toList(); | 1376 var keys = mangledFieldNames.keys.toList(); |
1380 keys.sort(); | 1377 keys.sort(); |
1381 var properties = []; | 1378 var properties = []; |
1382 for (String key in keys) { | 1379 for (String key in keys) { |
1383 var value = js.string('${mangledFieldNames[key]}'); | 1380 var value = js.string('${mangledFieldNames[key]}'); |
1384 properties.add(new jsAst.Property(js.string(key), value)); | 1381 properties.add(new jsAst.Property(js.string(key), value)); |
1385 } | 1382 } |
1386 | 1383 |
1387 jsAst.Expression mangledNamesAccess = | 1384 jsAst.Expression mangledNamesAccess = |
1388 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); | 1385 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); |
1389 var map = new jsAst.ObjectInitializer(properties); | 1386 var map = new jsAst.ObjectInitializer(properties); |
1390 mainBuffer.write( | 1387 mainBuffer.addBuffer( |
1391 jsAst.prettyPrint( | 1388 jsAst.prettyPrint( |
1392 js.statement('# = #', [mangledNamesAccess, map]), | 1389 js.statement('# = #', [mangledNamesAccess, map]), |
1393 compiler, | 1390 compiler, |
1394 monitor: compiler.dumpInfoTask)); | 1391 monitor: compiler.dumpInfoTask)); |
1395 if (compiler.enableMinification) { | 1392 if (compiler.enableMinification) { |
1396 mainBuffer.write(';'); | 1393 mainBuffer.add(';'); |
1397 } | 1394 } |
1398 } | 1395 } |
1399 if (!mangledGlobalFieldNames.isEmpty) { | 1396 if (!mangledGlobalFieldNames.isEmpty) { |
1400 var keys = mangledGlobalFieldNames.keys.toList(); | 1397 var keys = mangledGlobalFieldNames.keys.toList(); |
1401 keys.sort(); | 1398 keys.sort(); |
1402 var properties = []; | 1399 var properties = []; |
1403 for (String key in keys) { | 1400 for (String key in keys) { |
1404 var value = js.string('${mangledGlobalFieldNames[key]}'); | 1401 var value = js.string('${mangledGlobalFieldNames[key]}'); |
1405 properties.add(new jsAst.Property(js.string(key), value)); | 1402 properties.add(new jsAst.Property(js.string(key), value)); |
1406 } | 1403 } |
1407 jsAst.Expression mangledGlobalNamesAccess = | 1404 jsAst.Expression mangledGlobalNamesAccess = |
1408 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); | 1405 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); |
1409 var map = new jsAst.ObjectInitializer(properties); | 1406 var map = new jsAst.ObjectInitializer(properties); |
1410 mainBuffer.write( | 1407 mainBuffer.addBuffer( |
1411 jsAst.prettyPrint( | 1408 jsAst.prettyPrint( |
1412 js.statement('# = #', [mangledGlobalNamesAccess, map]), | 1409 js.statement('# = #', [mangledGlobalNamesAccess, map]), |
1413 compiler, | 1410 compiler, |
1414 monitor: compiler.dumpInfoTask)); | 1411 monitor: compiler.dumpInfoTask)); |
1415 if (compiler.enableMinification) { | 1412 if (compiler.enableMinification) { |
1416 mainBuffer.write(';'); | 1413 mainBuffer.add(';'); |
1417 } | 1414 } |
1418 } | 1415 } |
1419 } | 1416 } |
1420 | 1417 |
1421 void checkEverythingEmitted(Iterable<Element> elements) { | 1418 void checkEverythingEmitted(Iterable<Element> elements) { |
1422 List<Element> pendingStatics; | 1419 List<Element> pendingStatics; |
1423 if (!compiler.hasIncrementalSupport) { | 1420 if (!compiler.hasIncrementalSupport) { |
1424 pendingStatics = | 1421 pendingStatics = |
1425 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); | 1422 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); |
1426 | 1423 |
1427 pendingStatics.forEach((element) => | 1424 pendingStatics.forEach((element) => |
1428 compiler.reportInfo( | 1425 compiler.reportInfo( |
1429 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); | 1426 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); |
1430 } | 1427 } |
1431 | 1428 |
1432 if (pendingStatics != null && !pendingStatics.isEmpty) { | 1429 if (pendingStatics != null && !pendingStatics.isEmpty) { |
1433 compiler.internalError(pendingStatics.first, | 1430 compiler.internalError(pendingStatics.first, |
1434 'Pending statics (see above).'); | 1431 'Pending statics (see above).'); |
1435 } | 1432 } |
1436 } | 1433 } |
1437 | 1434 |
1438 void emitMainOutputUnit(Map<OutputUnit, String> deferredLoadHashes, | 1435 void emitMainOutputUnit(Map<OutputUnit, String> deferredLoadHashes, |
1439 CodeBuffer nativeBuffer) { | 1436 CodeBuffer nativeBuffer) { |
| 1437 LineColumnCollector lineColumnCollector; |
| 1438 List<CodeOutputListener> codeOutputListeners; |
| 1439 if (generateSourceMap) { |
| 1440 lineColumnCollector = new LineColumnCollector(); |
| 1441 codeOutputListeners = <CodeOutputListener>[lineColumnCollector]; |
| 1442 } |
| 1443 |
| 1444 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 1445 CodeOutput mainOutput = |
| 1446 new StreamCodeOutput(compiler.outputProvider('', 'js'), |
| 1447 codeOutputListeners); |
| 1448 outputBuffers[mainOutputUnit] = mainOutput; |
| 1449 |
1440 bool isProgramSplit = compiler.deferredLoadTask.isProgramSplit; | 1450 bool isProgramSplit = compiler.deferredLoadTask.isProgramSplit; |
1441 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; | |
1442 | 1451 |
1443 mainBuffer.write(buildGeneratedBy()); | 1452 mainOutput.add(buildGeneratedBy()); |
1444 addComment(HOOKS_API_USAGE, mainBuffer); | 1453 addComment(HOOKS_API_USAGE, mainOutput); |
1445 | 1454 |
1446 if (isProgramSplit) { | 1455 if (isProgramSplit) { |
1447 /// For deferred loading we communicate the initializers via this global | 1456 /// For deferred loading we communicate the initializers via this global |
1448 /// variable. The deferred hunks will add their initialization to this. | 1457 /// variable. The deferred hunks will add their initialization to this. |
1449 /// The semicolon is important in minified mode, without it the | 1458 /// The semicolon is important in minified mode, without it the |
1450 /// following parenthesis looks like a call to the object literal. | 1459 /// following parenthesis looks like a call to the object literal. |
1451 mainBuffer..write( | 1460 mainOutput.add( |
1452 'self.${deferredInitializers} = self.${deferredInitializers} || ' | 1461 'self.${deferredInitializers} = self.${deferredInitializers} || ' |
1453 'Object.create(null);$n'); | 1462 'Object.create(null);$n'); |
1454 } | 1463 } |
1455 | 1464 |
1456 // Using a named function here produces easier to read stack traces in | 1465 // Using a named function here produces easier to read stack traces in |
1457 // Chrome/V8. | 1466 // Chrome/V8. |
1458 mainBuffer.write('(function(${namer.currentIsolate})$_{\n'); | 1467 mainOutput.add('(function(${namer.currentIsolate})$_{\n'); |
1459 if (compiler.hasIncrementalSupport) { | 1468 if (compiler.hasIncrementalSupport) { |
1460 mainBuffer.write(jsAst.prettyPrint(js.statement( | 1469 mainOutput.addBuffer(jsAst.prettyPrint(js.statement( |
1461 """ | 1470 """ |
1462 { | 1471 { |
1463 #helper = #helper || Object.create(null); | 1472 #helper = #helper || Object.create(null); |
1464 #helper.patch = function(a) { eval(a)}; | 1473 #helper.patch = function(a) { eval(a)}; |
1465 #helper.schemaChange = #schemaChange; | 1474 #helper.schemaChange = #schemaChange; |
1466 #helper.addMethod = #addMethod; | 1475 #helper.addMethod = #addMethod; |
1467 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) { | 1476 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) { |
1468 var descriptor = Object.create(null); | 1477 var descriptor = Object.create(null); |
1469 this.addStubs(descriptor, array, name, isStatic, originalDescriptor, []); | 1478 this.addStubs(descriptor, array, name, isStatic, originalDescriptor, []); |
1470 return descriptor; | 1479 return descriptor; |
1471 }; | 1480 }; |
1472 }""", | 1481 }""", |
1473 { 'helper': js('this.#', [namer.incrementalHelperName]), | 1482 { 'helper': js('this.#', [namer.incrementalHelperName]), |
1474 'schemaChange': buildSchemaChangeFunction(), | 1483 'schemaChange': buildSchemaChangeFunction(), |
1475 'addMethod': buildIncrementalAddMethod() }), compiler)); | 1484 'addMethod': buildIncrementalAddMethod() }), compiler)); |
1476 } | 1485 } |
1477 if (isProgramSplit) { | 1486 if (isProgramSplit) { |
1478 /// We collect all the global state of the, so it can be passed to the | 1487 /// We collect all the global state of the, so it can be passed to the |
1479 /// initializer of deferred files. | 1488 /// initializer of deferred files. |
1480 mainBuffer.write('var ${globalsHolder}$_=${_}Object.create(null)$N'); | 1489 mainOutput.add('var ${globalsHolder}$_=${_}Object.create(null)$N'); |
1481 } | 1490 } |
1482 mainBuffer.write('function dart()$_{$n' | 1491 mainOutput.add('function dart()$_{$n' |
1483 '${_}${_}this.x$_=${_}0$N' | 1492 '${_}${_}this.x$_=${_}0$N' |
1484 '${_}${_}delete this.x$N' | 1493 '${_}${_}delete this.x$N' |
1485 '}$n'); | 1494 '}$n'); |
1486 for (String globalObject in Namer.reservedGlobalObjectNames) { | 1495 for (String globalObject in Namer.reservedGlobalObjectNames) { |
1487 // The global objects start as so-called "slow objects". For V8, this | 1496 // The global objects start as so-called "slow objects". For V8, this |
1488 // means that it won't try to make map transitions as we add properties | 1497 // means that it won't try to make map transitions as we add properties |
1489 // to these objects. Later on, we attempt to turn these objects into | 1498 // to these objects. Later on, we attempt to turn these objects into |
1490 // fast objects by calling "convertToFastObject" (see | 1499 // fast objects by calling "convertToFastObject" (see |
1491 // [emitConvertToFastObjectFunction]). | 1500 // [emitConvertToFastObjectFunction]). |
1492 mainBuffer.write('var ${globalObject}$_=${_}'); | 1501 mainOutput.add('var ${globalObject}$_=${_}'); |
1493 if(isProgramSplit) { | 1502 if(isProgramSplit) { |
1494 mainBuffer.write('${globalsHolder}.$globalObject$_=${_}'); | 1503 mainOutput.add('${globalsHolder}.$globalObject$_=${_}'); |
1495 } | 1504 } |
1496 mainBuffer.write('new dart$N'); | 1505 mainOutput.add('new dart$N'); |
1497 } | 1506 } |
1498 | 1507 |
1499 mainBuffer.write('function ${namer.isolateName}()$_{}\n'); | 1508 mainOutput.add('function ${namer.isolateName}()$_{}\n'); |
1500 if (isProgramSplit) { | 1509 if (isProgramSplit) { |
1501 mainBuffer | 1510 mainOutput |
1502 .write('${globalsHolder}.${namer.isolateName}$_=$_' | 1511 .add('${globalsHolder}.${namer.isolateName}$_=$_' |
1503 '${namer.isolateName}$N' | 1512 '${namer.isolateName}$N' |
1504 '${globalsHolder}.$initName$_=${_}$initName$N'); | 1513 '${globalsHolder}.$initName$_=${_}$initName$N'); |
1505 } | 1514 } |
1506 mainBuffer.write('init()$N$n'); | 1515 mainOutput.add('init()$N$n'); |
1507 mainBuffer.write('$isolateProperties$_=$_$isolatePropertiesName$N'); | 1516 mainOutput.add('$isolateProperties$_=$_$isolatePropertiesName$N'); |
1508 | 1517 |
1509 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); | 1518 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); |
1510 | 1519 |
1511 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; | 1520 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; |
1512 if (classes != null) { | 1521 if (classes != null) { |
1513 for (ClassElement element in classes) { | 1522 for (ClassElement element in classes) { |
1514 generateClass(element, getElementDescriptor(element)); | 1523 generateClass(element, getElementDescriptor(element)); |
1515 } | 1524 } |
1516 } | 1525 } |
1517 | 1526 |
1518 if (compiler.enableMinification) { | 1527 if (compiler.enableMinification) { |
1519 mainBuffer.write(';'); | 1528 mainOutput.add(';'); |
1520 } | 1529 } |
1521 | 1530 |
1522 if (elementDescriptors.isNotEmpty) { | 1531 if (elementDescriptors.isNotEmpty) { |
1523 Iterable<LibraryElement> libraries = | 1532 Iterable<LibraryElement> libraries = |
1524 task.outputLibraryLists[mainOutputUnit]; | 1533 task.outputLibraryLists[mainOutputUnit]; |
1525 if (libraries == null) libraries = []; | 1534 if (libraries == null) libraries = []; |
1526 emitLibraries(libraries); | 1535 emitLibraries(libraries); |
1527 emitTypedefs(); | 1536 emitTypedefs(); |
1528 emitMangledNames(); | 1537 emitMangledNames(mainOutput); |
1529 | 1538 |
1530 checkEverythingEmitted(elementDescriptors.keys); | 1539 checkEverythingEmitted(elementDescriptors.keys); |
1531 | 1540 |
1532 CodeBuffer libraryBuffer = new CodeBuffer(); | 1541 mainOutput |
1533 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1542 ..add('(') |
1534 writeLibraryDescriptors(libraryBuffer, library); | 1543 ..addBuffer( |
1535 elementDescriptors.remove(library); | |
1536 } | |
1537 | |
1538 mainBuffer | |
1539 ..write('(') | |
1540 ..write( | |
1541 jsAst.prettyPrint( | 1544 jsAst.prettyPrint( |
1542 getReflectionDataParser(this, backend), | 1545 getReflectionDataParser(this, backend), |
1543 compiler)) | 1546 compiler)) |
1544 ..write(')') | 1547 ..add(')') |
1545 ..write('([$n') | 1548 ..add('([$n'); |
1546 ..write(libraryBuffer) | 1549 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
1547 ..write('])$N'); | 1550 writeLibraryDescriptors(mainOutput, library); |
| 1551 elementDescriptors.remove(library); |
| 1552 } |
| 1553 mainOutput.add('])$N'); |
1548 } | 1554 } |
1549 | 1555 |
1550 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); | 1556 interceptorEmitter.emitGetInterceptorMethods(mainOutput); |
1551 interceptorEmitter.emitOneShotInterceptors(mainBuffer); | 1557 interceptorEmitter.emitOneShotInterceptors(mainOutput); |
1552 | 1558 |
1553 if (task.outputContainsConstantList) { | 1559 if (task.outputContainsConstantList) { |
1554 emitMakeConstantList(mainBuffer); | 1560 emitMakeConstantList(mainOutput); |
1555 } | 1561 } |
1556 | 1562 |
1557 // Constants in checked mode call into RTI code to set type information | 1563 // Constants in checked mode call into RTI code to set type information |
1558 // which may need getInterceptor (and one-shot interceptor) methods, so | 1564 // which may need getInterceptor (and one-shot interceptor) methods, so |
1559 // we have to make sure that [emitGetInterceptorMethods] and | 1565 // we have to make sure that [emitGetInterceptorMethods] and |
1560 // [emitOneShotInterceptors] have been called. | 1566 // [emitOneShotInterceptors] have been called. |
1561 emitCompileTimeConstants(mainBuffer, mainOutputUnit); | 1567 emitCompileTimeConstants(mainOutput, mainOutputUnit); |
1562 | 1568 |
1563 emitDeferredBoilerPlate(mainBuffer, deferredLoadHashes); | 1569 emitDeferredBoilerPlate(mainOutput, deferredLoadHashes); |
1564 | 1570 |
1565 // Static field initializations require the classes and compile-time | 1571 // Static field initializations require the classes and compile-time |
1566 // constants to be set up. | 1572 // constants to be set up. |
1567 emitStaticNonFinalFieldInitializations(mainBuffer, mainOutputUnit); | 1573 emitStaticNonFinalFieldInitializations(mainOutput, mainOutputUnit); |
1568 interceptorEmitter.emitInterceptedNames(mainBuffer); | 1574 interceptorEmitter.emitInterceptedNames(mainOutput); |
1569 interceptorEmitter.emitMapTypeToInterceptor(mainBuffer); | 1575 interceptorEmitter.emitMapTypeToInterceptor(mainOutput); |
1570 emitLazilyInitializedStaticFields(mainBuffer); | 1576 emitLazilyInitializedStaticFields(mainOutput); |
1571 | 1577 |
1572 mainBuffer.writeln(); | 1578 mainOutput.add('\n'); |
1573 mainBuffer.write(nativeBuffer); | 1579 mainOutput.addBuffer(nativeBuffer); |
1574 | 1580 |
1575 metadataEmitter.emitMetadata(mainBuffer); | 1581 metadataEmitter.emitMetadata(mainOutput); |
1576 | 1582 |
1577 isolateProperties = isolatePropertiesName; | 1583 isolateProperties = isolatePropertiesName; |
1578 // The following code should not use the short-hand for the | 1584 // The following code should not use the short-hand for the |
1579 // initialStatics. | 1585 // initialStatics. |
1580 mainBuffer.write('${namer.currentIsolate}$_=${_}null$N'); | 1586 mainOutput.add('${namer.currentIsolate}$_=${_}null$N'); |
1581 | 1587 |
1582 emitFinishIsolateConstructorInvocation(mainBuffer); | 1588 emitFinishIsolateConstructorInvocation(mainOutput); |
1583 mainBuffer.write( | 1589 mainOutput.add( |
1584 '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N'); | 1590 '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N'); |
1585 | 1591 |
1586 emitConvertToFastObjectFunction(); | 1592 emitConvertToFastObjectFunction(mainOutput); |
1587 for (String globalObject in Namer.reservedGlobalObjectNames) { | 1593 for (String globalObject in Namer.reservedGlobalObjectNames) { |
1588 mainBuffer.write('$globalObject = convertToFastObject($globalObject)$N'); | 1594 mainOutput.add('$globalObject = convertToFastObject($globalObject)$N'); |
1589 } | 1595 } |
1590 if (DEBUG_FAST_OBJECTS) { | 1596 if (DEBUG_FAST_OBJECTS) { |
1591 mainBuffer.write(r''' | 1597 mainOutput.add(r''' |
1592 // The following only works on V8 when run with option | 1598 // The following only works on V8 when run with option |
1593 // "--allow-natives-syntax". We use'new Function' because the | 1599 // "--allow-natives-syntax". We use'new Function' because the |
1594 // miniparser does not understand V8 native syntax. | 1600 // miniparser does not understand V8 native syntax. |
1595 if (typeof print === "function") { | 1601 if (typeof print === "function") { |
1596 var HasFastProperties = | 1602 var HasFastProperties = |
1597 new Function("a", "return %HasFastProperties(a)"); | 1603 new Function("a", "return %HasFastProperties(a)"); |
1598 print("Size of global helper object: " | 1604 print("Size of global helper object: " |
1599 + String(Object.getOwnPropertyNames(H).length) | 1605 + String(Object.getOwnPropertyNames(H).length) |
1600 + ", fast properties " + HasFastProperties(H)); | 1606 + ", fast properties " + HasFastProperties(H)); |
1601 print("Size of global platform object: " | 1607 print("Size of global platform object: " |
1602 + String(Object.getOwnPropertyNames(P).length) | 1608 + String(Object.getOwnPropertyNames(P).length) |
1603 + ", fast properties " + HasFastProperties(P)); | 1609 + ", fast properties " + HasFastProperties(P)); |
1604 print("Size of global dart:html object: " | 1610 print("Size of global dart:html object: " |
1605 + String(Object.getOwnPropertyNames(W).length) | 1611 + String(Object.getOwnPropertyNames(W).length) |
1606 + ", fast properties " + HasFastProperties(W)); | 1612 + ", fast properties " + HasFastProperties(W)); |
1607 print("Size of isolate properties object: " | 1613 print("Size of isolate properties object: " |
1608 + String(Object.getOwnPropertyNames($).length) | 1614 + String(Object.getOwnPropertyNames($).length) |
1609 + ", fast properties " + HasFastProperties($)); | 1615 + ", fast properties " + HasFastProperties($)); |
1610 print("Size of constant object: " | 1616 print("Size of constant object: " |
1611 + String(Object.getOwnPropertyNames(C).length) | 1617 + String(Object.getOwnPropertyNames(C).length) |
1612 + ", fast properties " + HasFastProperties(C)); | 1618 + ", fast properties " + HasFastProperties(C)); |
1613 var names = Object.getOwnPropertyNames($); | 1619 var names = Object.getOwnPropertyNames($); |
1614 for (var i = 0; i < names.length; i++) { | 1620 for (var i = 0; i < names.length; i++) { |
1615 print("$." + names[i]); | 1621 print("$." + names[i]); |
1616 } | 1622 } |
1617 } | 1623 } |
1618 '''); | 1624 '''); |
1619 for (String object in Namer.userGlobalObjects) { | 1625 for (String object in Namer.userGlobalObjects) { |
1620 mainBuffer.write(''' | 1626 mainOutput.add(''' |
1621 if (typeof print === "function") { | 1627 if (typeof print === "function") { |
1622 print("Size of $object: " | 1628 print("Size of $object: " |
1623 + String(Object.getOwnPropertyNames($object).length) | 1629 + String(Object.getOwnPropertyNames($object).length) |
1624 + ", fast properties " + HasFastProperties($object)); | 1630 + ", fast properties " + HasFastProperties($object)); |
1625 } | 1631 } |
1626 '''); | 1632 '''); |
1627 } | 1633 } |
1628 } | 1634 } |
1629 | 1635 |
1630 jsAst.FunctionDeclaration precompiledFunctionAst = | 1636 jsAst.FunctionDeclaration precompiledFunctionAst = |
1631 buildCspPrecompiledFunctionFor(mainOutputUnit); | 1637 buildCspPrecompiledFunctionFor(mainOutputUnit); |
1632 emitInitFunction(mainBuffer); | 1638 emitInitFunction(mainOutput); |
1633 emitMain(mainBuffer); | 1639 emitMain(mainOutput); |
1634 mainBuffer.write('})()\n'); | 1640 mainOutput.add('})()\n'); |
1635 | 1641 |
1636 if (compiler.useContentSecurityPolicy) { | 1642 if (compiler.useContentSecurityPolicy) { |
1637 mainBuffer.write( | 1643 mainOutput.addBuffer( |
1638 jsAst.prettyPrint( | 1644 jsAst.prettyPrint( |
1639 precompiledFunctionAst, | 1645 precompiledFunctionAst, |
1640 compiler, | 1646 compiler, |
1641 monitor: compiler.dumpInfoTask, | 1647 monitor: compiler.dumpInfoTask, |
1642 allowVariableMinification: false).getText()); | 1648 allowVariableMinification: false)); |
1643 } | 1649 } |
1644 | 1650 |
1645 String assembledCode = mainBuffer.getText(); | |
1646 if (generateSourceMap) { | 1651 if (generateSourceMap) { |
1647 outputSourceMap(assembledCode, mainBuffer, '', | 1652 mainOutput.add( |
1648 compiler.sourceMapUri, compiler.outputUri); | |
1649 mainBuffer.write( | |
1650 generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri)); | 1653 generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri)); |
1651 assembledCode = mainBuffer.getText(); | |
1652 } | 1654 } |
1653 | 1655 |
1654 compiler.outputProvider('', 'js') | 1656 mainOutput.close(); |
1655 ..add(assembledCode) | 1657 |
1656 ..close(); | 1658 if (generateSourceMap) { |
| 1659 outputSourceMap(mainOutput, lineColumnCollector, '', |
| 1660 compiler.sourceMapUri, compiler.outputUri); |
| 1661 } |
1657 } | 1662 } |
1658 | 1663 |
1659 /// Used by incremental compilation to patch up the prototype of | 1664 /// Used by incremental compilation to patch up the prototype of |
1660 /// [oldConstructor] for use as prototype of [newConstructor]. | 1665 /// [oldConstructor] for use as prototype of [newConstructor]. |
1661 jsAst.Fun buildSchemaChangeFunction() { | 1666 jsAst.Fun buildSchemaChangeFunction() { |
1662 return js(''' | 1667 return js(''' |
1663 function(newConstructor, oldConstructor, superclass) { | 1668 function(newConstructor, oldConstructor, superclass) { |
1664 // Invariant: newConstructor.prototype has no interesting properties besides | 1669 // Invariant: newConstructor.prototype has no interesting properties besides |
1665 // generated accessors. These are copied to oldPrototype which will be | 1670 // generated accessors. These are copied to oldPrototype which will be |
1666 // updated by other incremental changes. | 1671 // updated by other incremental changes. |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1795 generateClass(element, getElementDescriptor(element)); | 1800 generateClass(element, getElementDescriptor(element)); |
1796 } | 1801 } |
1797 } | 1802 } |
1798 | 1803 |
1799 if (elementDescriptors.isNotEmpty) { | 1804 if (elementDescriptors.isNotEmpty) { |
1800 Iterable<LibraryElement> libraries = | 1805 Iterable<LibraryElement> libraries = |
1801 task.outputLibraryLists[outputUnit]; | 1806 task.outputLibraryLists[outputUnit]; |
1802 if (libraries == null) libraries = []; | 1807 if (libraries == null) libraries = []; |
1803 emitLibraries(libraries); | 1808 emitLibraries(libraries); |
1804 | 1809 |
| 1810 // TODO(johnniwinther): Avoid creating [CodeBuffer]s. |
1805 CodeBuffer buffer = new CodeBuffer(); | 1811 CodeBuffer buffer = new CodeBuffer(); |
1806 outputBuffers[outputUnit] = buffer; | 1812 outputBuffers[outputUnit] = buffer; |
1807 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1813 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
1808 writeLibraryDescriptors(buffer, library); | 1814 writeLibraryDescriptors(buffer, library); |
1809 elementDescriptors.remove(library); | 1815 elementDescriptors.remove(library); |
1810 } | 1816 } |
1811 } | 1817 } |
1812 } | 1818 } |
1813 | 1819 |
1814 return emitDeferredCode(outputBuffers); | 1820 return emitDeferredCode(outputBuffers); |
1815 } | 1821 } |
1816 | 1822 |
1817 CodeBuffer buildNativesBuffer() { | 1823 CodeBuffer buildNativesBuffer() { |
1818 // Emit native classes on [nativeBuffer]. | 1824 // Emit native classes on [nativeBuffer]. |
| 1825 // TODO(johnniwinther): Avoid creating a [CodeBuffer]. |
1819 final CodeBuffer nativeBuffer = new CodeBuffer(); | 1826 final CodeBuffer nativeBuffer = new CodeBuffer(); |
1820 | 1827 |
1821 if (nativeClasses.isEmpty) return nativeBuffer; | 1828 if (nativeClasses.isEmpty) return nativeBuffer; |
1822 | 1829 |
1823 | 1830 |
1824 addComment('Native classes', nativeBuffer); | 1831 addComment('Native classes', nativeBuffer); |
1825 | 1832 |
1826 nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer, | 1833 nativeEmitter.generateNativeClasses(nativeClasses, additionalProperties); |
1827 additionalProperties); | |
1828 | 1834 |
1829 nativeEmitter.finishGenerateNativeClasses(); | 1835 nativeEmitter.finishGenerateNativeClasses(); |
1830 nativeEmitter.assembleCode(nativeBuffer); | 1836 nativeEmitter.assembleCode(nativeBuffer); |
1831 | 1837 |
1832 return nativeBuffer; | 1838 return nativeBuffer; |
1833 } | 1839 } |
1834 | 1840 |
1835 int emitProgram(Program program) { | 1841 int emitProgram(Program program) { |
1836 // Shorten the code by using [namer.currentIsolate] as temporary. | 1842 // Shorten the code by using [namer.currentIsolate] as temporary. |
1837 isolateProperties = namer.currentIsolate; | 1843 isolateProperties = namer.currentIsolate; |
1838 | 1844 |
1839 // Emit deferred units first, so we have their hashes. | 1845 // Emit deferred units first, so we have their hashes. |
1840 // Map from OutputUnit to a hash of its content. The hash uniquely | 1846 // Map from OutputUnit to a hash of its content. The hash uniquely |
1841 // identifies the code of the output-unit. It does not include | 1847 // identifies the code of the output-unit. It does not include |
1842 // boilerplate JS code, like the sourcemap directives or the hash | 1848 // boilerplate JS code, like the sourcemap directives or the hash |
1843 // itself. | 1849 // itself. |
1844 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); | 1850 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); |
1845 CodeBuffer nativeBuffer = buildNativesBuffer(); | 1851 CodeBuffer nativeBuffer = buildNativesBuffer(); |
1846 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); | 1852 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); |
1847 | 1853 |
1848 if (backend.requiresPreamble && | 1854 if (backend.requiresPreamble && |
1849 !backend.htmlLibraryIsLoaded) { | 1855 !backend.htmlLibraryIsLoaded) { |
1850 compiler.reportHint(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); | 1856 compiler.reportHint(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); |
1851 } | 1857 } |
1852 | |
1853 // Return the total program size. | 1858 // Return the total program size. |
1854 return outputBuffers.values.fold(0, (a, b) => a + b.length); | 1859 return outputBuffers.values.fold(0, (a, b) => a + b.length); |
1855 } | 1860 } |
1856 | 1861 |
1857 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { | 1862 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { |
1858 if (sourceMapUri != null && fileUri != null) { | 1863 if (sourceMapUri != null && fileUri != null) { |
1859 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); | 1864 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); |
1860 return ''' | 1865 return ''' |
1861 | 1866 |
1862 //# sourceMappingURL=$sourceMapFileName | 1867 //# sourceMappingURL=$sourceMapFileName |
(...skipping 18 matching lines...) Expand all Loading... |
1881 } | 1886 } |
1882 } | 1887 } |
1883 if (owner == null) { | 1888 if (owner == null) { |
1884 compiler.internalError(element, 'Owner is null.'); | 1889 compiler.internalError(element, 'Owner is null.'); |
1885 } | 1890 } |
1886 return elementDescriptors.putIfAbsent( | 1891 return elementDescriptors.putIfAbsent( |
1887 owner, | 1892 owner, |
1888 () => new ClassBuilder(owner, namer)); | 1893 () => new ClassBuilder(owner, namer)); |
1889 } | 1894 } |
1890 | 1895 |
1891 /// Emits support-code for deferred loading into [buffer]. | 1896 /// Emits support-code for deferred loading into [output]. |
1892 void emitDeferredBoilerPlate(CodeBuffer buffer, | 1897 void emitDeferredBoilerPlate(CodeOutput output, |
1893 Map<OutputUnit, String> deferredLoadHashes) { | 1898 Map<OutputUnit, String> deferredLoadHashes) { |
1894 // Function for checking if a hunk is loaded given its hash. | 1899 // Function for checking if a hunk is loaded given its hash. |
1895 buffer.write(jsAst.prettyPrint( | 1900 output.addBuffer(jsAst.prettyPrint( |
1896 js('# = function(hunkHash) {' | 1901 js('# = function(hunkHash) {' |
1897 ' return !!$deferredInitializers[hunkHash];' | 1902 ' return !!$deferredInitializers[hunkHash];' |
1898 '}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)), | 1903 '}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)), |
1899 compiler, monitor: compiler.dumpInfoTask)); | 1904 compiler, monitor: compiler.dumpInfoTask)); |
1900 buffer.write('$N'); | 1905 output.add('$N'); |
1901 // Function for initializing a loaded hunk, given its hash. | 1906 // Function for initializing a loaded hunk, given its hash. |
1902 buffer.write(jsAst.prettyPrint( | 1907 output.addBuffer(jsAst.prettyPrint( |
1903 js('# = function(hunkHash) {' | 1908 js('# = function(hunkHash) {' |
1904 ' $deferredInitializers[hunkHash](' | 1909 ' $deferredInitializers[hunkHash](' |
1905 '$globalsHolder, ${namer.currentIsolate})' | 1910 '$globalsHolder, ${namer.currentIsolate})' |
1906 '}', | 1911 '}', |
1907 generateEmbeddedGlobalAccess( | 1912 generateEmbeddedGlobalAccess( |
1908 embeddedNames.INITIALIZE_LOADED_HUNK)), | 1913 embeddedNames.INITIALIZE_LOADED_HUNK)), |
1909 compiler, monitor: compiler.dumpInfoTask)); | 1914 compiler, monitor: compiler.dumpInfoTask)); |
1910 buffer.write('$N'); | 1915 output.add('$N'); |
1911 // Write a javascript mapping from Deferred import load ids (derrived | 1916 // Write a javascript mapping from Deferred import load ids (derrived |
1912 // from the import prefix.) to a list of lists of uris of hunks to load, | 1917 // from the import prefix.) to a list of lists of uris of hunks to load, |
1913 // and a corresponding mapping to a list of hashes used by | 1918 // and a corresponding mapping to a list of hashes used by |
1914 // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED. | 1919 // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED. |
1915 Map<String, List<String>> deferredLibraryUris = | 1920 Map<String, List<String>> deferredLibraryUris = |
1916 new Map<String, List<String>>(); | 1921 new Map<String, List<String>>(); |
1917 Map<String, List<String>> deferredLibraryHashes = | 1922 Map<String, List<String>> deferredLibraryHashes = |
1918 new Map<String, List<String>>(); | 1923 new Map<String, List<String>>(); |
1919 compiler.deferredLoadTask.hunksToLoad.forEach( | 1924 compiler.deferredLoadTask.hunksToLoad.forEach( |
1920 (String loadId, List<OutputUnit>outputUnits) { | 1925 (String loadId, List<OutputUnit>outputUnits) { |
(...skipping 13 matching lines...) Expand all Loading... |
1934 List<jsAst.Property> properties = new List<jsAst.Property>(); | 1939 List<jsAst.Property> properties = new List<jsAst.Property>(); |
1935 mapping.forEach((String key, List<String> values) { | 1940 mapping.forEach((String key, List<String> values) { |
1936 properties.add(new jsAst.Property(js.escapedString(key), | 1941 properties.add(new jsAst.Property(js.escapedString(key), |
1937 new jsAst.ArrayInitializer( | 1942 new jsAst.ArrayInitializer( |
1938 values.map(js.escapedString).toList()))); | 1943 values.map(js.escapedString).toList()))); |
1939 }); | 1944 }); |
1940 jsAst.Node initializer = | 1945 jsAst.Node initializer = |
1941 new jsAst.ObjectInitializer(properties, isOneLiner: true); | 1946 new jsAst.ObjectInitializer(properties, isOneLiner: true); |
1942 | 1947 |
1943 jsAst.Node globalName = generateEmbeddedGlobalAccess(name); | 1948 jsAst.Node globalName = generateEmbeddedGlobalAccess(name); |
1944 buffer.write(jsAst.prettyPrint( | 1949 output.addBuffer(jsAst.prettyPrint( |
1945 js("# = #", [globalName, initializer]), | 1950 js("# = #", [globalName, initializer]), |
1946 compiler, monitor: compiler.dumpInfoTask)); | 1951 compiler, monitor: compiler.dumpInfoTask)); |
1947 buffer.write('$N'); | 1952 output.add('$N'); |
1948 | |
1949 } | 1953 } |
1950 | 1954 |
1951 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); | 1955 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); |
1952 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, | 1956 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, |
1953 deferredLibraryHashes); | 1957 deferredLibraryHashes); |
1954 } | 1958 } |
1955 | 1959 |
1956 /// Emits code for all output units except the main. | 1960 /// Emits code for all output units except the main. |
1957 /// Returns a mapping from outputUnit to a hash of the corresponding hunk that | 1961 /// Returns a mapping from outputUnit to a hash of the corresponding hunk that |
1958 /// can be used for calling the initializer. | 1962 /// can be used for calling the initializer. |
1959 Map<OutputUnit, String> emitDeferredCode( | 1963 Map<OutputUnit, String> emitDeferredCode( |
1960 Map<OutputUnit, CodeBuffer> deferredBuffers) { | 1964 Map<OutputUnit, CodeBuffer> deferredBuffers) { |
1961 | 1965 |
1962 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); | 1966 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); |
1963 | 1967 |
1964 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { | 1968 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { |
1965 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue; | 1969 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue; |
1966 | 1970 |
1967 CodeBuffer libraryDescriptorBuffer = deferredBuffers[outputUnit]; | 1971 CodeOutput libraryDescriptorBuffer = deferredBuffers[outputUnit]; |
1968 | 1972 |
1969 CodeBuffer outputBuffer = new CodeBuffer(); | 1973 List<CodeOutputListener> outputListeners = <CodeOutputListener>[]; |
| 1974 Hasher hasher = new Hasher(); |
| 1975 outputListeners.add(hasher); |
1970 | 1976 |
1971 outputBuffer..write(buildGeneratedBy()) | 1977 LineColumnCollector lineColumnCollector; |
1972 ..write('${deferredInitializers}.current$_=$_' | 1978 if (generateSourceMap) { |
1973 'function$_(${globalsHolder}) {$N'); | 1979 lineColumnCollector = new LineColumnCollector(); |
| 1980 outputListeners.add(lineColumnCollector); |
| 1981 } |
| 1982 |
| 1983 String partPrefix = deferredPartFileName(outputUnit, addExtension: false); |
| 1984 CodeOutput output = new StreamCodeOutput( |
| 1985 compiler.outputProvider(partPrefix, 'part.js'), |
| 1986 outputListeners); |
| 1987 |
| 1988 outputBuffers[outputUnit] = output; |
| 1989 |
| 1990 output |
| 1991 ..add(buildGeneratedBy()) |
| 1992 ..add('${deferredInitializers}.current$_=$_' |
| 1993 'function$_(${globalsHolder}) {$N'); |
1974 for (String globalObject in Namer.reservedGlobalObjectNames) { | 1994 for (String globalObject in Namer.reservedGlobalObjectNames) { |
1975 outputBuffer | 1995 output |
1976 .write('var $globalObject$_=$_' | 1996 .add('var $globalObject$_=$_' |
1977 '${globalsHolder}.$globalObject$N'); | 1997 '${globalsHolder}.$globalObject$N'); |
1978 } | 1998 } |
1979 outputBuffer | 1999 output |
1980 ..write('var init$_=$_${globalsHolder}.init$N') | 2000 ..add('var init$_=$_${globalsHolder}.init$N') |
1981 ..write('var ${namer.isolateName}$_=$_' | 2001 ..add('var ${namer.isolateName}$_=$_' |
1982 '${globalsHolder}.${namer.isolateName}$N'); | 2002 '${globalsHolder}.${namer.isolateName}$N'); |
1983 if (libraryDescriptorBuffer != null) { | 2003 if (libraryDescriptorBuffer != null) { |
1984 // TODO(ahe): This defines a lot of properties on the | 2004 // TODO(ahe): This defines a lot of properties on the |
1985 // Isolate.prototype object. We know this will turn it into a | 2005 // Isolate.prototype object. We know this will turn it into a |
1986 // slow object in V8, so instead we should do something similar | 2006 // slow object in V8, so instead we should do something similar |
1987 // to Isolate.$finishIsolateConstructor. | 2007 // to Isolate.$finishIsolateConstructor. |
1988 outputBuffer | 2008 output |
1989 ..write('var ${namer.currentIsolate}$_=$_$isolatePropertiesName;$n') | 2009 ..add('var ${namer.currentIsolate}$_=$_$isolatePropertiesName;$n') |
1990 ..write('(') | 2010 ..add('(') |
1991 ..write( | 2011 ..addBuffer( |
1992 jsAst.prettyPrint( | 2012 jsAst.prettyPrint( |
1993 getReflectionDataParser(this, backend), | 2013 getReflectionDataParser(this, backend), |
1994 compiler, monitor: compiler.dumpInfoTask)) | 2014 compiler, monitor: compiler.dumpInfoTask)) |
1995 ..write(')') | 2015 ..add(')') |
1996 ..write('([$n') | 2016 ..add('([$n') |
1997 ..addBuffer(libraryDescriptorBuffer) | 2017 ..addBuffer(libraryDescriptorBuffer) |
1998 ..write('])$N'); | 2018 ..add('])$N'); |
1999 | |
2000 } | 2019 } |
2001 | 2020 |
2002 // Set the currentIsolate variable to the current isolate (which is | 2021 // Set the currentIsolate variable to the current isolate (which is |
2003 // provided as second argument). | 2022 // provided as second argument). |
2004 // We need to do this, because we use the same variable for setting up | 2023 // We need to do this, because we use the same variable for setting up |
2005 // the isolate-properties and for storing the current isolate. During | 2024 // the isolate-properties and for storing the current isolate. During |
2006 // the setup (the code above this lines) we must set the variable to | 2025 // the setup (the code above this lines) we must set the variable to |
2007 // the isolate-properties. | 2026 // the isolate-properties. |
2008 // After we have done the setup it must point to the current Isolate. | 2027 // After we have done the setup it must point to the current Isolate. |
2009 // Otherwise all methods/functions accessing isolate variables will | 2028 // Otherwise all methods/functions accessing isolate variables will |
2010 // access the wrong object. | 2029 // access the wrong object. |
2011 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); | 2030 output.add("${namer.currentIsolate}$_=${_}arguments[1]$N"); |
2012 | 2031 |
2013 emitCompileTimeConstants(outputBuffer, outputUnit); | 2032 emitCompileTimeConstants(output, outputUnit); |
2014 emitStaticNonFinalFieldInitializations(outputBuffer, outputUnit); | 2033 emitStaticNonFinalFieldInitializations(output, outputUnit); |
2015 outputBuffer.write('}$N'); | 2034 output.add('}$N'); |
2016 | 2035 |
2017 if (compiler.useContentSecurityPolicy) { | 2036 if (compiler.useContentSecurityPolicy) { |
2018 jsAst.FunctionDeclaration precompiledFunctionAst = | 2037 jsAst.FunctionDeclaration precompiledFunctionAst = |
2019 buildCspPrecompiledFunctionFor(outputUnit); | 2038 buildCspPrecompiledFunctionFor(outputUnit); |
2020 | 2039 |
2021 outputBuffer.write( | 2040 output.addBuffer( |
2022 jsAst.prettyPrint( | 2041 jsAst.prettyPrint( |
2023 precompiledFunctionAst, compiler, | 2042 precompiledFunctionAst, compiler, |
2024 monitor: compiler.dumpInfoTask, | 2043 monitor: compiler.dumpInfoTask, |
2025 allowVariableMinification: false).getText()); | 2044 allowVariableMinification: false)); |
2026 } | 2045 } |
2027 | 2046 |
2028 // Make a unique hash of the code (before the sourcemaps are added) | 2047 // Make a unique hash of the code (before the sourcemaps are added) |
2029 // This will be used to retrieve the initializing function from the global | 2048 // This will be used to retrieve the initializing function from the global |
2030 // variable. | 2049 // variable. |
2031 String hash = hashOfString(outputBuffer.getText()); | 2050 String hash = hasher.getHash(); |
2032 | 2051 |
2033 outputBuffer.write('${deferredInitializers}["$hash"]$_=$_' | 2052 output.add('${deferredInitializers}["$hash"]$_=$_' |
2034 '${deferredInitializers}.current$N'); | 2053 '${deferredInitializers}.current$N'); |
2035 | 2054 |
2036 String partPrefix = deferredPartFileName(outputUnit, addExtension: false); | |
2037 if (generateSourceMap) { | 2055 if (generateSourceMap) { |
| 2056 |
2038 Uri mapUri, partUri; | 2057 Uri mapUri, partUri; |
2039 Uri sourceMapUri = compiler.sourceMapUri; | 2058 Uri sourceMapUri = compiler.sourceMapUri; |
2040 Uri outputUri = compiler.outputUri; | 2059 Uri outputUri = compiler.outputUri; |
2041 | 2060 |
2042 String partName = "$partPrefix.part"; | 2061 String partName = "$partPrefix.part"; |
2043 | 2062 |
2044 if (sourceMapUri != null) { | 2063 if (sourceMapUri != null) { |
2045 String mapFileName = partName + ".js.map"; | 2064 String mapFileName = partName + ".js.map"; |
2046 List<String> mapSegments = sourceMapUri.pathSegments.toList(); | 2065 List<String> mapSegments = sourceMapUri.pathSegments.toList(); |
2047 mapSegments[mapSegments.length - 1] = mapFileName; | 2066 mapSegments[mapSegments.length - 1] = mapFileName; |
2048 mapUri = compiler.sourceMapUri.replace(pathSegments: mapSegments); | 2067 mapUri = compiler.sourceMapUri.replace(pathSegments: mapSegments); |
2049 } | 2068 } |
2050 | 2069 |
2051 if (outputUri != null) { | 2070 if (outputUri != null) { |
2052 String partFileName = partName + ".js"; | 2071 String partFileName = partName + ".js"; |
2053 List<String> partSegments = outputUri.pathSegments.toList(); | 2072 List<String> partSegments = outputUri.pathSegments.toList(); |
2054 partSegments[partSegments.length - 1] = partFileName; | 2073 partSegments[partSegments.length - 1] = partFileName; |
2055 partUri = compiler.outputUri.replace(pathSegments: partSegments); | 2074 partUri = compiler.outputUri.replace(pathSegments: partSegments); |
2056 } | 2075 } |
2057 | 2076 |
2058 outputSourceMap(outputBuffer.getText(), outputBuffer, partName, | 2077 output.add(generateSourceMapTag(mapUri, partUri)); |
2059 mapUri, partUri); | 2078 output.close(); |
2060 outputBuffer.write(generateSourceMapTag(mapUri, partUri)); | 2079 outputSourceMap(output, lineColumnCollector, partName, |
| 2080 mapUri, partUri); |
| 2081 } else { |
| 2082 output.close(); |
2061 } | 2083 } |
2062 | 2084 |
2063 outputBuffers[outputUnit] = outputBuffer; | |
2064 compiler.outputProvider(partPrefix, 'part.js') | |
2065 ..add(outputBuffer.getText()) | |
2066 ..close(); | |
2067 | |
2068 hunkHashes[outputUnit] = hash; | 2085 hunkHashes[outputUnit] = hash; |
2069 } | 2086 } |
2070 return hunkHashes; | 2087 return hunkHashes; |
2071 } | 2088 } |
2072 | 2089 |
2073 String buildGeneratedBy() { | 2090 String buildGeneratedBy() { |
2074 var suffix = ''; | 2091 var suffix = ''; |
2075 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; | 2092 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; |
2076 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; | 2093 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; |
2077 } | 2094 } |
2078 | 2095 |
2079 void outputSourceMap(String code, CodeBuffer buffer, String name, | 2096 void outputSourceMap(CodeOutput output, |
2080 [Uri sourceMapUri, Uri fileUri]) { | 2097 LineColumnProvider lineColumnProvider, |
| 2098 String name, |
| 2099 [Uri sourceMapUri, |
| 2100 Uri fileUri]) { |
2081 if (!generateSourceMap) return; | 2101 if (!generateSourceMap) return; |
2082 // Create a source file for the compilation output. This allows using | 2102 // Create a source file for the compilation output. This allows using |
2083 // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder]. | 2103 // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder]. |
2084 SourceFile compiledFile = new StringSourceFile(null, code); | |
2085 SourceMapBuilder sourceMapBuilder = | 2104 SourceMapBuilder sourceMapBuilder = |
2086 new SourceMapBuilder(sourceMapUri, fileUri, compiledFile); | 2105 new SourceMapBuilder(sourceMapUri, fileUri, lineColumnProvider); |
2087 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); | 2106 output.forEachSourceLocation(sourceMapBuilder.addMapping); |
2088 String sourceMap = sourceMapBuilder.build(); | 2107 String sourceMap = sourceMapBuilder.build(); |
2089 compiler.outputProvider(name, 'js.map') | 2108 compiler.outputProvider(name, 'js.map') |
2090 ..add(sourceMap) | 2109 ..add(sourceMap) |
2091 ..close(); | 2110 ..close(); |
2092 } | 2111 } |
2093 | 2112 |
2094 void invalidateCaches() { | 2113 void invalidateCaches() { |
2095 if (!compiler.hasIncrementalSupport) return; | 2114 if (!compiler.hasIncrementalSupport) return; |
2096 if (cachedElements.isEmpty) return; | 2115 if (cachedElements.isEmpty) return; |
2097 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2116 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
2098 if (element.isInstanceMember) { | 2117 if (element.isInstanceMember) { |
2099 cachedClassBuilders.remove(element.enclosingClass); | 2118 cachedClassBuilders.remove(element.enclosingClass); |
2100 | 2119 |
2101 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2120 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
2102 | 2121 |
2103 } | 2122 } |
2104 } | 2123 } |
2105 } | 2124 } |
2106 } | 2125 } |
OLD | NEW |