Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: lib/compiler/implementation/js_backend/emitter.dart

Issue 10855174: Lazy implementation of final variables. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix tests. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 /** 5 /**
6 * A function element that represents a closure call. The signature is copied 6 * A function element that represents a closure call. The signature is copied
7 * from the given element. 7 * from the given element.
8 */ 8 */
9 class ClosureInvocationElement extends FunctionElement { 9 class ClosureInvocationElement extends FunctionElement {
10 ClosureInvocationElement(SourceString name, 10 ClosureInvocationElement(SourceString name,
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 buffer.add("$finishClassesName($classesCollector);\n"); 649 buffer.add("$finishClassesName($classesCollector);\n");
650 // Reset the map. 650 // Reset the map.
651 buffer.add("$classesCollector = {};\n"); 651 buffer.add("$classesCollector = {};\n");
652 } 652 }
653 } 653 }
654 654
655 void emitStaticFunctionsWithNamer(CodeBuffer buffer, 655 void emitStaticFunctionsWithNamer(CodeBuffer buffer,
656 Map<Element, CodeBuffer> generatedCode, 656 Map<Element, CodeBuffer> generatedCode,
657 String functionNamer(Element element)) { 657 String functionNamer(Element element)) {
658 generatedCode.forEach((Element element, CodeBuffer functionBuffer) { 658 generatedCode.forEach((Element element, CodeBuffer functionBuffer) {
659 if (!element.isInstanceMember()) { 659 if (!element.isInstanceMember() && element.kind != ElementKind.FIELD) {
kasperl 2012/08/16 14:41:37 Don't we have an element.isField() tester?
floitsch 2012/08/16 22:52:33 Done.
660 String functionName = functionNamer(element); 660 String functionName = functionNamer(element);
661 buffer.add('$isolateProperties.$functionName = '); 661 buffer.add('$isolateProperties.$functionName = ');
662 addMappings(functionBuffer, buffer.length); 662 addMappings(functionBuffer, buffer.length);
663 buffer.add(functionBuffer); 663 buffer.add(functionBuffer);
664 buffer.add(';\n\n'); 664 buffer.add(';\n\n');
665 } 665 }
666 }); 666 });
667 } 667 }
668 668
669 void emitStaticFunctions(CodeBuffer buffer) { 669 void emitStaticFunctions(CodeBuffer buffer) {
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 handler.getStaticNonFinalFieldsForEmission(); 827 handler.getStaticNonFinalFieldsForEmission();
828 for (Element element in staticNonFinalFields) { 828 for (Element element in staticNonFinalFields) {
829 buffer.add('$isolateProperties.${namer.getName(element)} = '); 829 buffer.add('$isolateProperties.${namer.getName(element)} = ');
830 compiler.withCurrentElement(element, () { 830 compiler.withCurrentElement(element, () {
831 handler.writeJsCodeForVariable(buffer, element); 831 handler.writeJsCodeForVariable(buffer, element);
832 }); 832 });
833 buffer.add(';\n'); 833 buffer.add(';\n');
834 } 834 }
835 } 835 }
836 836
837 void emitLazilyInitializedStaticFields(CodeBuffer buffer) {
838 String nonBailoutElementNamer(Element element) {
839 if (element.kind == ElementKind.FIELD) {
kasperl 2012/08/16 14:41:37 isField
floitsch 2012/08/16 22:52:33 Done.
840 return namer.getLazyInitializerName(element);
841 } else {
842 return namer.getName(element);
843 }
844 }
845
846 String bailoutElementNamer(Element element) {
847 if (element.kind == ElementKind.FIELD) {
kasperl 2012/08/16 14:41:37 isField
floitsch 2012/08/16 22:52:33 Done.
848 return namer.getLazyInitializerBailoutName(element);
849 } else {
850 return namer.getBailoutName(element);
851 }
852 }
853
854 ConstantHandler handler = compiler.constantHandler;
855 List<VariableElement> lazyFields =
856 handler.getLazilyInitializedFieldsForEmission();
857 if (!lazyFields.isEmpty()) {
858 JavaScriptBackend backend = compiler.backend;
859 String isolatePropertiesSentinelAccess =
860 '$isolateProperties.${namer.LAZY_INITIALIZATION_SENTINEL}';
861 buffer.add('$isolatePropertiesSentinelAccess = {};\n');
862 for (VariableElement element in lazyFields) {
863 StringBuffer code = compiler.codegenWorld.generatedCode[element];
864 assert(code != null);
865 // The code only computes the initial value. We build the lazy-check
866 // here.
867 String fieldName = namer.getName(element);
868 String lazyGetterName =
869 '$isolateProperties.${namer.getLazyInitializerName(element)}';
870 // We store the function that computes the initial value as field of
871 // the lazy getter.
872 // The lazy getter itself will be replaced at first access.
873 String directFieldAccess = namer.isolateAccess(element);
874 String sentinelAccess =
875 '${namer.CURRENT_ISOLATE}.${namer.LAZY_INITIALIZATION_SENTINEL}';
876 buffer.add('''
877 $lazyGetterName = function() {
kasperl 2012/08/16 14:41:37 As we discussed, I think this needs to do the try-
floitsch 2012/08/16 22:52:33 Done.
878 var value = $directFieldAccess;
879 if (value === $sentinelAccess) {
880 value = ${namer.isolateLazyInitializerAccess(element)}.lazy();
881 $directFieldAccess = value;
882 }
883 ${namer.isolateLazyInitializerAccess(element)} = function() { return $directFi eldAccess; };
884 return value;
885 };
886 ''');
887 buffer.add('$lazyGetterName.lazy = ');
888 buffer.add(code);
889 buffer.add('\n$isolateProperties.${namer.getName(element)} = ');
890 buffer.add(isolatePropertiesSentinelAccess);
891 buffer.add(';\n');
892 }
893 }
894 }
895
837 void emitCompileTimeConstants(CodeBuffer buffer) { 896 void emitCompileTimeConstants(CodeBuffer buffer) {
838 ConstantHandler handler = compiler.constantHandler; 897 ConstantHandler handler = compiler.constantHandler;
839 List<Constant> constants = handler.getConstantsForEmission(); 898 List<Constant> constants = handler.getConstantsForEmission();
840 bool addedMakeConstantList = false; 899 bool addedMakeConstantList = false;
841 for (Constant constant in constants) { 900 for (Constant constant in constants) {
842 String name = handler.getNameForConstant(constant); 901 String name = handler.getNameForConstant(constant);
843 // The name is null when the constant is already a JS constant. 902 // The name is null when the constant is already a JS constant.
844 // TODO(floitsch): every constant should be registered, so that we can 903 // TODO(floitsch): every constant should be registered, so that we can
845 // share the ones that take up too much space (like some strings). 904 // share the ones that take up too much space (like some strings).
846 if (name === null) continue; 905 if (name === null) continue;
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1121 boundClosureBuffer.clear(); 1180 boundClosureBuffer.clear();
1122 emitStaticFunctions(mainBuffer); 1181 emitStaticFunctions(mainBuffer);
1123 emitStaticFunctionGetters(mainBuffer); 1182 emitStaticFunctionGetters(mainBuffer);
1124 // We need to finish the classes before we construct compile time 1183 // We need to finish the classes before we construct compile time
1125 // constants. 1184 // constants.
1126 emitFinishClassesInvocationIfNecessary(mainBuffer); 1185 emitFinishClassesInvocationIfNecessary(mainBuffer);
1127 emitCompileTimeConstants(mainBuffer); 1186 emitCompileTimeConstants(mainBuffer);
1128 // Static field initializations require the classes and compile-time 1187 // Static field initializations require the classes and compile-time
1129 // constants to be set up. 1188 // constants to be set up.
1130 emitStaticNonFinalFieldInitializations(mainBuffer); 1189 emitStaticNonFinalFieldInitializations(mainBuffer);
1190 emitLazilyInitializedStaticFields(mainBuffer);
1131 1191
1132 isolateProperties = isolatePropertiesName; 1192 isolateProperties = isolatePropertiesName;
1133 // The following code should not use the short-hand for the 1193 // The following code should not use the short-hand for the
1134 // initialStatics. 1194 // initialStatics.
1135 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); 1195 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n');
1136 mainBuffer.add(boundClosureBuffer); 1196 mainBuffer.add(boundClosureBuffer);
1137 emitFinishClassesInvocationIfNecessary(mainBuffer); 1197 emitFinishClassesInvocationIfNecessary(mainBuffer);
1138 // After this assignment we will produce invalid JavaScript code if we use 1198 // After this assignment we will produce invalid JavaScript code if we use
1139 // the classesCollector variable. 1199 // the classesCollector variable.
1140 classesCollector = 'classesCollector should not be used from now on'; 1200 classesCollector = 'classesCollector should not be used from now on';
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 sourceName = token.slowToString(); 1233 sourceName = token.slowToString();
1174 } 1234 }
1175 int totalOffset = bufferOffset + offset; 1235 int totalOffset = bufferOffset + offset;
1176 sourceMapBuilder.addMapping( 1236 sourceMapBuilder.addMapping(
1177 sourceFile, token.charOffset, sourceName, totalOffset); 1237 sourceFile, token.charOffset, sourceName, totalOffset);
1178 }); 1238 });
1179 } 1239 }
1180 } 1240 }
1181 1241
1182 typedef void DefineMemberFunction(String invocationName, CodeBuffer definition); 1242 typedef void DefineMemberFunction(String invocationName, CodeBuffer definition);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698