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

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

Issue 2675103003: Refactor BackendHelpers to be reusageable with KernelWorldBuilder (Closed)
Patch Set: Created 3 years, 10 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 '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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 // but may be inlined in a loop. 107 // but may be inlined in a loop.
108 static const int _mayInlineInLoopMustNotOutside = 1; 108 static const int _mayInlineInLoopMustNotOutside = 1;
109 // The function can be inlined in a loop, but not outside. 109 // The function can be inlined in a loop, but not outside.
110 static const int _canInlineInLoopMustNotOutside = 2; 110 static const int _canInlineInLoopMustNotOutside = 2;
111 // May-inline means that we know that it can be inlined inside a loop, but 111 // May-inline means that we know that it can be inlined inside a loop, but
112 // don't know about the general case yet. 112 // don't know about the general case yet.
113 static const int _canInlineInLoopMayInlineOutside = 3; 113 static const int _canInlineInLoopMayInlineOutside = 3;
114 static const int _canInline = 4; 114 static const int _canInline = 4;
115 static const int _mustInline = 5; 115 static const int _mustInline = 5;
116 116
117 final Map<FunctionElement, int> _cachedDecisions = 117 final Map<MethodElement, int> _cachedDecisions =
118 new Map<FunctionElement, int>(); 118 new Map<MethodElement, int>();
119 119
120 /// Returns the current cache decision. This should only be used for testing. 120 /// Returns the current cache decision. This should only be used for testing.
121 int getCurrentCacheDecisionForTesting(Element element) { 121 int getCurrentCacheDecisionForTesting(Element element) {
122 return _cachedDecisions[element]; 122 return _cachedDecisions[element];
123 } 123 }
124 124
125 // Returns `true`/`false` if we have a cached decision. 125 // Returns `true`/`false` if we have a cached decision.
126 // Returns `null` otherwise. 126 // Returns `null` otherwise.
127 bool canInline(FunctionElement element, {bool insideLoop}) { 127 bool canInline(MethodElement element, {bool insideLoop}) {
128 int decision = _cachedDecisions[element]; 128 int decision = _cachedDecisions[element];
129 129
130 if (decision == null) { 130 if (decision == null) {
131 // These synthetic elements are not yet present when we initially compute 131 // These synthetic elements are not yet present when we initially compute
132 // this cache from metadata annotations, so look for their parent. 132 // this cache from metadata annotations, so look for their parent.
133 if (element is ConstructorBodyElement) { 133 if (element is ConstructorBodyElement) {
134 ConstructorBodyElement body = element; 134 ConstructorBodyElement body = element;
135 decision = _cachedDecisions[body.constructor]; 135 decision = _cachedDecisions[body.constructor];
136 } 136 }
137 if (decision == null) { 137 if (decision == null) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 case _canInline: 172 case _canInline:
173 case _mustInline: 173 case _mustInline:
174 return true; 174 return true;
175 } 175 }
176 } 176 }
177 177
178 // Quiet static checker. 178 // Quiet static checker.
179 return null; 179 return null;
180 } 180 }
181 181
182 void markAsInlinable(FunctionElement element, {bool insideLoop}) { 182 void markAsInlinable(MethodElement element, {bool insideLoop}) {
183 int oldDecision = _cachedDecisions[element]; 183 int oldDecision = _cachedDecisions[element];
184 184
185 if (oldDecision == null) { 185 if (oldDecision == null) {
186 oldDecision = _unknown; 186 oldDecision = _unknown;
187 } 187 }
188 188
189 if (insideLoop) { 189 if (insideLoop) {
190 switch (oldDecision) { 190 switch (oldDecision) {
191 case _mustNotInline: 191 case _mustNotInline:
192 throw new SpannableAssertionFailure( 192 throw new SpannableAssertionFailure(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 break; 227 break;
228 228
229 case _canInline: 229 case _canInline:
230 case _mustInline: 230 case _mustInline:
231 // Do nothing. 231 // Do nothing.
232 break; 232 break;
233 } 233 }
234 } 234 }
235 } 235 }
236 236
237 void markAsNonInlinable(FunctionElement element, {bool insideLoop: true}) { 237 void markAsNonInlinable(MethodElement element, {bool insideLoop: true}) {
238 int oldDecision = _cachedDecisions[element]; 238 int oldDecision = _cachedDecisions[element];
239 239
240 if (oldDecision == null) { 240 if (oldDecision == null) {
241 oldDecision = _unknown; 241 oldDecision = _unknown;
242 } 242 }
243 243
244 if (insideLoop) { 244 if (insideLoop) {
245 switch (oldDecision) { 245 switch (oldDecision) {
246 case _canInlineInLoopMustNotOutside: 246 case _canInlineInLoopMustNotOutside:
247 case _canInlineInLoopMayInlineOutside: 247 case _canInlineInLoopMayInlineOutside:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 285
286 case _mayInlineInLoopMustNotOutside: 286 case _mayInlineInLoopMustNotOutside:
287 case _canInlineInLoopMustNotOutside: 287 case _canInlineInLoopMustNotOutside:
288 case _mustNotInline: 288 case _mustNotInline:
289 // Do nothing. 289 // Do nothing.
290 break; 290 break;
291 } 291 }
292 } 292 }
293 } 293 }
294 294
295 void markAsMustInline(FunctionElement element) { 295 void markAsMustInline(MethodElement element) {
296 _cachedDecisions[element] = _mustInline; 296 _cachedDecisions[element] = _mustInline;
297 } 297 }
298 } 298 }
299 299
300 enum SyntheticConstantKind { 300 enum SyntheticConstantKind {
301 DUMMY_INTERCEPTOR, 301 DUMMY_INTERCEPTOR,
302 EMPTY_VALUE, 302 EMPTY_VALUE,
303 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. 303 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data.
304 NAME 304 NAME
305 } 305 }
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 interceptedElements = new Map<String, Set<Element>>(), 568 interceptedElements = new Map<String, Set<Element>>(),
569 rti = new _RuntimeTypes(compiler), 569 rti = new _RuntimeTypes(compiler),
570 rtiEncoder = new _RuntimeTypesEncoder(compiler), 570 rtiEncoder = new _RuntimeTypesEncoder(compiler),
571 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(), 571 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(),
572 annotations = new Annotations(compiler), 572 annotations = new Annotations(compiler),
573 this.sourceInformationStrategy = generateSourceMap 573 this.sourceInformationStrategy = generateSourceMap
574 ? (useNewSourceInfo 574 ? (useNewSourceInfo
575 ? new PositionSourceInformationStrategy() 575 ? new PositionSourceInformationStrategy()
576 : const StartEndSourceInformationStrategy()) 576 : const StartEndSourceInformationStrategy())
577 : const JavaScriptSourceInformationStrategy(), 577 : const JavaScriptSourceInformationStrategy(),
578 helpers = new BackendHelpers(compiler), 578 helpers = new BackendHelpersImpl(compiler),
579 impacts = new BackendImpacts(compiler), 579 impacts = new BackendImpacts(compiler),
580 frontend = new JSFrontendAccess(compiler), 580 frontend = new JSFrontendAccess(compiler),
581 super(compiler) { 581 super(compiler) {
582 emitter = 582 emitter =
583 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter); 583 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter);
584 typeVariableHandler = new TypeVariableHandler(compiler); 584 typeVariableHandler = new TypeVariableHandler(compiler);
585 customElementsAnalysis = new CustomElementsAnalysis(this); 585 customElementsAnalysis = new CustomElementsAnalysis(this);
586 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); 586 lookupMapAnalysis = new LookupMapAnalysis(this, reporter);
587 jsInteropAnalysis = new JsInteropAnalysis(this); 587 jsInteropAnalysis = new JsInteropAnalysis(this);
588 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution); 588 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 if (element.isClass && element.isPatched) { 665 if (element.isClass && element.isPatched) {
666 // Both declaration and implementation may declare fields, so we 666 // Both declaration and implementation may declare fields, so we
667 // add both to the list of helpers. 667 // add both to the list of helpers.
668 helpersUsed.add(element.implementation); 668 helpersUsed.add(element.implementation);
669 } 669 }
670 return element; 670 return element;
671 } 671 }
672 672
673 bool _isValidBackendUse(Element element) { 673 bool _isValidBackendUse(Element element) {
674 assert(invariant(element, element.isDeclaration, message: "")); 674 assert(invariant(element, element.isDeclaration, message: ""));
675 if (element == helpers.streamIteratorConstructor || 675 if (element is ConstructorElement &&
676 (element == helpers.streamIteratorConstructor ||
676 compiler.commonElements.isSymbolConstructor(element) || 677 compiler.commonElements.isSymbolConstructor(element) ||
677 helpers.isSymbolValidatedConstructor(element) || 678 helpers.isSymbolValidatedConstructor(element) ||
678 element == helpers.syncCompleterConstructor || 679 element == helpers.syncCompleterConstructor)) {
679 element == commonElements.symbolClass || 680 // TODO(johnniwinther): These are valid but we could be more precise.
681 return true;
682 } else if (element == commonElements.symbolClass ||
680 element == helpers.objectNoSuchMethod) { 683 element == helpers.objectNoSuchMethod) {
681 // TODO(johnniwinther): These are valid but we could be more precise. 684 // TODO(johnniwinther): These are valid but we could be more precise.
682 return true; 685 return true;
683 } else if (element.implementationLibrary.isPatch || 686 } else if (element.implementationLibrary.isPatch ||
684 // Needed to detect deserialized injected elements, that is 687 // Needed to detect deserialized injected elements, that is
685 // element declared in patch files. 688 // element declared in patch files.
686 (element.library.isPlatformLibrary && 689 (element.library.isPlatformLibrary &&
687 element.sourcePosition.uri.path 690 element.sourcePosition.uri.path
688 .contains('_internal/js_runtime/lib/')) || 691 .contains('_internal/js_runtime/lib/')) ||
689 element.library == helpers.jsHelperLibrary || 692 element.library == helpers.jsHelperLibrary ||
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
1082 FunctionConstantValue function = constant; 1085 FunctionConstantValue function = constant;
1083 impactBuilder 1086 impactBuilder
1084 .registerStaticUse(new StaticUse.staticTearOff(function.element)); 1087 .registerStaticUse(new StaticUse.staticTearOff(function.element));
1085 } else if (constant.isInterceptor) { 1088 } else if (constant.isInterceptor) {
1086 // An interceptor constant references the class's prototype chain. 1089 // An interceptor constant references the class's prototype chain.
1087 InterceptorConstantValue interceptor = constant; 1090 InterceptorConstantValue interceptor = constant;
1088 ClassElement cls = interceptor.cls; 1091 ClassElement cls = interceptor.cls;
1089 computeImpactForInstantiatedConstantType(cls.thisType, impactBuilder); 1092 computeImpactForInstantiatedConstantType(cls.thisType, impactBuilder);
1090 } else if (constant.isType) { 1093 } else if (constant.isType) {
1091 if (isForResolution) { 1094 if (isForResolution) {
1095 MethodElement helper = helpers.createRuntimeType;
1092 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( 1096 impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
1093 // TODO(johnniwinther): Find the right [CallStructure]. 1097 // TODO(johnniwinther): Find the right [CallStructure].
1094 helpers.createRuntimeType, 1098 helper,
1095 null)); 1099 null));
1096 registerBackendUse(helpers.createRuntimeType); 1100 registerBackendUse(helper);
1097 } 1101 }
1098 impactBuilder 1102 impactBuilder
1099 .registerTypeUse(new TypeUse.instantiation(backendClasses.typeType)); 1103 .registerTypeUse(new TypeUse.instantiation(backendClasses.typeType));
1100 } 1104 }
1101 lookupMapAnalysis.registerConstantKey(constant); 1105 lookupMapAnalysis.registerConstantKey(constant);
1102 } 1106 }
1103 1107
1104 void computeImpactForInstantiatedConstantType( 1108 void computeImpactForInstantiatedConstantType(
1105 DartType type, WorldImpactBuilder impactBuilder) { 1109 DartType type, WorldImpactBuilder impactBuilder) {
1106 if (type is ResolutionInterfaceType) { 1110 if (type is ResolutionInterfaceType) {
(...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after
1880 metadata.ensureResolved(resolution); 1884 metadata.ensureResolved(resolution);
1881 ConstantValue constant = 1885 ConstantValue constant =
1882 constants.getConstantValueForMetadata(metadata); 1886 constants.getConstantValueForMetadata(metadata);
1883 constants.addCompileTimeConstantForEmission(constant); 1887 constants.addCompileTimeConstantForEmission(constant);
1884 } 1888 }
1885 return true; 1889 return true;
1886 } 1890 }
1887 return false; 1891 return false;
1888 } 1892 }
1889 1893
1890 void onLibraryCreated(LibraryElement library) {
Siggi Cherem (dart-lang) 2017/02/06 17:15:58 yay - I was close to make this change after I refa
1891 helpers.onLibraryCreated(library);
1892 }
1893
1894 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { 1894 Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
1895 return super.onLibraryScanned(library, loader).then((_) { 1895 return super.onLibraryScanned(library, loader).then((_) {
1896 if (library.isPlatformLibrary && 1896 if (library.isPlatformLibrary &&
1897 // Don't patch library currently disallowed. 1897 // Don't patch library currently disallowed.
1898 !library.isSynthesized && 1898 !library.isSynthesized &&
1899 !library.isPatched && 1899 !library.isPatched &&
1900 // Don't patch deserialized libraries. 1900 // Don't patch deserialized libraries.
1901 !compiler.serialization.isDeserialized(library)) { 1901 !compiler.serialization.isDeserialized(library)) {
1902 // Apply patch, if any. 1902 // Apply patch, if any.
1903 Uri patchUri = compiler.resolvePatchUri(library.canonicalUri.path); 1903 Uri patchUri = compiler.resolvePatchUri(library.canonicalUri.path);
1904 if (patchUri != null) { 1904 if (patchUri != null) {
1905 return compiler.patchParser.patchLibrary(loader, patchUri, library); 1905 return compiler.patchParser.patchLibrary(loader, patchUri, library);
1906 } 1906 }
1907 } 1907 }
1908 }).then((_) { 1908 }).then((_) {
1909 helpers.onLibraryScanned(library);
1910 Uri uri = library.canonicalUri; 1909 Uri uri = library.canonicalUri;
1911 if (uri == Uris.dart_html) { 1910 if (uri == Uris.dart_html) {
1912 htmlLibraryIsLoaded = true; 1911 htmlLibraryIsLoaded = true;
1913 } else if (uri == LookupMapAnalysis.PACKAGE_LOOKUP_MAP) { 1912 } else if (uri == LookupMapAnalysis.PACKAGE_LOOKUP_MAP) {
1914 lookupMapAnalysis.init(library); 1913 lookupMapAnalysis.init(library);
1915 } 1914 }
1916 annotations.onLibraryScanned(library); 1915 annotations.onLibraryScanned(library);
1917 }); 1916 });
1918 } 1917 }
1919 1918
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
2162 for (Element closure in closureMap[null]) { 2161 for (Element closure in closureMap[null]) {
2163 if (referencedFromMirrorSystem(closure)) { 2162 if (referencedFromMirrorSystem(closure)) {
2164 reflectableMembers.add(closure); 2163 reflectableMembers.add(closure);
2165 foundClosure = true; 2164 foundClosure = true;
2166 } 2165 }
2167 } 2166 }
2168 } 2167 }
2169 // As we do not think about closures as classes, yet, we have to make sure 2168 // As we do not think about closures as classes, yet, we have to make sure
2170 // their superclasses are available for reflection manually. 2169 // their superclasses are available for reflection manually.
2171 if (foundClosure) { 2170 if (foundClosure) {
2172 reflectableMembers.add(helpers.closureClass); 2171 ClassElement cls = helpers.closureClass;
2172 reflectableMembers.add(cls);
2173 } 2173 }
2174 Set<Element> closurizedMembers = 2174 Set<Element> closurizedMembers =
2175 compiler.resolutionWorldBuilder.closurizedMembers; 2175 compiler.resolutionWorldBuilder.closurizedMembers;
2176 if (closurizedMembers.any(reflectableMembers.contains)) { 2176 if (closurizedMembers.any(reflectableMembers.contains)) {
2177 reflectableMembers.add(helpers.boundClosureClass); 2177 ClassElement cls = helpers.boundClosureClass;
2178 reflectableMembers.add(cls);
2178 } 2179 }
2179 // Add typedefs. 2180 // Add typedefs.
2180 reflectableMembers 2181 reflectableMembers
2181 .addAll(closedWorld.allTypedefs.where(referencedFromMirrorSystem)); 2182 .addAll(closedWorld.allTypedefs.where(referencedFromMirrorSystem));
2182 // Register all symbols of reflectable elements 2183 // Register all symbols of reflectable elements
2183 for (Element element in reflectableMembers) { 2184 for (Element element in reflectableMembers) {
2184 symbolsUsed.add(element.name); 2185 symbolsUsed.add(element.name);
2185 } 2186 }
2186 _membersNeededForReflection = reflectableMembers; 2187 _membersNeededForReflection = reflectableMembers;
2187 } 2188 }
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
2491 if (hasNoThrows && !hasNoInline) { 2492 if (hasNoThrows && !hasNoInline) {
2492 reporter.internalError( 2493 reporter.internalError(
2493 element, "@NoThrows() should always be combined with @NoInline."); 2494 element, "@NoThrows() should always be combined with @NoInline.");
2494 } 2495 }
2495 if (hasNoSideEffects && !hasNoInline) { 2496 if (hasNoSideEffects && !hasNoInline) {
2496 reporter.internalError(element, 2497 reporter.internalError(element,
2497 "@NoSideEffects() should always be combined with @NoInline."); 2498 "@NoSideEffects() should always be combined with @NoInline.");
2498 } 2499 }
2499 } 2500 }
2500 2501
2501 FunctionElement helperForBadMain() => helpers.badMain; 2502 MethodElement helperForBadMain() => helpers.badMain;
2502 2503
2503 FunctionElement helperForMissingMain() => helpers.missingMain; 2504 MethodElement helperForMissingMain() => helpers.missingMain;
2504 2505
2505 FunctionElement helperForMainArity() => helpers.mainHasTooManyParameters; 2506 MethodElement helperForMainArity() => helpers.mainHasTooManyParameters;
2506 2507
2507 @override 2508 @override
2508 WorldImpact computeMainImpact(MethodElement mainMethod, 2509 WorldImpact computeMainImpact(MethodElement mainMethod,
2509 {bool forResolution}) { 2510 {bool forResolution}) {
2510 WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl(); 2511 WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
2511 if (mainMethod.parameters.isNotEmpty) { 2512 if (mainMethod.parameters.isNotEmpty) {
2512 impactTransformer.registerBackendImpact( 2513 impactTransformer.registerBackendImpact(
2513 mainImpact, impacts.mainWithArguments); 2514 mainImpact, impacts.mainWithArguments);
2514 mainImpact.registerStaticUse( 2515 mainImpact.registerStaticUse(
2515 new StaticUse.staticInvoke(mainMethod, CallStructure.TWO_ARGS)); 2516 new StaticUse.staticInvoke(mainMethod, CallStructure.TWO_ARGS));
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 break; 2998 break;
2998 case BackendFeature.needToInitializeIsolateAffinityTag: 2999 case BackendFeature.needToInitializeIsolateAffinityTag:
2999 backend.needToInitializeIsolateAffinityTag = true; 3000 backend.needToInitializeIsolateAffinityTag = true;
3000 break; 3001 break;
3001 } 3002 }
3002 } 3003 }
3003 } 3004 }
3004 3005
3005 /// Register [type] as required for the runtime type information system. 3006 /// Register [type] as required for the runtime type information system.
3006 void registerRequiredType(ResolutionDartType type) { 3007 void registerRequiredType(ResolutionDartType type) {
3008 if (!type.isInterfaceType) return;
3007 // If [argument] has type variables or is a type variable, this method 3009 // If [argument] has type variables or is a type variable, this method
3008 // registers a RTI dependency between the class where the type variable is 3010 // registers a RTI dependency between the class where the type variable is
3009 // defined (that is the enclosing class of the current element being 3011 // defined (that is the enclosing class of the current element being
3010 // resolved) and the class of [type]. If the class of [type] requires RTI, 3012 // resolved) and the class of [type]. If the class of [type] requires RTI,
3011 // then the class of the type variable does too. 3013 // then the class of the type variable does too.
3012 ClassElement contextClass = Types.getClassContext(type); 3014 ClassElement contextClass = Types.getClassContext(type);
3013 if (contextClass != null) { 3015 if (contextClass != null) {
3014 backend.rti.registerRtiDependency(type.element, contextClass); 3016 backend.rti.registerRtiDependency(type.element, contextClass);
3015 } 3017 }
3016 } 3018 }
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
3278 @override 3280 @override
3279 bool isNativeClass(ClassElement element) { 3281 bool isNativeClass(ClassElement element) {
3280 return helpers.backend.isNative(element); 3282 return helpers.backend.isNative(element);
3281 } 3283 }
3282 3284
3283 @override 3285 @override
3284 bool isNativeMember(MemberElement element) { 3286 bool isNativeMember(MemberElement element) {
3285 return helpers.backend.isNative(element); 3287 return helpers.backend.isNative(element);
3286 } 3288 }
3287 } 3289 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698