OLD | NEW |
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 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 /** | 7 /** |
8 * Generates the code for all used classes in the program. Static fields (even | 8 * Generates the code for all used classes in the program. Static fields (even |
9 * in classes) are ignored, since they can be treated as non-class elements. | 9 * in classes) are ignored, since they can be treated as non-class elements. |
10 * | 10 * |
(...skipping 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 Element isolateMain) { | 968 Element isolateMain) { |
969 String mainAccess = "${namer.isolateStaticClosureAccess(appMain)}"; | 969 String mainAccess = "${namer.isolateStaticClosureAccess(appMain)}"; |
970 // Since we pass the closurized version of the main method to | 970 // Since we pass the closurized version of the main method to |
971 // the isolate method, we must make sure that it exists. | 971 // the isolate method, we must make sure that it exists. |
972 return "${namer.isolateAccess(isolateMain)}($mainAccess)"; | 972 return "${namer.isolateAccess(isolateMain)}($mainAccess)"; |
973 } | 973 } |
974 | 974 |
975 jsAst.Expression generateDispatchPropertyInitialization() { | 975 jsAst.Expression generateDispatchPropertyInitialization() { |
976 return js('!#', js.fun([], [ | 976 return js('!#', js.fun([], [ |
977 | 977 |
978 // On V8, the 'intern' function converts a string to a symbol, which | |
979 // makes property access much faster. | |
980 new jsAst.FunctionDeclaration(new jsAst.VariableDeclaration('intern'), | |
981 js.fun(['s'], [ | |
982 js('var o = {}'), | |
983 js('o[s] = 1'), | |
984 js.return_(js('Object.keys(convertToFastObject(o))[0]'))])), | |
985 | |
986 // To ensure that different programs loaded into the same context (page) | 978 // To ensure that different programs loaded into the same context (page) |
987 // use distinct dispatch properies, we place an object on `Object` to | 979 // use distinct dispatch properies, we place an object on `Object` to |
988 // contain the names already in use. | 980 // contain the names already in use. |
989 js('var tableProperty = "___dart_dispatch_property_names_"'), | 981 js('var tableProperty = "___dart_dispatch_property_names_"'), |
990 js('var usedProperties = Object[tableProperty] ||' | 982 js('var usedProperties = Object[tableProperty] ||' |
991 '(Object[tableProperty] = Object.create(null))'), | 983 '(Object[tableProperty] = Object.create(null))'), |
992 | 984 |
993 js('var rootProperty = "${generateDispatchPropertyName()}"'), | 985 js('var rootProperty = "${generateDispatchPropertyName()}"'), |
994 js.for_('var i = 0', null, 'i++', [ | 986 js.for_('var i = 0', null, 'i++', [ |
995 js('property = intern(rootProperty + "_" + i + "_")'), | 987 js('property = convertToJSSymbol(rootProperty + "_" + i + "_")'), |
996 js.if_('!(property in usedProperties)', [ | 988 js.if_('!(property in usedProperties)', [ |
997 js('usedProperties[property] = 1'), | 989 js('usedProperties[property] = 1'), |
998 js.return_( | 990 js.return_( |
999 js('init.dispatchPropertyName = property'))])])])()); | 991 js('init.dispatchPropertyName = property'))])])])()); |
1000 } | 992 } |
1001 | 993 |
1002 String generateDispatchPropertyName() { | 994 String generateDispatchPropertyName() { |
1003 // TODO(sra): MD5 of contributing source code or URIs? | 995 // TODO(sra): MD5 of contributing source code or URIs? |
1004 return '___dart_dispatch_record_ZxYxX_'; | 996 return '___dart_dispatch_record_ZxYxX_'; |
1005 } | 997 } |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 ); | 1149 ); |
1158 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( | 1150 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( |
1159 new jsAst.VariableDeclaration('init'), fun); | 1151 new jsAst.VariableDeclaration('init'), fun); |
1160 buffer.write(jsAst.prettyPrint(decl, compiler).getText()); | 1152 buffer.write(jsAst.prettyPrint(decl, compiler).getText()); |
1161 if (compiler.enableMinification) buffer.write('\n'); | 1153 if (compiler.enableMinification) buffer.write('\n'); |
1162 } | 1154 } |
1163 | 1155 |
1164 void emitConvertToFastObjectFunction() { | 1156 void emitConvertToFastObjectFunction() { |
1165 // Create an instance that uses 'properties' as prototype. This should make | 1157 // Create an instance that uses 'properties' as prototype. This should make |
1166 // 'properties' a fast object. | 1158 // 'properties' a fast object. |
1167 mainBuffer.add(r'''function convertToFastObject(properties) { | 1159 mainBuffer.add(r''' |
| 1160 function convertToFastObject(properties) { |
1168 function MyClass() {}; | 1161 function MyClass() {}; |
1169 MyClass.prototype = properties; | 1162 MyClass.prototype = properties; |
1170 new MyClass(); | 1163 new MyClass(); |
1171 '''); | 1164 '''); |
1172 if (DEBUG_FAST_OBJECTS) { | 1165 if (DEBUG_FAST_OBJECTS) { |
1173 ClassElement primitives = | 1166 ClassElement primitives = |
1174 compiler.findHelper('Primitives'); | 1167 compiler.findHelper('Primitives'); |
1175 FunctionElement printHelper = | 1168 FunctionElement printHelper = |
1176 compiler.lookupElementIn( | 1169 compiler.lookupElementIn( |
1177 primitives, 'printString'); | 1170 primitives, 'printString'); |
1178 String printHelperName = namer.isolateAccess(printHelper); | 1171 String printHelperName = namer.isolateAccess(printHelper); |
1179 mainBuffer.add(''' | 1172 mainBuffer.add(''' |
1180 // The following only works on V8 when run with option "--allow-natives-syntax". | 1173 // The following only works on V8 when run with option "--allow-natives-syntax". |
1181 if (typeof $printHelperName === "function") { | 1174 if (typeof $printHelperName === "function") { |
1182 $printHelperName("Size of global object: " | 1175 $printHelperName("Size of global object: " |
1183 + String(Object.getOwnPropertyNames(properties).length) | 1176 + String(Object.getOwnPropertyNames(properties).length) |
1184 + ", fast properties " + %HasFastProperties(properties)); | 1177 + ", fast properties " + %HasFastProperties(properties)); |
1185 } | 1178 } |
1186 '''); | 1179 '''); |
1187 } | 1180 } |
1188 mainBuffer.add(r''' | 1181 mainBuffer.add(r''' |
1189 return properties; | 1182 return properties; |
1190 } | 1183 } |
1191 '''); | 1184 '''); |
| 1185 // On V8, the 'intern' function converts a string to a symbol, which |
| 1186 // makes property access much faster. |
| 1187 mainBuffer.add(r''' |
| 1188 function convertToJSSymbol(s) { |
| 1189 var o = {}; |
| 1190 o[s] = 1; |
| 1191 return Object.keys(convertToFastObject(o))[0]; |
| 1192 } |
| 1193 '''); |
1192 } | 1194 } |
1193 | 1195 |
1194 void writeLibraryDescriptors(LibraryElement library) { | 1196 void writeLibraryDescriptors(LibraryElement library) { |
1195 var uri = library.canonicalUri; | 1197 var uri = library.canonicalUri; |
1196 if (uri.scheme == 'file' && compiler.sourceMapUri != null) { | 1198 if (uri.scheme == 'file' && compiler.sourceMapUri != null) { |
1197 // TODO(ahe): It is a hack to use compiler.sourceMapUri | 1199 // TODO(ahe): It is a hack to use compiler.sourceMapUri |
1198 // here. It should be relative to the main JavaScript | 1200 // here. It should be relative to the main JavaScript |
1199 // output file. | 1201 // output file. |
1200 uri = relativize( | 1202 uri = relativize( |
1201 compiler.sourceMapUri, library.canonicalUri, false); | 1203 compiler.sourceMapUri, library.canonicalUri, false); |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1618 String sourceMap = buildSourceMap(mainBuffer, compiledFile); | 1620 String sourceMap = buildSourceMap(mainBuffer, compiledFile); |
1619 compiler.outputProvider(name, 'js.map') | 1621 compiler.outputProvider(name, 'js.map') |
1620 ..add(sourceMap) | 1622 ..add(sourceMap) |
1621 ..close(); | 1623 ..close(); |
1622 } | 1624 } |
1623 | 1625 |
1624 void registerReadTypeVariable(TypeVariableElement element) { | 1626 void registerReadTypeVariable(TypeVariableElement element) { |
1625 readTypeVariables.add(element); | 1627 readTypeVariables.add(element); |
1626 } | 1628 } |
1627 } | 1629 } |
OLD | NEW |