Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(649)

Side by Side Diff: pkg/compiler/lib/src/js_backend/backend.dart

Issue 2531303002: Decouple WorkItem from Compiler (Closed)
Patch Set: Updated cf. comments. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/enqueue.dart ('k') | pkg/compiler/lib/src/js_backend/backend_helpers.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 library js_backend.backend; 5 library js_backend.backend;
6 6
7 import 'dart:async' show Future; 7 import 'dart:async' show Future;
8 8
9 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; 9 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
10 10
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 328
329 FunctionInlineCache inlineCache = new FunctionInlineCache(); 329 FunctionInlineCache inlineCache = new FunctionInlineCache();
330 330
331 /// If [true], the compiler will emit code that logs whenever a method is 331 /// If [true], the compiler will emit code that logs whenever a method is
332 /// called. When TRACE_METHOD is 'console' this will be logged 332 /// called. When TRACE_METHOD is 'console' this will be logged
333 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the 333 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the
334 /// information will be sent to a server via a POST request. 334 /// information will be sent to a server via a POST request.
335 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); 335 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls');
336 static const bool TRACE_CALLS = 336 static const bool TRACE_CALLS =
337 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; 337 TRACE_METHOD == 'post' || TRACE_METHOD == 'console';
338 MethodElement traceHelper;
339 338
340 TypeMask get stringType => compiler.closedWorld.commonMasks.stringType; 339 TypeMask get stringType => compiler.closedWorld.commonMasks.stringType;
341 TypeMask get doubleType => compiler.closedWorld.commonMasks.doubleType; 340 TypeMask get doubleType => compiler.closedWorld.commonMasks.doubleType;
342 TypeMask get intType => compiler.closedWorld.commonMasks.intType; 341 TypeMask get intType => compiler.closedWorld.commonMasks.intType;
343 TypeMask get uint32Type => compiler.closedWorld.commonMasks.uint32Type; 342 TypeMask get uint32Type => compiler.closedWorld.commonMasks.uint32Type;
344 TypeMask get uint31Type => compiler.closedWorld.commonMasks.uint31Type; 343 TypeMask get uint31Type => compiler.closedWorld.commonMasks.uint31Type;
345 TypeMask get positiveIntType => 344 TypeMask get positiveIntType =>
346 compiler.closedWorld.commonMasks.positiveIntType; 345 compiler.closedWorld.commonMasks.positiveIntType;
347 TypeMask get numType => compiler.closedWorld.commonMasks.numType; 346 TypeMask get numType => compiler.closedWorld.commonMasks.numType;
348 TypeMask get boolType => compiler.closedWorld.commonMasks.boolType; 347 TypeMask get boolType => compiler.closedWorld.commonMasks.boolType;
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 // differences. 1028 // differences.
1030 assert(invariant(interceptorMember, 1029 assert(invariant(interceptorMember,
1031 interceptorMember.enclosingClass == interceptorClass, 1030 interceptorMember.enclosingClass == interceptorClass,
1032 message: 1031 message:
1033 "Member ${member.name} not overridden in ${interceptorClass}. " 1032 "Member ${member.name} not overridden in ${interceptorClass}. "
1034 "Found $interceptorMember from " 1033 "Found $interceptorMember from "
1035 "${interceptorMember.enclosingClass}.")); 1034 "${interceptorMember.enclosingClass}."));
1036 }); 1035 });
1037 } 1036 }
1038 1037
1039 void addInterceptorsForNativeClassMembers( 1038 void addInterceptorsForNativeClassMembers(ClassElement cls,
1040 ClassElement cls, Enqueuer enqueuer) { 1039 {bool forResolution}) {
1041 if (enqueuer.isResolutionQueue) { 1040 if (forResolution) {
1042 cls.ensureResolved(resolution); 1041 cls.ensureResolved(resolution);
1043 cls.forEachMember((ClassElement classElement, Element member) { 1042 cls.forEachMember((ClassElement classElement, Element member) {
1044 if (member.name == Identifiers.call) { 1043 if (member.name == Identifiers.call) {
1045 return; 1044 return;
1046 } 1045 }
1047 if (member.isSynthesized) return; 1046 if (member.isSynthesized) return;
1048 // All methods on [Object] are shadowed by [Interceptor]. 1047 // All methods on [Object] are shadowed by [Interceptor].
1049 if (classElement == coreClasses.objectClass) return; 1048 if (classElement == coreClasses.objectClass) return;
1050 Set<Element> set = interceptedElements.putIfAbsent( 1049 Set<Element> set = interceptedElements.putIfAbsent(
1051 member.name, () => new Set<Element>()); 1050 member.name, () => new Set<Element>());
1052 set.add(member); 1051 set.add(member);
1053 }, includeSuperAndInjectedMembers: true); 1052 }, includeSuperAndInjectedMembers: true);
1054 1053
1055 // Walk superclass chain to find mixins. 1054 // Walk superclass chain to find mixins.
1056 for (; cls != null; cls = cls.superclass) { 1055 for (; cls != null; cls = cls.superclass) {
1057 if (cls.isMixinApplication) { 1056 if (cls.isMixinApplication) {
1058 MixinApplicationElement mixinApplication = cls; 1057 MixinApplicationElement mixinApplication = cls;
1059 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin); 1058 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin);
1060 } 1059 }
1061 } 1060 }
1062 } 1061 }
1063 } 1062 }
1064 1063
1065 void addInterceptors(ClassElement cls, Enqueuer enqueuer) { 1064 void addInterceptors(ClassElement cls, WorldImpactBuilder impactBuilder,
1066 if (enqueuer.isResolutionQueue) { 1065 {bool forResolution}) {
1066 if (forResolution) {
1067 if (_interceptedClasses.add(cls)) {
1068 cls.ensureResolved(resolution);
1069 cls.forEachMember((ClassElement classElement, Element member) {
1070 // All methods on [Object] are shadowed by [Interceptor].
1071 if (classElement == coreClasses.objectClass) return;
1072 Set<Element> set = interceptedElements.putIfAbsent(
1073 member.name, () => new Set<Element>());
1074 set.add(member);
1075 }, includeSuperAndInjectedMembers: true);
1076 }
1067 _interceptedClasses.add(helpers.jsInterceptorClass); 1077 _interceptedClasses.add(helpers.jsInterceptorClass);
1068 _interceptedClasses.add(cls);
1069 cls.ensureResolved(resolution);
1070 cls.forEachMember((ClassElement classElement, Element member) {
1071 // All methods on [Object] are shadowed by [Interceptor].
1072 if (classElement == coreClasses.objectClass) return;
1073 Set<Element> set = interceptedElements.putIfAbsent(
1074 member.name, () => new Set<Element>());
1075 set.add(member);
1076 }, includeSuperAndInjectedMembers: true);
1077 } 1078 }
1078 enqueueClass(enqueuer, cls); 1079 impactTransformer.registerBackendInstantiation(impactBuilder, cls);
1079 } 1080 }
1080 1081
1081 Set<ClassElement> get interceptedClasses { 1082 Set<ClassElement> get interceptedClasses {
1082 assert(compiler.enqueuer.resolution.queueIsClosed); 1083 assert(compiler.enqueuer.resolution.queueIsClosed);
1083 return _interceptedClasses; 1084 return _interceptedClasses;
1084 } 1085 }
1085 1086
1086 void registerSpecializedGetInterceptor(Set<ClassElement> classes) { 1087 void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
1087 jsAst.Name name = namer.nameForGetInterceptor(classes); 1088 jsAst.Name name = namer.nameForGetInterceptor(classes);
1088 if (classes.contains(helpers.jsInterceptorClass)) { 1089 if (classes.contains(helpers.jsInterceptorClass)) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 // constant emitter will generate a call to the createRuntimeType 1162 // constant emitter will generate a call to the createRuntimeType
1162 // helper so we register a use of that. 1163 // helper so we register a use of that.
1163 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( 1164 impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
1164 // TODO(johnniwinther): Find the right [CallStructure]. 1165 // TODO(johnniwinther): Find the right [CallStructure].
1165 helpers.createRuntimeType, 1166 helpers.createRuntimeType,
1166 null)); 1167 null));
1167 } 1168 }
1168 } 1169 }
1169 } 1170 }
1170 1171
1171 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { 1172 WorldImpact registerInstantiatedClass(ClassElement cls,
1172 _processClass(cls, enqueuer); 1173 {bool forResolution}) {
1174 return _processClass(cls, forResolution: forResolution);
1173 } 1175 }
1174 1176
1175 void registerImplementedClass(ClassElement cls, Enqueuer enqueuer) { 1177 WorldImpact registerImplementedClass(ClassElement cls, {bool forResolution}) {
1176 _processClass(cls, enqueuer); 1178 return _processClass(cls, forResolution: forResolution);
1177 } 1179 }
1178 1180
1179 void _processClass(ClassElement cls, Enqueuer enqueuer) { 1181 WorldImpact _processClass(ClassElement cls, {bool forResolution}) {
1182 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
1180 if (!cls.typeVariables.isEmpty) { 1183 if (!cls.typeVariables.isEmpty) {
1181 typeVariableHandler.registerClassWithTypeVariables(cls, enqueuer); 1184 typeVariableHandler.registerClassWithTypeVariables(cls,
1185 forResolution: forResolution);
1182 } 1186 }
1183 1187
1184 // Register any helper that will be needed by the backend. 1188 // Register any helper that will be needed by the backend.
1185 if (enqueuer.isResolutionQueue) { 1189 if (forResolution) {
1186 if (cls == coreClasses.intClass || 1190 if (cls == coreClasses.intClass ||
1187 cls == coreClasses.doubleClass || 1191 cls == coreClasses.doubleClass ||
1188 cls == coreClasses.numClass) { 1192 cls == coreClasses.numClass) {
1189 // The backend will try to optimize number operations and use the 1193 impactTransformer.registerBackendImpact(
1190 // `iae` helper directly. 1194 impactBuilder, impacts.numClasses);
1191 enqueue(enqueuer, helpers.throwIllegalArgumentException);
1192 } else if (cls == coreClasses.listClass || 1195 } else if (cls == coreClasses.listClass ||
1193 cls == coreClasses.stringClass) { 1196 cls == coreClasses.stringClass) {
1194 // The backend will try to optimize array and string access and use the 1197 impactTransformer.registerBackendImpact(
1195 // `ioore` and `iae` helpers directly. 1198 impactBuilder, impacts.listOrStringClasses);
1196 enqueue(enqueuer, helpers.throwIndexOutOfRangeException);
1197 enqueue(enqueuer, helpers.throwIllegalArgumentException);
1198 } else if (cls == coreClasses.functionClass) { 1199 } else if (cls == coreClasses.functionClass) {
1199 enqueueClass(enqueuer, helpers.closureClass); 1200 impactTransformer.registerBackendImpact(
1201 impactBuilder, impacts.functionClass);
1200 } else if (cls == coreClasses.mapClass) { 1202 } else if (cls == coreClasses.mapClass) {
1201 // The backend will use a literal list to initialize the entries 1203 impactTransformer.registerBackendImpact(
1202 // of the map. 1204 impactBuilder, impacts.mapClass);
1203 enqueueClass(enqueuer, coreClasses.listClass);
1204 enqueueClass(enqueuer, helpers.mapLiteralClass);
1205 // For map literals, the dependency between the implementation class 1205 // For map literals, the dependency between the implementation class
1206 // and [Map] is not visible, so we have to add it manually. 1206 // and [Map] is not visible, so we have to add it manually.
1207 rti.registerRtiDependency(helpers.mapLiteralClass, cls); 1207 rti.registerRtiDependency(helpers.mapLiteralClass, cls);
1208 } else if (cls == helpers.boundClosureClass) { 1208 } else if (cls == helpers.boundClosureClass) {
1209 // TODO(johnniwinther): Is this a noop? 1209 impactTransformer.registerBackendImpact(
1210 enqueueClass(enqueuer, helpers.boundClosureClass); 1210 impactBuilder, impacts.boundClosureClass);
1211 } else if (isNativeOrExtendsNative(cls)) { 1211 } else if (isNativeOrExtendsNative(cls)) {
1212 enqueue(enqueuer, helpers.getNativeInterceptorMethod); 1212 impactTransformer.registerBackendImpact(
1213 enqueueClass(enqueuer, helpers.jsInterceptorClass); 1213 impactBuilder, impacts.nativeOrExtendsClass);
1214 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass);
1215 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass);
1216 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass);
1217 } else if (cls == helpers.mapLiteralClass) { 1214 } else if (cls == helpers.mapLiteralClass) {
1218 // For map literals, the dependency between the implementation class 1215 impactTransformer.registerBackendImpact(
1219 // and [Map] is not visible, so we have to add it manually. 1216 impactBuilder, impacts.mapLiteralClass);
1220 Element getFactory(String name, int arity) {
1221 // The constructor is on the patch class, but dart2js unit tests don't
1222 // have a patch class.
1223 ClassElement implementation = cls.implementation;
1224 ConstructorElement ctor = implementation.lookupConstructor(name);
1225 if (ctor == null ||
1226 (Name.isPrivateName(name) &&
1227 ctor.library != helpers.mapLiteralClass.library)) {
1228 reporter.internalError(
1229 helpers.mapLiteralClass,
1230 "Map literal class ${helpers.mapLiteralClass} missing "
1231 "'$name' constructor"
1232 " ${helpers.mapLiteralClass.constructors}");
1233 }
1234 return ctor;
1235 }
1236
1237 Element getMember(String name) {
1238 // The constructor is on the patch class, but dart2js unit tests don't
1239 // have a patch class.
1240 ClassElement implementation = cls.implementation;
1241 Element element = implementation.lookupLocalMember(name);
1242 if (element == null || !element.isFunction || !element.isStatic) {
1243 reporter.internalError(
1244 helpers.mapLiteralClass,
1245 "Map literal class ${helpers.mapLiteralClass} missing "
1246 "'$name' static member function");
1247 }
1248 return element;
1249 }
1250
1251 helpers.mapLiteralConstructor = getFactory('_literal', 1);
1252 helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0);
1253 enqueue(enqueuer, helpers.mapLiteralConstructor);
1254 enqueue(enqueuer, helpers.mapLiteralConstructorEmpty);
1255
1256 helpers.mapLiteralUntypedMaker = getMember('_makeLiteral');
1257 helpers.mapLiteralUntypedEmptyMaker = getMember('_makeEmpty');
1258 enqueue(enqueuer, helpers.mapLiteralUntypedMaker);
1259 enqueue(enqueuer, helpers.mapLiteralUntypedEmptyMaker);
1260 } 1217 }
1261 } 1218 }
1262 if (cls == helpers.closureClass) { 1219 if (cls == helpers.closureClass) {
1263 enqueue(enqueuer, helpers.closureFromTearOff); 1220 impactTransformer.registerBackendImpact(
1221 impactBuilder, impacts.closureClass);
1264 } 1222 }
1265 if (cls == coreClasses.stringClass || cls == helpers.jsStringClass) { 1223 if (cls == coreClasses.stringClass || cls == helpers.jsStringClass) {
1266 addInterceptors(helpers.jsStringClass, enqueuer); 1224 addInterceptors(helpers.jsStringClass, impactBuilder,
1225 forResolution: forResolution);
1267 } else if (cls == coreClasses.listClass || 1226 } else if (cls == coreClasses.listClass ||
1268 cls == helpers.jsArrayClass || 1227 cls == helpers.jsArrayClass ||
1269 cls == helpers.jsFixedArrayClass || 1228 cls == helpers.jsFixedArrayClass ||
1270 cls == helpers.jsExtendableArrayClass || 1229 cls == helpers.jsExtendableArrayClass ||
1271 cls == helpers.jsUnmodifiableArrayClass) { 1230 cls == helpers.jsUnmodifiableArrayClass) {
1272 addInterceptors(helpers.jsArrayClass, enqueuer); 1231 addInterceptors(helpers.jsArrayClass, impactBuilder,
1273 addInterceptors(helpers.jsMutableArrayClass, enqueuer); 1232 forResolution: forResolution);
1274 addInterceptors(helpers.jsFixedArrayClass, enqueuer); 1233 addInterceptors(helpers.jsMutableArrayClass, impactBuilder,
1275 addInterceptors(helpers.jsExtendableArrayClass, enqueuer); 1234 forResolution: forResolution);
1276 addInterceptors(helpers.jsUnmodifiableArrayClass, enqueuer); 1235 addInterceptors(helpers.jsFixedArrayClass, impactBuilder,
1277 if (enqueuer.isResolutionQueue) { 1236 forResolution: forResolution);
1278 // Literal lists can be translated into calls to these functions: 1237 addInterceptors(helpers.jsExtendableArrayClass, impactBuilder,
1279 enqueue(enqueuer, helpers.jsArrayTypedConstructor); 1238 forResolution: forResolution);
1280 enqueue(enqueuer, helpers.setRuntimeTypeInfo); 1239 addInterceptors(helpers.jsUnmodifiableArrayClass, impactBuilder,
1281 enqueue(enqueuer, helpers.getTypeArgumentByIndex); 1240 forResolution: forResolution);
1241 if (forResolution) {
1242 impactTransformer.registerBackendImpact(
1243 impactBuilder, impacts.listClasses);
1282 } 1244 }
1283 } else if (cls == coreClasses.intClass || cls == helpers.jsIntClass) { 1245 } else if (cls == coreClasses.intClass || cls == helpers.jsIntClass) {
1284 addInterceptors(helpers.jsIntClass, enqueuer); 1246 addInterceptors(helpers.jsIntClass, impactBuilder,
1285 addInterceptors(helpers.jsPositiveIntClass, enqueuer); 1247 forResolution: forResolution);
1286 addInterceptors(helpers.jsUInt32Class, enqueuer); 1248 addInterceptors(helpers.jsPositiveIntClass, impactBuilder,
1287 addInterceptors(helpers.jsUInt31Class, enqueuer); 1249 forResolution: forResolution);
1288 addInterceptors(helpers.jsNumberClass, enqueuer); 1250 addInterceptors(helpers.jsUInt32Class, impactBuilder,
1251 forResolution: forResolution);
1252 addInterceptors(helpers.jsUInt31Class, impactBuilder,
1253 forResolution: forResolution);
1254 addInterceptors(helpers.jsNumberClass, impactBuilder,
1255 forResolution: forResolution);
1289 } else if (cls == coreClasses.doubleClass || cls == helpers.jsDoubleClass) { 1256 } else if (cls == coreClasses.doubleClass || cls == helpers.jsDoubleClass) {
1290 addInterceptors(helpers.jsDoubleClass, enqueuer); 1257 addInterceptors(helpers.jsDoubleClass, impactBuilder,
1291 addInterceptors(helpers.jsNumberClass, enqueuer); 1258 forResolution: forResolution);
1259 addInterceptors(helpers.jsNumberClass, impactBuilder,
1260 forResolution: forResolution);
1292 } else if (cls == coreClasses.boolClass || cls == helpers.jsBoolClass) { 1261 } else if (cls == coreClasses.boolClass || cls == helpers.jsBoolClass) {
1293 addInterceptors(helpers.jsBoolClass, enqueuer); 1262 addInterceptors(helpers.jsBoolClass, impactBuilder,
1263 forResolution: forResolution);
1294 } else if (cls == coreClasses.nullClass || cls == helpers.jsNullClass) { 1264 } else if (cls == coreClasses.nullClass || cls == helpers.jsNullClass) {
1295 addInterceptors(helpers.jsNullClass, enqueuer); 1265 addInterceptors(helpers.jsNullClass, impactBuilder,
1266 forResolution: forResolution);
1296 } else if (cls == coreClasses.numClass || cls == helpers.jsNumberClass) { 1267 } else if (cls == coreClasses.numClass || cls == helpers.jsNumberClass) {
1297 addInterceptors(helpers.jsIntClass, enqueuer); 1268 addInterceptors(helpers.jsIntClass, impactBuilder,
1298 addInterceptors(helpers.jsPositiveIntClass, enqueuer); 1269 forResolution: forResolution);
1299 addInterceptors(helpers.jsUInt32Class, enqueuer); 1270 addInterceptors(helpers.jsPositiveIntClass, impactBuilder,
1300 addInterceptors(helpers.jsUInt31Class, enqueuer); 1271 forResolution: forResolution);
1301 addInterceptors(helpers.jsDoubleClass, enqueuer); 1272 addInterceptors(helpers.jsUInt32Class, impactBuilder,
1302 addInterceptors(helpers.jsNumberClass, enqueuer); 1273 forResolution: forResolution);
1274 addInterceptors(helpers.jsUInt31Class, impactBuilder,
1275 forResolution: forResolution);
1276 addInterceptors(helpers.jsDoubleClass, impactBuilder,
1277 forResolution: forResolution);
1278 addInterceptors(helpers.jsNumberClass, impactBuilder,
1279 forResolution: forResolution);
1303 } else if (cls == helpers.jsJavaScriptObjectClass) { 1280 } else if (cls == helpers.jsJavaScriptObjectClass) {
1304 addInterceptors(helpers.jsJavaScriptObjectClass, enqueuer); 1281 addInterceptors(helpers.jsJavaScriptObjectClass, impactBuilder,
1282 forResolution: forResolution);
1305 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { 1283 } else if (cls == helpers.jsPlainJavaScriptObjectClass) {
1306 addInterceptors(helpers.jsPlainJavaScriptObjectClass, enqueuer); 1284 addInterceptors(helpers.jsPlainJavaScriptObjectClass, impactBuilder,
1285 forResolution: forResolution);
1307 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { 1286 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) {
1308 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, enqueuer); 1287 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, impactBuilder,
1288 forResolution: forResolution);
1309 } else if (cls == helpers.jsJavaScriptFunctionClass) { 1289 } else if (cls == helpers.jsJavaScriptFunctionClass) {
1310 addInterceptors(helpers.jsJavaScriptFunctionClass, enqueuer); 1290 addInterceptors(helpers.jsJavaScriptFunctionClass, impactBuilder,
1291 forResolution: forResolution);
1311 } else if (isNativeOrExtendsNative(cls)) { 1292 } else if (isNativeOrExtendsNative(cls)) {
1312 addInterceptorsForNativeClassMembers(cls, enqueuer); 1293 addInterceptorsForNativeClassMembers(cls, forResolution: forResolution);
1313 } else if (cls == helpers.jsIndexingBehaviorInterface) { 1294 } else if (cls == helpers.jsIndexingBehaviorInterface) {
1314 // These two helpers are used by the emitter and the codegen. 1295 impactTransformer.registerBackendImpact(
1315 // Because we cannot enqueue elements at the time of emission, 1296 impactBuilder, impacts.jsIndexingBehavior);
1316 // we make sure they are always generated.
1317 enqueue(enqueuer, helpers.isJsIndexable);
1318 } 1297 }
1319 1298
1320 customElementsAnalysis.registerInstantiatedClass(cls, 1299 customElementsAnalysis.registerInstantiatedClass(cls,
1321 forResolution: enqueuer.isResolutionQueue); 1300 forResolution: forResolution);
1322 if (!enqueuer.isResolutionQueue) { 1301 if (!forResolution) {
1323 lookupMapAnalysis.registerInstantiatedClass(cls); 1302 lookupMapAnalysis.registerInstantiatedClass(cls);
1324 } 1303 }
1304
1305 return impactBuilder;
1325 } 1306 }
1326 1307
1327 void registerInstantiatedType(InterfaceType type) { 1308 void registerInstantiatedType(InterfaceType type) {
1328 lookupMapAnalysis.registerInstantiatedType(type); 1309 lookupMapAnalysis.registerInstantiatedType(type);
1329 } 1310 }
1330 1311
1331 void enqueueHelpers(ResolutionEnqueuer enqueuer) { 1312 @override
1313 WorldImpact computeHelpersImpact() {
1332 assert(helpers.interceptorsLibrary != null); 1314 assert(helpers.interceptorsLibrary != null);
1315 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
1333 // TODO(ngeoffray): Not enqueuing those two classes currently make 1316 // TODO(ngeoffray): Not enqueuing those two classes currently make
1334 // the compiler potentially crash. However, any reasonable program 1317 // the compiler potentially crash. However, any reasonable program
1335 // will instantiate those two classes. 1318 // will instantiate those two classes.
1336 addInterceptors(helpers.jsBoolClass, enqueuer); 1319 addInterceptors(helpers.jsBoolClass, impactBuilder, forResolution: true);
1337 addInterceptors(helpers.jsNullClass, enqueuer); 1320 addInterceptors(helpers.jsNullClass, impactBuilder, forResolution: true);
1338 if (compiler.options.enableTypeAssertions) { 1321 if (compiler.options.enableTypeAssertions) {
1339 // Unconditionally register the helper that checks if the 1322 impactTransformer.registerBackendImpact(
1340 // expression in an if/while/for is a boolean. 1323 impactBuilder, impacts.enableTypeAssertions);
1341 // TODO(ngeoffray): Should we have the resolver register those instead?
1342 Element e = helpers.boolConversionCheck;
1343 if (e != null) enqueue(enqueuer, e);
1344 } 1324 }
1345 1325
1346 if (TRACE_CALLS) { 1326 if (TRACE_CALLS) {
1347 traceHelper = TRACE_METHOD == 'console' 1327 impactTransformer.registerBackendImpact(
1348 ? helpers.consoleTraceHelper 1328 impactBuilder, impacts.traceHelper);
1349 : helpers.postTraceHelper;
1350 assert(traceHelper != null);
1351 enqueue(enqueuer, traceHelper);
1352 } 1329 }
1353 enqueue(enqueuer, helpers.assertUnreachableMethod); 1330 impactTransformer.registerBackendImpact(
1354 registerCheckedModeHelpers(enqueuer); 1331 impactBuilder, impacts.assertUnreachable);
1332 _registerCheckedModeHelpers(impactBuilder);
1333 return impactBuilder;
1355 } 1334 }
1356 1335
1357 onResolutionComplete() { 1336 onResolutionComplete() {
1358 super.onResolutionComplete(); 1337 super.onResolutionComplete();
1359 computeMembersNeededForReflection(); 1338 computeMembersNeededForReflection();
1360 rti.computeClassesNeedingRti(); 1339 rti.computeClassesNeedingRti();
1361 _registeredMetadata.clear(); 1340 _registeredMetadata.clear();
1362 } 1341 }
1363 1342
1364 onTypeInferenceComplete() { 1343 onTypeInferenceComplete() {
1365 super.onTypeInferenceComplete(); 1344 super.onTypeInferenceComplete();
1366 noSuchMethodRegistry.onTypeInferenceComplete(); 1345 noSuchMethodRegistry.onTypeInferenceComplete();
1367 } 1346 }
1368 1347
1369 void registerGetRuntimeTypeArgument() { 1348 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod,
1370 enqueueImpact(compiler.enqueuer.resolution, impacts.getRuntimeTypeArgument); 1349 {bool forResolution}) {
1350 if (forResolution || methodNeedsRti(callMethod)) {
1351 return _registerComputeSignature();
1352 }
1353 return const WorldImpact();
1371 } 1354 }
1372 1355
1373 void registerCallMethodWithFreeTypeVariables( 1356 WorldImpact registerClosureWithFreeTypeVariables(Element closure,
1374 Element callMethod, Enqueuer enqueuer) { 1357 {bool forResolution}) {
1375 if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) { 1358 if (forResolution || methodNeedsRti(closure)) {
1376 registerComputeSignature(enqueuer); 1359 return _registerComputeSignature();
1377 } 1360 }
1361 return const WorldImpact();
1378 } 1362 }
1379 1363
1380 void registerClosureWithFreeTypeVariables( 1364 WorldImpact registerBoundClosure() {
1381 Element closure, Enqueuer enqueuer) { 1365 return impactTransformer.createImpactFor(impacts.memberClosure);
1382 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) {
1383 registerComputeSignature(enqueuer);
1384 }
1385 } 1366 }
1386 1367
1387 void registerBoundClosure(Enqueuer enqueuer) { 1368 WorldImpact registerGetOfStaticFunction() {
1388 helpers.boundClosureClass.ensureResolved(resolution); 1369 return impactTransformer.createImpactFor(impacts.staticClosure);
1389 enqueuer.registerInstantiatedType(helpers.boundClosureClass.rawType);
1390 } 1370 }
1391 1371
1392 void registerGetOfStaticFunction(Enqueuer enqueuer) { 1372 WorldImpact _registerComputeSignature() {
1393 helpers.closureClass.ensureResolved(resolution);
1394 enqueuer.registerInstantiatedType(helpers.closureClass.rawType);
1395 }
1396
1397 void registerComputeSignature(Enqueuer enqueuer) {
1398 // Calls to [:computeSignature:] are generated by the emitter and we 1373 // Calls to [:computeSignature:] are generated by the emitter and we
1399 // therefore need to enqueue the used elements in the codegen enqueuer as 1374 // therefore need to enqueue the used elements in the codegen enqueuer as
1400 // well as in the resolution enqueuer. 1375 // well as in the resolution enqueuer.
1401 enqueueImpact(enqueuer, impacts.computeSignature); 1376 return impactTransformer.createImpactFor(impacts.computeSignature);
1402 } 1377 }
1403 1378
1404 void registerRuntimeType(ResolutionEnqueuer enqueuer) { 1379 WorldImpact registerRuntimeType() {
1405 registerComputeSignature(enqueuer); 1380 return impactTransformer.createImpactFor(impacts.runtimeTypeSupport);
1406 enqueue(enqueuer, helpers.setRuntimeTypeInfo);
1407 registerGetRuntimeTypeArgument();
1408 enqueue(enqueuer, helpers.getRuntimeTypeInfo);
1409 enqueueClass(enqueuer, coreClasses.listClass);
1410 } 1381 }
1411 1382
1412 void registerTypeVariableBoundsSubtypeCheck( 1383 void registerTypeVariableBoundsSubtypeCheck(
1413 DartType typeArgument, DartType bound) { 1384 DartType typeArgument, DartType bound) {
1414 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound); 1385 rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound);
1415 } 1386 }
1416 1387
1417 void registerCheckDeferredIsLoaded(ResolutionEnqueuer enqueuer) { 1388 WorldImpact computeDeferredLoadingImpact() {
1418 enqueue(enqueuer, helpers.checkDeferredIsLoaded); 1389 return impactTransformer.createImpactFor(impacts.deferredLoading);
1419 // Also register the types of the arguments passed to this method.
1420 enqueueClass(enqueuer, coreClasses.stringClass);
1421 } 1390 }
1422 1391
1423 void registerNoSuchMethod(FunctionElement noSuchMethod) { 1392 void registerNoSuchMethod(FunctionElement noSuchMethod) {
1424 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod); 1393 noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod);
1425 } 1394 }
1426 1395
1427 /// Called when resolving a call to a foreign function. 1396 /// Called when resolving a call to a foreign function.
1428 native.NativeBehavior resolveForeignCall(Send node, Element element, 1397 native.NativeBehavior resolveForeignCall(Send node, Element element,
1429 CallStructure callStructure, ForeignResolver resolver) { 1398 CallStructure callStructure, ForeignResolver resolver) {
1430 native.NativeResolutionEnqueuer nativeEnqueuer = 1399 native.NativeResolutionEnqueuer nativeEnqueuer =
(...skipping 20 matching lines...) Expand all
1451 } 1420 }
1452 } 1421 }
1453 } 1422 }
1454 reporter.reportErrorMessage( 1423 reporter.reportErrorMessage(
1455 node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); 1424 node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
1456 } 1425 }
1457 // No native behavior for this call. 1426 // No native behavior for this call.
1458 return null; 1427 return null;
1459 } 1428 }
1460 1429
1461 void enableNoSuchMethod(Enqueuer world) { 1430 WorldImpact enableNoSuchMethod() {
1462 enqueue(world, helpers.createInvocationMirror); 1431 return impactTransformer.createImpactFor(impacts.noSuchMethodSupport);
1463 world.registerDynamicUse(new DynamicUse(Selectors.noSuchMethod_, null));
1464 } 1432 }
1465 1433
1466 void enableIsolateSupport(Enqueuer enqueuer) { 1434 WorldImpact enableIsolateSupport({bool forResolution}) {
1435 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
1467 // TODO(floitsch): We should also ensure that the class IsolateMessage is 1436 // TODO(floitsch): We should also ensure that the class IsolateMessage is
1468 // instantiated. Currently, just enabling isolate support works. 1437 // instantiated. Currently, just enabling isolate support works.
1469 if (compiler.mainFunction != null) { 1438 if (compiler.mainFunction != null) {
1470 // The JavaScript backend implements [Isolate.spawn] by looking up 1439 // The JavaScript backend implements [Isolate.spawn] by looking up
1471 // top-level functions by name. So all top-level function tear-off 1440 // top-level functions by name. So all top-level function tear-off
1472 // closures have a private name field. 1441 // closures have a private name field.
1473 // 1442 //
1474 // The JavaScript backend of [Isolate.spawnUri] uses the same internal 1443 // The JavaScript backend of [Isolate.spawnUri] uses the same internal
1475 // implementation as [Isolate.spawn], and fails if it cannot look main up 1444 // implementation as [Isolate.spawn], and fails if it cannot look main up
1476 // by name. 1445 // by name.
1477 enqueuer.registerStaticUse( 1446 impactBuilder.registerStaticUse(
1478 new StaticUse.staticTearOff(compiler.mainFunction)); 1447 new StaticUse.staticTearOff(compiler.mainFunction));
1479 } 1448 }
1480 if (enqueuer.isResolutionQueue) { 1449 impactTransformer.registerBackendImpact(
1481 void enqueue(Element element) { 1450 impactBuilder, impacts.isolateSupport);
1482 enqueuer.addToWorkList(element); 1451 if (forResolution) {
1483 compiler.globalDependencies.registerDependency(element); 1452 impactTransformer.registerBackendImpact(
1484 helpersUsed.add(element.declaration); 1453 impactBuilder, impacts.isolateSupportForResolution);
1485 }
1486
1487 enqueue(helpers.startRootIsolate);
1488 enqueue(helpers.currentIsolate);
1489 enqueue(helpers.callInIsolate);
1490 } else {
1491 enqueuer.addToWorkList(helpers.startRootIsolate);
1492 } 1454 }
1455 return impactBuilder;
1493 } 1456 }
1494 1457
1495 bool classNeedsRti(ClassElement cls) { 1458 bool classNeedsRti(ClassElement cls) {
1496 if (compiler.resolverWorld.hasRuntimeTypeSupport) return true; 1459 if (compiler.resolverWorld.hasRuntimeTypeSupport) return true;
1497 return rti.classesNeedingRti.contains(cls.declaration); 1460 return rti.classesNeedingRti.contains(cls.declaration);
1498 } 1461 }
1499 1462
1500 bool classNeedsRtiField(ClassElement cls) { 1463 bool classNeedsRtiField(ClassElement cls) {
1501 if (cls.rawType.typeArguments.isEmpty) return false; 1464 if (cls.rawType.typeArguments.isEmpty) return false;
1502 if (compiler.resolverWorld.hasRuntimeTypeSupport) return true; 1465 if (compiler.resolverWorld.hasRuntimeTypeSupport) return true;
1503 return rti.classesNeedingRti.contains(cls.declaration); 1466 return rti.classesNeedingRti.contains(cls.declaration);
1504 } 1467 }
1505 1468
1506 bool isComplexNoSuchMethod(FunctionElement element) => 1469 bool isComplexNoSuchMethod(FunctionElement element) =>
1507 noSuchMethodRegistry.isComplex(element); 1470 noSuchMethodRegistry.isComplex(element);
1508 1471
1509 bool isDefaultEqualityImplementation(Element element) { 1472 bool isDefaultEqualityImplementation(Element element) {
1510 assert(element.name == '=='); 1473 assert(element.name == '==');
1511 ClassElement classElement = element.enclosingClass; 1474 ClassElement classElement = element.enclosingClass;
1512 return classElement == coreClasses.objectClass || 1475 return classElement == coreClasses.objectClass ||
1513 classElement == helpers.jsInterceptorClass || 1476 classElement == helpers.jsInterceptorClass ||
1514 classElement == helpers.jsNullClass; 1477 classElement == helpers.jsNullClass;
1515 } 1478 }
1516 1479
1517 bool methodNeedsRti(FunctionElement function) { 1480 bool methodNeedsRti(FunctionElement function) {
1518 return rti.methodsNeedingRti.contains(function) || 1481 return rti.methodsNeedingRti.contains(function) ||
1519 compiler.resolverWorld.hasRuntimeTypeSupport; 1482 compiler.resolverWorld.hasRuntimeTypeSupport;
1520 } 1483 }
1521 1484
1522 /// Enqueue [e] in [enqueuer].
1523 ///
1524 /// This method calls [registerBackendUse].
1525 void enqueue(Enqueuer enqueuer, Element e) {
1526 if (e == null) return;
1527 registerBackendUse(e);
1528 enqueuer.addToWorkList(e);
1529 compiler.globalDependencies.registerDependency(e);
1530 }
1531
1532 /// Register instantiation of [cls] in [enqueuer].
1533 ///
1534 /// This method calls [registerBackendUse].
1535 void enqueueClass(Enqueuer enqueuer, ClassElement cls) {
1536 if (cls == null) return;
1537 registerBackendUse(cls);
1538 helpersUsed.add(cls.declaration);
1539 if (cls.declaration != cls.implementation) {
1540 helpersUsed.add(cls.implementation);
1541 }
1542 cls.ensureResolved(resolution);
1543 enqueuer.registerInstantiatedType(cls.rawType);
1544 }
1545
1546 /// Register instantiation of [type] in [enqueuer].
1547 ///
1548 /// This method calls [registerBackendUse].
1549 void enqueueType(Enqueuer enqueuer, InterfaceType type) {
1550 if (type == null) return;
1551 ClassElement cls = type.element;
1552 registerBackendUse(cls);
1553 helpersUsed.add(cls.declaration);
1554 if (cls.declaration != cls.implementation) {
1555 helpersUsed.add(cls.implementation);
1556 }
1557 cls.ensureResolved(resolution);
1558 enqueuer.registerInstantiatedType(type);
1559 }
1560
1561 void enqueueImpact(Enqueuer enqueuer, BackendImpact impact) {
1562 for (Element staticUse in impact.staticUses) {
1563 enqueue(enqueuer, staticUse);
1564 }
1565 for (InterfaceType type in impact.instantiatedTypes) {
1566 enqueueType(enqueuer, type);
1567 }
1568 for (ClassElement cls in impact.instantiatedClasses) {
1569 enqueueClass(enqueuer, cls);
1570 }
1571 for (BackendImpact otherImpact in impact.otherImpacts) {
1572 enqueueImpact(enqueuer, otherImpact);
1573 }
1574 }
1575
1576 CodegenEnqueuer get codegenEnqueuer => compiler.enqueuer.codegen; 1485 CodegenEnqueuer get codegenEnqueuer => compiler.enqueuer.codegen;
1577 1486
1578 CodegenEnqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler) { 1487 CodegenEnqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler) {
1579 return new CodegenEnqueuer( 1488 return new CodegenEnqueuer(
1580 task, compiler, const TreeShakingEnqueuerStrategy()); 1489 task, compiler, const TreeShakingEnqueuerStrategy());
1581 } 1490 }
1582 1491
1583 WorldImpact codegen(CodegenWorkItem work) { 1492 WorldImpact codegen(CodegenWorkItem work) {
1584 Element element = work.element; 1493 Element element = work.element;
1585 if (compiler.elementHasCompileTimeError(element)) { 1494 if (compiler.elementHasCompileTimeError(element)) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1627 constant.isImplicit || 1536 constant.isImplicit ||
1628 constant.isPotential, 1537 constant.isPotential,
1629 message: "Constant expression without value: " 1538 message: "Constant expression without value: "
1630 "${constant.toStructuredText()}.")); 1539 "${constant.toStructuredText()}."));
1631 } 1540 }
1632 } else { 1541 } else {
1633 // If the constant-handler was not able to produce a result we have to 1542 // If the constant-handler was not able to produce a result we have to
1634 // go through the builder (below) to generate the lazy initializer for 1543 // go through the builder (below) to generate the lazy initializer for
1635 // the static variable. 1544 // the static variable.
1636 // We also need to register the use of the cyclic-error helper. 1545 // We also need to register the use of the cyclic-error helper.
1637 compiler.enqueuer.codegen.registerStaticUse(new StaticUse.staticInvoke( 1546 work.registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke(
1638 helpers.cyclicThrowHelper, CallStructure.ONE_ARG)); 1547 helpers.cyclicThrowHelper, CallStructure.ONE_ARG));
1639 } 1548 }
1640 } 1549 }
1641 1550
1642 jsAst.Fun function = functionCompiler.compile(work); 1551 jsAst.Fun function = functionCompiler.compile(work);
1643 if (function.sourceInformation == null) { 1552 if (function.sourceInformation == null) {
1644 function = function.withSourceInformation( 1553 function = function.withSourceInformation(
1645 sourceInformationStrategy.buildSourceMappedMarker()); 1554 sourceInformationStrategy.buildSourceMappedMarker());
1646 } 1555 }
1647 generatedCode[element] = function; 1556 generatedCode[element] = function;
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1849 // interceptors? 1758 // interceptors?
1850 return typeCast ? 'interceptedTypeCast' : 'interceptedTypeCheck'; 1759 return typeCast ? 'interceptedTypeCast' : 'interceptedTypeCheck';
1851 } else { 1760 } else {
1852 return typeCast ? 'propertyTypeCast' : 'propertyTypeCheck'; 1761 return typeCast ? 'propertyTypeCast' : 'propertyTypeCheck';
1853 } 1762 }
1854 } 1763 }
1855 } 1764 }
1856 } 1765 }
1857 } 1766 }
1858 1767
1859 void registerCheckedModeHelpers(ResolutionEnqueuer enqueuer) { 1768 void _registerCheckedModeHelpers(WorldImpactBuilder impactBuilder) {
1860 // We register all the helpers in the resolution queue. 1769 // We register all the helpers in the resolution queue.
1861 // TODO(13155): Find a way to register fewer helpers. 1770 // TODO(13155): Find a way to register fewer helpers.
1771 List<Element> staticUses = <Element>[];
1862 for (CheckedModeHelper helper in checkedModeHelpers) { 1772 for (CheckedModeHelper helper in checkedModeHelpers) {
1863 enqueue(enqueuer, helper.getStaticUse(compiler).element); 1773 staticUses.add(helper.getStaticUse(compiler).element);
1864 } 1774 }
1775 impactTransformer.registerBackendImpact(
1776 impactBuilder, new BackendImpact(globalUses: staticUses));
1865 } 1777 }
1866 1778
1867 /** 1779 /**
1868 * Returns [:true:] if the checking of [type] is performed directly on the 1780 * Returns [:true:] if the checking of [type] is performed directly on the
1869 * object and not on an interceptor. 1781 * object and not on an interceptor.
1870 */ 1782 */
1871 bool hasDirectCheckFor(DartType type) { 1783 bool hasDirectCheckFor(DartType type) {
1872 Element element = type.element; 1784 Element element = type.element;
1873 return element == coreClasses.stringClass || 1785 return element == coreClasses.stringClass ||
1874 element == coreClasses.boolClass || 1786 element == coreClasses.boolClass ||
(...skipping 10 matching lines...) Expand all
1885 bool mayGenerateInstanceofCheck(DartType type) { 1797 bool mayGenerateInstanceofCheck(DartType type) {
1886 // We can use an instanceof check for raw types that have no subclass that 1798 // We can use an instanceof check for raw types that have no subclass that
1887 // is mixed-in or in an implements clause. 1799 // is mixed-in or in an implements clause.
1888 1800
1889 if (!type.isRaw) return false; 1801 if (!type.isRaw) return false;
1890 ClassElement classElement = type.element; 1802 ClassElement classElement = type.element;
1891 if (isInterceptorClass(classElement)) return false; 1803 if (isInterceptorClass(classElement)) return false;
1892 return compiler.closedWorld.hasOnlySubclasses(classElement); 1804 return compiler.closedWorld.hasOnlySubclasses(classElement);
1893 } 1805 }
1894 1806
1895 void registerStaticUse(Enqueuer enqueuer, Element element) { 1807 WorldImpact registerStaticUse(Element element, {bool forResolution}) {
1808 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl();
1896 if (element == helpers.disableTreeShakingMarker) { 1809 if (element == helpers.disableTreeShakingMarker) {
1897 isTreeShakingDisabled = true; 1810 isTreeShakingDisabled = true;
1898 } else if (element == helpers.preserveNamesMarker) { 1811 } else if (element == helpers.preserveNamesMarker) {
1899 mustPreserveNames = true; 1812 mustPreserveNames = true;
1900 } else if (element == helpers.preserveMetadataMarker) { 1813 } else if (element == helpers.preserveMetadataMarker) {
1901 mustRetainMetadata = true; 1814 mustRetainMetadata = true;
1902 } else if (element == helpers.preserveUrisMarker) { 1815 } else if (element == helpers.preserveUrisMarker) {
1903 if (compiler.options.preserveUris) mustPreserveUris = true; 1816 if (compiler.options.preserveUris) mustPreserveUris = true;
1904 } else if (element == helpers.preserveLibraryNamesMarker) { 1817 } else if (element == helpers.preserveLibraryNamesMarker) {
1905 mustRetainLibraryNames = true; 1818 mustRetainLibraryNames = true;
1906 } else if (element == helpers.getIsolateAffinityTagMarker) { 1819 } else if (element == helpers.getIsolateAffinityTagMarker) {
1907 needToInitializeIsolateAffinityTag = true; 1820 needToInitializeIsolateAffinityTag = true;
1908 } else if (element.isDeferredLoaderGetter) { 1821 } else if (element.isDeferredLoaderGetter) {
1909 // TODO(sigurdm): Create a function registerLoadLibraryAccess. 1822 // TODO(sigurdm): Create a function registerLoadLibraryAccess.
1910 if (!isLoadLibraryFunctionResolved) { 1823 if (!isLoadLibraryFunctionResolved) {
1911 isLoadLibraryFunctionResolved = true; 1824 isLoadLibraryFunctionResolved = true;
1912 if (enqueuer.isResolutionQueue) { 1825 if (forResolution) {
1913 enqueue(enqueuer, helpers.loadLibraryWrapper); 1826 impactTransformer.registerBackendImpact(
1827 worldImpact, impacts.loadLibrary);
1914 } 1828 }
1915 } 1829 }
1916 } else if (element == helpers.requiresPreambleMarker) { 1830 } else if (element == helpers.requiresPreambleMarker) {
1917 requiresPreamble = true; 1831 requiresPreamble = true;
1918 } 1832 }
1919 customElementsAnalysis.registerStaticUse(element, 1833 customElementsAnalysis.registerStaticUse(element,
1920 forResolution: enqueuer.isResolutionQueue); 1834 forResolution: forResolution);
1835 return worldImpact;
1921 } 1836 }
1922 1837
1923 /// Called when [:const Symbol(name):] is seen. 1838 /// Called when [:const Symbol(name):] is seen.
1924 void registerConstSymbol(String name) { 1839 void registerConstSymbol(String name) {
1925 symbolsUsed.add(name); 1840 symbolsUsed.add(name);
1926 if (name.endsWith('=')) { 1841 if (name.endsWith('=')) {
1927 symbolsUsed.add(name.substring(0, name.length - 1)); 1842 symbolsUsed.add(name.substring(0, name.length - 1));
1928 } 1843 }
1929 } 1844 }
1930 1845
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
2337 return staticFields; 2252 return staticFields;
2338 } 2253 }
2339 2254
2340 /// Called when [enqueuer] is empty, but before it is closed. 2255 /// Called when [enqueuer] is empty, but before it is closed.
2341 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { 2256 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) {
2342 // Add elements used synthetically, that is, through features rather than 2257 // Add elements used synthetically, that is, through features rather than
2343 // syntax, for instance custom elements. 2258 // syntax, for instance custom elements.
2344 // 2259 //
2345 // Return early if any elements are added to avoid counting the elements as 2260 // Return early if any elements are added to avoid counting the elements as
2346 // due to mirrors. 2261 // due to mirrors.
2262 enqueuer.applyImpact(customElementsAnalysis.flush(
2263 forResolution: enqueuer.isResolutionQueue));
2347 enqueuer.applyImpact( 2264 enqueuer.applyImpact(
2348 compiler.impactStrategy,
2349 customElementsAnalysis.flush(
2350 forResolution: enqueuer.isResolutionQueue));
2351 enqueuer.applyImpact(compiler.impactStrategy,
2352 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); 2265 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue));
2353 enqueuer.applyImpact(compiler.impactStrategy, 2266 enqueuer.applyImpact(
2354 typeVariableHandler.flush(forResolution: enqueuer.isResolutionQueue)); 2267 typeVariableHandler.flush(forResolution: enqueuer.isResolutionQueue));
2355 2268
2356 if (!enqueuer.queueIsEmpty) return false; 2269 if (!enqueuer.queueIsEmpty) return false;
2357 2270
2358 noSuchMethodRegistry.onQueueEmpty(); 2271 noSuchMethodRegistry.onQueueEmpty();
2359 if (!enabledNoSuchMethod && 2272 if (!enabledNoSuchMethod &&
2360 (noSuchMethodRegistry.hasThrowingNoSuchMethod || 2273 (noSuchMethodRegistry.hasThrowingNoSuchMethod ||
2361 noSuchMethodRegistry.hasComplexNoSuchMethod)) { 2274 noSuchMethodRegistry.hasComplexNoSuchMethod)) {
2362 enableNoSuchMethod(enqueuer); 2275 enqueuer.applyImpact(enableNoSuchMethod());
2363 enabledNoSuchMethod = true; 2276 enabledNoSuchMethod = true;
2364 } 2277 }
2365 2278
2366 if (compiler.options.useKernel && compiler.mainApp != null) { 2279 if (compiler.options.useKernel && compiler.mainApp != null) {
2367 kernelTask.buildKernelIr(); 2280 kernelTask.buildKernelIr();
2368 } 2281 }
2369 2282
2370 if (compiler.options.hasIncrementalSupport) { 2283 if (compiler.options.hasIncrementalSupport) {
2371 // Always enable tear-off closures during incremental compilation. 2284 // Always enable tear-off closures during incremental compilation.
2372 Element e = helpers.closureFromTearOff; 2285 Element element = helpers.closureFromTearOff;
2373 if (e != null && !enqueuer.isProcessed(e)) { 2286 if (element != null && !enqueuer.isProcessed(element)) {
2374 registerBackendUse(e); 2287 enqueuer.applyImpact(
2375 enqueuer.addToWorkList(e); 2288 impactTransformer.createImpactFor(impacts.closureClass));
2376 } 2289 }
2377 } 2290 }
2378 2291
2379 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) { 2292 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) {
2380 preMirrorsMethodCount = generatedCode.length; 2293 preMirrorsMethodCount = generatedCode.length;
2381 } 2294 }
2382 2295
2383 if (isTreeShakingDisabled) { 2296 if (isTreeShakingDisabled) {
2384 enqueuer.applyImpact( 2297 enqueuer.applyImpact(mirrorsAnalysis.computeImpactForReflectiveElements(
2385 compiler.impactStrategy, 2298 recentClasses,
2386 mirrorsAnalysis.computeImpactForReflectiveElements(recentClasses, 2299 enqueuer.processedClasses,
2387 enqueuer.processedClasses, compiler.libraryLoader.libraries, 2300 compiler.libraryLoader.libraries,
2388 forResolution: enqueuer.isResolutionQueue)); 2301 forResolution: enqueuer.isResolutionQueue));
2389 } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) { 2302 } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) {
2390 // Add all static elements (not classes) that have been requested for 2303 // Add all static elements (not classes) that have been requested for
2391 // reflection. If there is no mirror-usage these are probably not 2304 // reflection. If there is no mirror-usage these are probably not
2392 // necessary, but the backend relies on them being resolved. 2305 // necessary, but the backend relies on them being resolved.
2393 enqueuer.applyImpact( 2306 enqueuer.applyImpact(mirrorsAnalysis
2394 compiler.impactStrategy, 2307 .computeImpactForReflectiveStaticFields(_findStaticFieldTargets(),
2395 mirrorsAnalysis.computeImpactForReflectiveStaticFields(
2396 _findStaticFieldTargets(),
2397 forResolution: enqueuer.isResolutionQueue)); 2308 forResolution: enqueuer.isResolutionQueue));
2398 } 2309 }
2399 2310
2400 if (mustPreserveNames) reporter.log('Preserving names.'); 2311 if (mustPreserveNames) reporter.log('Preserving names.');
2401 2312
2402 if (mustRetainMetadata) { 2313 if (mustRetainMetadata) {
2403 reporter.log('Retaining metadata.'); 2314 reporter.log('Retaining metadata.');
2404 2315
2405 compiler.libraryLoader.libraries.forEach(retainMetadataOf); 2316 compiler.libraryLoader.libraries.forEach(retainMetadataOf);
2406 2317
(...skipping 16 matching lines...) Expand all
2423 // elements and process these instead. 2334 // elements and process these instead.
2424 processMetadata(compiler.enqueuer.resolution.processedElements, 2335 processMetadata(compiler.enqueuer.resolution.processedElements,
2425 registerMetadataConstant); 2336 registerMetadataConstant);
2426 } else { 2337 } else {
2427 for (Dependency dependency in metadataConstants) { 2338 for (Dependency dependency in metadataConstants) {
2428 computeImpactForCompileTimeConstant( 2339 computeImpactForCompileTimeConstant(
2429 dependency.constant, impactBuilder, enqueuer.isResolutionQueue); 2340 dependency.constant, impactBuilder, enqueuer.isResolutionQueue);
2430 } 2341 }
2431 metadataConstants.clear(); 2342 metadataConstants.clear();
2432 } 2343 }
2433 enqueuer.applyImpact(compiler.impactStrategy, impactBuilder.flush()); 2344 enqueuer.applyImpact(impactBuilder.flush());
2434 } 2345 }
2435 return true; 2346 return true;
2436 } 2347 }
2437 2348
2438 /// Call [registerMetadataConstant] on all metadata from [elements]. 2349 /// Call [registerMetadataConstant] on all metadata from [elements].
2439 void processMetadata(Iterable<Element> elements, 2350 void processMetadata(Iterable<Element> elements,
2440 void onMetadata(MetadataAnnotation metadata)) { 2351 void onMetadata(MetadataAnnotation metadata)) {
2441 void processLibraryMetadata(LibraryElement library) { 2352 void processLibraryMetadata(LibraryElement library) {
2442 if (_registeredMetadata.add(library)) { 2353 if (_registeredMetadata.add(library)) {
2443 library.metadata.forEach(onMetadata); 2354 library.metadata.forEach(onMetadata);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2572 2483
2573 FunctionElement helperForMainArity() => helpers.mainHasTooManyParameters; 2484 FunctionElement helperForMainArity() => helpers.mainHasTooManyParameters;
2574 2485
2575 void forgetElement(Element element) { 2486 void forgetElement(Element element) {
2576 constants.forgetElement(element); 2487 constants.forgetElement(element);
2577 constantCompilerTask.dartConstantCompiler.forgetElement(element); 2488 constantCompilerTask.dartConstantCompiler.forgetElement(element);
2578 aliasedSuperMembers.remove(element); 2489 aliasedSuperMembers.remove(element);
2579 } 2490 }
2580 2491
2581 @override 2492 @override
2582 WorldImpact computeMainImpact(Enqueuer enqueuer, MethodElement mainMethod) { 2493 WorldImpact computeMainImpact(MethodElement mainMethod,
2494 {bool forResolution}) {
2583 WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl(); 2495 WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
2584 if (mainMethod.parameters.isNotEmpty) { 2496 if (mainMethod.parameters.isNotEmpty) {
2585 impactTransformer.registerBackendImpact( 2497 impactTransformer.registerBackendImpact(
2586 mainImpact, impacts.mainWithArguments); 2498 mainImpact, impacts.mainWithArguments);
2587 mainImpact.registerStaticUse( 2499 mainImpact.registerStaticUse(
2588 new StaticUse.staticInvoke(mainMethod, CallStructure.TWO_ARGS)); 2500 new StaticUse.staticInvoke(mainMethod, CallStructure.TWO_ARGS));
2589 // If the main method takes arguments, this compilation could be the 2501 // If the main method takes arguments, this compilation could be the
2590 // target of Isolate.spawnUri. Strictly speaking, that can happen also if 2502 // target of Isolate.spawnUri. Strictly speaking, that can happen also if
2591 // main takes no arguments, but in this case the spawned isolate can't 2503 // main takes no arguments, but in this case the spawned isolate can't
2592 // communicate with the spawning isolate. 2504 // communicate with the spawning isolate.
2593 enqueuer.enableIsolateSupport(); 2505 mainImpact.addImpact(enableIsolateSupport(forResolution: forResolution));
2594 } 2506 }
2595 mainImpact.registerStaticUse( 2507 mainImpact.registerStaticUse(
2596 new StaticUse.staticInvoke(mainMethod, CallStructure.NO_ARGS)); 2508 new StaticUse.staticInvoke(mainMethod, CallStructure.NO_ARGS));
2597 return mainImpact; 2509 return mainImpact;
2598 } 2510 }
2599 2511
2600 /// Returns the filename for the output-unit named [name]. 2512 /// Returns the filename for the output-unit named [name].
2601 /// 2513 ///
2602 /// The filename is of the form "<main output file>_<name>.part.js". 2514 /// The filename is of the form "<main output file>_<name>.part.js".
2603 /// If [addExtension] is false, the ".part.js" suffix is left out. 2515 /// If [addExtension] is false, the ".part.js" suffix is left out.
2604 String deferredPartFileName(String name, {bool addExtension: true}) { 2516 String deferredPartFileName(String name, {bool addExtension: true}) {
2605 assert(name != ""); 2517 assert(name != "");
2606 String outPath = compiler.options.outputUri != null 2518 String outPath = compiler.options.outputUri != null
2607 ? compiler.options.outputUri.path 2519 ? compiler.options.outputUri.path
2608 : "out"; 2520 : "out";
2609 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); 2521 String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
2610 String extension = addExtension ? ".part.js" : ""; 2522 String extension = addExtension ? ".part.js" : "";
2611 return "${outName}_$name$extension"; 2523 return "${outName}_$name$extension";
2612 } 2524 }
2613 2525
2614 @override 2526 @override
2615 bool enableDeferredLoadingIfSupported( 2527 bool enableDeferredLoadingIfSupported(Spannable node) => true;
2616 ResolutionEnqueuer enqueuer, Spannable node) {
2617 registerCheckDeferredIsLoaded(enqueuer);
2618 return true;
2619 }
2620 2528
2621 @override 2529 @override
2622 bool enableCodegenWithErrorsIfSupported(Spannable node) => true; 2530 bool enableCodegenWithErrorsIfSupported(Spannable node) => true;
2623 2531
2624 jsAst.Expression rewriteAsync( 2532 jsAst.Expression rewriteAsync(
2625 FunctionElement element, jsAst.Expression code) { 2533 FunctionElement element, jsAst.Expression code) {
2626 AsyncRewriterBase rewriter = null; 2534 AsyncRewriterBase rewriter = null;
2627 jsAst.Name name = namer.methodPropertyName(element); 2535 jsAst.Name name = namer.methodPropertyName(element);
2628 switch (element.asyncMarker) { 2536 switch (element.asyncMarker) {
2629 case AsyncMarker.ASYNC: 2537 case AsyncMarker.ASYNC:
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
3004 } 2912 }
3005 2913
3006 for (native.NativeBehavior behavior in worldImpact.nativeData) { 2914 for (native.NativeBehavior behavior in worldImpact.nativeData) {
3007 enqueuer.nativeEnqueuer 2915 enqueuer.nativeEnqueuer
3008 .registerNativeBehavior(transformed, behavior, worldImpact); 2916 .registerNativeBehavior(transformed, behavior, worldImpact);
3009 } 2917 }
3010 2918
3011 return transformed; 2919 return transformed;
3012 } 2920 }
3013 2921
2922 WorldImpact createImpactFor(BackendImpact impact) {
2923 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
2924 registerBackendImpact(impactBuilder, impact);
2925 return impactBuilder;
2926 }
2927
2928 void registerBackendStaticUse(
2929 WorldImpactBuilder worldImpact, MethodElement element,
2930 {bool isGlobal: false}) {
2931 backend.registerBackendUse(element);
2932 worldImpact.registerStaticUse(
2933 // TODO(johnniwinther): Store the correct use in impacts.
2934 new StaticUse.foreignUse(element));
2935 if (isGlobal) {
2936 backend.compiler.globalDependencies.registerDependency(element);
2937 }
2938 }
2939
2940 void registerBackendInstantiation(
2941 WorldImpactBuilder worldImpact, ClassElement cls,
2942 {bool isGlobal: false}) {
2943 cls.ensureResolved(backend.resolution);
2944 backend.registerBackendUse(cls);
2945 worldImpact.registerTypeUse(new TypeUse.instantiation(cls.rawType));
2946 if (isGlobal) {
2947 backend.compiler.globalDependencies.registerDependency(cls);
2948 }
2949 }
2950
3014 void registerBackendImpact( 2951 void registerBackendImpact(
3015 WorldImpactBuilder worldImpact, BackendImpact backendImpact) { 2952 WorldImpactBuilder worldImpact, BackendImpact backendImpact) {
3016 for (Element staticUse in backendImpact.staticUses) { 2953 for (Element staticUse in backendImpact.staticUses) {
3017 assert(staticUse != null); 2954 assert(staticUse != null);
3018 backend.registerBackendUse(staticUse); 2955 registerBackendStaticUse(worldImpact, staticUse);
3019 worldImpact.registerStaticUse( 2956 }
3020 // TODO(johnniwinther): Store the correct use in impacts. 2957 for (Element staticUse in backendImpact.globalUses) {
3021 new StaticUse.foreignUse(staticUse)); 2958 assert(staticUse != null);
2959 registerBackendStaticUse(worldImpact, staticUse, isGlobal: true);
3022 } 2960 }
3023 for (Selector selector in backendImpact.dynamicUses) { 2961 for (Selector selector in backendImpact.dynamicUses) {
3024 assert(selector != null); 2962 assert(selector != null);
3025 worldImpact.registerDynamicUse(new DynamicUse(selector, null)); 2963 worldImpact.registerDynamicUse(new DynamicUse(selector, null));
3026 } 2964 }
3027 for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) { 2965 for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) {
3028 backend.registerBackendUse(instantiatedType.element); 2966 backend.registerBackendUse(instantiatedType.element);
3029 worldImpact.registerTypeUse(new TypeUse.instantiation(instantiatedType)); 2967 worldImpact.registerTypeUse(new TypeUse.instantiation(instantiatedType));
3030 } 2968 }
3031 for (ClassElement cls in backendImpact.instantiatedClasses) { 2969 for (ClassElement cls in backendImpact.instantiatedClasses) {
3032 cls.ensureResolved(backend.resolution); 2970 registerBackendInstantiation(worldImpact, cls);
3033 backend.registerBackendUse(cls); 2971 }
3034 worldImpact.registerTypeUse(new TypeUse.instantiation(cls.rawType)); 2972 for (ClassElement cls in backendImpact.globalClasses) {
2973 registerBackendInstantiation(worldImpact, cls, isGlobal: true);
3035 } 2974 }
3036 for (BackendImpact otherImpact in backendImpact.otherImpacts) { 2975 for (BackendImpact otherImpact in backendImpact.otherImpacts) {
3037 registerBackendImpact(worldImpact, otherImpact); 2976 registerBackendImpact(worldImpact, otherImpact);
3038 } 2977 }
3039 for (BackendFeature feature in backendImpact.features) { 2978 for (BackendFeature feature in backendImpact.features) {
3040 switch (feature) { 2979 switch (feature) {
3041 case BackendFeature.needToInitializeDispatchProperty: 2980 case BackendFeature.needToInitializeDispatchProperty:
3042 backend.needToInitializeDispatchProperty = true; 2981 backend.needToInitializeDispatchProperty = true;
3043 break; 2982 break;
3044 case BackendFeature.needToInitializeIsolateAffinityTag: 2983 case BackendFeature.needToInitializeIsolateAffinityTag:
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
3290 ClassElement get mapImplementation => helpers.mapLiteralClass; 3229 ClassElement get mapImplementation => helpers.mapLiteralClass;
3291 ClassElement get constMapImplementation => helpers.constMapLiteralClass; 3230 ClassElement get constMapImplementation => helpers.constMapLiteralClass;
3292 ClassElement get typeImplementation => helpers.typeLiteralClass; 3231 ClassElement get typeImplementation => helpers.typeLiteralClass;
3293 ClassElement get boolImplementation => helpers.jsBoolClass; 3232 ClassElement get boolImplementation => helpers.jsBoolClass;
3294 ClassElement get nullImplementation => helpers.jsNullClass; 3233 ClassElement get nullImplementation => helpers.jsNullClass;
3295 ClassElement get syncStarIterableImplementation => helpers.syncStarIterable; 3234 ClassElement get syncStarIterableImplementation => helpers.syncStarIterable;
3296 ClassElement get asyncFutureImplementation => helpers.futureImplementation; 3235 ClassElement get asyncFutureImplementation => helpers.futureImplementation;
3297 ClassElement get asyncStarStreamImplementation => helpers.controllerStream; 3236 ClassElement get asyncStarStreamImplementation => helpers.controllerStream;
3298 ClassElement get functionImplementation => helpers.coreClasses.functionClass; 3237 ClassElement get functionImplementation => helpers.coreClasses.functionClass;
3299 } 3238 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/enqueue.dart ('k') | pkg/compiler/lib/src/js_backend/backend_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698