| 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 |