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 js_backend; | 5 part of js_backend; |
6 | 6 |
7 const VERBOSE_OPTIMIZER_HINTS = false; | 7 const VERBOSE_OPTIMIZER_HINTS = false; |
8 | 8 |
9 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 functionCompiler = compiler.useCpsIr | 674 functionCompiler = compiler.useCpsIr |
675 ? new CpsFunctionCompiler( | 675 ? new CpsFunctionCompiler( |
676 compiler, this, sourceInformationStrategy) | 676 compiler, this, sourceInformationStrategy) |
677 : new SsaFunctionCompiler(this, sourceInformationStrategy); | 677 : new SsaFunctionCompiler(this, sourceInformationStrategy); |
678 } | 678 } |
679 | 679 |
680 ConstantSystem get constantSystem => constants.constantSystem; | 680 ConstantSystem get constantSystem => constants.constantSystem; |
681 | 681 |
682 DiagnosticReporter get reporter => compiler.reporter; | 682 DiagnosticReporter get reporter => compiler.reporter; |
683 | 683 |
| 684 CoreClasses get coreClasses => compiler.coreClasses; |
| 685 |
| 686 CoreTypes get coreTypes => compiler.coreTypes; |
| 687 |
684 Resolution get resolution => compiler.resolution; | 688 Resolution get resolution => compiler.resolution; |
685 | 689 |
686 /// Returns constant environment for the JavaScript interpretation of the | 690 /// Returns constant environment for the JavaScript interpretation of the |
687 /// constants. | 691 /// constants. |
688 JavaScriptConstantCompiler get constants { | 692 JavaScriptConstantCompiler get constants { |
689 return constantCompilerTask.jsConstantCompiler; | 693 return constantCompilerTask.jsConstantCompiler; |
690 } | 694 } |
691 | 695 |
692 FunctionElement resolveExternalFunction(FunctionElement element) { | 696 FunctionElement resolveExternalFunction(FunctionElement element) { |
693 if (isForeign(element) || isJsInterop(element)) return element; | 697 if (isForeign(element) || isJsInterop(element)) return element; |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1063 | 1067 |
1064 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { | 1068 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { |
1065 return specialOperatorEqClasses.contains( | 1069 return specialOperatorEqClasses.contains( |
1066 operatorEqfunction.enclosingClass); | 1070 operatorEqfunction.enclosingClass); |
1067 } | 1071 } |
1068 | 1072 |
1069 void validateInterceptorImplementsAllObjectMethods( | 1073 void validateInterceptorImplementsAllObjectMethods( |
1070 ClassElement interceptorClass) { | 1074 ClassElement interceptorClass) { |
1071 if (interceptorClass == null) return; | 1075 if (interceptorClass == null) return; |
1072 interceptorClass.ensureResolved(resolution); | 1076 interceptorClass.ensureResolved(resolution); |
1073 compiler.objectClass.forEachMember((_, Element member) { | 1077 coreClasses.objectClass.forEachMember((_, Element member) { |
1074 if (member.isGenerativeConstructor) return; | 1078 if (member.isGenerativeConstructor) return; |
1075 Element interceptorMember = interceptorClass.lookupMember(member.name); | 1079 Element interceptorMember = interceptorClass.lookupMember(member.name); |
1076 // Interceptors must override all Object methods due to calling convention | 1080 // Interceptors must override all Object methods due to calling convention |
1077 // differences. | 1081 // differences. |
1078 assert(interceptorMember.enclosingClass == interceptorClass); | 1082 assert(interceptorMember.enclosingClass == interceptorClass); |
1079 }); | 1083 }); |
1080 } | 1084 } |
1081 | 1085 |
1082 void addInterceptorsForNativeClassMembers( | 1086 void addInterceptorsForNativeClassMembers( |
1083 ClassElement cls, Enqueuer enqueuer) { | 1087 ClassElement cls, Enqueuer enqueuer) { |
1084 if (enqueuer.isResolutionQueue) { | 1088 if (enqueuer.isResolutionQueue) { |
1085 cls.ensureResolved(resolution); | 1089 cls.ensureResolved(resolution); |
1086 cls.forEachMember((ClassElement classElement, Element member) { | 1090 cls.forEachMember((ClassElement classElement, Element member) { |
1087 if (member.name == Identifiers.call) { | 1091 if (member.name == Identifiers.call) { |
1088 reporter.reportErrorMessage( | 1092 reporter.reportErrorMessage( |
1089 member, | 1093 member, |
1090 MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); | 1094 MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS); |
1091 return; | 1095 return; |
1092 } | 1096 } |
1093 if (member.isSynthesized) return; | 1097 if (member.isSynthesized) return; |
1094 // All methods on [Object] are shadowed by [Interceptor]. | 1098 // All methods on [Object] are shadowed by [Interceptor]. |
1095 if (classElement == compiler.objectClass) return; | 1099 if (classElement == coreClasses.objectClass) return; |
1096 Set<Element> set = interceptedElements.putIfAbsent( | 1100 Set<Element> set = interceptedElements.putIfAbsent( |
1097 member.name, () => new Set<Element>()); | 1101 member.name, () => new Set<Element>()); |
1098 set.add(member); | 1102 set.add(member); |
1099 }, | 1103 }, |
1100 includeSuperAndInjectedMembers: true); | 1104 includeSuperAndInjectedMembers: true); |
1101 | 1105 |
1102 // Walk superclass chain to find mixins. | 1106 // Walk superclass chain to find mixins. |
1103 for (; cls != null; cls = cls.superclass) { | 1107 for (; cls != null; cls = cls.superclass) { |
1104 if (cls.isMixinApplication) { | 1108 if (cls.isMixinApplication) { |
1105 MixinApplicationElement mixinApplication = cls; | 1109 MixinApplicationElement mixinApplication = cls; |
1106 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); | 1110 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); |
1107 } | 1111 } |
1108 } | 1112 } |
1109 } | 1113 } |
1110 } | 1114 } |
1111 | 1115 |
1112 void addInterceptors(ClassElement cls, | 1116 void addInterceptors(ClassElement cls, |
1113 Enqueuer enqueuer, | 1117 Enqueuer enqueuer, |
1114 Registry registry) { | 1118 Registry registry) { |
1115 if (enqueuer.isResolutionQueue) { | 1119 if (enqueuer.isResolutionQueue) { |
1116 _interceptedClasses.add(jsInterceptorClass); | 1120 _interceptedClasses.add(jsInterceptorClass); |
1117 _interceptedClasses.add(cls); | 1121 _interceptedClasses.add(cls); |
1118 cls.ensureResolved(resolution); | 1122 cls.ensureResolved(resolution); |
1119 cls.forEachMember((ClassElement classElement, Element member) { | 1123 cls.forEachMember((ClassElement classElement, Element member) { |
1120 // All methods on [Object] are shadowed by [Interceptor]. | 1124 // All methods on [Object] are shadowed by [Interceptor]. |
1121 if (classElement == compiler.objectClass) return; | 1125 if (classElement == coreClasses.objectClass) return; |
1122 Set<Element> set = interceptedElements.putIfAbsent( | 1126 Set<Element> set = interceptedElements.putIfAbsent( |
1123 member.name, () => new Set<Element>()); | 1127 member.name, () => new Set<Element>()); |
1124 set.add(member); | 1128 set.add(member); |
1125 }, | 1129 }, |
1126 includeSuperAndInjectedMembers: true); | 1130 includeSuperAndInjectedMembers: true); |
1127 } | 1131 } |
1128 enqueueClass(enqueuer, cls, registry); | 1132 enqueueClass(enqueuer, cls, registry); |
1129 } | 1133 } |
1130 | 1134 |
1131 Set<ClassElement> get interceptedClasses { | 1135 Set<ClassElement> get interceptedClasses { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1177 registerInstantiatedConstantType(interceptor.dispatchedType, registry); | 1181 registerInstantiatedConstantType(interceptor.dispatchedType, registry); |
1178 } else if (constant.isType) { | 1182 } else if (constant.isType) { |
1179 enqueueInResolution(helpers.createRuntimeType, registry); | 1183 enqueueInResolution(helpers.createRuntimeType, registry); |
1180 registry.registerInstantiation(typeImplementation.rawType); | 1184 registry.registerInstantiation(typeImplementation.rawType); |
1181 } | 1185 } |
1182 lookupMapAnalysis.registerConstantKey(constant); | 1186 lookupMapAnalysis.registerConstantKey(constant); |
1183 } | 1187 } |
1184 | 1188 |
1185 void registerInstantiatedConstantType(DartType type, Registry registry) { | 1189 void registerInstantiatedConstantType(DartType type, Registry registry) { |
1186 DartType instantiatedType = | 1190 DartType instantiatedType = |
1187 type.isFunctionType ? compiler.functionClass.rawType : type; | 1191 type.isFunctionType ? coreTypes.functionType : type; |
1188 if (type is InterfaceType) { | 1192 if (type is InterfaceType) { |
1189 registry.registerInstantiation(instantiatedType); | 1193 registry.registerInstantiation(instantiatedType); |
1190 if (!type.treatAsRaw && classNeedsRti(type.element)) { | 1194 if (!type.treatAsRaw && classNeedsRti(type.element)) { |
1191 registry.registerStaticInvocation(helpers.setRuntimeTypeInfo); | 1195 registry.registerStaticInvocation(helpers.setRuntimeTypeInfo); |
1192 } | 1196 } |
1193 if (type.element == typeImplementation) { | 1197 if (type.element == typeImplementation) { |
1194 // If we use a type literal in a constant, the compile time | 1198 // If we use a type literal in a constant, the compile time |
1195 // constant emitter will generate a call to the createRuntimeType | 1199 // constant emitter will generate a call to the createRuntimeType |
1196 // helper so we register a use of that. | 1200 // helper so we register a use of that. |
1197 registry.registerStaticInvocation(helpers.createRuntimeType); | 1201 registry.registerStaticInvocation(helpers.createRuntimeType); |
(...skipping 25 matching lines...) Expand all Loading... |
1223 void _processClass(ClassElement cls, | 1227 void _processClass(ClassElement cls, |
1224 Enqueuer enqueuer, | 1228 Enqueuer enqueuer, |
1225 Registry registry) { | 1229 Registry registry) { |
1226 if (!cls.typeVariables.isEmpty) { | 1230 if (!cls.typeVariables.isEmpty) { |
1227 typeVariableHandler.registerClassWithTypeVariables(cls, enqueuer, | 1231 typeVariableHandler.registerClassWithTypeVariables(cls, enqueuer, |
1228 registry); | 1232 registry); |
1229 } | 1233 } |
1230 | 1234 |
1231 // Register any helper that will be needed by the backend. | 1235 // Register any helper that will be needed by the backend. |
1232 if (enqueuer.isResolutionQueue) { | 1236 if (enqueuer.isResolutionQueue) { |
1233 if (cls == compiler.intClass | 1237 if (cls == coreClasses.intClass || |
1234 || cls == compiler.doubleClass | 1238 cls == coreClasses.doubleClass || |
1235 || cls == compiler.numClass) { | 1239 cls == coreClasses.numClass) { |
1236 // The backend will try to optimize number operations and use the | 1240 // The backend will try to optimize number operations and use the |
1237 // `iae` helper directly. | 1241 // `iae` helper directly. |
1238 enqueue(enqueuer, findHelper('iae'), registry); | 1242 enqueue(enqueuer, findHelper('iae'), registry); |
1239 } else if (cls == compiler.listClass | 1243 } else if (cls == coreClasses.listClass || |
1240 || cls == compiler.stringClass) { | 1244 cls == coreClasses.stringClass) { |
1241 // The backend will try to optimize array and string access and use the | 1245 // The backend will try to optimize array and string access and use the |
1242 // `ioore` and `iae` helpers directly. | 1246 // `ioore` and `iae` helpers directly. |
1243 enqueue(enqueuer, findHelper('ioore'), registry); | 1247 enqueue(enqueuer, findHelper('ioore'), registry); |
1244 enqueue(enqueuer, findHelper('iae'), registry); | 1248 enqueue(enqueuer, findHelper('iae'), registry); |
1245 } else if (cls == compiler.functionClass) { | 1249 } else if (cls == coreClasses.functionClass) { |
1246 enqueueClass(enqueuer, closureClass, registry); | 1250 enqueueClass(enqueuer, closureClass, registry); |
1247 } else if (cls == compiler.mapClass) { | 1251 } else if (cls == coreClasses.mapClass) { |
1248 // The backend will use a literal list to initialize the entries | 1252 // The backend will use a literal list to initialize the entries |
1249 // of the map. | 1253 // of the map. |
1250 enqueueClass(enqueuer, compiler.listClass, registry); | 1254 enqueueClass(enqueuer, coreClasses.listClass, registry); |
1251 enqueueClass(enqueuer, mapLiteralClass, registry); | 1255 enqueueClass(enqueuer, mapLiteralClass, registry); |
1252 // For map literals, the dependency between the implementation class | 1256 // For map literals, the dependency between the implementation class |
1253 // and [Map] is not visible, so we have to add it manually. | 1257 // and [Map] is not visible, so we have to add it manually. |
1254 rti.registerRtiDependency(mapLiteralClass, cls); | 1258 rti.registerRtiDependency(mapLiteralClass, cls); |
1255 } else if (cls == boundClosureClass) { | 1259 } else if (cls == boundClosureClass) { |
1256 // TODO(johnniwinther): Is this a noop? | 1260 // TODO(johnniwinther): Is this a noop? |
1257 enqueueClass(enqueuer, boundClosureClass, registry); | 1261 enqueueClass(enqueuer, boundClosureClass, registry); |
1258 } else if (isNativeOrExtendsNative(cls)) { | 1262 } else if (isNativeOrExtendsNative(cls)) { |
1259 enqueue(enqueuer, getNativeInterceptorMethod, registry); | 1263 enqueue(enqueuer, getNativeInterceptorMethod, registry); |
1260 enqueueClass(enqueuer, jsInterceptorClass, compiler.globalDependencies); | 1264 enqueueClass(enqueuer, jsInterceptorClass, compiler.globalDependencies); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1298 | 1302 |
1299 mapLiteralUntypedMaker = getMember('_makeLiteral'); | 1303 mapLiteralUntypedMaker = getMember('_makeLiteral'); |
1300 mapLiteralUntypedEmptyMaker = getMember('_makeEmpty'); | 1304 mapLiteralUntypedEmptyMaker = getMember('_makeEmpty'); |
1301 enqueueInResolution(mapLiteralUntypedMaker, registry); | 1305 enqueueInResolution(mapLiteralUntypedMaker, registry); |
1302 enqueueInResolution(mapLiteralUntypedEmptyMaker, registry); | 1306 enqueueInResolution(mapLiteralUntypedEmptyMaker, registry); |
1303 } | 1307 } |
1304 } | 1308 } |
1305 if (cls == closureClass) { | 1309 if (cls == closureClass) { |
1306 enqueue(enqueuer, findHelper('closureFromTearOff'), registry); | 1310 enqueue(enqueuer, findHelper('closureFromTearOff'), registry); |
1307 } | 1311 } |
1308 if (cls == compiler.stringClass || cls == jsStringClass) { | 1312 if (cls == coreClasses.stringClass || |
| 1313 cls == jsStringClass) { |
1309 addInterceptors(jsStringClass, enqueuer, registry); | 1314 addInterceptors(jsStringClass, enqueuer, registry); |
1310 } else if (cls == compiler.listClass || | 1315 } else if (cls == coreClasses.listClass || |
1311 cls == jsArrayClass || | 1316 cls == jsArrayClass || |
1312 cls == jsFixedArrayClass || | 1317 cls == jsFixedArrayClass || |
1313 cls == jsExtendableArrayClass || | 1318 cls == jsExtendableArrayClass || |
1314 cls == jsUnmodifiableArrayClass) { | 1319 cls == jsUnmodifiableArrayClass) { |
1315 addInterceptors(jsArrayClass, enqueuer, registry); | 1320 addInterceptors(jsArrayClass, enqueuer, registry); |
1316 addInterceptors(jsMutableArrayClass, enqueuer, registry); | 1321 addInterceptors(jsMutableArrayClass, enqueuer, registry); |
1317 addInterceptors(jsFixedArrayClass, enqueuer, registry); | 1322 addInterceptors(jsFixedArrayClass, enqueuer, registry); |
1318 addInterceptors(jsExtendableArrayClass, enqueuer, registry); | 1323 addInterceptors(jsExtendableArrayClass, enqueuer, registry); |
1319 addInterceptors(jsUnmodifiableArrayClass, enqueuer, registry); | 1324 addInterceptors(jsUnmodifiableArrayClass, enqueuer, registry); |
1320 } else if (cls == compiler.intClass || cls == jsIntClass) { | 1325 } else if (cls == coreClasses.intClass || |
| 1326 cls == jsIntClass) { |
1321 addInterceptors(jsIntClass, enqueuer, registry); | 1327 addInterceptors(jsIntClass, enqueuer, registry); |
1322 addInterceptors(jsPositiveIntClass, enqueuer, registry); | 1328 addInterceptors(jsPositiveIntClass, enqueuer, registry); |
1323 addInterceptors(jsUInt32Class, enqueuer, registry); | 1329 addInterceptors(jsUInt32Class, enqueuer, registry); |
1324 addInterceptors(jsUInt31Class, enqueuer, registry); | 1330 addInterceptors(jsUInt31Class, enqueuer, registry); |
1325 addInterceptors(jsNumberClass, enqueuer, registry); | 1331 addInterceptors(jsNumberClass, enqueuer, registry); |
1326 } else if (cls == compiler.doubleClass || cls == jsDoubleClass) { | 1332 } else if (cls == coreClasses.doubleClass || |
| 1333 cls == jsDoubleClass) { |
1327 addInterceptors(jsDoubleClass, enqueuer, registry); | 1334 addInterceptors(jsDoubleClass, enqueuer, registry); |
1328 addInterceptors(jsNumberClass, enqueuer, registry); | 1335 addInterceptors(jsNumberClass, enqueuer, registry); |
1329 } else if (cls == compiler.boolClass || cls == jsBoolClass) { | 1336 } else if (cls == coreClasses.boolClass || |
| 1337 cls == jsBoolClass) { |
1330 addInterceptors(jsBoolClass, enqueuer, registry); | 1338 addInterceptors(jsBoolClass, enqueuer, registry); |
1331 } else if (cls == compiler.nullClass || cls == jsNullClass) { | 1339 } else if (cls == coreClasses.nullClass || |
| 1340 cls == jsNullClass) { |
1332 addInterceptors(jsNullClass, enqueuer, registry); | 1341 addInterceptors(jsNullClass, enqueuer, registry); |
1333 } else if (cls == compiler.numClass || cls == jsNumberClass) { | 1342 } else if (cls == coreClasses.numClass || |
| 1343 cls == jsNumberClass) { |
1334 addInterceptors(jsIntClass, enqueuer, registry); | 1344 addInterceptors(jsIntClass, enqueuer, registry); |
1335 addInterceptors(jsPositiveIntClass, enqueuer, registry); | 1345 addInterceptors(jsPositiveIntClass, enqueuer, registry); |
1336 addInterceptors(jsUInt32Class, enqueuer, registry); | 1346 addInterceptors(jsUInt32Class, enqueuer, registry); |
1337 addInterceptors(jsUInt31Class, enqueuer, registry); | 1347 addInterceptors(jsUInt31Class, enqueuer, registry); |
1338 addInterceptors(jsDoubleClass, enqueuer, registry); | 1348 addInterceptors(jsDoubleClass, enqueuer, registry); |
1339 addInterceptors(jsNumberClass, enqueuer, registry); | 1349 addInterceptors(jsNumberClass, enqueuer, registry); |
1340 } else if (cls == jsJavaScriptObjectClass) { | 1350 } else if (cls == jsJavaScriptObjectClass) { |
1341 addInterceptors(jsJavaScriptObjectClass, enqueuer, registry); | 1351 addInterceptors(jsJavaScriptObjectClass, enqueuer, registry); |
1342 } else if (cls == jsPlainJavaScriptObjectClass) { | 1352 } else if (cls == jsPlainJavaScriptObjectClass) { |
1343 addInterceptors(jsPlainJavaScriptObjectClass, enqueuer, registry); | 1353 addInterceptors(jsPlainJavaScriptObjectClass, enqueuer, registry); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1477 // therefore need to enqueue the used elements in the codegen enqueuer as | 1487 // therefore need to enqueue the used elements in the codegen enqueuer as |
1478 // well as in the resolution enqueuer. | 1488 // well as in the resolution enqueuer. |
1479 enqueueImpact(enqueuer, impacts.computeSignature, registry); | 1489 enqueueImpact(enqueuer, impacts.computeSignature, registry); |
1480 } | 1490 } |
1481 | 1491 |
1482 void registerRuntimeType(Enqueuer enqueuer, Registry registry) { | 1492 void registerRuntimeType(Enqueuer enqueuer, Registry registry) { |
1483 registerComputeSignature(enqueuer, registry); | 1493 registerComputeSignature(enqueuer, registry); |
1484 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); | 1494 enqueueInResolution(helpers.setRuntimeTypeInfo, registry); |
1485 registerGetRuntimeTypeArgument(registry); | 1495 registerGetRuntimeTypeArgument(registry); |
1486 enqueueInResolution(helpers.getRuntimeTypeInfo, registry); | 1496 enqueueInResolution(helpers.getRuntimeTypeInfo, registry); |
1487 enqueueClass(enqueuer, compiler.listClass, registry); | 1497 enqueueClass(enqueuer, coreClasses.listClass, registry); |
1488 } | 1498 } |
1489 | 1499 |
1490 void registerIsCheckForCodegen(DartType type, | 1500 void registerIsCheckForCodegen(DartType type, |
1491 Enqueuer world, | 1501 Enqueuer world, |
1492 Registry registry) { | 1502 Registry registry) { |
1493 assert(!registry.isForResolution); | 1503 assert(!registry.isForResolution); |
1494 type = type.unaliased; | 1504 type = type.unaliased; |
1495 enqueueClass(world, compiler.boolClass, registry); | 1505 enqueueClass(world, coreClasses.boolClass, registry); |
1496 bool inCheckedMode = compiler.enableTypeAssertions; | 1506 bool inCheckedMode = compiler.enableTypeAssertions; |
1497 // [registerIsCheck] is also called for checked mode checks, so we | 1507 // [registerIsCheck] is also called for checked mode checks, so we |
1498 // need to register checked mode helpers. | 1508 // need to register checked mode helpers. |
1499 if (inCheckedMode) { | 1509 if (inCheckedMode) { |
1500 // All helpers are added to resolution queue in enqueueHelpers. These | 1510 // All helpers are added to resolution queue in enqueueHelpers. These |
1501 // calls to enqueueInResolution serve as assertions that the helper was | 1511 // calls to enqueueInResolution serve as assertions that the helper was |
1502 // in fact added. | 1512 // in fact added. |
1503 // TODO(13155): Find a way to enqueue helpers lazily. | 1513 // TODO(13155): Find a way to enqueue helpers lazily. |
1504 CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: false); | 1514 CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: false); |
1505 if (helper != null) { | 1515 if (helper != null) { |
1506 enqueue(world, helper.getElement(compiler), registry); | 1516 enqueue(world, helper.getElement(compiler), registry); |
1507 } | 1517 } |
1508 // We also need the native variant of the check (for DOM types). | 1518 // We also need the native variant of the check (for DOM types). |
1509 helper = getNativeCheckedModeHelper(type, typeCast: false); | 1519 helper = getNativeCheckedModeHelper(type, typeCast: false); |
1510 if (helper != null) { | 1520 if (helper != null) { |
1511 enqueue(world, helper.getElement(compiler), registry); | 1521 enqueue(world, helper.getElement(compiler), registry); |
1512 } | 1522 } |
1513 } | 1523 } |
1514 if (!type.treatAsRaw || type.containsTypeVariables) { | 1524 if (!type.treatAsRaw || type.containsTypeVariables) { |
1515 enqueueClass(world, compiler.listClass, registry); | 1525 enqueueClass(world, coreClasses.listClass, registry); |
1516 } | 1526 } |
1517 if (type.element != null && isNative(type.element)) { | 1527 if (type.element != null && isNative(type.element)) { |
1518 // We will neeed to add the "$is" and "$as" properties on the | 1528 // We will neeed to add the "$is" and "$as" properties on the |
1519 // JavaScript object prototype, so we make sure | 1529 // JavaScript object prototype, so we make sure |
1520 // [:defineProperty:] is compiled. | 1530 // [:defineProperty:] is compiled. |
1521 enqueue(world, findHelper('defineProperty'), registry); | 1531 enqueue(world, findHelper('defineProperty'), registry); |
1522 } | 1532 } |
1523 } | 1533 } |
1524 | 1534 |
1525 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, | 1535 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, |
1526 DartType bound) { | 1536 DartType bound) { |
1527 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); | 1537 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); |
1528 } | 1538 } |
1529 | 1539 |
1530 void registerCheckDeferredIsLoaded(Registry registry) { | 1540 void registerCheckDeferredIsLoaded(Registry registry) { |
1531 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); | 1541 enqueueInResolution(helpers.checkDeferredIsLoaded, registry); |
1532 // Also register the types of the arguments passed to this method. | 1542 // Also register the types of the arguments passed to this method. |
1533 enqueueClass(compiler.enqueuer.resolution, compiler.stringClass, registry); | 1543 enqueueClass( |
| 1544 compiler.enqueuer.resolution, coreClasses.stringClass, registry); |
1534 } | 1545 } |
1535 | 1546 |
1536 void registerNoSuchMethod(FunctionElement noSuchMethod) { | 1547 void registerNoSuchMethod(FunctionElement noSuchMethod) { |
1537 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod); | 1548 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod); |
1538 } | 1549 } |
1539 | 1550 |
1540 /// Called when resolving a call to a foreign function. | 1551 /// Called when resolving a call to a foreign function. |
1541 void registerForeignCall(Send node, | 1552 void registerForeignCall(Send node, |
1542 Element element, | 1553 Element element, |
1543 CallStructure callStructure, | 1554 CallStructure callStructure, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1608 return rti.classesNeedingRti.contains(cls.declaration) || | 1619 return rti.classesNeedingRti.contains(cls.declaration) || |
1609 compiler.enabledRuntimeType; | 1620 compiler.enabledRuntimeType; |
1610 } | 1621 } |
1611 | 1622 |
1612 bool isComplexNoSuchMethod(FunctionElement element) => | 1623 bool isComplexNoSuchMethod(FunctionElement element) => |
1613 noSuchMethodRegistry.isComplex(element); | 1624 noSuchMethodRegistry.isComplex(element); |
1614 | 1625 |
1615 bool isDefaultEqualityImplementation(Element element) { | 1626 bool isDefaultEqualityImplementation(Element element) { |
1616 assert(element.name == '=='); | 1627 assert(element.name == '=='); |
1617 ClassElement classElement = element.enclosingClass; | 1628 ClassElement classElement = element.enclosingClass; |
1618 return classElement == compiler.objectClass | 1629 return classElement == coreClasses.objectClass |
1619 || classElement == jsInterceptorClass | 1630 || classElement == jsInterceptorClass |
1620 || classElement == jsNullClass; | 1631 || classElement == jsNullClass; |
1621 } | 1632 } |
1622 | 1633 |
1623 bool methodNeedsRti(FunctionElement function) { | 1634 bool methodNeedsRti(FunctionElement function) { |
1624 return rti.methodsNeedingRti.contains(function) || | 1635 return rti.methodsNeedingRti.contains(function) || |
1625 compiler.enabledRuntimeType; | 1636 compiler.enabledRuntimeType; |
1626 } | 1637 } |
1627 | 1638 |
1628 /// The backend must *always* call this method when enqueuing an | 1639 /// The backend must *always* call this method when enqueuing an |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1752 return new native.NativeResolutionEnqueuer(world, compiler); | 1763 return new native.NativeResolutionEnqueuer(world, compiler); |
1753 } | 1764 } |
1754 | 1765 |
1755 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { | 1766 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { |
1756 return new native.NativeCodegenEnqueuer(world, compiler, emitter); | 1767 return new native.NativeCodegenEnqueuer(world, compiler, emitter); |
1757 } | 1768 } |
1758 | 1769 |
1759 ClassElement defaultSuperclass(ClassElement element) { | 1770 ClassElement defaultSuperclass(ClassElement element) { |
1760 if (isJsInterop(element)) return jsJavaScriptObjectClass; | 1771 if (isJsInterop(element)) return jsJavaScriptObjectClass; |
1761 // Native classes inherit from Interceptor. | 1772 // Native classes inherit from Interceptor. |
1762 return isNative(element) ? jsInterceptorClass : compiler.objectClass; | 1773 return isNative(element) ? jsInterceptorClass : coreClasses.objectClass; |
1763 } | 1774 } |
1764 | 1775 |
1765 /** | 1776 /** |
1766 * Unit test hook that returns code of an element as a String. | 1777 * Unit test hook that returns code of an element as a String. |
1767 * | 1778 * |
1768 * Invariant: [element] must be a declaration element. | 1779 * Invariant: [element] must be a declaration element. |
1769 */ | 1780 */ |
1770 String getGeneratedCode(Element element) { | 1781 String getGeneratedCode(Element element) { |
1771 assert(invariant(element, element.isDeclaration)); | 1782 assert(invariant(element, element.isDeclaration)); |
1772 return jsAst.prettyPrint(generatedCode[element], compiler).getText(); | 1783 return jsAst.prettyPrint(generatedCode[element], compiler).getText(); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1865 | 1876 |
1866 // TODO(13955), TODO(9731). The test for non-primitive types should use an | 1877 // TODO(13955), TODO(9731). The test for non-primitive types should use an |
1867 // interceptor. The interceptor should be an argument to HTypeConversion so | 1878 // interceptor. The interceptor should be an argument to HTypeConversion so |
1868 // that it can be optimized by standard interceptor optimizations. | 1879 // that it can be optimized by standard interceptor optimizations. |
1869 nativeCheck = true; | 1880 nativeCheck = true; |
1870 | 1881 |
1871 if (type.isVoid) { | 1882 if (type.isVoid) { |
1872 assert(!typeCast); // Cannot cast to void. | 1883 assert(!typeCast); // Cannot cast to void. |
1873 if (nativeCheckOnly) return null; | 1884 if (nativeCheckOnly) return null; |
1874 return 'voidTypeCheck'; | 1885 return 'voidTypeCheck'; |
1875 } else if (element == jsStringClass || element == compiler.stringClass) { | 1886 } else if (element == jsStringClass || |
| 1887 element == coreClasses.stringClass) { |
1876 if (nativeCheckOnly) return null; | 1888 if (nativeCheckOnly) return null; |
1877 return typeCast | 1889 return typeCast |
1878 ? 'stringTypeCast' | 1890 ? 'stringTypeCast' |
1879 : 'stringTypeCheck'; | 1891 : 'stringTypeCheck'; |
1880 } else if (element == jsDoubleClass || element == compiler.doubleClass) { | 1892 } else if (element == jsDoubleClass || |
| 1893 element == coreClasses.doubleClass) { |
1881 if (nativeCheckOnly) return null; | 1894 if (nativeCheckOnly) return null; |
1882 return typeCast | 1895 return typeCast |
1883 ? 'doubleTypeCast' | 1896 ? 'doubleTypeCast' |
1884 : 'doubleTypeCheck'; | 1897 : 'doubleTypeCheck'; |
1885 } else if (element == jsNumberClass || element == compiler.numClass) { | 1898 } else if (element == jsNumberClass || |
| 1899 element == coreClasses.numClass) { |
1886 if (nativeCheckOnly) return null; | 1900 if (nativeCheckOnly) return null; |
1887 return typeCast | 1901 return typeCast |
1888 ? 'numTypeCast' | 1902 ? 'numTypeCast' |
1889 : 'numTypeCheck'; | 1903 : 'numTypeCheck'; |
1890 } else if (element == jsBoolClass || element == compiler.boolClass) { | 1904 } else if (element == jsBoolClass || |
| 1905 element == coreClasses.boolClass) { |
1891 if (nativeCheckOnly) return null; | 1906 if (nativeCheckOnly) return null; |
1892 return typeCast | 1907 return typeCast |
1893 ? 'boolTypeCast' | 1908 ? 'boolTypeCast' |
1894 : 'boolTypeCheck'; | 1909 : 'boolTypeCheck'; |
1895 } else if (element == jsIntClass || element == compiler.intClass | 1910 } else if (element == jsIntClass || |
1896 || element == jsUInt32Class || element == jsUInt31Class | 1911 element == coreClasses.intClass || |
1897 || element == jsPositiveIntClass) { | 1912 element == jsUInt32Class || |
| 1913 element == jsUInt31Class || |
| 1914 element == jsPositiveIntClass) { |
1898 if (nativeCheckOnly) return null; | 1915 if (nativeCheckOnly) return null; |
1899 return typeCast | 1916 return typeCast |
1900 ? 'intTypeCast' | 1917 ? 'intTypeCast' |
1901 : 'intTypeCheck'; | 1918 : 'intTypeCheck'; |
1902 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { | 1919 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { |
1903 if (nativeCheck) { | 1920 if (nativeCheck) { |
1904 return typeCast | 1921 return typeCast |
1905 ? 'numberOrStringSuperNativeTypeCast' | 1922 ? 'numberOrStringSuperNativeTypeCast' |
1906 : 'numberOrStringSuperNativeTypeCheck'; | 1923 : 'numberOrStringSuperNativeTypeCheck'; |
1907 } else { | 1924 } else { |
1908 return typeCast | 1925 return typeCast |
1909 ? 'numberOrStringSuperTypeCast' | 1926 ? 'numberOrStringSuperTypeCast' |
1910 : 'numberOrStringSuperTypeCheck'; | 1927 : 'numberOrStringSuperTypeCheck'; |
1911 } | 1928 } |
1912 } else if (Elements.isStringOnlySupertype(element, compiler)) { | 1929 } else if (Elements.isStringOnlySupertype(element, compiler)) { |
1913 if (nativeCheck) { | 1930 if (nativeCheck) { |
1914 return typeCast | 1931 return typeCast |
1915 ? 'stringSuperNativeTypeCast' | 1932 ? 'stringSuperNativeTypeCast' |
1916 : 'stringSuperNativeTypeCheck'; | 1933 : 'stringSuperNativeTypeCheck'; |
1917 } else { | 1934 } else { |
1918 return typeCast | 1935 return typeCast |
1919 ? 'stringSuperTypeCast' | 1936 ? 'stringSuperTypeCast' |
1920 : 'stringSuperTypeCheck'; | 1937 : 'stringSuperTypeCheck'; |
1921 } | 1938 } |
1922 } else if ((element == compiler.listClass || element == jsArrayClass) && | 1939 } else if ((element == coreClasses.listClass || |
| 1940 element == jsArrayClass) && |
1923 type.treatAsRaw) { | 1941 type.treatAsRaw) { |
1924 if (nativeCheckOnly) return null; | 1942 if (nativeCheckOnly) return null; |
1925 return typeCast | 1943 return typeCast |
1926 ? 'listTypeCast' | 1944 ? 'listTypeCast' |
1927 : 'listTypeCheck'; | 1945 : 'listTypeCheck'; |
1928 } else { | 1946 } else { |
1929 if (Elements.isListSupertype(element, compiler)) { | 1947 if (Elements.isListSupertype(element, compiler)) { |
1930 if (nativeCheck) { | 1948 if (nativeCheck) { |
1931 return typeCast | 1949 return typeCast |
1932 ? 'listSuperNativeTypeCast' | 1950 ? 'listSuperNativeTypeCast' |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1971 enqueueInResolution(helper.getElement(compiler), registry); | 1989 enqueueInResolution(helper.getElement(compiler), registry); |
1972 } | 1990 } |
1973 } | 1991 } |
1974 | 1992 |
1975 /** | 1993 /** |
1976 * Returns [:true:] if the checking of [type] is performed directly on the | 1994 * Returns [:true:] if the checking of [type] is performed directly on the |
1977 * object and not on an interceptor. | 1995 * object and not on an interceptor. |
1978 */ | 1996 */ |
1979 bool hasDirectCheckFor(DartType type) { | 1997 bool hasDirectCheckFor(DartType type) { |
1980 Element element = type.element; | 1998 Element element = type.element; |
1981 return element == compiler.stringClass || | 1999 return element == coreClasses.stringClass || |
1982 element == compiler.boolClass || | 2000 element == coreClasses.boolClass || |
1983 element == compiler.numClass || | 2001 element == coreClasses.numClass || |
1984 element == compiler.intClass || | 2002 element == coreClasses.intClass || |
1985 element == compiler.doubleClass || | 2003 element == coreClasses.doubleClass || |
1986 element == jsArrayClass || | 2004 element == jsArrayClass || |
1987 element == jsMutableArrayClass || | 2005 element == jsMutableArrayClass || |
1988 element == jsExtendableArrayClass || | 2006 element == jsExtendableArrayClass || |
1989 element == jsFixedArrayClass || | 2007 element == jsFixedArrayClass || |
1990 element == jsUnmodifiableArrayClass; | 2008 element == jsUnmodifiableArrayClass; |
1991 } | 2009 } |
1992 | 2010 |
1993 bool mayGenerateInstanceofCheck(DartType type) { | 2011 bool mayGenerateInstanceofCheck(DartType type) { |
1994 // We can use an instanceof check for raw types that have no subclass that | 2012 // We can use an instanceof check for raw types that have no subclass that |
1995 // is mixed-in or in an implements clause. | 2013 // is mixed-in or in an implements clause. |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2239 invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); | 2257 invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); |
2240 } | 2258 } |
2241 | 2259 |
2242 // [LinkedHashMap] is reexported from dart:collection and can therefore not | 2260 // [LinkedHashMap] is reexported from dart:collection and can therefore not |
2243 // be loaded from dart:core in [onLibraryScanned]. | 2261 // be loaded from dart:core in [onLibraryScanned]. |
2244 mapLiteralClass = compiler.coreLibrary.find('LinkedHashMap'); | 2262 mapLiteralClass = compiler.coreLibrary.find('LinkedHashMap'); |
2245 assert(invariant(compiler.coreLibrary, mapLiteralClass != null, | 2263 assert(invariant(compiler.coreLibrary, mapLiteralClass != null, |
2246 message: "Element 'LinkedHashMap' not found in 'dart:core'.")); | 2264 message: "Element 'LinkedHashMap' not found in 'dart:core'.")); |
2247 | 2265 |
2248 implementationClasses = <ClassElement, ClassElement>{}; | 2266 implementationClasses = <ClassElement, ClassElement>{}; |
2249 implementationClasses[compiler.intClass] = jsIntClass; | 2267 implementationClasses[coreClasses.intClass] = jsIntClass; |
2250 implementationClasses[compiler.boolClass] = jsBoolClass; | 2268 implementationClasses[coreClasses.boolClass] = jsBoolClass; |
2251 implementationClasses[compiler.numClass] = jsNumberClass; | 2269 implementationClasses[coreClasses.numClass] = jsNumberClass; |
2252 implementationClasses[compiler.doubleClass] = jsDoubleClass; | 2270 implementationClasses[coreClasses.doubleClass] = jsDoubleClass; |
2253 implementationClasses[compiler.stringClass] = jsStringClass; | 2271 implementationClasses[coreClasses.stringClass] = jsStringClass; |
2254 implementationClasses[compiler.listClass] = jsArrayClass; | 2272 implementationClasses[coreClasses.listClass] = jsArrayClass; |
2255 implementationClasses[compiler.nullClass] = jsNullClass; | 2273 implementationClasses[coreClasses.nullClass] = jsNullClass; |
2256 | 2274 |
2257 // These methods are overwritten with generated versions. | 2275 // These methods are overwritten with generated versions. |
2258 inlineCache.markAsNonInlinable(getInterceptorMethod, insideLoop: true); | 2276 inlineCache.markAsNonInlinable(getInterceptorMethod, insideLoop: true); |
2259 | 2277 |
2260 // TODO(kasperl): Some tests do not define the special JSArray | 2278 // TODO(kasperl): Some tests do not define the special JSArray |
2261 // subclasses, so we check to see if they are defined before | 2279 // subclasses, so we check to see if they are defined before |
2262 // trying to resolve them. | 2280 // trying to resolve them. |
2263 if (jsFixedArrayClass != null) { | 2281 if (jsFixedArrayClass != null) { |
2264 jsFixedArrayClass.ensureResolved(resolution); | 2282 jsFixedArrayClass.ensureResolved(resolution); |
2265 } | 2283 } |
(...skipping 15 matching lines...) Expand all Loading... |
2281 jsArrayClass.ensureResolved(resolution); | 2299 jsArrayClass.ensureResolved(resolution); |
2282 jsArrayTypedConstructor = compiler.lookupElementIn(jsArrayClass, 'typed'); | 2300 jsArrayTypedConstructor = compiler.lookupElementIn(jsArrayClass, 'typed'); |
2283 jsArrayRemoveLast = compiler.lookupElementIn(jsArrayClass, 'removeLast'); | 2301 jsArrayRemoveLast = compiler.lookupElementIn(jsArrayClass, 'removeLast'); |
2284 jsArrayAdd = compiler.lookupElementIn(jsArrayClass, 'add'); | 2302 jsArrayAdd = compiler.lookupElementIn(jsArrayClass, 'add'); |
2285 | 2303 |
2286 jsStringClass.ensureResolved(resolution); | 2304 jsStringClass.ensureResolved(resolution); |
2287 jsStringSplit = compiler.lookupElementIn(jsStringClass, 'split'); | 2305 jsStringSplit = compiler.lookupElementIn(jsStringClass, 'split'); |
2288 jsStringOperatorAdd = compiler.lookupElementIn(jsStringClass, '+'); | 2306 jsStringOperatorAdd = compiler.lookupElementIn(jsStringClass, '+'); |
2289 jsStringToString = compiler.lookupElementIn(jsStringClass, 'toString'); | 2307 jsStringToString = compiler.lookupElementIn(jsStringClass, 'toString'); |
2290 | 2308 |
2291 objectEquals = compiler.lookupElementIn(compiler.objectClass, '=='); | 2309 objectEquals = compiler.lookupElementIn(coreClasses.objectClass, '=='); |
2292 | 2310 |
2293 specialOperatorEqClasses | 2311 specialOperatorEqClasses |
2294 ..add(compiler.objectClass) | 2312 ..add(coreClasses.objectClass) |
2295 ..add(jsInterceptorClass) | 2313 ..add(jsInterceptorClass) |
2296 ..add(jsNullClass); | 2314 ..add(jsNullClass); |
2297 | 2315 |
2298 validateInterceptorImplementsAllObjectMethods(jsInterceptorClass); | 2316 validateInterceptorImplementsAllObjectMethods(jsInterceptorClass); |
2299 // The null-interceptor must also implement *all* methods. | 2317 // The null-interceptor must also implement *all* methods. |
2300 validateInterceptorImplementsAllObjectMethods(jsNullClass); | 2318 validateInterceptorImplementsAllObjectMethods(jsNullClass); |
2301 | 2319 |
2302 return new Future.value(); | 2320 return new Future.value(); |
2303 } | 2321 } |
2304 | 2322 |
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3214 } | 3232 } |
3215 | 3233 |
3216 /// Records that [constant] is used by the element behind [registry]. | 3234 /// Records that [constant] is used by the element behind [registry]. |
3217 class Dependency { | 3235 class Dependency { |
3218 final ConstantValue constant; | 3236 final ConstantValue constant; |
3219 final Element annotatedElement; | 3237 final Element annotatedElement; |
3220 | 3238 |
3221 const Dependency(this.constant, this.annotatedElement); | 3239 const Dependency(this.constant, this.annotatedElement); |
3222 } | 3240 } |
3223 | 3241 |
OLD | NEW |