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

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

Issue 2846433003: Run closed_world2_test using the normal compiler pipeline. (Closed)
Patch Set: Created 3 years, 8 months 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
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 '../common.dart'; 7 import '../common.dart';
8 import '../common/backend_api.dart' 8 import '../common/backend_api.dart'
9 show ForeignResolver, NativeRegistry, ImpactTransformer; 9 show ForeignResolver, NativeRegistry, ImpactTransformer;
10 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem; 10 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 // but may be inlined in a loop. 102 // but may be inlined in a loop.
103 static const int _mayInlineInLoopMustNotOutside = 1; 103 static const int _mayInlineInLoopMustNotOutside = 1;
104 // The function can be inlined in a loop, but not outside. 104 // The function can be inlined in a loop, but not outside.
105 static const int _canInlineInLoopMustNotOutside = 2; 105 static const int _canInlineInLoopMustNotOutside = 2;
106 // May-inline means that we know that it can be inlined inside a loop, but 106 // May-inline means that we know that it can be inlined inside a loop, but
107 // don't know about the general case yet. 107 // don't know about the general case yet.
108 static const int _canInlineInLoopMayInlineOutside = 3; 108 static const int _canInlineInLoopMayInlineOutside = 3;
109 static const int _canInline = 4; 109 static const int _canInline = 4;
110 static const int _mustInline = 5; 110 static const int _mustInline = 5;
111 111
112 final Map<MethodElement, int> _cachedDecisions = 112 final Map<FunctionEntity, int> _cachedDecisions =
113 new Map<MethodElement, int>(); 113 new Map<FunctionEntity, int>();
114 114
115 /// Returns the current cache decision. This should only be used for testing. 115 /// Returns the current cache decision. This should only be used for testing.
116 int getCurrentCacheDecisionForTesting(Element element) { 116 int getCurrentCacheDecisionForTesting(Element element) {
117 return _cachedDecisions[element]; 117 return _cachedDecisions[element];
118 } 118 }
119 119
120 // Returns `true`/`false` if we have a cached decision. 120 // Returns `true`/`false` if we have a cached decision.
121 // Returns `null` otherwise. 121 // Returns `null` otherwise.
122 bool canInline(MethodElement element, {bool insideLoop}) { 122 bool canInline(FunctionEntity element, {bool insideLoop}) {
123 int decision = _cachedDecisions[element]; 123 int decision = _cachedDecisions[element];
124 124
125 if (decision == null) { 125 if (decision == null) {
126 // These synthetic elements are not yet present when we initially compute 126 // These synthetic elements are not yet present when we initially compute
127 // this cache from metadata annotations, so look for their parent. 127 // this cache from metadata annotations, so look for their parent.
128 if (element is ConstructorBodyElement) { 128 if (element is ConstructorBodyElement) {
129 ConstructorBodyElement body = element; 129 ConstructorBodyElement body = element;
130 decision = _cachedDecisions[body.constructor]; 130 decision = _cachedDecisions[body.constructor];
131 } 131 }
132 if (decision == null) { 132 if (decision == null) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 case _canInline: 167 case _canInline:
168 case _mustInline: 168 case _mustInline:
169 return true; 169 return true;
170 } 170 }
171 } 171 }
172 172
173 // Quiet static checker. 173 // Quiet static checker.
174 return null; 174 return null;
175 } 175 }
176 176
177 void markAsInlinable(MethodElement element, {bool insideLoop}) { 177 void markAsInlinable(FunctionEntity element, {bool insideLoop}) {
178 int oldDecision = _cachedDecisions[element]; 178 int oldDecision = _cachedDecisions[element];
179 179
180 if (oldDecision == null) { 180 if (oldDecision == null) {
181 oldDecision = _unknown; 181 oldDecision = _unknown;
182 } 182 }
183 183
184 if (insideLoop) { 184 if (insideLoop) {
185 switch (oldDecision) { 185 switch (oldDecision) {
186 case _mustNotInline: 186 case _mustNotInline:
187 throw new SpannableAssertionFailure( 187 throw new SpannableAssertionFailure(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 break; 222 break;
223 223
224 case _canInline: 224 case _canInline:
225 case _mustInline: 225 case _mustInline:
226 // Do nothing. 226 // Do nothing.
227 break; 227 break;
228 } 228 }
229 } 229 }
230 } 230 }
231 231
232 void markAsNonInlinable(MethodElement element, {bool insideLoop: true}) { 232 void markAsNonInlinable(FunctionEntity element, {bool insideLoop: true}) {
233 int oldDecision = _cachedDecisions[element]; 233 int oldDecision = _cachedDecisions[element];
234 234
235 if (oldDecision == null) { 235 if (oldDecision == null) {
236 oldDecision = _unknown; 236 oldDecision = _unknown;
237 } 237 }
238 238
239 if (insideLoop) { 239 if (insideLoop) {
240 switch (oldDecision) { 240 switch (oldDecision) {
241 case _canInlineInLoopMustNotOutside: 241 case _canInlineInLoopMustNotOutside:
242 case _canInlineInLoopMayInlineOutside: 242 case _canInlineInLoopMayInlineOutside:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 280
281 case _mayInlineInLoopMustNotOutside: 281 case _mayInlineInLoopMustNotOutside:
282 case _canInlineInLoopMustNotOutside: 282 case _canInlineInLoopMustNotOutside:
283 case _mustNotInline: 283 case _mustNotInline:
284 // Do nothing. 284 // Do nothing.
285 break; 285 break;
286 } 286 }
287 } 287 }
288 } 288 }
289 289
290 void markAsMustInline(MethodElement element) { 290 void markAsMustInline(FunctionEntity element) {
291 _cachedDecisions[element] = _mustInline; 291 _cachedDecisions[element] = _mustInline;
292 } 292 }
293 } 293 }
294 294
295 enum SyntheticConstantKind { 295 enum SyntheticConstantKind {
296 DUMMY_INTERCEPTOR, 296 DUMMY_INTERCEPTOR,
297 EMPTY_VALUE, 297 EMPTY_VALUE,
298 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. 298 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data.
299 NAME 299 NAME
300 } 300 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 343
344 Namer get namer { 344 Namer get namer {
345 assert(invariant(NO_LOCATION_SPANNABLE, _namer != null, 345 assert(invariant(NO_LOCATION_SPANNABLE, _namer != null,
346 message: "Namer has not been created yet.")); 346 message: "Namer has not been created yet."));
347 return _namer; 347 return _namer;
348 } 348 }
349 349
350 /** 350 /**
351 * Set of classes whose `operator ==` methods handle `null` themselves. 351 * Set of classes whose `operator ==` methods handle `null` themselves.
352 */ 352 */
353 final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>(); 353 final Set<ClassEntity> specialOperatorEqClasses = new Set<ClassEntity>();
354 354
355 List<CompilerTask> get tasks { 355 List<CompilerTask> get tasks {
356 List<CompilerTask> result = functionCompiler.tasks; 356 List<CompilerTask> result = functionCompiler.tasks;
357 result.add(emitter); 357 result.add(emitter);
358 result.add(patchResolverTask); 358 result.add(patchResolverTask);
359 result.add(kernelTask); 359 result.add(kernelTask);
360 return result; 360 return result;
361 } 361 }
362 362
363 final RuntimeTypesNeedBuilder _rtiNeedBuilder; 363 final RuntimeTypesNeedBuilder _rtiNeedBuilder;
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 if (class_.isSubclassOf(commonElements.jsArrayClass)) 718 if (class_.isSubclassOf(commonElements.jsArrayClass))
719 return commonElements.jsArrayClass; 719 return commonElements.jsArrayClass;
720 return class_; 720 return class_;
721 } 721 }
722 722
723 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { 723 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) {
724 return specialOperatorEqClasses.contains(operatorEqfunction.enclosingClass); 724 return specialOperatorEqClasses.contains(operatorEqfunction.enclosingClass);
725 } 725 }
726 726
727 void validateInterceptorImplementsAllObjectMethods( 727 void validateInterceptorImplementsAllObjectMethods(
728 ClassElement interceptorClass) { 728 ClassEntity interceptorClass) {
729 if (interceptorClass == null) return; 729 if (interceptorClass == null) return;
730 interceptorClass.ensureResolved(resolution); 730 ClassEntity objectClass = commonElements.objectClass;
731 ClassElement objectClass = commonElements.objectClass; 731 compiler.elementEnvironment.forEachClassMember(objectClass,
732 objectClass.forEachMember((_, Element member) { 732 (_, MemberEntity member) {
733 if (member.isGenerativeConstructor) return; 733 if (member.isConstructor) return;
734 Element interceptorMember = interceptorClass.lookupMember(member.name); 734 MemberEntity interceptorMember = compiler.elementEnvironment
735 .lookupClassMember(interceptorClass, member.name);
735 // Interceptors must override all Object methods due to calling convention 736 // Interceptors must override all Object methods due to calling convention
736 // differences. 737 // differences.
737 assert(invariant(interceptorMember, 738 assert(invariant(interceptorMember,
738 interceptorMember.enclosingClass == interceptorClass, 739 interceptorMember.enclosingClass == interceptorClass,
739 message: 740 message:
740 "Member ${member.name} not overridden in ${interceptorClass}. " 741 "Member ${member.name} not overridden in ${interceptorClass}. "
741 "Found $interceptorMember from " 742 "Found $interceptorMember from "
742 "${interceptorMember.enclosingClass}.")); 743 "${interceptorMember.enclosingClass}."));
743 }); 744 });
744 } 745 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 824
824 ResolutionEnqueuer createResolutionEnqueuer( 825 ResolutionEnqueuer createResolutionEnqueuer(
825 CompilerTask task, Compiler compiler) { 826 CompilerTask task, Compiler compiler) {
826 _nativeBasicData = 827 _nativeBasicData =
827 nativeBasicDataBuilder.close(compiler.elementEnvironment); 828 nativeBasicDataBuilder.close(compiler.elementEnvironment);
828 _nativeResolutionEnqueuer = new native.NativeResolutionEnqueuer( 829 _nativeResolutionEnqueuer = new native.NativeResolutionEnqueuer(
829 compiler.options, 830 compiler.options,
830 compiler.elementEnvironment, 831 compiler.elementEnvironment,
831 commonElements, 832 commonElements,
832 backendUsageBuilder, 833 backendUsageBuilder,
833 compiler.frontEndStrategy.createNativeClassResolver(nativeBasicData)); 834 compiler.frontEndStrategy.createNativeClassFinder(nativeBasicData));
834 _nativeData = new NativeDataImpl(nativeBasicData); 835 _nativeData = new NativeDataImpl(nativeBasicData);
835 _customElementsResolutionAnalysis = compiler.frontEndStrategy 836 _customElementsResolutionAnalysis = compiler.frontEndStrategy
836 .createCustomElementsResolutionAnalysis( 837 .createCustomElementsResolutionAnalysis(
837 nativeBasicData, backendUsageBuilder); 838 nativeBasicData, backendUsageBuilder);
838 impactTransformer = new JavaScriptImpactTransformer( 839 impactTransformer = new JavaScriptImpactTransformer(
839 compiler.options, 840 compiler.options,
840 compiler.elementEnvironment, 841 compiler.elementEnvironment,
841 commonElements, 842 commonElements,
842 impacts, 843 impacts,
843 nativeBasicData, 844 nativeBasicData,
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
1162 /// Called when code generation has been completed. 1163 /// Called when code generation has been completed.
1163 void onCodegenEnd() { 1164 void onCodegenEnd() {
1164 sourceInformationStrategy.onComplete(); 1165 sourceInformationStrategy.onComplete();
1165 tracer.close(); 1166 tracer.close();
1166 } 1167 }
1167 1168
1168 // Does this element belong in the output 1169 // Does this element belong in the output
1169 bool shouldOutput(Element element) => true; 1170 bool shouldOutput(Element element) => true;
1170 1171
1171 /// Returns `true` if the `native` pseudo keyword is supported for [library]. 1172 /// Returns `true` if the `native` pseudo keyword is supported for [library].
1172 bool canLibraryUseNative(LibraryElement library) { 1173 bool canLibraryUseNative(LibraryEntity library) {
1173 return native.maybeEnableNative(compiler, library); 1174 return native.maybeEnableNative(compiler, library);
1174 } 1175 }
1175 1176
1176 bool isTargetSpecificLibrary(LibraryElement library) { 1177 bool isTargetSpecificLibrary(LibraryElement library) {
1177 Uri canonicalUri = library.canonicalUri; 1178 Uri canonicalUri = library.canonicalUri;
1178 if (canonicalUri == Uris.dart__js_helper || 1179 if (canonicalUri == Uris.dart__js_helper ||
1179 canonicalUri == Uris.dart__interceptors) { 1180 canonicalUri == Uris.dart__interceptors) {
1180 return true; 1181 return true;
1181 } 1182 }
1182 return false; 1183 return false;
1183 } 1184 }
1184 1185
1185 /// Process backend specific annotations. 1186 /// Process backend specific annotations.
1186 void processAnnotations( 1187 void processAnnotations(
1187 MemberElement element, ClosedWorldRefiner closedWorldRefiner) { 1188 MemberElement element, ClosedWorldRefiner closedWorldRefiner) {
1188 if (element.isMalformed) { 1189 if (element.isMalformed) {
1189 // Elements that are marked as malformed during parsing or resolution 1190 // Elements that are marked as malformed during parsing or resolution
1190 // might be registered here. These should just be ignored. 1191 // might be registered here. These should just be ignored.
1191 return; 1192 return;
1192 } 1193 }
1193 1194
1194 MemberElement implementation = element.implementation;
1195 if (element.isFunction || element.isConstructor) { 1195 if (element.isFunction || element.isConstructor) {
1196 if (annotations.noInline(implementation)) { 1196 MethodElement method = element.implementation;
1197 inlineCache.markAsNonInlinable(implementation); 1197 if (annotations.noInline(method)) {
1198 inlineCache.markAsNonInlinable(method);
1198 } 1199 }
1199 } 1200 }
1201 if (element.isField) return;
1202 MethodElement method = element;
1200 1203
1201 LibraryElement library = element.library; 1204 LibraryElement library = method.library;
1202 if (!library.isPlatformLibrary && !canLibraryUseNative(library)) return; 1205 if (!library.isPlatformLibrary && !canLibraryUseNative(library)) return;
1203 bool hasNoInline = false; 1206 bool hasNoInline = false;
1204 bool hasForceInline = false; 1207 bool hasForceInline = false;
1205 bool hasNoThrows = false; 1208 bool hasNoThrows = false;
1206 bool hasNoSideEffects = false; 1209 bool hasNoSideEffects = false;
1207 for (MetadataAnnotation metadata in element.implementation.metadata) { 1210 for (MetadataAnnotation metadata in method.implementation.metadata) {
1208 metadata.ensureResolved(resolution); 1211 metadata.ensureResolved(resolution);
1209 ConstantValue constantValue = 1212 ConstantValue constantValue =
1210 compiler.constants.getConstantValue(metadata.constant); 1213 compiler.constants.getConstantValue(metadata.constant);
1211 if (!constantValue.isConstructedObject) continue; 1214 if (!constantValue.isConstructedObject) continue;
1212 ObjectConstantValue value = constantValue; 1215 ObjectConstantValue value = constantValue;
1213 ClassElement cls = value.type.element; 1216 ClassElement cls = value.type.element;
1214 if (cls == commonElements.forceInlineClass) { 1217 if (cls == commonElements.forceInlineClass) {
1215 hasForceInline = true; 1218 hasForceInline = true;
1216 if (VERBOSE_OPTIMIZER_HINTS) { 1219 if (VERBOSE_OPTIMIZER_HINTS) {
1217 reporter.reportHintMessage( 1220 reporter.reportHintMessage(
1218 element, MessageKind.GENERIC, {'text': "Must inline"}); 1221 method, MessageKind.GENERIC, {'text': "Must inline"});
1219 } 1222 }
1220 inlineCache.markAsMustInline(element); 1223 inlineCache.markAsMustInline(method);
1221 } else if (cls == commonElements.noInlineClass) { 1224 } else if (cls == commonElements.noInlineClass) {
1222 hasNoInline = true; 1225 hasNoInline = true;
1223 if (VERBOSE_OPTIMIZER_HINTS) { 1226 if (VERBOSE_OPTIMIZER_HINTS) {
1224 reporter.reportHintMessage( 1227 reporter.reportHintMessage(
1225 element, MessageKind.GENERIC, {'text': "Cannot inline"}); 1228 method, MessageKind.GENERIC, {'text': "Cannot inline"});
1226 } 1229 }
1227 inlineCache.markAsNonInlinable(element); 1230 inlineCache.markAsNonInlinable(method);
1228 } else if (cls == commonElements.noThrowsClass) { 1231 } else if (cls == commonElements.noThrowsClass) {
1229 hasNoThrows = true; 1232 hasNoThrows = true;
1230 if (!Elements.isStaticOrTopLevelFunction(element) && 1233 if (!Elements.isStaticOrTopLevelFunction(method) &&
1231 !element.isFactoryConstructor) { 1234 !method.isFactoryConstructor) {
1232 reporter.internalError( 1235 reporter.internalError(
1233 element, 1236 method,
1234 "@NoThrows() is currently limited to top-level" 1237 "@NoThrows() is currently limited to top-level"
1235 " or static functions and factory constructors."); 1238 " or static functions and factory constructors.");
1236 } 1239 }
1237 if (VERBOSE_OPTIMIZER_HINTS) { 1240 if (VERBOSE_OPTIMIZER_HINTS) {
1238 reporter.reportHintMessage( 1241 reporter.reportHintMessage(
1239 element, MessageKind.GENERIC, {'text': "Cannot throw"}); 1242 method, MessageKind.GENERIC, {'text': "Cannot throw"});
1240 } 1243 }
1241 closedWorldRefiner.registerCannotThrow(element); 1244 closedWorldRefiner.registerCannotThrow(method);
1242 } else if (cls == commonElements.noSideEffectsClass) { 1245 } else if (cls == commonElements.noSideEffectsClass) {
1243 hasNoSideEffects = true; 1246 hasNoSideEffects = true;
1244 if (VERBOSE_OPTIMIZER_HINTS) { 1247 if (VERBOSE_OPTIMIZER_HINTS) {
1245 reporter.reportHintMessage( 1248 reporter.reportHintMessage(
1246 element, MessageKind.GENERIC, {'text': "Has no side effects"}); 1249 method, MessageKind.GENERIC, {'text': "Has no side effects"});
1247 } 1250 }
1248 closedWorldRefiner.registerSideEffectsFree(element); 1251 closedWorldRefiner.registerSideEffectsFree(method);
1249 } 1252 }
1250 } 1253 }
1251 if (hasForceInline && hasNoInline) { 1254 if (hasForceInline && hasNoInline) {
1252 reporter.internalError( 1255 reporter.internalError(
1253 element, "@ForceInline() must not be used with @NoInline."); 1256 method, "@ForceInline() must not be used with @NoInline.");
1254 } 1257 }
1255 if (hasNoThrows && !hasNoInline) { 1258 if (hasNoThrows && !hasNoInline) {
1256 reporter.internalError( 1259 reporter.internalError(
1257 element, "@NoThrows() should always be combined with @NoInline."); 1260 method, "@NoThrows() should always be combined with @NoInline.");
1258 } 1261 }
1259 if (hasNoSideEffects && !hasNoInline) { 1262 if (hasNoSideEffects && !hasNoInline) {
1260 reporter.internalError(element, 1263 reporter.internalError(
1261 "@NoSideEffects() should always be combined with @NoInline."); 1264 method, "@NoSideEffects() should always be combined with @NoInline.");
1262 } 1265 }
1263 } 1266 }
1264 1267
1265 MethodElement helperForBadMain() => commonElements.badMain; 1268 MethodElement helperForBadMain() => commonElements.badMain;
1266 1269
1267 MethodElement helperForMissingMain() => commonElements.missingMain; 1270 MethodElement helperForMissingMain() => commonElements.missingMain;
1268 1271
1269 MethodElement helperForMainArity() => commonElements.mainHasTooManyParameters; 1272 MethodElement helperForMainArity() => commonElements.mainHasTooManyParameters;
1270 1273
1271 /// Enable deferred loading. Returns `true` if the backend supports deferred 1274 /// Enable deferred loading. Returns `true` if the backend supports deferred
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1448 1451
1449 bool canUseAliasedSuperMember(MemberEntity member, Selector selector) { 1452 bool canUseAliasedSuperMember(MemberEntity member, Selector selector) {
1450 return !selector.isGetter; 1453 return !selector.isGetter;
1451 } 1454 }
1452 1455
1453 /// Returns `true` if [member] is called from a subclass via `super`. 1456 /// Returns `true` if [member] is called from a subclass via `super`.
1454 bool isAliasedSuperMember(MemberEntity member) { 1457 bool isAliasedSuperMember(MemberEntity member) {
1455 return _aliasedSuperMembers.contains(member); 1458 return _aliasedSuperMembers.contains(member);
1456 } 1459 }
1457 } 1460 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698