| 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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   166     if (_jsVariableReserved == null) { |   166     if (_jsVariableReserved == null) { | 
|   167       _jsVariableReserved = new Set<String>(); |   167       _jsVariableReserved = new Set<String>(); | 
|   168       _jsVariableReserved.addAll(javaScriptKeywords); |   168       _jsVariableReserved.addAll(javaScriptKeywords); | 
|   169       _jsVariableReserved.addAll(reservedPropertySymbols); |   169       _jsVariableReserved.addAll(reservedPropertySymbols); | 
|   170       _jsVariableReserved.addAll(reservedGlobalSymbols); |   170       _jsVariableReserved.addAll(reservedGlobalSymbols); | 
|   171     } |   171     } | 
|   172     return _jsVariableReserved; |   172     return _jsVariableReserved; | 
|   173   } |   173   } | 
|   174  |   174  | 
|   175   final String CURRENT_ISOLATE; |   175   final String CURRENT_ISOLATE; | 
 |   176   String get SETUP_OBJECT => CURRENT_ISOLATE; | 
|   176  |   177  | 
|   177   final String getterPrefix = r'get$'; |   178   final String getterPrefix = r'get$'; | 
|   178   final String setterPrefix = r'set$'; |   179   final String setterPrefix = r'set$'; | 
|   179   final String metadataField = '@'; |   180   final String metadataField = '@'; | 
|   180  |   181  | 
|   181   /** |   182   /** | 
|   182    * Map from top-level or static elements to their unique identifiers provided |   183    * Map from top-level or static elements to their unique identifiers provided | 
|   183    * by [getName]. |   184    * by [getName]. | 
|   184    * |   185    * | 
|   185    * Invariant: Keys must be declaration elements. |   186    * Invariant: Keys must be declaration elements. | 
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   759   } |   760   } | 
|   760  |   761  | 
|   761   String isolateStaticClosureAccess(Element element) { |   762   String isolateStaticClosureAccess(Element element) { | 
|   762     return "$CURRENT_ISOLATE.${getStaticClosureName(element)}"; |   763     return "$CURRENT_ISOLATE.${getStaticClosureName(element)}"; | 
|   763   } |   764   } | 
|   764  |   765  | 
|   765   String operatorIsPrefix() => r'$is'; |   766   String operatorIsPrefix() => r'$is'; | 
|   766  |   767  | 
|   767   String operatorAsPrefix() => r'$as'; |   768   String operatorAsPrefix() => r'$as'; | 
|   768  |   769  | 
 |   770   String operatorSignature() => r'$signature'; | 
 |   771  | 
 |   772   String functionTypeTag() => r'func'; | 
 |   773  | 
 |   774   String functionTypeVoidReturnTag() => r'void'; | 
 |   775  | 
 |   776   String functionTypeReturnTypeTag() => r'ret'; | 
 |   777  | 
 |   778   String functionTypeRequiredParametersTag() => r'args'; | 
 |   779  | 
 |   780   String functionTypeOptionalParametersTag() => r'opt'; | 
 |   781  | 
 |   782   String functionTypeNamedParametersTag() => r'named'; | 
 |   783  | 
 |   784   Map<FunctionType,String> functionTypeNameMap = | 
 |   785       new Map<FunctionType,String>(); | 
 |   786   FunctionTypeNamer functionTypeNamer = new FunctionTypeNamer(); | 
 |   787  | 
 |   788   String getFunctionTypeName(FunctionType functionType) { | 
 |   789     return functionTypeNameMap.putIfAbsent(functionType, () { | 
 |   790       String proposedName = functionTypeNamer.computeName(functionType); | 
 |   791       String freshName = getFreshName(proposedName, usedInstanceNames, | 
 |   792                                       suggestedInstanceNames, ensureSafe: true); | 
 |   793       return freshName; | 
 |   794     }); | 
 |   795   } | 
 |   796  | 
 |   797   String operatorIsType(DartType type) { | 
 |   798     if (type.kind == TypeKind.FUNCTION) { | 
 |   799       // TODO(erikcorry): Reduce from $isx to ix when we are minifying. | 
 |   800       return '${operatorIsPrefix()}_${getFunctionTypeName(type)}'; | 
 |   801     } | 
 |   802     return operatorIs(type.element); | 
 |   803   } | 
 |   804  | 
|   769   String operatorIs(Element element) { |   805   String operatorIs(Element element) { | 
|   770     // TODO(erikcorry): Reduce from $isx to ix when we are minifying. |   806     // TODO(erikcorry): Reduce from $isx to ix when we are minifying. | 
|   771     return '${operatorIsPrefix()}${getRuntimeTypeName(element)}'; |   807     return '${operatorIsPrefix()}${getRuntimeTypeName(element)}'; | 
|   772   } |   808   } | 
|   773  |   809  | 
|   774   /* |   810   /* | 
|   775    * Returns a name that does not clash with reserved JS keywords, |   811    * Returns a name that does not clash with reserved JS keywords, | 
|   776    * and also ensures it won't clash with other identifiers. |   812    * and also ensures it won't clash with other identifiers. | 
|   777    */ |   813    */ | 
|   778   String _safeName(String name, Set<String> reserved) { |   814   String _safeName(String name, Set<String> reserved) { | 
|   779     if (reserved.contains(name) || name.startsWith(r'$')) { |   815     if (reserved.contains(name) || name.startsWith(r'$')) { | 
|   780       name = '\$$name'; |   816       name = '\$$name'; | 
|   781     } |   817     } | 
|   782     assert(!reserved.contains(name)); |   818     assert(!reserved.contains(name)); | 
|   783     return name; |   819     return name; | 
|   784   } |   820   } | 
|   785  |   821  | 
|   786   String substitutionName(Element element) { |   822   String substitutionName(Element element) { | 
|   787     return '${operatorAsPrefix()}${getName(element)}'; |   823     return '${operatorAsPrefix()}${getName(element)}'; | 
|   788   } |   824   } | 
|   789  |   825  | 
 |   826   String signatureLocation(FunctionType type) { | 
 |   827     ClassElement classElement = Types.getClassContext(type); | 
 |   828     if (classElement != null) { | 
 |   829       return '${isolateAccess(classElement)}'; | 
 |   830     } else { | 
 |   831       return '${SETUP_OBJECT}'; | 
 |   832     } | 
 |   833   } | 
 |   834  | 
 |   835   String signatureName(FunctionType type) { | 
 |   836     String signature = '${operatorSignature()}_${getFunctionTypeName(type)}'; | 
 |   837     return '${signatureLocation(type)}.$signature'; | 
 |   838   } | 
 |   839  | 
|   790   String safeName(String name) => _safeName(name, jsReserved); |   840   String safeName(String name) => _safeName(name, jsReserved); | 
|   791   String safeVariableName(String name) => _safeName(name, jsVariableReserved); |   841   String safeVariableName(String name) => _safeName(name, jsVariableReserved); | 
|   792  |   842  | 
|   793   SourceString operatorNameToIdentifier(SourceString name) { |   843   SourceString operatorNameToIdentifier(SourceString name) { | 
|   794     if (name == null) return null; |   844     if (name == null) return null; | 
|   795     String value = name.stringValue; |   845     String value = name.stringValue; | 
|   796     if (value == null) { |   846     if (value == null) { | 
|   797       return name; |   847       return name; | 
|   798     } else if (value == '==') { |   848     } else if (value == '==') { | 
|   799       return const SourceString(r'$eq'); |   849       return const SourceString(r'$eq'); | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   834     } else if (value == '-') { |   884     } else if (value == '-') { | 
|   835       return const SourceString(r'$sub'); |   885       return const SourceString(r'$sub'); | 
|   836     } else if (value == 'unary-') { |   886     } else if (value == 'unary-') { | 
|   837       return const SourceString(r'$negate'); |   887       return const SourceString(r'$negate'); | 
|   838     } else { |   888     } else { | 
|   839       return name; |   889       return name; | 
|   840     } |   890     } | 
|   841   } |   891   } | 
|   842 } |   892 } | 
|   843  |   893  | 
|   844  |  | 
|   845 /** |   894 /** | 
|   846  * Generator of names for [Constant] values. |   895  * Generator of names for [Constant] values. | 
|   847  * |   896  * | 
|   848  * The names are stable under perturbations of the source.  The name is either a |   897  * The names are stable under perturbations of the source.  The name is either a | 
|   849  * short sequence of words, if this can be found from the constant, or a type |   898  * short sequence of words, if this can be found from the constant, or a type | 
|   850  * followed by a hash tag. |   899  * followed by a hash tag. | 
|   851  * |   900  * | 
|   852  *     List_imX                // A List, with hash tag. |   901  *     List_imX                // A List, with hash tag. | 
|   853  *     C_Sentinel              // const Sentinel(),  "C_" added to avoid clash |   902  *     C_Sentinel              // const Sentinel(),  "C_" added to avoid clash | 
|   854  *                             //   with class name. |   903  *                             //   with class name. | 
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1008     String name = backend.rti.getRawTypeRepresentation(type); |  1057     String name = backend.rti.getRawTypeRepresentation(type); | 
|  1009     addIdentifier(name); |  1058     addIdentifier(name); | 
|  1010   } |  1059   } | 
|  1011  |  1060  | 
|  1012   visitInterceptor(InterceptorConstant constant) { |  1061   visitInterceptor(InterceptorConstant constant) { | 
|  1013     addRoot(constant.dispatchedType.element.name.slowToString()); |  1062     addRoot(constant.dispatchedType.element.name.slowToString()); | 
|  1014     add('methods'); |  1063     add('methods'); | 
|  1015   } |  1064   } | 
|  1016 } |  1065 } | 
|  1017  |  1066  | 
|  1018  |  | 
|  1019 /** |  1067 /** | 
|  1020  * Generates canonical hash values for [Constant]s. |  1068  * Generates canonical hash values for [Constant]s. | 
|  1021  * |  1069  * | 
|  1022  * Unfortunately, [Constant.hashCode] is not stable under minor perturbations, |  1070  * Unfortunately, [Constant.hashCode] is not stable under minor perturbations, | 
|  1023  * so it can't be used for generating names.  This hasher keeps consistency |  1071  * so it can't be used for generating names.  This hasher keeps consistency | 
|  1024  * between runs by basing hash values of the names of elements, rather than |  1072  * between runs by basing hash values of the names of elements, rather than | 
|  1025  * their hashCodes. |  1073  * their hashCodes. | 
|  1026  */ |  1074  */ | 
|  1027 class ConstantCanonicalHasher implements ConstantVisitor<int> { |  1075 class ConstantCanonicalHasher implements ConstantVisitor<int> { | 
|  1028  |  1076  | 
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1154     hash = hash ^ (hash >> 6); |  1202     hash = hash ^ (hash >> 6); | 
|  1155     return hash; |  1203     return hash; | 
|  1156   } |  1204   } | 
|  1157  |  1205  | 
|  1158   static int _finish(int hash) { |  1206   static int _finish(int hash) { | 
|  1159     hash = _MASK & (hash + (((_MASK >> 3) & hash) <<  3)); |  1207     hash = _MASK & (hash + (((_MASK >> 3) & hash) <<  3)); | 
|  1160     hash = hash & (hash >> 11); |  1208     hash = hash & (hash >> 11); | 
|  1161     return _MASK & (hash + (((_MASK >> 15) & hash) << 15)); |  1209     return _MASK & (hash + (((_MASK >> 15) & hash) << 15)); | 
|  1162   } |  1210   } | 
|  1163 } |  1211 } | 
 |  1212  | 
 |  1213 class FunctionTypeNamer extends DartTypeVisitor { | 
 |  1214   StringBuffer sb; | 
 |  1215  | 
 |  1216   String computeName(DartType type) { | 
 |  1217     sb = new StringBuffer(); | 
 |  1218     visit(type); | 
 |  1219     return sb.toString(); | 
 |  1220   } | 
 |  1221  | 
 |  1222   visit(DartType type) { | 
 |  1223     type.accept(this, null); | 
 |  1224   } | 
 |  1225  | 
 |  1226   visitType(DartType type, _) { | 
 |  1227     sb.write(type.name.slowToString()); | 
 |  1228   } | 
 |  1229  | 
 |  1230   visitFunctionType(FunctionType type, _) { | 
 |  1231     visit(type.returnType); | 
 |  1232     sb.write('_'); | 
 |  1233     for (Link<DartType> link = type.parameterTypes; | 
 |  1234          !link.isEmpty; | 
 |  1235          link = link.tail) { | 
 |  1236       sb.write('_'); | 
 |  1237       visit(link.head); | 
 |  1238     } | 
 |  1239     bool first = false; | 
 |  1240     for (Link<DartType> link = type.optionalParameterTypes; | 
 |  1241          !link.isEmpty; | 
 |  1242          link = link.tail) { | 
 |  1243       if (!first) { | 
 |  1244         sb.write('_'); | 
 |  1245       } | 
 |  1246       sb.write('_'); | 
 |  1247       visit(link.head); | 
 |  1248       first = true; | 
 |  1249     } | 
 |  1250     if (!type.namedParameterTypes.isEmpty) { | 
 |  1251       first = false; | 
 |  1252       for (Link<DartType> link = type.namedParameterTypes; | 
 |  1253           !link.isEmpty; | 
 |  1254           link = link.tail) { | 
 |  1255         if (!first) { | 
 |  1256           sb.write('_'); | 
 |  1257         } | 
 |  1258         sb.write('_'); | 
 |  1259         visit(link.head); | 
 |  1260         first = true; | 
 |  1261       } | 
 |  1262     } | 
 |  1263   } | 
 |  1264 } | 
| OLD | NEW |