| 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; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 new Map<Element, ClassBuilder>(); | 88 new Map<Element, ClassBuilder>(); |
| 89 | 89 |
| 90 final bool generateSourceMap; | 90 final bool generateSourceMap; |
| 91 | 91 |
| 92 OldEmitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task) | 92 OldEmitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task) |
| 93 : this.compiler = compiler, | 93 : this.compiler = compiler, |
| 94 this.namer = namer, | 94 this.namer = namer, |
| 95 cachedEmittedConstants = compiler.cacheStrategy.newSet(), | 95 cachedEmittedConstants = compiler.cacheStrategy.newSet(), |
| 96 cachedClassBuilders = compiler.cacheStrategy.newMap(), | 96 cachedClassBuilders = compiler.cacheStrategy.newMap(), |
| 97 cachedElements = compiler.cacheStrategy.newSet() { | 97 cachedElements = compiler.cacheStrategy.newSet() { |
| 98 constantEmitter = | 98 constantEmitter = new ConstantEmitter( |
| 99 new ConstantEmitter(compiler, namer, makeConstantListTemplate); | 99 compiler, namer, this.constantReference, makeConstantListTemplate); |
| 100 containerBuilder.emitter = this; | 100 containerBuilder.emitter = this; |
| 101 classEmitter.emitter = this; | 101 classEmitter.emitter = this; |
| 102 nsmEmitter.emitter = this; | 102 nsmEmitter.emitter = this; |
| 103 interceptorEmitter.emitter = this; | 103 interceptorEmitter.emitter = this; |
| 104 } | 104 } |
| 105 | 105 |
| 106 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { | 106 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { |
| 107 return _cspPrecompiledFunctions.putIfAbsent( | 107 return _cspPrecompiledFunctions.putIfAbsent( |
| 108 outputUnit, | 108 outputUnit, |
| 109 () => new List<jsAst.Node>()); | 109 () => new List<jsAst.Node>()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 121 void clearCspPrecompiledNodes() { | 121 void clearCspPrecompiledNodes() { |
| 122 _cspPrecompiledFunctions.clear(); | 122 _cspPrecompiledFunctions.clear(); |
| 123 _cspPrecompiledConstructorNames.clear(); | 123 _cspPrecompiledConstructorNames.clear(); |
| 124 } | 124 } |
| 125 | 125 |
| 126 void addComment(String comment, CodeOutput output) { | 126 void addComment(String comment, CodeOutput output) { |
| 127 output.addBuffer(jsAst.prettyPrint(js.comment(comment), compiler)); | 127 output.addBuffer(jsAst.prettyPrint(js.comment(comment), compiler)); |
| 128 } | 128 } |
| 129 | 129 |
| 130 @override | 130 @override |
| 131 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { |
| 132 if (constant.isFunction) return true; // Already emitted. |
| 133 if (constant.isPrimitive) return true; // Inlined. |
| 134 if (constant.isDummy) return true; // Inlined. |
| 135 // The name is null when the constant is already a JS constant. |
| 136 // TODO(floitsch): every constant should be registered, so that we can |
| 137 // share the ones that take up too much space (like some strings). |
| 138 if (namer.constantName(constant) == null) return true; |
| 139 return false; |
| 140 } |
| 141 |
| 142 @override |
| 143 int compareConstants(ConstantValue a, ConstantValue b) { |
| 144 // Inlined constants don't affect the order and sometimes don't even have |
| 145 // names. |
| 146 int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1; |
| 147 int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1; |
| 148 if (cmp1 + cmp2 < 2) return cmp1 - cmp2; |
| 149 |
| 150 // Emit constant interceptors first. Constant interceptors for primitives |
| 151 // might be used by code that builds other constants. See Issue 18173. |
| 152 if (a.isInterceptor != b.isInterceptor) { |
| 153 return a.isInterceptor ? -1 : 1; |
| 154 } |
| 155 |
| 156 // Sorting by the long name clusters constants with the same constructor |
| 157 // which compresses a tiny bit better. |
| 158 int r = namer.constantLongName(a).compareTo(namer.constantLongName(b)); |
| 159 if (r != 0) return r; |
| 160 // Resolve collisions in the long name by using the constant name (i.e. JS |
| 161 // name) which is unique. |
| 162 return namer.constantName(a).compareTo(namer.constantName(b)); |
| 163 } |
| 164 |
| 165 @override |
| 131 jsAst.Expression constantReference(ConstantValue value) { | 166 jsAst.Expression constantReference(ConstantValue value) { |
| 132 return constantEmitter.reference(value); | 167 if (value.isFunction) { |
| 168 FunctionConstantValue functionConstant = value; |
| 169 return isolateStaticClosureAccess(functionConstant.element); |
| 170 } |
| 171 |
| 172 // We are only interested in the "isInlined" part, but it does not hurt to |
| 173 // test for the other predicates. |
| 174 if (isConstantInlinedOrAlreadyEmitted(value)) { |
| 175 return constantEmitter.generate(value); |
| 176 } |
| 177 return js('#.#', [namer.globalObjectForConstant(value), |
| 178 namer.constantName(value)]); |
| 133 } | 179 } |
| 134 | 180 |
| 135 jsAst.Expression constantInitializerExpression(ConstantValue value) { | 181 jsAst.Expression constantInitializerExpression(ConstantValue value) { |
| 136 return constantEmitter.initializationExpression(value); | 182 return constantEmitter.generate(value); |
| 137 } | 183 } |
| 138 | 184 |
| 139 String get name => 'CodeEmitter'; | 185 String get name => 'CodeEmitter'; |
| 140 | 186 |
| 141 String get finishIsolateConstructorName | 187 String get finishIsolateConstructorName |
| 142 => '${namer.isolateName}.\$finishIsolateConstructor'; | 188 => '${namer.isolateName}.\$finishIsolateConstructor'; |
| 143 String get isolatePropertiesName | 189 String get isolatePropertiesName |
| 144 => '${namer.isolateName}.${namer.isolatePropertiesName}'; | 190 => '${namer.isolateName}.${namer.isolatePropertiesName}'; |
| 145 String get lazyInitializerProperty | 191 String get lazyInitializerProperty |
| 146 => r'$lazy'; | 192 => r'$lazy'; |
| (...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); | 781 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); |
| 736 JavaScriptConstantCompiler handler = backend.constants; | 782 JavaScriptConstantCompiler handler = backend.constants; |
| 737 | 783 |
| 738 Iterable<Element> fields = task.outputStaticNonFinalFieldLists[outputUnit]; | 784 Iterable<Element> fields = task.outputStaticNonFinalFieldLists[outputUnit]; |
| 739 // If the outputUnit does not contain any static non-final fields, then | 785 // If the outputUnit does not contain any static non-final fields, then |
| 740 // [fields] is `null`. | 786 // [fields] is `null`. |
| 741 if (fields != null) { | 787 if (fields != null) { |
| 742 for (Element element in fields) { | 788 for (Element element in fields) { |
| 743 compiler.withCurrentElement(element, () { | 789 compiler.withCurrentElement(element, () { |
| 744 ConstantValue constant = handler.getInitialValueFor(element).value; | 790 ConstantValue constant = handler.getInitialValueFor(element).value; |
| 745 emitInitialization( | 791 emitInitialization(element, constantReference(constant)); |
| 746 element, | |
| 747 constantEmitter.referenceInInitializationContext(constant)); | |
| 748 }); | 792 }); |
| 749 } | 793 } |
| 750 } | 794 } |
| 751 | 795 |
| 752 if (inMainUnit && task.outputStaticNonFinalFieldLists.length > 1) { | 796 if (inMainUnit && task.outputStaticNonFinalFieldLists.length > 1) { |
| 753 // In the main output-unit we output a stub initializer for deferred | 797 // In the main output-unit we output a stub initializer for deferred |
| 754 // variables, so that `isolateProperties` stays a fast object. | 798 // variables, so that `isolateProperties` stays a fast object. |
| 755 task.outputStaticNonFinalFieldLists.forEach( | 799 task.outputStaticNonFinalFieldLists.forEach( |
| 756 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { | 800 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { |
| 757 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. | 801 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 output.add(metadata); | 856 output.add(metadata); |
| 813 } | 857 } |
| 814 } else { | 858 } else { |
| 815 throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}'; | 859 throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}'; |
| 816 } | 860 } |
| 817 output.add(',$n'); | 861 output.add(',$n'); |
| 818 } | 862 } |
| 819 output.add('];$n'); | 863 output.add('];$n'); |
| 820 } | 864 } |
| 821 | 865 |
| 822 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { | |
| 823 if (constant.isFunction) return true; // Already emitted. | |
| 824 if (constant.isPrimitive) return true; // Inlined. | |
| 825 if (constant.isDummy) return true; // Inlined. | |
| 826 // The name is null when the constant is already a JS constant. | |
| 827 // TODO(floitsch): every constant should be registered, so that we can | |
| 828 // share the ones that take up too much space (like some strings). | |
| 829 if (namer.constantName(constant) == null) return true; | |
| 830 return false; | |
| 831 } | |
| 832 | |
| 833 int compareConstants(ConstantValue a, ConstantValue b) { | |
| 834 // Inlined constants don't affect the order and sometimes don't even have | |
| 835 // names. | |
| 836 int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1; | |
| 837 int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1; | |
| 838 if (cmp1 + cmp2 < 2) return cmp1 - cmp2; | |
| 839 | |
| 840 // Emit constant interceptors first. Constant interceptors for primitives | |
| 841 // might be used by code that builds other constants. See Issue 18173. | |
| 842 if (a.isInterceptor != b.isInterceptor) { | |
| 843 return a.isInterceptor ? -1 : 1; | |
| 844 } | |
| 845 | |
| 846 // Sorting by the long name clusters constants with the same constructor | |
| 847 // which compresses a tiny bit better. | |
| 848 int r = namer.constantLongName(a).compareTo(namer.constantLongName(b)); | |
| 849 if (r != 0) return r; | |
| 850 // Resolve collisions in the long name by using the constant name (i.e. JS | |
| 851 // name) which is unique. | |
| 852 return namer.constantName(a).compareTo(namer.constantName(b)); | |
| 853 } | |
| 854 | |
| 855 void emitCompileTimeConstants(CodeOutput output, | 866 void emitCompileTimeConstants(CodeOutput output, |
| 856 List<Constant> constants, | 867 List<Constant> constants, |
| 857 {bool isMainFragment}) { | 868 {bool isMainFragment}) { |
| 858 assert(isMainFragment != null); | 869 assert(isMainFragment != null); |
| 859 | 870 |
| 860 if (constants.isEmpty) return; | 871 if (constants.isEmpty) return; |
| 861 CodeOutput constantOutput = output; | 872 CodeOutput constantOutput = output; |
| 862 if (compiler.hasIncrementalSupport && isMainFragment) { | 873 if (compiler.hasIncrementalSupport && isMainFragment) { |
| 863 constantOutput = cachedEmittedConstantsBuffer; | 874 constantOutput = cachedEmittedConstantsBuffer; |
| 864 } | 875 } |
| (...skipping 1136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2001 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2012 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 2002 if (element.isInstanceMember) { | 2013 if (element.isInstanceMember) { |
| 2003 cachedClassBuilders.remove(element.enclosingClass); | 2014 cachedClassBuilders.remove(element.enclosingClass); |
| 2004 | 2015 |
| 2005 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2016 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 2006 | 2017 |
| 2007 } | 2018 } |
| 2008 } | 2019 } |
| 2009 } | 2020 } |
| 2010 } | 2021 } |
| OLD | NEW |