| 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 TypeTestEmitter get typeTestEmitter => task.typeTestEmitter; | 15 TypeTestEmitter get typeTestEmitter => task.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 final Set<Constant> cachedEmittedConstants; | 19 final Set<ConstantValue> cachedEmittedConstants; |
| 20 final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer(); | 20 final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer(); |
| 21 final Map<Element, ClassBuilder> cachedClassBuilders; | 21 final Map<Element, ClassBuilder> cachedClassBuilders; |
| 22 final Set<Element> cachedElements; | 22 final Set<Element> cachedElements; |
| 23 | 23 |
| 24 bool needsDefineClass = false; | 24 bool needsDefineClass = false; |
| 25 bool needsMixinSupport = false; | 25 bool needsMixinSupport = false; |
| 26 bool needsLazyInitializer = false; | 26 bool needsLazyInitializer = false; |
| 27 final Namer namer; | 27 final Namer namer; |
| 28 ConstantEmitter constantEmitter; | 28 ConstantEmitter constantEmitter; |
| 29 NativeEmitter get nativeEmitter => task.nativeEmitter; | 29 NativeEmitter get nativeEmitter => task.nativeEmitter; |
| 30 | 30 |
| 31 // The full code that is written to each hunk part-file. | 31 // The full code that is written to each hunk part-file. |
| 32 Map<OutputUnit, CodeBuffer> outputBuffers = new Map<OutputUnit, CodeBuffer>(); | 32 Map<OutputUnit, CodeBuffer> outputBuffers = new Map<OutputUnit, CodeBuffer>(); |
| 33 final CodeBuffer deferredConstants = new CodeBuffer(); | 33 final CodeBuffer deferredConstants = new CodeBuffer(); |
| 34 | 34 |
| 35 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | 35 /** Shorter access to [isolatePropertiesName]. Both here in the code, as |
| 36 well as in the generated code. */ | 36 well as in the generated code. */ |
| 37 String isolateProperties; | 37 String isolateProperties; |
| 38 String classesCollector; | 38 String classesCollector; |
| 39 Set<ClassElement> get neededClasses => task.neededClasses; | 39 Set<ClassElement> get neededClasses => task.neededClasses; |
| 40 Map<OutputUnit, List<ClassElement>> get outputClassLists | 40 Map<OutputUnit, List<ClassElement>> get outputClassLists |
| 41 => task.outputClassLists; | 41 => task.outputClassLists; |
| 42 Map<OutputUnit, List<Constant>> get outputConstantLists | 42 Map<OutputUnit, List<ConstantValue>> get outputConstantLists |
| 43 => task.outputConstantLists; | 43 => task.outputConstantLists; |
| 44 List<ClassElement> get nativeClasses => task.nativeClasses; | 44 List<ClassElement> get nativeClasses => task.nativeClasses; |
| 45 final Map<String, String> mangledFieldNames = <String, String>{}; | 45 final Map<String, String> mangledFieldNames = <String, String>{}; |
| 46 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; | 46 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; |
| 47 final Set<String> recordedMangledNames = new Set<String>(); | 47 final Set<String> recordedMangledNames = new Set<String>(); |
| 48 | 48 |
| 49 final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties = | 49 final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties = |
| 50 new Map<ClassElement, Map<String, jsAst.Expression>>(); | 50 new Map<ClassElement, Map<String, jsAst.Expression>>(); |
| 51 | 51 |
| 52 Set<ClassElement> get instantiatedClasses => task.instantiatedClasses; | 52 Set<ClassElement> get instantiatedClasses => task.instantiatedClasses; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 /// Used by the incremental compiler. | 135 /// Used by the incremental compiler. |
| 136 void clearCspPrecompiledNodes() { | 136 void clearCspPrecompiledNodes() { |
| 137 _cspPrecompiledFunctions.clear(); | 137 _cspPrecompiledFunctions.clear(); |
| 138 _cspPrecompiledConstructorNames.clear(); | 138 _cspPrecompiledConstructorNames.clear(); |
| 139 } | 139 } |
| 140 | 140 |
| 141 void addComment(String comment, CodeBuffer buffer) { | 141 void addComment(String comment, CodeBuffer buffer) { |
| 142 buffer.write(jsAst.prettyPrint(js.comment(comment), compiler)); | 142 buffer.write(jsAst.prettyPrint(js.comment(comment), compiler)); |
| 143 } | 143 } |
| 144 | 144 |
| 145 jsAst.Expression constantReference(Constant value) { | 145 jsAst.Expression constantReference(ConstantValue value) { |
| 146 return constantEmitter.reference(value); | 146 return constantEmitter.reference(value); |
| 147 } | 147 } |
| 148 | 148 |
| 149 jsAst.Expression constantInitializerExpression(Constant value) { | 149 jsAst.Expression constantInitializerExpression(ConstantValue value) { |
| 150 return constantEmitter.initializationExpression(value); | 150 return constantEmitter.initializationExpression(value); |
| 151 } | 151 } |
| 152 | 152 |
| 153 String get name => 'CodeEmitter'; | 153 String get name => 'CodeEmitter'; |
| 154 | 154 |
| 155 String get currentGenerateAccessorName | 155 String get currentGenerateAccessorName |
| 156 => '${namer.currentIsolate}.\$generateAccessor'; | 156 => '${namer.currentIsolate}.\$generateAccessor'; |
| 157 String get generateAccessorHolder | 157 String get generateAccessorHolder |
| 158 => '$isolatePropertiesName.\$generateAccessor'; | 158 => '$isolatePropertiesName.\$generateAccessor'; |
| 159 String get finishClassesProperty | 159 String get finishClassesProperty |
| (...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 896 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 896 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 897 JavaScriptConstantCompiler handler = backend.constants; | 897 JavaScriptConstantCompiler handler = backend.constants; |
| 898 Iterable<VariableElement> staticNonFinalFields = | 898 Iterable<VariableElement> staticNonFinalFields = |
| 899 handler.getStaticNonFinalFieldsForEmission(); | 899 handler.getStaticNonFinalFieldsForEmission(); |
| 900 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 900 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
| 901 // [:interceptedNames:] is handled in [emitInterceptedNames]. | 901 // [:interceptedNames:] is handled in [emitInterceptedNames]. |
| 902 if (element == backend.interceptedNames) continue; | 902 if (element == backend.interceptedNames) continue; |
| 903 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. | 903 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. |
| 904 if (element == backend.mapTypeToInterceptor) continue; | 904 if (element == backend.mapTypeToInterceptor) continue; |
| 905 compiler.withCurrentElement(element, () { | 905 compiler.withCurrentElement(element, () { |
| 906 Constant initialValue = handler.getInitialValueFor(element).value; | 906 ConstantValue initialValue = handler.getInitialValueFor(element).value; |
| 907 jsAst.Expression init = | 907 jsAst.Expression init = |
| 908 js('$isolateProperties.# = #', | 908 js('$isolateProperties.# = #', |
| 909 [namer.getNameOfGlobalField(element), | 909 [namer.getNameOfGlobalField(element), |
| 910 constantEmitter.referenceInInitializationContext(initialValue)]); | 910 constantEmitter.referenceInInitializationContext(initialValue)]); |
| 911 buffer.write(jsAst.prettyPrint(init, compiler, | 911 buffer.write(jsAst.prettyPrint(init, compiler, |
| 912 monitor: compiler.dumpInfoTask)); | 912 monitor: compiler.dumpInfoTask)); |
| 913 buffer.write('$N'); | 913 buffer.write('$N'); |
| 914 }); | 914 }); |
| 915 } | 915 } |
| 916 } | 916 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 946 buffer.write("$N"); | 946 buffer.write("$N"); |
| 947 } | 947 } |
| 948 } | 948 } |
| 949 } | 949 } |
| 950 | 950 |
| 951 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { | 951 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { |
| 952 // Nothing to do, the 'lazy' function will create the getter. | 952 // Nothing to do, the 'lazy' function will create the getter. |
| 953 return null; | 953 return null; |
| 954 } | 954 } |
| 955 | 955 |
| 956 bool isConstantInlinedOrAlreadyEmitted(Constant constant) { | 956 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { |
| 957 if (constant.isFunction) return true; // Already emitted. | 957 if (constant.isFunction) return true; // Already emitted. |
| 958 if (constant.isPrimitive) return true; // Inlined. | 958 if (constant.isPrimitive) return true; // Inlined. |
| 959 if (constant.isDummy) return true; // Inlined. | 959 if (constant.isDummy) return true; // Inlined. |
| 960 // The name is null when the constant is already a JS constant. | 960 // The name is null when the constant is already a JS constant. |
| 961 // TODO(floitsch): every constant should be registered, so that we can | 961 // TODO(floitsch): every constant should be registered, so that we can |
| 962 // share the ones that take up too much space (like some strings). | 962 // share the ones that take up too much space (like some strings). |
| 963 if (namer.constantName(constant) == null) return true; | 963 if (namer.constantName(constant) == null) return true; |
| 964 return false; | 964 return false; |
| 965 } | 965 } |
| 966 | 966 |
| 967 int compareConstants(Constant a, Constant b) { | 967 int compareConstants(ConstantValue a, ConstantValue b) { |
| 968 // Inlined constants don't affect the order and sometimes don't even have | 968 // Inlined constants don't affect the order and sometimes don't even have |
| 969 // names. | 969 // names. |
| 970 int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1; | 970 int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1; |
| 971 int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1; | 971 int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1; |
| 972 if (cmp1 + cmp2 < 2) return cmp1 - cmp2; | 972 if (cmp1 + cmp2 < 2) return cmp1 - cmp2; |
| 973 | 973 |
| 974 // Emit constant interceptors first. Constant interceptors for primitives | 974 // Emit constant interceptors first. Constant interceptors for primitives |
| 975 // might be used by code that builds other constants. See Issue 18173. | 975 // might be used by code that builds other constants. See Issue 18173. |
| 976 if (a.isInterceptor != b.isInterceptor) { | 976 if (a.isInterceptor != b.isInterceptor) { |
| 977 return a.isInterceptor ? -1 : 1; | 977 return a.isInterceptor ? -1 : 1; |
| 978 } | 978 } |
| 979 | 979 |
| 980 // Sorting by the long name clusters constants with the same constructor | 980 // Sorting by the long name clusters constants with the same constructor |
| 981 // which compresses a tiny bit better. | 981 // which compresses a tiny bit better. |
| 982 int r = namer.constantLongName(a).compareTo(namer.constantLongName(b)); | 982 int r = namer.constantLongName(a).compareTo(namer.constantLongName(b)); |
| 983 if (r != 0) return r; | 983 if (r != 0) return r; |
| 984 // Resolve collisions in the long name by using the constant name (i.e. JS | 984 // Resolve collisions in the long name by using the constant name (i.e. JS |
| 985 // name) which is unique. | 985 // name) which is unique. |
| 986 return namer.constantName(a).compareTo(namer.constantName(b)); | 986 return namer.constantName(a).compareTo(namer.constantName(b)); |
| 987 } | 987 } |
| 988 | 988 |
| 989 void emitCompileTimeConstants(CodeBuffer buffer, OutputUnit outputUnit) { | 989 void emitCompileTimeConstants(CodeBuffer buffer, OutputUnit outputUnit) { |
| 990 List<Constant> constants = outputConstantLists[outputUnit]; | 990 List<ConstantValue> constants = outputConstantLists[outputUnit]; |
| 991 if (constants == null) return; | 991 if (constants == null) return; |
| 992 bool isMainBuffer = buffer == mainBuffer; | 992 bool isMainBuffer = buffer == mainBuffer; |
| 993 if (compiler.hasIncrementalSupport && isMainBuffer) { | 993 if (compiler.hasIncrementalSupport && isMainBuffer) { |
| 994 buffer = cachedEmittedConstantsBuffer; | 994 buffer = cachedEmittedConstantsBuffer; |
| 995 } | 995 } |
| 996 for (Constant constant in constants) { | 996 for (ConstantValue constant in constants) { |
| 997 if (compiler.hasIncrementalSupport && isMainBuffer) { | 997 if (compiler.hasIncrementalSupport && isMainBuffer) { |
| 998 if (cachedEmittedConstants.contains(constant)) continue; | 998 if (cachedEmittedConstants.contains(constant)) continue; |
| 999 cachedEmittedConstants.add(constant); | 999 cachedEmittedConstants.add(constant); |
| 1000 } | 1000 } |
| 1001 String name = namer.constantName(constant); | 1001 String name = namer.constantName(constant); |
| 1002 if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); | 1002 if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); |
| 1003 jsAst.Expression init = js('#.# = #', | 1003 jsAst.Expression init = js('#.# = #', |
| 1004 [namer.globalObjectForConstant(constant), name, | 1004 [namer.globalObjectForConstant(constant), name, |
| 1005 constantInitializerExpression(constant)]); | 1005 constantInitializerExpression(constant)]); |
| 1006 buffer.write(jsAst.prettyPrint(init, compiler, | 1006 buffer.write(jsAst.prettyPrint(init, compiler, |
| (...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1919 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 1919 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 1920 if (element.isInstanceMember) { | 1920 if (element.isInstanceMember) { |
| 1921 cachedClassBuilders.remove(element.enclosingClass); | 1921 cachedClassBuilders.remove(element.enclosingClass); |
| 1922 | 1922 |
| 1923 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 1923 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 1924 | 1924 |
| 1925 } | 1925 } |
| 1926 } | 1926 } |
| 1927 } | 1927 } |
| 1928 } | 1928 } |
| OLD | NEW |