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

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

Issue 2854013002: Make JavaScriptBackend.processAnnotations element-model agnostic (Closed)
Patch Set: Fix and check declaration invariant. Created 3 years, 7 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
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<FunctionEntity, int> _cachedDecisions = 112 final Map<FunctionEntity, int> _cachedDecisions =
113 new Map<FunctionEntity, int>(); 113 new Map<FunctionEntity, int>();
114 114
115 /// Checks that [method] is the canonical representative for this method.
116 ///
117 /// For a [MethodElement] this means it must be the declaration element.
118 bool checkFunction(FunctionEntity method) {
119 if (method is MethodElement) return method.isDeclaration;
120 return true;
121 }
122
115 /// Returns the current cache decision. This should only be used for testing. 123 /// Returns the current cache decision. This should only be used for testing.
116 int getCurrentCacheDecisionForTesting(Element element) { 124 int getCurrentCacheDecisionForTesting(FunctionEntity element) {
125 assert(checkFunction(element));
117 return _cachedDecisions[element]; 126 return _cachedDecisions[element];
118 } 127 }
119 128
120 // Returns `true`/`false` if we have a cached decision. 129 // Returns `true`/`false` if we have a cached decision.
121 // Returns `null` otherwise. 130 // Returns `null` otherwise.
122 bool canInline(FunctionEntity element, {bool insideLoop}) { 131 bool canInline(FunctionEntity element, {bool insideLoop}) {
132 assert(checkFunction(element));
123 int decision = _cachedDecisions[element]; 133 int decision = _cachedDecisions[element];
124 134
125 if (decision == null) { 135 if (decision == null) {
126 // These synthetic elements are not yet present when we initially compute 136 // These synthetic elements are not yet present when we initially compute
127 // this cache from metadata annotations, so look for their parent. 137 // this cache from metadata annotations, so look for their parent.
128 if (element is ConstructorBodyElement) { 138 if (element is ConstructorBodyElement) {
129 ConstructorBodyElement body = element; 139 ConstructorBodyElement body = element;
130 decision = _cachedDecisions[body.constructor]; 140 decision = _cachedDecisions[body.constructor];
131 } 141 }
132 if (decision == null) { 142 if (decision == null) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 case _mustInline: 178 case _mustInline:
169 return true; 179 return true;
170 } 180 }
171 } 181 }
172 182
173 // Quiet static checker. 183 // Quiet static checker.
174 return null; 184 return null;
175 } 185 }
176 186
177 void markAsInlinable(FunctionEntity element, {bool insideLoop}) { 187 void markAsInlinable(FunctionEntity element, {bool insideLoop}) {
188 assert(checkFunction(element));
178 int oldDecision = _cachedDecisions[element]; 189 int oldDecision = _cachedDecisions[element];
179 190
180 if (oldDecision == null) { 191 if (oldDecision == null) {
181 oldDecision = _unknown; 192 oldDecision = _unknown;
182 } 193 }
183 194
184 if (insideLoop) { 195 if (insideLoop) {
185 switch (oldDecision) { 196 switch (oldDecision) {
186 case _mustNotInline: 197 case _mustNotInline:
187 throw new SpannableAssertionFailure( 198 throw new SpannableAssertionFailure(
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 234
224 case _canInline: 235 case _canInline:
225 case _mustInline: 236 case _mustInline:
226 // Do nothing. 237 // Do nothing.
227 break; 238 break;
228 } 239 }
229 } 240 }
230 } 241 }
231 242
232 void markAsNonInlinable(FunctionEntity element, {bool insideLoop: true}) { 243 void markAsNonInlinable(FunctionEntity element, {bool insideLoop: true}) {
244 assert(checkFunction(element));
233 int oldDecision = _cachedDecisions[element]; 245 int oldDecision = _cachedDecisions[element];
234 246
235 if (oldDecision == null) { 247 if (oldDecision == null) {
236 oldDecision = _unknown; 248 oldDecision = _unknown;
237 } 249 }
238 250
239 if (insideLoop) { 251 if (insideLoop) {
240 switch (oldDecision) { 252 switch (oldDecision) {
241 case _canInlineInLoopMustNotOutside: 253 case _canInlineInLoopMustNotOutside:
242 case _canInlineInLoopMayInlineOutside: 254 case _canInlineInLoopMayInlineOutside:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 case _mayInlineInLoopMustNotOutside: 293 case _mayInlineInLoopMustNotOutside:
282 case _canInlineInLoopMustNotOutside: 294 case _canInlineInLoopMustNotOutside:
283 case _mustNotInline: 295 case _mustNotInline:
284 // Do nothing. 296 // Do nothing.
285 break; 297 break;
286 } 298 }
287 } 299 }
288 } 300 }
289 301
290 void markAsMustInline(FunctionEntity element) { 302 void markAsMustInline(FunctionEntity element) {
303 assert(checkFunction(element));
291 _cachedDecisions[element] = _mustInline; 304 _cachedDecisions[element] = _mustInline;
292 } 305 }
293 } 306 }
294 307
295 enum SyntheticConstantKind { 308 enum SyntheticConstantKind {
296 DUMMY_INTERCEPTOR, 309 DUMMY_INTERCEPTOR,
297 EMPTY_VALUE, 310 EMPTY_VALUE,
298 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data. 311 TYPEVARIABLE_REFERENCE, // Reference to a type in reflection data.
299 NAME 312 NAME
300 } 313 }
301 314
302 class JavaScriptBackend { 315 class JavaScriptBackend {
303 static const String JS = 'JS'; 316 static const String JS = 'JS';
304 static const String JS_BUILTIN = 'JS_BUILTIN'; 317 static const String JS_BUILTIN = 'JS_BUILTIN';
305 static const String JS_EMBEDDED_GLOBAL = 'JS_EMBEDDED_GLOBAL'; 318 static const String JS_EMBEDDED_GLOBAL = 'JS_EMBEDDED_GLOBAL';
306 static const String JS_INTERCEPTOR_CONSTANT = 'JS_INTERCEPTOR_CONSTANT'; 319 static const String JS_INTERCEPTOR_CONSTANT = 'JS_INTERCEPTOR_CONSTANT';
307 320
308 final Compiler compiler; 321 final Compiler compiler;
309 322
310 /// Returns true if the backend supports reflection. 323 /// Returns true if the backend supports reflection.
311 bool get supportsReflection => emitter.supportsReflection; 324 bool get supportsReflection => emitter.supportsReflection;
312 325
313 final OptimizerHintsForTests annotations; 326 final OptimizerHintsForTests optimizerHints;
314 327
315 /// Set of classes that need to be considered for reflection although not 328 /// Set of classes that need to be considered for reflection although not
316 /// otherwise visible during resolution. 329 /// otherwise visible during resolution.
317 Iterable<ClassEntity> get classesRequiredForReflection { 330 Iterable<ClassEntity> get classesRequiredForReflection {
318 // TODO(herhut): Clean this up when classes needed for rti are tracked. 331 // TODO(herhut): Clean this up when classes needed for rti are tracked.
319 return [commonElements.closureClass, commonElements.jsIndexableClass]; 332 return [commonElements.closureClass, commonElements.jsIndexableClass];
320 } 333 }
321 334
322 FunctionCompiler functionCompiler; 335 FunctionCompiler functionCompiler;
323 336
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 } 484 }
472 } 485 }
473 486
474 JavaScriptBackend(this.compiler, 487 JavaScriptBackend(this.compiler,
475 {bool generateSourceMap: true, 488 {bool generateSourceMap: true,
476 bool useStartupEmitter: false, 489 bool useStartupEmitter: false,
477 bool useMultiSourceInfo: false, 490 bool useMultiSourceInfo: false,
478 bool useNewSourceInfo: false, 491 bool useNewSourceInfo: false,
479 bool useKernel: false}) 492 bool useKernel: false})
480 : _rti = new _RuntimeTypes(compiler), 493 : _rti = new _RuntimeTypes(compiler),
481 annotations = new OptimizerHintsForTests(compiler), 494 optimizerHints = new OptimizerHintsForTests(
495 compiler.elementEnvironment, compiler.commonElements),
482 this.sourceInformationStrategy = createSourceInformationStrategy( 496 this.sourceInformationStrategy = createSourceInformationStrategy(
483 generateSourceMap: generateSourceMap, 497 generateSourceMap: generateSourceMap,
484 useMultiSourceInfo: useMultiSourceInfo, 498 useMultiSourceInfo: useMultiSourceInfo,
485 useNewSourceInfo: useNewSourceInfo), 499 useNewSourceInfo: useNewSourceInfo),
486 constantCompilerTask = new JavaScriptConstantTask(compiler), 500 constantCompilerTask = new JavaScriptConstantTask(compiler),
487 _nativeDataResolver = new NativeDataResolverImpl(compiler), 501 _nativeDataResolver = new NativeDataResolverImpl(compiler),
488 _rtiNeedBuilder = 502 _rtiNeedBuilder =
489 compiler.frontEndStrategy.createRuntimeTypesNeedBuilder() { 503 compiler.frontEndStrategy.createRuntimeTypesNeedBuilder() {
490 _target = new JavaScriptBackendTarget(this); 504 _target = new JavaScriptBackendTarget(this);
491 impacts = new BackendImpacts(compiler.options, commonElements); 505 impacts = new BackendImpacts(compiler.options, commonElements);
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 bool isTargetSpecificLibrary(LibraryElement library) { 1186 bool isTargetSpecificLibrary(LibraryElement library) {
1173 Uri canonicalUri = library.canonicalUri; 1187 Uri canonicalUri = library.canonicalUri;
1174 if (canonicalUri == Uris.dart__js_helper || 1188 if (canonicalUri == Uris.dart__js_helper ||
1175 canonicalUri == Uris.dart__interceptors) { 1189 canonicalUri == Uris.dart__interceptors) {
1176 return true; 1190 return true;
1177 } 1191 }
1178 return false; 1192 return false;
1179 } 1193 }
1180 1194
1181 /// Process backend specific annotations. 1195 /// Process backend specific annotations.
1196 // TODO(johnniwinther): Merge this with [AnnotationProcessor] and use
1197 // [ElementEnvironment.getMemberMetadata] in [AnnotationProcessor].
1182 void processAnnotations( 1198 void processAnnotations(
1183 MemberElement element, ClosedWorldRefiner closedWorldRefiner) { 1199 MemberEntity element, ClosedWorldRefiner closedWorldRefiner) {
1184 if (element.isMalformed) { 1200 if (element is MemberElement && element.isMalformed) {
1185 // Elements that are marked as malformed during parsing or resolution 1201 // Elements that are marked as malformed during parsing or resolution
1186 // might be registered here. These should just be ignored. 1202 // might be registered here. These should just be ignored.
1187 return; 1203 return;
1188 } 1204 }
1189 1205
1190 if (element.isFunction || element.isConstructor) { 1206 if (element.isFunction || element.isConstructor) {
1191 MethodElement method = element.implementation; 1207 if (optimizerHints.noInline(element)) {
1192 if (annotations.noInline(method)) { 1208 inlineCache.markAsNonInlinable(element);
1193 inlineCache.markAsNonInlinable(method);
1194 } 1209 }
1195 } 1210 }
1196 if (element.isField) return; 1211 if (element.isField) return;
1197 MethodElement method = element; 1212 FunctionEntity method = element;
1198 1213
1199 LibraryElement library = method.library; 1214 LibraryEntity library = method.library;
1200 if (!library.isPlatformLibrary && !canLibraryUseNative(library)) return; 1215 if (library.canonicalUri.scheme != 'dart' &&
1216 !canLibraryUseNative(library)) {
1217 return;
1218 }
1201 bool hasNoInline = false; 1219 bool hasNoInline = false;
1202 bool hasForceInline = false; 1220 bool hasForceInline = false;
1203 bool hasNoThrows = false; 1221 bool hasNoThrows = false;
1204 bool hasNoSideEffects = false; 1222 bool hasNoSideEffects = false;
1205 for (MetadataAnnotation metadata in method.implementation.metadata) { 1223 for (ConstantValue constantValue
1206 metadata.ensureResolved(resolution); 1224 in compiler.elementEnvironment.getMemberMetadata(method)) {
1207 ConstantValue constantValue =
1208 compiler.constants.getConstantValue(metadata.constant);
1209 if (!constantValue.isConstructedObject) continue; 1225 if (!constantValue.isConstructedObject) continue;
1210 ObjectConstantValue value = constantValue; 1226 ObjectConstantValue value = constantValue;
1211 ClassElement cls = value.type.element; 1227 ClassEntity cls = value.type.element;
1212 if (cls == commonElements.forceInlineClass) { 1228 if (cls == commonElements.forceInlineClass) {
1213 hasForceInline = true; 1229 hasForceInline = true;
1214 if (VERBOSE_OPTIMIZER_HINTS) { 1230 if (VERBOSE_OPTIMIZER_HINTS) {
1215 reporter.reportHintMessage( 1231 reporter.reportHintMessage(
1216 method, MessageKind.GENERIC, {'text': "Must inline"}); 1232 method, MessageKind.GENERIC, {'text': "Must inline"});
1217 } 1233 }
1218 inlineCache.markAsMustInline(method); 1234 inlineCache.markAsMustInline(method);
1219 } else if (cls == commonElements.noInlineClass) { 1235 } else if (cls == commonElements.noInlineClass) {
1220 hasNoInline = true; 1236 hasNoInline = true;
1221 if (VERBOSE_OPTIMIZER_HINTS) { 1237 if (VERBOSE_OPTIMIZER_HINTS) {
1222 reporter.reportHintMessage( 1238 reporter.reportHintMessage(
1223 method, MessageKind.GENERIC, {'text': "Cannot inline"}); 1239 method, MessageKind.GENERIC, {'text': "Cannot inline"});
1224 } 1240 }
1225 inlineCache.markAsNonInlinable(method); 1241 inlineCache.markAsNonInlinable(method);
1226 } else if (cls == commonElements.noThrowsClass) { 1242 } else if (cls == commonElements.noThrowsClass) {
1227 hasNoThrows = true; 1243 hasNoThrows = true;
1228 if (!Elements.isStaticOrTopLevelFunction(method) && 1244 bool isValid = true;
1229 !method.isFactoryConstructor) { 1245 if (method.isTopLevel) {
1246 isValid = true;
1247 } else if (method.isStatic) {
1248 isValid = true;
1249 } else if (method is ConstructorEntity && method.isFactoryConstructor) {
1250 isValid = true;
1251 }
1252 if (!isValid) {
1230 reporter.internalError( 1253 reporter.internalError(
1231 method, 1254 method,
1232 "@NoThrows() is currently limited to top-level" 1255 "@NoThrows() is currently limited to top-level"
1233 " or static functions and factory constructors."); 1256 " or static functions and factory constructors.");
1234 } 1257 }
1235 if (VERBOSE_OPTIMIZER_HINTS) { 1258 if (VERBOSE_OPTIMIZER_HINTS) {
1236 reporter.reportHintMessage( 1259 reporter.reportHintMessage(
1237 method, MessageKind.GENERIC, {'text': "Cannot throw"}); 1260 method, MessageKind.GENERIC, {'text': "Cannot throw"});
1238 } 1261 }
1239 closedWorldRefiner.registerCannotThrow(method); 1262 closedWorldRefiner.registerCannotThrow(method);
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1452 1475
1453 bool canUseAliasedSuperMember(MemberEntity member, Selector selector) { 1476 bool canUseAliasedSuperMember(MemberEntity member, Selector selector) {
1454 return !selector.isGetter; 1477 return !selector.isGetter;
1455 } 1478 }
1456 1479
1457 /// Returns `true` if [member] is called from a subclass via `super`. 1480 /// Returns `true` if [member] is called from a subclass via `super`.
1458 bool isAliasedSuperMember(MemberEntity member) { 1481 bool isAliasedSuperMember(MemberEntity member) {
1459 return _aliasedSuperMembers.contains(member); 1482 return _aliasedSuperMembers.contains(member);
1460 } 1483 }
1461 } 1484 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/annotations.dart ('k') | pkg/compiler/lib/src/kernel/element_map.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698