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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
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(AstElement element)
15 : this.internal(element.resolvedAst.node, element.resolvedAst.elements);
16
17 ElementAst.internal(this.ast, this.treeElements);
18 }
19
20 class DartBackend extends Backend {
21 final List<CompilerTask> tasks;
22 final bool stripAsserts;
23
24 // TODO(zarah) Maybe change this to a command-line option.
25 // Right now, it is set by the tests.
26 bool useMirrorHelperLibrary = false;
27
28 /// Updated to a [MirrorRenamerImpl] instance if the [useMirrorHelperLibrary]
29 /// field is set and mirror are needed.
30 MirrorRenamer mirrorRenamer = const MirrorRenamer();
31
32 final DartOutputter outputter;
33
34 // Used in test.
35 PlaceholderRenamer get placeholderRenamer => outputter.renamer;
36 Map<ClassNode, List<Node>> get memberNodes => outputter.output.memberNodes;
37
38 ConstantSystem get constantSystem {
39 return constantCompilerTask.constantCompiler.constantSystem;
40 }
41
42 BackendConstantEnvironment get constants => constantCompilerTask;
43
44 DartConstantTask constantCompilerTask;
45
46 DartResolutionCallbacks resolutionCallbacks;
47
48 final Set<ClassElement> usedTypeLiterals = new Set<ClassElement>();
49
50 /**
51 * Tells whether it is safe to remove type declarations from variables,
52 * functions parameters. It becomes not safe if:
53 * 1) TypeError is used somewhere in the code,
54 * 2) The code has typedefs in right hand side of IS checks,
55 * 3) The code has classes which extend typedefs, have type arguments typedefs
56 * or type variable bounds typedefs.
57 * These restrictions can be less strict.
58 */
59 bool isSafeToRemoveTypeDeclarations(
60 Map<ClassElement, Iterable<Element>> classMembers) {
61 ClassElement typeErrorElement = compiler.coreLibrary.find('TypeError');
62 if (classMembers.containsKey(typeErrorElement) ||
63 compiler.resolverWorld.isChecks.any(
64 (DartType type) => type.element == typeErrorElement)) {
65 return false;
66 }
67 Set<DartType> processedTypes = new Set<DartType>();
68 List<DartType> workQueue = new List<DartType>();
69 workQueue.addAll(
70 classMembers.keys.map((classElement) => classElement.thisType));
71 workQueue.addAll(compiler.resolverWorld.isChecks);
72
73 while (!workQueue.isEmpty) {
74 DartType type = workQueue.removeLast();
75 if (processedTypes.contains(type)) continue;
76 processedTypes.add(type);
77 if (type is FunctionType) return false;
78 if (type is TypedefType) return false;
79 if (type is InterfaceType) {
80 InterfaceType interfaceType = type;
81 // Check all type arguments.
82 interfaceType.typeArguments.forEach(workQueue.add);
83 ClassElement element = type.element;
84 // Check all supertypes.
85 if (element.allSupertypes != null) {
86 element.allSupertypes.forEach(workQueue.add);
87 }
88 }
89 }
90 return true;
91 }
92
93 DartBackend(Compiler compiler, List<String> strips, {bool multiFile})
94 : tasks = <CompilerTask>[],
95 stripAsserts = strips.indexOf('asserts') != -1,
96 constantCompilerTask = new DartConstantTask(compiler),
97 outputter = new DartOutputter(
98 compiler, compiler.outputProvider,
99 forceStripTypes: strips.indexOf('types') != -1,
100 multiFile: multiFile,
101 enableMinification: compiler.enableMinification),
102 super(compiler) {
103 resolutionCallbacks = new DartResolutionCallbacks(this);
104 }
105
106 bool classNeedsRti(ClassElement cls) => false;
107 bool methodNeedsRti(FunctionElement function) => false;
108
109 void enqueueHelpers(ResolutionEnqueuer world, Registry registry) {
110 // Right now resolver doesn't always resolve interfaces needed
111 // for literals, so force them. TODO(antonm): fix in the resolver.
112 final LITERAL_TYPE_NAMES = const [
113 'Map', 'List', 'num', 'int', 'double', 'bool'
114 ];
115 final coreLibrary = compiler.coreLibrary;
116 for (final name in LITERAL_TYPE_NAMES) {
117 ClassElement classElement = coreLibrary.findLocal(name);
118 classElement.ensureResolved(compiler);
119 }
120 // Enqueue the methods that the VM might invoke on user objects because
121 // we don't trust the resolution to always get these included.
122 world.registerInvocation(new Selector.call("toString", null, 0));
123 world.registerInvokedGetter(new Selector.getter("hashCode", null));
124 world.registerInvocation(new Selector.binaryOperator("=="));
125 world.registerInvocation(new Selector.call("compareTo", null, 1));
126 }
127
128 void codegen(CodegenWorkItem work) { }
129
130 /// Create an [ElementAst] from the CPS IR.
131 static ElementAst createElementAst(Compiler compiler,
132 Tracer tracer,
133 ConstantSystem constantSystem,
134 Element element,
135 cps_ir.FunctionDefinition function) {
136 // Transformations on the CPS IR.
137 if (tracer != null) {
138 tracer.traceCompilation(element.name, null);
139 }
140
141 void traceGraph(String title, var irObject) {
142 if (tracer != null) {
143 tracer.traceGraph(title, irObject);
144 }
145 }
146
147 new ConstantPropagator(compiler, constantSystem).rewrite(function);
148 traceGraph("Sparse constant propagation", function);
149 new RedundantPhiEliminator().rewrite(function);
150 traceGraph("Redundant phi elimination", function);
151 new ShrinkingReducer().rewrite(function);
152 traceGraph("Shrinking reductions", function);
153
154 // Do not rewrite the IR after variable allocation. Allocation
155 // makes decisions based on an approximation of IR variable live
156 // ranges that can be invalidated by transforming the IR.
157 new cps_ir.RegisterAllocator().visit(function);
158
159 tree_builder.Builder builder = new tree_builder.Builder(compiler);
160 tree_ir.FunctionDefinition definition = builder.build(function);
161 assert(definition != null);
162 traceGraph('Tree builder', definition);
163
164 // Transformations on the Tree IR.
165 new StatementRewriter().rewrite(definition);
166 traceGraph('Statement rewriter', definition);
167 new CopyPropagator().rewrite(definition);
168 traceGraph('Copy propagation', definition);
169 new LoopRewriter().rewrite(definition);
170 traceGraph('Loop rewriter', definition);
171 new LogicalRewriter().rewrite(definition);
172 traceGraph('Logical rewriter', definition);
173 new backend_ast_emitter.UnshadowParameters().unshadow(definition);
174 traceGraph('Unshadow parameters', definition);
175
176 TreeElementMapping treeElements = new TreeElementMapping(element);
177 backend_ast.Node backendAst =
178 backend_ast_emitter.emit(definition);
179 Node frontend_ast = backend2frontend.emit(treeElements, backendAst);
180 return new ElementAst.internal(frontend_ast, treeElements);
181
182 }
183
184 /**
185 * Tells whether we should output given element. Corelib classes like
186 * Object should not be in the resulting code.
187 */
188 @override
189 bool shouldOutput(Element element) {
190 return (!element.library.isPlatformLibrary &&
191 !element.isSynthesized &&
192 element is! AbstractFieldElement)
193 || mirrorRenamer.isMirrorHelperLibrary(element.library);
194 }
195
196 void assembleProgram() {
197
198 ElementAst computeElementAst(AstElement element) {
199 if (!compiler.irBuilder.hasIr(element)) {
200 return new ElementAst(element);
201 } else {
202 cps_ir.FunctionDefinition function = compiler.irBuilder.getIr(element);
203 return createElementAst(compiler,
204 compiler.tracer, constantSystem, element, function);
205 }
206 }
207
208 // TODO(johnniwinther): Remove the need for this method.
209 void postProcessElementAst(
210 AstElement element, ElementAst elementAst,
211 newTypedefElementCallback,
212 newClassElementCallback) {
213 ReferencedElementCollector collector =
214 new ReferencedElementCollector(compiler,
215 element,
216 elementAst,
217 newTypedefElementCallback,
218 newClassElementCallback);
219 collector.collect();
220 }
221
222 String assembledCode = outputter.assembleProgram(
223 libraries: compiler.libraryLoader.libraries,
224 instantiatedClasses: compiler.resolverWorld.directlyInstantiatedClasses,
225 resolvedElements: compiler.enqueuer.resolution.resolvedElements,
226 usedTypeLiterals: usedTypeLiterals,
227 postProcessElementAst: postProcessElementAst,
228 computeElementAst: computeElementAst,
229 shouldOutput: shouldOutput,
230 isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations,
231 sortElements: sortElements,
232 mirrorRenamer: mirrorRenamer,
233 mainFunction: compiler.mainFunction,
234 outputUri: compiler.outputUri);
235 compiler.assembledCode = assembledCode;
236
237 int totalSize = assembledCode.length;
238
239 // Output verbose info about size ratio of resulting bundle to all
240 // referenced non-platform sources.
241 logResultBundleSizeInfo(
242 outputter.libraryInfo.userLibraries,
243 outputter.elementInfo.topLevelElements,
244 assembledCode.length);
245 }
246
247 void logResultBundleSizeInfo(Iterable<LibraryElement> userLibraries,
248 Iterable<Element> topLevelElements,
249 int totalOutputSize) {
250 // Sum total size of scripts in each referenced library.
251 int nonPlatformSize = 0;
252 for (LibraryElement lib in userLibraries) {
253 for (CompilationUnitElement compilationUnit in lib.compilationUnits) {
254 nonPlatformSize += compilationUnit.script.file.length;
255 }
256 }
257 int percentage = totalOutputSize * 100 ~/ nonPlatformSize;
258 log('Total used non-platform files size: ${nonPlatformSize} bytes, '
259 'Output total size: $totalOutputSize bytes (${percentage}%)');
260 }
261
262 log(String message) => compiler.log('[DartBackend] $message');
263
264 Future onLibrariesLoaded(Map<Uri, LibraryElement> loadedLibraries) {
265 // All platform classes must be resolved to ensure that their member names
266 // are preserved.
267 loadedLibraries.values.forEach((LibraryElement library) {
268 if (library.isPlatformLibrary) {
269 library.forEachLocalMember((Element element) {
270 if (element.isClass) {
271 ClassElement classElement = element;
272 classElement.ensureResolved(compiler);
273 }
274 });
275 }
276 });
277 if (useMirrorHelperLibrary &&
278 loadedLibraries.containsKey(Compiler.DART_MIRRORS)) {
279 return compiler.libraryLoader.loadLibrary(
280 compiler.translateResolvedUri(
281 loadedLibraries[Compiler.DART_MIRRORS],
282 MirrorRenamerImpl.DART_MIRROR_HELPER, null)).
283 then((LibraryElement library) {
284 mirrorRenamer = new MirrorRenamerImpl(compiler, this, library);
285 });
286 }
287 return new Future.value();
288 }
289
290 void registerStaticUse(Element element, Enqueuer enqueuer) {
291 if (element == compiler.mirrorSystemGetNameFunction) {
292 FunctionElement getNameFunction = mirrorRenamer.getNameFunction;
293 if (getNameFunction != null) {
294 enqueuer.addToWorkList(getNameFunction);
295 }
296 }
297 }
298 }
299
300 class DartResolutionCallbacks extends ResolutionCallbacks {
301 final DartBackend backend;
302
303 DartResolutionCallbacks(this.backend);
304
305 void onTypeLiteral(DartType type, Registry registry) {
306 if (type.isInterfaceType) {
307 backend.usedTypeLiterals.add(type.element);
308 }
309 }
310 }
311
312 class EmitterUnparser extends Unparser {
313 final Map<Node, String> renames;
314
315 EmitterUnparser(this.renames, {bool minify, bool stripTypes})
316 : super(minify: minify, stripTypes: stripTypes);
317
318 visit(Node node) {
319 if (node != null && renames.containsKey(node)) {
320 write(renames[node]);
321 } else {
322 super.visit(node);
323 }
324 }
325
326 unparseSendReceiver(Send node, {bool spacesNeeded: false}) {
327 // TODO(smok): Remove ugly hack for library prefices.
328 if (node.receiver != null && renames[node.receiver] == '') return;
329 super.unparseSendReceiver(node, spacesNeeded: spacesNeeded);
330 }
331
332 unparseFunctionName(Node name) {
333 if (name != null && renames.containsKey(name)) {
334 write(renames[name]);
335 } else {
336 super.unparseFunctionName(name);
337 }
338 }
339 }
340
341
342 /**
343 * Some elements are not recorded by resolver now,
344 * for example, typedefs or classes which are only
345 * used in signatures, as/is operators or in super clauses
346 * (just to name a few). Retraverse AST to pick those up.
347 */
348 class ReferencedElementCollector extends Visitor {
349 final Compiler compiler;
350 final Element element;
351 final ElementAst elementAst;
352 final newTypedefElementCallback;
353 final newClassElementCallback;
354
355 ReferencedElementCollector(this.compiler,
356 this.element,
357 this.elementAst,
358 this.newTypedefElementCallback,
359 this.newClassElementCallback);
360
361 visitNode(Node node) {
362 node.visitChildren(this);
363 }
364
365 visitTypeAnnotation(TypeAnnotation typeAnnotation) {
366 TreeElements treeElements = elementAst.treeElements;
367 final DartType type = treeElements.getType(typeAnnotation);
368 assert(invariant(typeAnnotation, type != null,
369 message: "Missing type for type annotation: $treeElements."));
370 if (type.isTypedef) newTypedefElementCallback(type.element);
371 if (type.isInterfaceType) newClassElementCallback(type.element);
372 typeAnnotation.visitChildren(this);
373 }
374
375 void collect() {
376 compiler.withCurrentElement(element, () {
377 elementAst.ast.accept(this);
378 });
379 }
380 }
381
382 Comparator compareBy(f) => (x, y) => f(x).compareTo(f(y));
383
384 List sorted(Iterable l, comparison) {
385 final result = new List.from(l);
386 result.sort(comparison);
387 return result;
388 }
389
390 compareElements(e0, e1) {
391 int result = compareBy((e) => e.library.canonicalUri.toString())(e0, e1);
392 if (result != 0) return result;
393 return compareBy((e) => e.position.charOffset)(e0, e1);
394 }
395
396 List<Element> sortElements(Iterable<Element> elements) =>
397 sorted(elements, compareElements);
398
399 /// [ConstantCompilerTask] for compilation of constants for the Dart backend.
400 ///
401 /// Since this task needs no distinction between frontend and backend constants
402 /// it also serves as the [BackendConstantEnvironment].
403 class DartConstantTask extends ConstantCompilerTask
404 implements BackendConstantEnvironment {
405 final DartConstantCompiler constantCompiler;
406
407 DartConstantTask(Compiler compiler)
408 : this.constantCompiler = new DartConstantCompiler(compiler),
409 super(compiler);
410
411 String get name => 'ConstantHandler';
412
413 ConstantExpression getConstantForVariable(VariableElement element) {
414 return constantCompiler.getConstantForVariable(element);
415 }
416
417 ConstantExpression getConstantForNode(Node node, TreeElements elements) {
418 return constantCompiler.getConstantForNode(node, elements);
419 }
420
421 ConstantExpression getConstantForMetadata(MetadataAnnotation metadata) {
422 return metadata.constant;
423 }
424
425 ConstantExpression compileConstant(VariableElement element) {
426 return measure(() {
427 return constantCompiler.compileConstant(element);
428 });
429 }
430
431 void compileVariable(VariableElement element) {
432 measure(() {
433 constantCompiler.compileVariable(element);
434 });
435 }
436
437 ConstantExpression compileNode(Node node, TreeElements elements) {
438 return measure(() {
439 return constantCompiler.compileNodeWithDefinitions(node, elements);
440 });
441 }
442
443 ConstantExpression compileMetadata(MetadataAnnotation metadata,
444 Node node,
445 TreeElements elements) {
446 return measure(() {
447 return constantCompiler.compileMetadata(metadata, node, elements);
448 });
449 }
450 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698