| 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 |