Chromium Code Reviews| 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 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 847 } | 847 } |
| 848 | 848 |
| 849 void emitLazilyInitializedStaticFields(CodeOutput output) { | 849 void emitLazilyInitializedStaticFields(CodeOutput output) { |
| 850 JavaScriptConstantCompiler handler = backend.constants; | 850 JavaScriptConstantCompiler handler = backend.constants; |
| 851 List<VariableElement> lazyFields = | 851 List<VariableElement> lazyFields = |
| 852 handler.getLazilyInitializedFieldsForEmission(); | 852 handler.getLazilyInitializedFieldsForEmission(); |
| 853 if (!lazyFields.isEmpty) { | 853 if (!lazyFields.isEmpty) { |
| 854 needsLazyInitializer = true; | 854 needsLazyInitializer = true; |
| 855 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { | 855 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { |
| 856 jsAst.Expression init = | 856 jsAst.Expression init = |
| 857 buildLazilyInitializedStaticField(element, isolateProperties); | 857 buildLazilyInitializedStaticField(element); |
| 858 if (init == null) continue; | 858 if (init == null) continue; |
| 859 output.addBuffer( | 859 output.addBuffer( |
| 860 jsAst.prettyPrint(init, compiler, monitor: compiler.dumpInfoTask)); | 860 jsAst.prettyPrint(init, compiler, monitor: compiler.dumpInfoTask)); |
| 861 output.add("$N"); | 861 output.add("$N"); |
| 862 } | 862 } |
| 863 } | 863 } |
| 864 } | 864 } |
| 865 | 865 |
| 866 jsAst.Expression buildLazilyInitializedStaticField( | 866 jsAst.Expression buildLazilyInitializedStaticField( |
| 867 VariableElement element, String isolateProperties) { | 867 VariableElement element, {String isolateProperties}) { |
| 868 jsAst.Expression code = backend.generatedCode[element]; | 868 jsAst.Expression code = backend.generatedCode[element]; |
| 869 // The code is null if we ended up not needing the lazily | 869 // The code is null if we ended up not needing the lazily |
| 870 // initialized field after all because of constant folding | 870 // initialized field after all because of constant folding |
| 871 // before code generation. | 871 // before code generation. |
| 872 if (code == null) return null; | 872 if (code == null) return null; |
| 873 // The code only computes the initial value. We build the lazy-check | 873 // The code only computes the initial value. We build the lazy-check |
| 874 // here: | 874 // here: |
| 875 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); | 875 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); |
| 876 // The name is used for error reporting. The 'initial' must be a | 876 // The name is used for error reporting. The 'initial' must be a |
| 877 // closure that constructs the initial value. | 877 // closure that constructs the initial value. |
| 878 return js('#(#,#,#,#,#)', | 878 if (isolateProperties != null) { |
| 879 return js('#(#,#,#,#,#)', | |
| 880 [js(lazyInitializerName), | |
| 881 js.string(element.name), | |
| 882 js.string(namer.globalPropertyName(element)), | |
| 883 js.string(namer.lazyInitializerName(element)), | |
| 884 code, | |
| 885 isolateProperties]); | |
| 886 } | |
| 887 | |
| 888 return js('#(#,#,#,#)', | |
| 879 [js(lazyInitializerName), | 889 [js(lazyInitializerName), |
| 880 js(isolateProperties), | 890 js.string(element.name), |
| 881 js.string(element.name), | 891 js.string(namer.globalPropertyName(element)), |
| 882 js.string(namer.globalPropertyName(element)), | 892 js.string(namer.lazyInitializerName(element)), |
| 883 js.string(namer.lazyInitializerName(element)), | 893 code]); |
| 884 code]); | |
| 885 } | 894 } |
| 886 | 895 |
| 887 void emitMetadata(Program program, CodeOutput output) { | 896 void emitMetadata(Program program, CodeOutput output) { |
| 888 | 897 |
| 889 addMetadataGlobal(List<String> list, String global) { | 898 addMetadataGlobal(List<String> list, String global) { |
| 890 String globalAccess = generateEmbeddedGlobalAccessString(global); | 899 String globalAccess = generateEmbeddedGlobalAccessString(global); |
| 891 output.add('$globalAccess$_=$_['); | 900 output.add('$globalAccess$_=$_['); |
| 892 for (String data in list) { | 901 for (String data in list) { |
| 893 if (data is String) { | 902 if (data is String) { |
| 894 if (data != 'null') { | 903 if (data != 'null') { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 991 | 1000 |
| 992 output.add(';'); | 1001 output.add(';'); |
| 993 addComment('BEGIN invoke [main].', output); | 1002 addComment('BEGIN invoke [main].', output); |
| 994 output.addBuffer(jsAst.prettyPrint(invokeMain, | 1003 output.addBuffer(jsAst.prettyPrint(invokeMain, |
| 995 compiler, monitor: compiler.dumpInfoTask)); | 1004 compiler, monitor: compiler.dumpInfoTask)); |
| 996 output.add(N); | 1005 output.add(N); |
| 997 addComment('END invoke [main].', output); | 1006 addComment('END invoke [main].', output); |
| 998 } | 1007 } |
| 999 | 1008 |
| 1000 void emitInitFunction(CodeOutput output) { | 1009 void emitInitFunction(CodeOutput output) { |
| 1001 String isolate = namer.currentIsolate; | |
| 1002 jsAst.Expression allClassesAccess = | 1010 jsAst.Expression allClassesAccess = |
| 1003 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); | 1011 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
| 1004 jsAst.Expression getTypeFromNameAccess = | 1012 jsAst.Expression getTypeFromNameAccess = |
| 1005 generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME); | 1013 generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME); |
| 1006 jsAst.Expression interceptorsByTagAccess = | 1014 jsAst.Expression interceptorsByTagAccess = |
| 1007 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | 1015 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
| 1008 jsAst.Expression leafTagsAccess = | 1016 jsAst.Expression leafTagsAccess = |
| 1009 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | 1017 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
| 1010 jsAst.Expression finishedClassesAccess = | 1018 jsAst.Expression finishedClassesAccess = |
| 1011 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | 1019 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
| 1012 jsAst.Expression cyclicThrow = | 1020 jsAst.Expression cyclicThrow = |
| 1013 staticFunctionAccess(backend.getCyclicThrowHelper()); | 1021 staticFunctionAccess(backend.getCyclicThrowHelper()); |
| 1014 jsAst.Expression laziesAccess = | 1022 jsAst.Expression laziesAccess = |
| 1015 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); | 1023 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); |
| 1016 | 1024 |
| 1017 jsAst.FunctionDeclaration decl = js.statement(''' | 1025 jsAst.FunctionDeclaration decl = js.statement(''' |
| 1018 function init() { | 1026 function init() { |
| 1019 $isolateProperties = Object.create(null); | 1027 $isolateProperties = Object.create(null); |
| 1020 #allClasses = Object.create(null); | 1028 #allClasses = Object.create(null); |
| 1021 #getTypeFromName = function(name) {return #allClasses[name];}; | 1029 #getTypeFromName = function(name) {return #allClasses[name];}; |
| 1022 #interceptorsByTag = Object.create(null); | 1030 #interceptorsByTag = Object.create(null); |
| 1023 #leafTags = Object.create(null); | 1031 #leafTags = Object.create(null); |
| 1024 #finishedClasses = Object.create(null); | 1032 #finishedClasses = Object.create(null); |
| 1025 | 1033 |
| 1026 if (#needsLazyInitializer) { | 1034 if (#needsLazyInitializer) { |
|
herhut
2015/03/25 14:23:14
Please add a comment here that explains the specia
zarah
2015/03/25 14:46:04
Done.
| |
| 1027 $lazyInitializerName = function (prototype, staticName, fieldName, | 1035 $lazyInitializerName = function (staticName, fieldName, getterName, |
| 1028 getterName, lazyValue) { | 1036 lazyValue, prototype) { |
| 1029 if (!#lazies) #lazies = Object.create(null); | 1037 if (!#lazies) #lazies = Object.create(null); |
| 1030 #lazies[fieldName] = getterName; | 1038 #lazies[fieldName] = getterName; |
| 1031 | 1039 |
| 1040 prototype = prototype || $isolateProperties; | |
| 1032 var sentinelUndefined = {}; | 1041 var sentinelUndefined = {}; |
| 1033 var sentinelInProgress = {}; | 1042 var sentinelInProgress = {}; |
| 1034 prototype[fieldName] = sentinelUndefined; | 1043 prototype[fieldName] = sentinelUndefined; |
| 1035 | 1044 |
| 1036 prototype[getterName] = function () { | 1045 prototype[getterName] = function () { |
| 1037 var result = $isolate[fieldName]; | 1046 var result = this[fieldName]; |
| 1038 try { | 1047 try { |
| 1039 if (result === sentinelUndefined) { | 1048 if (result === sentinelUndefined) { |
| 1040 $isolate[fieldName] = sentinelInProgress; | 1049 this[fieldName] = sentinelInProgress; |
| 1041 | 1050 |
| 1042 try { | 1051 try { |
| 1043 result = $isolate[fieldName] = lazyValue(); | 1052 result = this[fieldName] = lazyValue(); |
| 1044 } finally { | 1053 } finally { |
| 1045 // Use try-finally, not try-catch/throw as it destroys the | 1054 // Use try-finally, not try-catch/throw as it destroys the |
| 1046 // stack trace. | 1055 // stack trace. |
| 1047 if (result === sentinelUndefined) | 1056 if (result === sentinelUndefined) |
| 1048 $isolate[fieldName] = null; | 1057 this[fieldName] = null; |
| 1049 } | 1058 } |
| 1050 } else { | 1059 } else { |
| 1051 if (result === sentinelInProgress) | 1060 if (result === sentinelInProgress) |
| 1052 #cyclicThrow(staticName); | 1061 #cyclicThrow(staticName); |
| 1053 } | 1062 } |
| 1054 | 1063 |
| 1055 return result; | 1064 return result; |
| 1056 } finally { | 1065 } finally { |
| 1057 $isolate[getterName] = function() { return this[fieldName]; }; | 1066 this[getterName] = function() { return this[fieldName]; }; |
| 1058 } | 1067 } |
| 1059 } | 1068 } |
| 1060 } | 1069 } |
| 1061 } | 1070 } |
| 1062 | 1071 |
| 1063 // We replace the old Isolate function with a new one that initializes | 1072 // We replace the old Isolate function with a new one that initializes |
| 1064 // all its fields with the initial (and often final) value of all | 1073 // all its fields with the initial (and often final) value of all |
| 1065 // globals. | 1074 // globals. |
| 1066 // | 1075 // |
| 1067 // We also copy over old values like the prototype, and the | 1076 // We also copy over old values like the prototype, and the |
| (...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2128 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2137 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 2129 if (element.isInstanceMember) { | 2138 if (element.isInstanceMember) { |
| 2130 cachedClassBuilders.remove(element.enclosingClass); | 2139 cachedClassBuilders.remove(element.enclosingClass); |
| 2131 | 2140 |
| 2132 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2141 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 2133 | 2142 |
| 2134 } | 2143 } |
| 2135 } | 2144 } |
| 2136 } | 2145 } |
| 2137 } | 2146 } |
| OLD | NEW |