| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Assigns JavaScript identifiers to Dart variables, class-names and members. | 8 * Assigns JavaScript identifiers to Dart variables, class-names and members. |
| 9 */ | 9 */ |
| 10 class Namer implements ClosureNamer { | 10 class Namer implements ClosureNamer { |
| (...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 } | 1089 } |
| 1090 | 1090 |
| 1091 void addIdentifier(String fragment) { | 1091 void addIdentifier(String fragment) { |
| 1092 if (fragment.length <= MAX_EXTRA_LENGTH && IDENTIFIER.hasMatch(fragment)) { | 1092 if (fragment.length <= MAX_EXTRA_LENGTH && IDENTIFIER.hasMatch(fragment)) { |
| 1093 add(fragment); | 1093 add(fragment); |
| 1094 } else { | 1094 } else { |
| 1095 failed = true; | 1095 failed = true; |
| 1096 } | 1096 } |
| 1097 } | 1097 } |
| 1098 | 1098 |
| 1099 _visit(ConstantValue constant) { | 1099 void _visit(ConstantValue constant) { |
| 1100 return constant.accept(this); | 1100 constant.accept(this, null); |
| 1101 } | 1101 } |
| 1102 | 1102 |
| 1103 visitFunction(FunctionConstantValue constant) { | 1103 @override |
| 1104 void visitFunction(FunctionConstantValue constant, [_]) { |
| 1104 add(constant.element.name); | 1105 add(constant.element.name); |
| 1105 } | 1106 } |
| 1106 | 1107 |
| 1107 visitNull(NullConstantValue constant) { | 1108 @override |
| 1109 void visitNull(NullConstantValue constant, [_]) { |
| 1108 add('null'); | 1110 add('null'); |
| 1109 } | 1111 } |
| 1110 | 1112 |
| 1111 visitInt(IntConstantValue constant) { | 1113 @override |
| 1114 void visitInt(IntConstantValue constant, [_]) { |
| 1112 // No `addRoot` since IntConstants are always inlined. | 1115 // No `addRoot` since IntConstants are always inlined. |
| 1113 if (constant.primitiveValue < 0) { | 1116 if (constant.primitiveValue < 0) { |
| 1114 add('m${-constant.primitiveValue}'); | 1117 add('m${-constant.primitiveValue}'); |
| 1115 } else { | 1118 } else { |
| 1116 add('${constant.primitiveValue}'); | 1119 add('${constant.primitiveValue}'); |
| 1117 } | 1120 } |
| 1118 } | 1121 } |
| 1119 | 1122 |
| 1120 visitDouble(DoubleConstantValue constant) { | 1123 @override |
| 1124 void visitDouble(DoubleConstantValue constant, [_]) { |
| 1121 failed = true; | 1125 failed = true; |
| 1122 } | 1126 } |
| 1123 | 1127 |
| 1124 visitTrue(TrueConstantValue constant) { | 1128 @override |
| 1125 add('true'); | 1129 void visitBool(BoolConstantValue constant, [_]) { |
| 1130 add(constant.isTrue ? 'true' : 'false'); |
| 1126 } | 1131 } |
| 1127 | 1132 |
| 1128 visitFalse(FalseConstantValue constant) { | 1133 @override |
| 1129 add('false'); | 1134 void visitString(StringConstantValue constant, [_]) { |
| 1130 } | |
| 1131 | |
| 1132 visitString(StringConstantValue constant) { | |
| 1133 // No `addRoot` since string constants are always inlined. | 1135 // No `addRoot` since string constants are always inlined. |
| 1134 addIdentifier(constant.primitiveValue.slowToString()); | 1136 addIdentifier(constant.primitiveValue.slowToString()); |
| 1135 } | 1137 } |
| 1136 | 1138 |
| 1137 visitList(ListConstantValue constant) { | 1139 @override |
| 1140 void visitList(ListConstantValue constant, [_]) { |
| 1138 // TODO(9476): Incorporate type parameters into name. | 1141 // TODO(9476): Incorporate type parameters into name. |
| 1139 addRoot('List'); | 1142 addRoot('List'); |
| 1140 int length = constant.length; | 1143 int length = constant.length; |
| 1141 if (constant.length == 0) { | 1144 if (constant.length == 0) { |
| 1142 add('empty'); | 1145 add('empty'); |
| 1143 } else if (length >= MAX_FRAGMENTS) { | 1146 } else if (length >= MAX_FRAGMENTS) { |
| 1144 failed = true; | 1147 failed = true; |
| 1145 } else { | 1148 } else { |
| 1146 for (int i = 0; i < length; i++) { | 1149 for (int i = 0; i < length; i++) { |
| 1147 _visit(constant.entries[i]); | 1150 _visit(constant.entries[i]); |
| 1148 if (failed) break; | 1151 if (failed) break; |
| 1149 } | 1152 } |
| 1150 } | 1153 } |
| 1151 } | 1154 } |
| 1152 | 1155 |
| 1153 visitMap(JavaScriptMapConstant constant) { | 1156 @override |
| 1157 void visitMap(JavaScriptMapConstant constant, [_]) { |
| 1154 // TODO(9476): Incorporate type parameters into name. | 1158 // TODO(9476): Incorporate type parameters into name. |
| 1155 addRoot('Map'); | 1159 addRoot('Map'); |
| 1156 if (constant.length == 0) { | 1160 if (constant.length == 0) { |
| 1157 add('empty'); | 1161 add('empty'); |
| 1158 } else { | 1162 } else { |
| 1159 // Using some bits from the keys hash tag groups the names Maps with the | 1163 // Using some bits from the keys hash tag groups the names Maps with the |
| 1160 // same structure. | 1164 // same structure. |
| 1161 add(getHashTag(constant.keyList, 2) + getHashTag(constant, 3)); | 1165 add(getHashTag(constant.keyList, 2) + getHashTag(constant, 3)); |
| 1162 } | 1166 } |
| 1163 } | 1167 } |
| 1164 | 1168 |
| 1165 visitConstructed(ConstructedConstantValue constant) { | 1169 @override |
| 1170 void visitConstructed(ConstructedConstantValue constant, [_]) { |
| 1166 addRoot(constant.type.element.name); | 1171 addRoot(constant.type.element.name); |
| 1167 for (int i = 0; i < constant.fields.length; i++) { | 1172 for (int i = 0; i < constant.fields.length; i++) { |
| 1168 _visit(constant.fields[i]); | 1173 _visit(constant.fields[i]); |
| 1169 if (failed) return; | 1174 if (failed) return; |
| 1170 } | 1175 } |
| 1171 } | 1176 } |
| 1172 | 1177 |
| 1173 visitType(TypeConstantValue constant) { | 1178 @override |
| 1179 void visitType(TypeConstantValue constant, [_]) { |
| 1174 addRoot('Type'); | 1180 addRoot('Type'); |
| 1175 DartType type = constant.representedType; | 1181 DartType type = constant.representedType; |
| 1176 JavaScriptBackend backend = compiler.backend; | 1182 JavaScriptBackend backend = compiler.backend; |
| 1177 String name = backend.rti.getTypeRepresentationForTypeConstant(type); | 1183 String name = backend.rti.getTypeRepresentationForTypeConstant(type); |
| 1178 addIdentifier(name); | 1184 addIdentifier(name); |
| 1179 } | 1185 } |
| 1180 | 1186 |
| 1181 visitInterceptor(InterceptorConstantValue constant) { | 1187 @override |
| 1188 void visitInterceptor(InterceptorConstantValue constant, [_]) { |
| 1182 addRoot(constant.dispatchedType.element.name); | 1189 addRoot(constant.dispatchedType.element.name); |
| 1183 add('methods'); | 1190 add('methods'); |
| 1184 } | 1191 } |
| 1185 | 1192 |
| 1186 visitDummy(DummyConstantValue constant) { | 1193 @override |
| 1194 void visitDummy(DummyConstantValue constant, [_]) { |
| 1187 add('dummy_receiver'); | 1195 add('dummy_receiver'); |
| 1188 } | 1196 } |
| 1189 | 1197 |
| 1190 visitDeferred(DeferredConstantValue constant) { | 1198 @override |
| 1199 void visitDeferred(DeferredConstantValue constant, [_]) { |
| 1191 addRoot('Deferred'); | 1200 addRoot('Deferred'); |
| 1192 } | 1201 } |
| 1193 } | 1202 } |
| 1194 | 1203 |
| 1195 /** | 1204 /** |
| 1196 * Generates canonical hash values for [ConstantValue]s. | 1205 * Generates canonical hash values for [ConstantValue]s. |
| 1197 * | 1206 * |
| 1198 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations, | 1207 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations, |
| 1199 * so it can't be used for generating names. This hasher keeps consistency | 1208 * so it can't be used for generating names. This hasher keeps consistency |
| 1200 * between runs by basing hash values of the names of elements, rather than | 1209 * between runs by basing hash values of the names of elements, rather than |
| 1201 * their hashCodes. | 1210 * their hashCodes. |
| 1202 */ | 1211 */ |
| 1203 class ConstantCanonicalHasher implements ConstantValueVisitor<int> { | 1212 class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> { |
| 1204 | 1213 |
| 1205 static const _MASK = 0x1fffffff; | 1214 static const _MASK = 0x1fffffff; |
| 1206 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024; | 1215 static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024; |
| 1207 | 1216 |
| 1208 | 1217 |
| 1209 final Compiler compiler; | 1218 final Compiler compiler; |
| 1210 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>(); | 1219 final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>(); |
| 1211 | 1220 |
| 1212 ConstantCanonicalHasher(this.compiler); | 1221 ConstantCanonicalHasher(this.compiler); |
| 1213 | 1222 |
| 1214 int getHash(ConstantValue constant) => _visit(constant); | 1223 int getHash(ConstantValue constant) => _visit(constant); |
| 1215 | 1224 |
| 1216 int _visit(ConstantValue constant) { | 1225 int _visit(ConstantValue constant) { |
| 1217 int hash = hashes[constant]; | 1226 int hash = hashes[constant]; |
| 1218 if (hash == null) { | 1227 if (hash == null) { |
| 1219 hash = _finish(constant.accept(this)); | 1228 hash = _finish(constant.accept(this, null)); |
| 1220 hashes[constant] = hash; | 1229 hashes[constant] = hash; |
| 1221 } | 1230 } |
| 1222 return hash; | 1231 return hash; |
| 1223 } | 1232 } |
| 1224 | 1233 |
| 1225 int visitNull(NullConstantValue constant) => 1; | 1234 @override |
| 1226 int visitTrue(TrueConstantValue constant) => 2; | 1235 int visitNull(NullConstantValue constant, [_]) => 1; |
| 1227 int visitFalse(FalseConstantValue constant) => 3; | |
| 1228 | 1236 |
| 1229 int visitFunction(FunctionConstantValue constant) { | 1237 @override |
| 1238 int visitBool(BoolConstantValue constant, [_]) { |
| 1239 return constant.isTrue ? 2 : 3; |
| 1240 } |
| 1241 |
| 1242 @override |
| 1243 int visitFunction(FunctionConstantValue constant, [_]) { |
| 1230 return _hashString(1, constant.element.name); | 1244 return _hashString(1, constant.element.name); |
| 1231 } | 1245 } |
| 1232 | 1246 |
| 1233 int visitInt(IntConstantValue constant) => _hashInt(constant.primitiveValue); | 1247 @override |
| 1248 int visitInt(IntConstantValue constant, [_]) { |
| 1249 return _hashInt(constant.primitiveValue); |
| 1250 } |
| 1234 | 1251 |
| 1235 int visitDouble(DoubleConstantValue constant) { | 1252 @override |
| 1253 int visitDouble(DoubleConstantValue constant, [_]) { |
| 1236 return _hashDouble(constant.primitiveValue); | 1254 return _hashDouble(constant.primitiveValue); |
| 1237 } | 1255 } |
| 1238 | 1256 |
| 1239 int visitString(StringConstantValue constant) { | 1257 @override |
| 1258 int visitString(StringConstantValue constant, [_]) { |
| 1240 return _hashString(2, constant.primitiveValue.slowToString()); | 1259 return _hashString(2, constant.primitiveValue.slowToString()); |
| 1241 } | 1260 } |
| 1242 | 1261 |
| 1243 int visitList(ListConstantValue constant) { | 1262 @override |
| 1263 int visitList(ListConstantValue constant, [_]) { |
| 1244 return _hashList(constant.length, constant.entries); | 1264 return _hashList(constant.length, constant.entries); |
| 1245 } | 1265 } |
| 1246 | 1266 |
| 1247 int visitMap(MapConstantValue constant) { | 1267 @override |
| 1268 int visitMap(MapConstantValue constant, [_]) { |
| 1248 int hash = _hashList(constant.length, constant.keys); | 1269 int hash = _hashList(constant.length, constant.keys); |
| 1249 return _hashList(hash, constant.values); | 1270 return _hashList(hash, constant.values); |
| 1250 } | 1271 } |
| 1251 | 1272 |
| 1252 int visitConstructed(ConstructedConstantValue constant) { | 1273 @override |
| 1274 int visitConstructed(ConstructedConstantValue constant, [_]) { |
| 1253 int hash = _hashString(3, constant.type.element.name); | 1275 int hash = _hashString(3, constant.type.element.name); |
| 1254 for (int i = 0; i < constant.fields.length; i++) { | 1276 for (int i = 0; i < constant.fields.length; i++) { |
| 1255 hash = _combine(hash, _visit(constant.fields[i])); | 1277 hash = _combine(hash, _visit(constant.fields[i])); |
| 1256 } | 1278 } |
| 1257 return hash; | 1279 return hash; |
| 1258 } | 1280 } |
| 1259 | 1281 |
| 1260 int visitType(TypeConstantValue constant) { | 1282 @override |
| 1283 int visitType(TypeConstantValue constant, [_]) { |
| 1261 DartType type = constant.representedType; | 1284 DartType type = constant.representedType; |
| 1262 JavaScriptBackend backend = compiler.backend; | 1285 JavaScriptBackend backend = compiler.backend; |
| 1263 String name = backend.rti.getTypeRepresentationForTypeConstant(type); | 1286 String name = backend.rti.getTypeRepresentationForTypeConstant(type); |
| 1264 return _hashString(4, name); | 1287 return _hashString(4, name); |
| 1265 } | 1288 } |
| 1266 | 1289 |
| 1267 visitInterceptor(InterceptorConstantValue constant) { | 1290 @override |
| 1291 int visitInterceptor(InterceptorConstantValue constant, [_]) { |
| 1268 String typeName = constant.dispatchedType.element.name; | 1292 String typeName = constant.dispatchedType.element.name; |
| 1269 return _hashString(5, typeName); | 1293 return _hashString(5, typeName); |
| 1270 } | 1294 } |
| 1271 | 1295 |
| 1272 visitDummy(DummyConstantValue constant) { | 1296 @override |
| 1297 visitDummy(DummyConstantValue constant, [_]) { |
| 1273 compiler.internalError(NO_LOCATION_SPANNABLE, | 1298 compiler.internalError(NO_LOCATION_SPANNABLE, |
| 1274 'DummyReceiverConstant should never be named and never be subconstant'); | 1299 'DummyReceiverConstant should never be named and never be subconstant'); |
| 1275 } | 1300 } |
| 1276 | 1301 |
| 1277 visitDeferred(DeferredConstantValue constant) { | 1302 @override |
| 1303 int visitDeferred(DeferredConstantValue constant, [_]) { |
| 1278 int hash = constant.prefix.hashCode; | 1304 int hash = constant.prefix.hashCode; |
| 1279 return _combine(hash, constant.referenced.accept(this)); | 1305 return _combine(hash, _visit(constant.referenced)); |
| 1280 } | 1306 } |
| 1281 | 1307 |
| 1282 int _hashString(int hash, String s) { | 1308 int _hashString(int hash, String s) { |
| 1283 int length = s.length; | 1309 int length = s.length; |
| 1284 hash = _combine(hash, length); | 1310 hash = _combine(hash, length); |
| 1285 // Increasing stride is O(log N) on large strings which are unlikely to have | 1311 // Increasing stride is O(log N) on large strings which are unlikely to have |
| 1286 // many collisions. | 1312 // many collisions. |
| 1287 for (int i = 0; i < length; i += 1 + (i >> 2)) { | 1313 for (int i = 0; i < length; i += 1 + (i >> 2)) { |
| 1288 hash = _combine(hash, s.codeUnitAt(i)); | 1314 hash = _combine(hash, s.codeUnitAt(i)); |
| 1289 } | 1315 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1397 if (!first) { | 1423 if (!first) { |
| 1398 sb.write('_'); | 1424 sb.write('_'); |
| 1399 } | 1425 } |
| 1400 sb.write('_'); | 1426 sb.write('_'); |
| 1401 visit(parameter); | 1427 visit(parameter); |
| 1402 first = true; | 1428 first = true; |
| 1403 } | 1429 } |
| 1404 } | 1430 } |
| 1405 } | 1431 } |
| 1406 } | 1432 } |
| OLD | NEW |