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

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

Issue 2246623002: Delete CPS IR (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) 2014, 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 /// Generate code using the cps-based IR pipeline.
6 library code_generator_task;
7
8 import '../../common.dart';
9 import '../../common/codegen.dart' show CodegenWorkItem;
10 import '../../common/tasks.dart' show CompilerTask, GenericTask;
11 import '../../compiler.dart' show Compiler;
12 import '../../constants/constant_system.dart';
13 import '../../cps_ir/cps_ir_builder_task.dart';
14 import '../../cps_ir/cps_ir_integrity.dart';
15 import '../../cps_ir/cps_ir_nodes.dart' as cps;
16 import '../../cps_ir/cps_ir_nodes_sexpr.dart';
17 import '../../cps_ir/finalize.dart' show Finalize;
18 import '../../cps_ir/optimizers.dart';
19 import '../../cps_ir/optimizers.dart' as cps_opt;
20 import '../../cps_ir/type_mask_system.dart';
21 import '../../diagnostics/invariant.dart' show DEBUG_MODE;
22 import '../../elements/elements.dart';
23 import '../../io/source_information.dart' show SourceInformationStrategy;
24 import '../../js/js.dart' as js;
25 import '../../js_backend/codegen/codegen.dart';
26 import '../../ssa/ssa.dart' as ssa;
27 import '../../tracer.dart';
28 import '../../tree_ir/optimization/optimization.dart';
29 import '../../tree_ir/optimization/optimization.dart' as tree_opt;
30 import '../../tree_ir/tree_ir_builder.dart' as tree_builder;
31 import '../../tree_ir/tree_ir_integrity.dart';
32 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir;
33 import '../../types/types.dart'
34 show FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask;
35 import '../js_backend.dart';
36 import 'codegen.dart';
37 import 'glue.dart';
38 import 'unsugar.dart';
39
40 class CpsFunctionCompiler implements FunctionCompiler {
41 final ConstantSystem constantSystem;
42 // TODO(karlklose): remove the compiler.
43 final Compiler compiler;
44 final Glue glue;
45 final SourceInformationStrategy sourceInformationFactory;
46
47 // TODO(karlklose,sigurdm): remove and update dart-doc of [compile].
48 final FunctionCompiler fallbackCompiler;
49 TypeMaskSystem typeSystem;
50
51 Tracer get tracer => compiler.tracer;
52
53 final IrBuilderTask cpsBuilderTask;
54 final GenericTask cpsOptimizationTask;
55 final GenericTask treeBuilderTask;
56 final GenericTask treeOptimizationTask;
57
58 Inliner inliner;
59
60 CpsFunctionCompiler(Compiler compiler, JavaScriptBackend backend,
61 SourceInformationStrategy sourceInformationFactory)
62 : fallbackCompiler =
63 new ssa.SsaFunctionCompiler(backend, sourceInformationFactory),
64 cpsBuilderTask = new IrBuilderTask(compiler, sourceInformationFactory),
65 sourceInformationFactory = sourceInformationFactory,
66 constantSystem = backend.constantSystem,
67 compiler = compiler,
68 glue = new Glue(compiler),
69 cpsOptimizationTask =
70 new GenericTask('CPS optimization', compiler.measurer),
71 treeBuilderTask = new GenericTask('Tree builder', compiler.measurer),
72 treeOptimizationTask =
73 new GenericTask('Tree optimization', compiler.measurer) {
74 inliner = new Inliner(this);
75 }
76
77 String get name => 'CPS Ir pipeline';
78
79 JavaScriptBackend get backend => compiler.backend;
80
81 DiagnosticReporter get reporter => compiler.reporter;
82
83 /// Generates JavaScript code for `work.element`.
84 js.Fun compile(CodegenWorkItem work) {
85 if (typeSystem == null) typeSystem = new TypeMaskSystem(compiler);
86 AstElement element = work.element;
87 return reporter.withCurrentElement(element, () {
88 try {
89 // TODO(karlklose): remove this fallback when we do not need it for
90 // testing anymore.
91 if (false) {
92 reporter.log('Using SSA compiler for platform element $element');
93 return fallbackCompiler.compile(work);
94 }
95
96 if (tracer != null) {
97 tracer.traceCompilation('$element', null);
98 }
99 cps.FunctionDefinition cpsFunction = compileToCpsIr(element);
100 optimizeCpsBeforeInlining(cpsFunction);
101 applyCpsPass(inliner, cpsFunction);
102 optimizeCpsAfterInlining(cpsFunction);
103 cpsIntegrityChecker = null;
104 tree_ir.FunctionDefinition treeFunction = compileToTreeIr(cpsFunction);
105 treeFunction = optimizeTreeIr(treeFunction);
106 return compileToJavaScript(work, treeFunction);
107 } on CodegenBailout catch (e) {
108 String message = "Unable to compile $element with the new compiler.\n"
109 " Reason: ${e.message}";
110 reporter.internalError(element, message);
111 }
112 });
113 }
114
115 void giveUp(String reason) {
116 throw new CodegenBailout(null, reason);
117 }
118
119 void traceGraph(String title, var irObject) {
120 if (tracer != null) {
121 tracer.traceGraph(title, irObject);
122 }
123 }
124
125 String stringify(cps.FunctionDefinition node) {
126 return new SExpressionStringifier().withTypes().visit(node);
127 }
128
129 /// For debugging purposes, replace a call to [applyCpsPass] with a call
130 /// to [debugCpsPass] to check that this pass is idempotent.
131 ///
132 /// This runs [pass] followed by shrinking reductions, and then checks that
133 /// one more run of [pass] does not change the IR. The intermediate shrinking
134 /// reductions pass is omitted if [pass] itself is shrinking reductions.
135 ///
136 /// If [targetName] is given, functions whose name contains that substring
137 /// will be dumped out if the idempotency test fails.
138 void debugCpsPass(cps_opt.Pass makePass(), cps.FunctionDefinition cpsFunction,
139 [String targetName]) {
140 String original = stringify(cpsFunction);
141 cps_opt.Pass pass = makePass();
142 pass.rewrite(cpsFunction);
143 assert(checkCpsIntegrity(cpsFunction, pass.passName));
144 if (pass is! ShrinkingReducer) {
145 new ShrinkingReducer().rewrite(cpsFunction);
146 }
147 String before = stringify(cpsFunction);
148 makePass().rewrite(cpsFunction);
149 String after = stringify(cpsFunction);
150 if (before != after) {
151 print('SExpression changed for ${cpsFunction.element}');
152 if (targetName != null && '${cpsFunction.element}'.contains(targetName)) {
153 print(original);
154 print('\n-->\n');
155 print(before);
156 print('\n-->\n');
157 print(after);
158 compiler.outputProvider('original', 'dump')
159 ..add(original)
160 ..close();
161 compiler.outputProvider('before', 'dump')
162 ..add(before)
163 ..close();
164 compiler.outputProvider('after', 'dump')
165 ..add(after)
166 ..close();
167 }
168 }
169 traceGraph(pass.passName, cpsFunction);
170 dumpTypedIr(pass.passName, cpsFunction);
171 }
172
173 void applyCpsPass(cps_opt.Pass pass, cps.FunctionDefinition cpsFunction) {
174 cpsOptimizationTask.measureSubtask(pass.passName, () {
175 pass.rewrite(cpsFunction);
176 });
177 traceGraph(pass.passName, cpsFunction);
178 dumpTypedIr(pass.passName, cpsFunction);
179 assert(checkCpsIntegrity(cpsFunction, pass.passName));
180 }
181
182 cps.FunctionDefinition compileToCpsIr(AstElement element) {
183 cps.FunctionDefinition cpsFunction = inliner.cache.getUnoptimized(element);
184 if (cpsFunction != null) return cpsFunction;
185
186 cpsFunction = cpsBuilderTask.buildNode(element, typeSystem);
187 if (cpsFunction == null) {
188 if (cpsBuilderTask.bailoutMessage == null) {
189 giveUp('unable to build cps definition of $element');
190 } else {
191 giveUp(cpsBuilderTask.bailoutMessage);
192 }
193 }
194 ParentVisitor.setParents(cpsFunction);
195 traceGraph('IR Builder', cpsFunction);
196 dumpTypedIr('IR Builder', cpsFunction);
197 // Eliminating redundant phis before the unsugaring pass will make it
198 // insert fewer getInterceptor calls.
199 applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
200 applyCpsPass(new UnsugarVisitor(glue), cpsFunction);
201 applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
202 applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
203 applyCpsPass(new InsertRefinements(typeSystem), cpsFunction);
204
205 inliner.cache.putUnoptimized(element, cpsFunction);
206 return cpsFunction;
207 }
208
209 static const Pattern PRINT_TYPED_IR_FILTER = null;
210
211 String formatTypeMask(TypeMask type) {
212 if (type is UnionTypeMask) {
213 return '[${type.disjointMasks.map(formatTypeMask).join(', ')}]';
214 } else if (type is FlatTypeMask) {
215 if (type.isEmpty) return "empty";
216 if (type.isNull) return "null";
217 String suffix = (type.isExact ? "" : "+") + (type.isNullable ? "?" : "!");
218 return '${type.base.name}$suffix';
219 } else if (type is ForwardingTypeMask) {
220 return formatTypeMask(type.forwardTo);
221 }
222 throw 'unsupported: $type';
223 }
224
225 void dumpTypedIr(String passName, cps.FunctionDefinition cpsFunction) {
226 if (PRINT_TYPED_IR_FILTER != null &&
227 PRINT_TYPED_IR_FILTER.matchAsPrefix(cpsFunction.element.name) != null) {
228 String printType(nodeOrRef, String s) {
229 cps.Node node =
230 nodeOrRef is cps.Reference ? nodeOrRef.definition : nodeOrRef;
231 return node is cps.Variable && node.type != null
232 ? '$s:${formatTypeMask(node.type)}'
233 : s;
234 }
235 DEBUG_MODE = true;
236 print(';;; ==== After $passName ====');
237 print(new SExpressionStringifier(printType).visit(cpsFunction));
238 }
239 }
240
241 CheckCpsIntegrity cpsIntegrityChecker;
242
243 bool checkCpsIntegrity(cps.FunctionDefinition node, String previousPass) {
244 cpsOptimizationTask.measureSubtask('Check integrity', () {
245 if (cpsIntegrityChecker == null) {
246 cpsIntegrityChecker = new CheckCpsIntegrity();
247 }
248 cpsIntegrityChecker.check(node, previousPass);
249 });
250 return true; // So this can be used from assert().
251 }
252
253 void optimizeCpsBeforeInlining(cps.FunctionDefinition cpsFunction) {
254 cpsOptimizationTask.measure(() {
255 applyCpsPass(new TypePropagator(this), cpsFunction);
256 applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
257 applyCpsPass(new ShrinkingReducer(), cpsFunction);
258 });
259 }
260
261 void optimizeCpsAfterInlining(cps.FunctionDefinition cpsFunction) {
262 cpsOptimizationTask.measure(() {
263 applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
264 applyCpsPass(new ShrinkingReducer(), cpsFunction);
265 applyCpsPass(new RedundantRefinementEliminator(typeSystem), cpsFunction);
266 applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction);
267 applyCpsPass(new TypePropagator(this, recomputeAll: true), cpsFunction);
268 applyCpsPass(new ShrinkingReducer(), cpsFunction);
269 applyCpsPass(new EagerlyLoadStatics(), cpsFunction);
270 applyCpsPass(new GVN(compiler, typeSystem), cpsFunction);
271 applyCpsPass(new PathBasedOptimizer(backend, typeSystem), cpsFunction);
272 applyCpsPass(new ShrinkingReducer(), cpsFunction);
273 applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction);
274 applyCpsPass(new BoundsChecker(typeSystem, compiler.world), cpsFunction);
275 applyCpsPass(new LoopInvariantBranchMotion(), cpsFunction);
276 applyCpsPass(new ShrinkingReducer(), cpsFunction);
277 applyCpsPass(new ScalarReplacer(compiler), cpsFunction);
278 applyCpsPass(new UseFieldInitializers(backend), cpsFunction);
279 applyCpsPass(new MutableVariableEliminator(), cpsFunction);
280 applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
281 applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
282 applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction);
283 applyCpsPass(new ShrinkingReducer(), cpsFunction);
284 applyCpsPass(new OptimizeInterceptors(backend, typeSystem), cpsFunction);
285 applyCpsPass(new BackwardNullCheckRemover(typeSystem), cpsFunction);
286 applyCpsPass(new ShrinkingReducer(), cpsFunction);
287 });
288 }
289
290 tree_ir.FunctionDefinition compileToTreeIr(cps.FunctionDefinition cpsNode) {
291 applyCpsPass(new Finalize(backend), cpsNode);
292 tree_builder.Builder builder =
293 new tree_builder.Builder(reporter.internalError, glue);
294 tree_ir.FunctionDefinition treeNode =
295 treeBuilderTask.measure(() => builder.buildFunction(cpsNode));
296 assert(treeNode != null);
297 traceGraph('Tree builder', treeNode);
298 assert(checkTreeIntegrity(treeNode));
299 return treeNode;
300 }
301
302 bool checkTreeIntegrity(tree_ir.FunctionDefinition node) {
303 treeOptimizationTask.measureSubtask('Check integrity', () {
304 new CheckTreeIntegrity().check(node);
305 });
306 return true; // So this can be used from assert().
307 }
308
309 tree_ir.FunctionDefinition optimizeTreeIr(tree_ir.FunctionDefinition node) {
310 void applyTreePass(tree_opt.Pass pass) {
311 treeOptimizationTask.measureSubtask(pass.passName, () {
312 pass.rewrite(node);
313 });
314 traceGraph(pass.passName, node);
315 assert(checkTreeIntegrity(node));
316 }
317
318 treeOptimizationTask.measure(() {
319 applyTreePass(new StatementRewriter());
320 applyTreePass(
321 new VariableMerger(minifying: compiler.options.enableMinification));
322 applyTreePass(new LoopRewriter());
323 applyTreePass(new LogicalRewriter());
324 applyTreePass(new PullIntoInitializers());
325 });
326
327 return node;
328 }
329
330 js.Fun compileToJavaScript(
331 CodegenWorkItem work, tree_ir.FunctionDefinition definition) {
332 CodeGenerator codeGen = new CodeGenerator(glue, work.registry);
333 Element element = work.element;
334 js.Fun code = codeGen.buildFunction(definition);
335 if (element is FunctionElement && element.asyncMarker != AsyncMarker.SYNC) {
336 code = backend.rewriteAsync(element, code);
337 work.registry.registerAsyncMarker(element);
338 }
339 return attachPosition(code, work.resolvedAst);
340 }
341
342 Iterable<CompilerTask> get tasks {
343 return <CompilerTask>[
344 cpsBuilderTask,
345 cpsOptimizationTask,
346 treeBuilderTask,
347 treeOptimizationTask
348 ]..addAll(fallbackCompiler.tasks);
349 }
350
351 js.Node attachPosition(js.Node node, ResolvedAst resolvedAst) {
352 return node.withSourceInformation(sourceInformationFactory
353 .createBuilderForContext(resolvedAst)
354 .buildDeclaration(resolvedAst));
355 }
356 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/codegen/glue.dart ('k') | pkg/compiler/lib/src/js_backend/codegen/unsugar.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698