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

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

Issue 2213673002: Delete dart_backend from compiler. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart_backend;
6
7 // TODO(ahe): This class is simply wrong. This backend should use
8 // elements when it can, not AST nodes. Perhaps a [Map<Element,
9 // TreeElements>] is what is needed.
10 class ElementAst {
11 final Node ast;
12 final TreeElements treeElements;
13
14 ElementAst(this.ast, this.treeElements);
15 }
16
17 class DartBackend extends Backend {
18 final List<CompilerTask> tasks;
19 final bool stripAsserts;
20
21 bool get supportsReflection => true;
22
23 // TODO(zarah) Maybe change this to a command-line option.
24 // Right now, it is set by the tests.
25 bool useMirrorHelperLibrary = false;
26
27 /// Updated to a [MirrorRenamerImpl] instance if the [useMirrorHelperLibrary]
28 /// field is set and mirror are needed.
29 MirrorRenamer mirrorRenamer = const MirrorRenamer();
30
31 final DartOutputter outputter;
32
33 // Used in test.
34 PlaceholderRenamer get placeholderRenamer => outputter.renamer;
35 Map<ClassNode, List<Node>> get memberNodes => outputter.output.memberNodes;
36
37 ConstantSystem get constantSystem {
38 return constantCompilerTask.constantCompiler.constantSystem;
39 }
40
41 BackendConstantEnvironment get constants => constantCompilerTask;
42
43 DartConstantTask constantCompilerTask;
44
45 DartImpactTransformer impactTransformer;
46
47 final Set<ClassElement> usedTypeLiterals = new Set<ClassElement>();
48
49 /// The set of visible platform classes that are implemented by instantiated
50 /// user classes.
51 final Set<ClassElement> _userImplementedPlatformClasses =
52 new Set<ClassElement>();
53
54 bool enableCodegenWithErrorsIfSupported(Spannable node) {
55 reporter.reportHintMessage(node, MessageKind.GENERIC, {
56 'text': "Generation of code with compile time errors is not "
57 "supported for dart2dart."
58 });
59 return false;
60 }
61
62 /**
63 * Tells whether it is safe to remove type declarations from variables,
64 * functions parameters. It becomes not safe if:
65 * 1) TypeError is used somewhere in the code,
66 * 2) The code has typedefs in right hand side of IS checks,
67 * 3) The code has classes which extend typedefs, have type arguments typedefs
68 * or type variable bounds typedefs.
69 * These restrictions can be less strict.
70 */
71 bool isSafeToRemoveTypeDeclarations(
72 Map<ClassElement, Iterable<Element>> classMembers) {
73 ClassElement typeErrorElement = compiler.coreLibrary.find('TypeError');
74 if (classMembers.containsKey(typeErrorElement) ||
75 compiler.resolverWorld.isChecks
76 .any((DartType type) => type.element == typeErrorElement)) {
77 return false;
78 }
79 Set<DartType> processedTypes = new Set<DartType>();
80 List<DartType> workQueue = new List<DartType>();
81 workQueue
82 .addAll(classMembers.keys.map((classElement) => classElement.thisType));
83 workQueue.addAll(compiler.resolverWorld.isChecks);
84
85 while (!workQueue.isEmpty) {
86 DartType type = workQueue.removeLast();
87 if (processedTypes.contains(type)) continue;
88 processedTypes.add(type);
89 if (type is FunctionType) return false;
90 if (type is TypedefType) return false;
91 if (type is InterfaceType) {
92 InterfaceType interfaceType = type;
93 // Check all type arguments.
94 interfaceType.typeArguments.forEach(workQueue.add);
95 ClassElement element = type.element;
96 // Check all supertypes.
97 if (element.allSupertypes != null) {
98 element.allSupertypes.forEach(workQueue.add);
99 }
100 }
101 }
102 return true;
103 }
104
105 DartBackend(Compiler compiler, List<String> strips, {bool multiFile})
106 : tasks = <CompilerTask>[],
107 stripAsserts = strips.indexOf('asserts') != -1,
108 constantCompilerTask = new DartConstantTask(compiler),
109 outputter = new DartOutputter(
110 compiler.reporter, compiler.outputProvider,
111 forceStripTypes: strips.indexOf('types') != -1,
112 multiFile: multiFile,
113 enableMinification: compiler.options.enableMinification),
114 super(compiler) {
115 impactTransformer = new DartImpactTransformer(this);
116 }
117
118 DiagnosticReporter get reporter => compiler.reporter;
119
120 Resolution get resolution => compiler.resolution;
121
122 bool classNeedsRti(ClassElement cls) => false;
123 bool methodNeedsRti(FunctionElement function) => false;
124
125 void enqueueHelpers(ResolutionEnqueuer world, Registry registry) {
126 // Right now resolver doesn't always resolve interfaces needed
127 // for literals, so force them. TODO(antonm): fix in the resolver.
128 final LITERAL_TYPE_NAMES = const [
129 'Map',
130 'List',
131 'num',
132 'int',
133 'double',
134 'bool'
135 ];
136 final coreLibrary = compiler.coreLibrary;
137 for (final name in LITERAL_TYPE_NAMES) {
138 ClassElement classElement = coreLibrary.findLocal(name);
139 classElement.ensureResolved(resolution);
140 }
141 // Enqueue the methods that the VM might invoke on user objects because
142 // we don't trust the resolution to always get these included.
143 world.registerDynamicUse(new DynamicUse(Selectors.toString_, null));
144 world.registerDynamicUse(new DynamicUse(Selectors.hashCode_, null));
145 world.registerDynamicUse(
146 new DynamicUse(new Selector.binaryOperator('=='), null));
147 world.registerDynamicUse(new DynamicUse(Selectors.compareTo, null));
148 }
149
150 WorldImpact codegen(CodegenWorkItem work) {
151 return const WorldImpact();
152 }
153
154 /**
155 * Tells whether we should output given element. Corelib classes like
156 * Object should not be in the resulting code.
157 */
158 @override
159 bool shouldOutput(Element element) {
160 return (!element.library.isPlatformLibrary &&
161 !element.isSynthesized &&
162 element is! AbstractFieldElement) ||
163 mirrorRenamer.isMirrorHelperLibrary(element.library);
164 }
165
166 int assembleProgram() {
167 ElementAst computeElementAst(AstElement element) {
168 return new ElementAst(
169 element.resolvedAst.node, element.resolvedAst.elements);
170 }
171
172 // TODO(johnniwinther): Remove the need for this method.
173 void postProcessElementAst(AstElement element, ElementAst elementAst,
174 newTypedefElementCallback, newClassElementCallback) {
175 ReferencedElementCollector collector = new ReferencedElementCollector(
176 reporter,
177 element,
178 elementAst,
179 newTypedefElementCallback,
180 newClassElementCallback);
181 collector.collect();
182 }
183
184 int totalSize = outputter.assembleProgram(
185 libraries: compiler.libraryLoader.libraries,
186 instantiatedClasses: compiler.resolverWorld.directlyInstantiatedClasses,
187 resolvedElements: compiler.enqueuer.resolution.processedElements,
188 usedTypeLiterals: usedTypeLiterals,
189 postProcessElementAst: postProcessElementAst,
190 computeElementAst: computeElementAst,
191 shouldOutput: shouldOutput,
192 isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations,
193 sortElements: Elements.sortedByPosition,
194 mirrorRenamer: mirrorRenamer,
195 mainFunction: compiler.mainFunction,
196 outputUri: compiler.options.outputUri);
197
198 // Output verbose info about size ratio of resulting bundle to all
199 // referenced non-platform sources.
200 logResultBundleSizeInfo(outputter.libraryInfo.userLibraries,
201 outputter.elementInfo.topLevelElements, totalSize);
202
203 return totalSize;
204 }
205
206 void logResultBundleSizeInfo(Iterable<LibraryElement> userLibraries,
207 Iterable<Element> topLevelElements, int totalOutputSize) {
208 // Sum total size of scripts in each referenced library.
209 int nonPlatformSize = 0;
210 for (LibraryElement lib in userLibraries) {
211 for (CompilationUnitElement compilationUnit in lib.compilationUnits) {
212 nonPlatformSize += compilationUnit.script.file.length;
213 }
214 }
215 int percentage = totalOutputSize * 100 ~/ nonPlatformSize;
216 log('Total used non-platform files size: ${nonPlatformSize} bytes, '
217 'Output total size: $totalOutputSize bytes (${percentage}%)');
218 }
219
220 log(String message) => reporter.log('[DartBackend] $message');
221
222 @override
223 Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
224 // All platform classes must be resolved to ensure that their member names
225 // are preserved.
226 loadedLibraries.forEachLibrary((LibraryElement library) {
227 if (library.isPlatformLibrary) {
228 library.forEachLocalMember((Element element) {
229 if (element.isClass) {
230 ClassElement classElement = element;
231 classElement.ensureResolved(resolution);
232 }
233 });
234 }
235 });
236 if (useMirrorHelperLibrary &&
237 loadedLibraries.containsLibrary(Uris.dart_mirrors)) {
238 return compiler.libraryLoader
239 .loadLibrary(compiler.resolvedUriTranslator.translate(
240 loadedLibraries.getLibrary(Uris.dart_mirrors),
241 MirrorRenamerImpl.DART_MIRROR_HELPER,
242 null))
243 .then((LibraryElement library) {
244 mirrorRenamer = new MirrorRenamerImpl(compiler, this, library);
245 });
246 }
247 return new Future.value();
248 }
249
250 @override
251 void registerStaticUse(Element element, Enqueuer enqueuer) {
252 if (element == compiler.mirrorSystemGetNameFunction) {
253 FunctionElement getNameFunction = mirrorRenamer.getNameFunction;
254 if (getNameFunction != null) {
255 enqueuer.addToWorkList(getNameFunction);
256 }
257 }
258 }
259
260 @override
261 void registerInstantiatedType(
262 InterfaceType type, Enqueuer enqueuer, Registry registry,
263 {bool mirrorUsage: false}) {
264 registerPlatformMembers(type, registerUse: registry.registerDynamicUse);
265 super.registerInstantiatedType(type, enqueuer, registry,
266 mirrorUsage: mirrorUsage);
267 }
268
269 /// Register dynamic access of members of [type] that implement members
270 /// of types defined in the platform libraries.
271 void registerPlatformMembers(InterfaceType type,
272 {void registerUse(DynamicUse dynamicUse)}) {
273 // Without patching, dart2dart has no way of performing sound tree-shaking
274 // in face external functions. Therefore we employ another scheme:
275 //
276 // Based on the assumption that the platform code only relies on the
277 // interfaces of it's own classes, we can approximate the semantics of
278 // external functions by eagerly registering dynamic invocation of instance
279 // members defined the platform interfaces.
280 //
281 // Since we only need to generate code for non-platform classes we can
282 // restrict this registration to platform interfaces implemented by
283 // instantiated non-platform classes.
284 //
285 // Consider for instance this program:
286 //
287 // import 'dart:math' show Random;
288 //
289 // class MyRandom implements Random {
290 // int nextInt() => 0;
291 // }
292 //
293 // main() {
294 // print([0, 1, 2].shuffle(new MyRandom()));
295 // }
296 //
297 // Here `MyRandom` is a subtype if `Random` defined in 'dart:math'. By the
298 // assumption, all methods defined `Random` are potentially called, and
299 // therefore, though there are no visible call sites from the user node,
300 // dynamic invocation of for instance `nextInt` should be registered. In
301 // this case, `nextInt` is actually called by the standard implementation of
302 // `shuffle`.
303
304 ClassElement cls = type.element;
305 if (!cls.library.isPlatformLibrary) {
306 for (Link<DartType> link = cls.allSupertypes;
307 !link.isEmpty;
308 link = link.tail) {
309 InterfaceType supertype = link.head;
310 ClassElement superclass = supertype.element;
311 LibraryElement library = superclass.library;
312 if (library.isPlatformLibrary) {
313 if (_userImplementedPlatformClasses.add(superclass)) {
314 // Register selectors for all instance methods since these might
315 // be called on user classes from within the platform
316 // implementation.
317 superclass.forEachLocalMember((MemberElement element) {
318 if (element.isConstructor || element.isStatic) return;
319
320 element.computeType(resolution);
321 Selector selector = new Selector.fromElement(element);
322 registerUse(new DynamicUse(selector, null));
323 });
324 }
325 }
326 }
327 }
328 }
329
330 @override
331 bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) {
332 // TODO(sigurdm): Implement deferred loading for dart2dart.
333 reporter.reportWarningMessage(
334 node, MessageKind.DEFERRED_LIBRARY_DART_2_DART);
335 return false;
336 }
337
338 @override
339 Uri resolvePatchUri(String libraryName, Uri) {
340 // Dart2dart does not use patches.
341 return null;
342 }
343 }
344
345 class DartImpactTransformer extends ImpactTransformer {
346 final DartBackend backend;
347
348 DartImpactTransformer(this.backend);
349
350 @override
351 WorldImpact transformResolutionImpact(ResolutionImpact worldImpact) {
352 TransformedWorldImpact transformed =
353 new TransformedWorldImpact(worldImpact);
354 for (TypeUse typeUse in worldImpact.typeUses) {
355 if (typeUse.kind == TypeUseKind.TYPE_LITERAL &&
356 typeUse.type.isInterfaceType) {
357 backend.usedTypeLiterals.add(typeUse.type.element);
358 }
359 if (typeUse.kind == TypeUseKind.INSTANTIATION) {
360 backend.registerPlatformMembers(typeUse.type,
361 registerUse: transformed.registerDynamicUse);
362 }
363 }
364 return transformed;
365 }
366 }
367
368 class EmitterUnparser extends Unparser {
369 final Map<Node, String> renames;
370
371 EmitterUnparser(this.renames, {bool minify, bool stripTypes})
372 : super(minify: minify, stripTypes: stripTypes);
373
374 visit(Node node) {
375 if (node != null && renames.containsKey(node)) {
376 write(renames[node]);
377 } else {
378 super.visit(node);
379 }
380 }
381
382 unparseSendReceiver(Send node, {bool spacesNeeded: false}) {
383 // TODO(smok): Remove ugly hack for library prefices.
384 if (node.receiver != null && renames[node.receiver] == '') return;
385 super.unparseSendReceiver(node, spacesNeeded: spacesNeeded);
386 }
387
388 unparseFunctionName(Node name) {
389 if (name != null && renames.containsKey(name)) {
390 write(renames[name]);
391 } else {
392 super.unparseFunctionName(name);
393 }
394 }
395 }
396
397 /**
398 * Some elements are not recorded by resolver now,
399 * for example, typedefs or classes which are only
400 * used in signatures, as/is operators or in super clauses
401 * (just to name a few). Retraverse AST to pick those up.
402 */
403 class ReferencedElementCollector extends Visitor {
404 final DiagnosticReporter reporter;
405 final Element element;
406 final ElementAst elementAst;
407 final newTypedefElementCallback;
408 final newClassElementCallback;
409
410 ReferencedElementCollector(this.reporter, this.element, this.elementAst,
411 this.newTypedefElementCallback, this.newClassElementCallback);
412
413 visitNode(Node node) {
414 node.visitChildren(this);
415 }
416
417 visitTypeAnnotation(TypeAnnotation typeAnnotation) {
418 TreeElements treeElements = elementAst.treeElements;
419 final DartType type = treeElements.getType(typeAnnotation);
420 assert(invariant(typeAnnotation, type != null,
421 message: "Missing type for type annotation: $treeElements."));
422 if (type.isTypedef) newTypedefElementCallback(type.element);
423 if (type.isInterfaceType) newClassElementCallback(type.element);
424 typeAnnotation.visitChildren(this);
425 }
426
427 void collect() {
428 reporter.withCurrentElement(element, () {
429 elementAst.ast.accept(this);
430 });
431 }
432 }
433
434 Comparator compareBy(f) => (x, y) => f(x).compareTo(f(y));
435
436 List sorted(Iterable l, comparison) {
437 final result = new List.from(l);
438 result.sort(comparison);
439 return result;
440 }
441
442 compareElements(e0, e1) {
443 int result = compareBy((e) => e.library.canonicalUri.toString())(e0, e1);
444 if (result != 0) return result;
445 return compareBy((e) => e.position.charOffset)(e0, e1);
446 }
447
448 /// [ConstantCompilerTask] for compilation of constants for the Dart backend.
449 ///
450 /// Since this task needs no distinction between frontend and backend constants
451 /// it also serves as the [BackendConstantEnvironment].
452 class DartConstantTask extends ConstantCompilerTask
453 implements BackendConstantEnvironment {
454 final DartConstantCompiler constantCompiler;
455
456 DartConstantTask(Compiler compiler)
457 : this.constantCompiler = new DartConstantCompiler(compiler),
458 super(compiler.measurer);
459
460 String get name => 'ConstantHandler';
461
462 @override
463 ConstantSystem get constantSystem => constantCompiler.constantSystem;
464
465 @override
466 bool hasConstantValue(ConstantExpression expression) {
467 return constantCompiler.hasConstantValue(expression);
468 }
469
470 @override
471 ConstantValue getConstantValue(ConstantExpression expression) {
472 return constantCompiler.getConstantValue(expression);
473 }
474
475 @override
476 ConstantValue getConstantValueForVariable(VariableElement element) {
477 return constantCompiler.getConstantValueForVariable(element);
478 }
479
480 @override
481 ConstantExpression getConstantForNode(Node node, TreeElements elements) {
482 return constantCompiler.getConstantForNode(node, elements);
483 }
484
485 @override
486 ConstantValue getConstantValueForNode(Node node, TreeElements elements) {
487 return getConstantValue(
488 constantCompiler.getConstantForNode(node, elements));
489 }
490
491 @override
492 ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata) {
493 return getConstantValue(metadata.constant);
494 }
495
496 @override
497 ConstantExpression compileConstant(VariableElement element) {
498 return measure(() {
499 return constantCompiler.compileConstant(element);
500 });
501 }
502
503 @override
504 void evaluate(ConstantExpression constant) {
505 return measure(() {
506 return constantCompiler.evaluate(constant);
507 });
508 }
509
510 @override
511 ConstantExpression compileVariable(VariableElement element) {
512 return measure(() {
513 return constantCompiler.compileVariable(element);
514 });
515 }
516
517 @override
518 ConstantExpression compileNode(Node node, TreeElements elements,
519 {bool enforceConst: true}) {
520 return measure(() {
521 return constantCompiler.compileNodeWithDefinitions(node, elements,
522 isConst: enforceConst);
523 });
524 }
525
526 @override
527 ConstantExpression compileMetadata(
528 MetadataAnnotation metadata, Node node, TreeElements elements) {
529 return measure(() {
530 return constantCompiler.compileMetadata(metadata, node, elements);
531 });
532 }
533
534 // TODO(johnniwinther): Remove this when values are computed from the
535 // expressions.
536 @override
537 void copyConstantValues(DartConstantTask task) {
538 constantCompiler.constantValueMap
539 .addAll(task.constantCompiler.constantValueMap);
540 }
541
542 @override
543 void registerLazyStatic(FieldElement element) {
544 // Do nothing.
545 }
546 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart2js.dart ('k') | pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698