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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart

Issue 1375213003: dart2js cps: Maintain parent pointers instead of recomputing them. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 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) 2014, the Dart project authors. Please see the AUTHORS file 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 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 dart2js.cps_ir.shrinking_reductions; 5 library dart2js.cps_ir.shrinking_reductions;
6 6
7 import 'cps_ir_nodes.dart'; 7 import 'cps_ir_nodes.dart';
8 import 'optimizers.dart'; 8 import 'optimizers.dart';
9 9
10 /** 10 /**
11 * [ShrinkingReducer] applies shrinking reductions to CPS terms as described 11 * [ShrinkingReducer] applies shrinking reductions to CPS terms as described
12 * in 'Compiling with Continuations, Continued' by Andrew Kennedy. 12 * in 'Compiling with Continuations, Continued' by Andrew Kennedy.
13 */ 13 */
14 class ShrinkingReducer extends Pass { 14 class ShrinkingReducer extends Pass {
15 String get passName => 'Shrinking reductions'; 15 String get passName => 'Shrinking reductions';
16 16
17 List<_ReductionTask> _worklist; 17 List<_ReductionTask> _worklist;
18 18
19 static final _DeletedNode _DELETED = new _DeletedNode(); 19 static final _DeletedNode _DELETED = new _DeletedNode();
20 20
21 /// Applies shrinking reductions to root, mutating root in the process. 21 /// Applies shrinking reductions to root, mutating root in the process.
22 @override 22 @override
23 void rewrite(FunctionDefinition root) { 23 void rewrite(FunctionDefinition root) {
24 _worklist = new List<_ReductionTask>(); 24 _worklist = new List<_ReductionTask>();
25 _RedexVisitor redexVisitor = new _RedexVisitor(_worklist); 25 _RedexVisitor redexVisitor = new _RedexVisitor(_worklist);
26 26
27 // Set all parent pointers.
28 new ParentVisitor().visit(root);
29
30 // Sweep over the term, collecting redexes into the worklist. 27 // Sweep over the term, collecting redexes into the worklist.
31 redexVisitor.visit(root); 28 redexVisitor.visit(root);
32 29
33 // Process the worklist. 30 // Process the worklist.
34 while (_worklist.isNotEmpty) { 31 while (_worklist.isNotEmpty) {
35 _ReductionTask task = _worklist.removeLast(); 32 _ReductionTask task = _worklist.removeLast();
36 _processTask(task); 33 _processTask(task);
37 } 34 }
38 } 35 }
39 36
40 /// Removes the given node from the CPS graph, replacing it with its body 37 /// Removes the given node from the CPS graph, replacing it with its body
41 /// and marking it as deleted. The node's parent must be a [[InteriorNode]]. 38 /// and marking it as deleted. The node's parent must be a [[InteriorNode]].
42 void _removeNode(InteriorNode node) { 39 void _removeNode(InteriorNode node) {
43 Node body = node.body; 40 Node body = node.body;
44 InteriorNode parent = node.parent; 41 InteriorNode parent = node.parent;
45 assert(parent.body == node); 42 assert(parent.body == node);
46 43
47 body.parent = parent; 44 body.parent = parent;
48 parent.body = body; 45 parent.body = body;
49 node.parent = _DELETED; 46 node.parent = _DELETED;
50 } 47 }
51 48
52 /// Remove a given continuation from the CPS graph. The LetCont itself is 49 /// Remove a given continuation from the CPS graph. The LetCont itself is
53 /// removed if the given continuation is the only binding. 50 /// removed if the given continuation is the only binding.
54 void _removeContinuation(Continuation cont) { 51 void _removeContinuation(Continuation cont) {
55 LetCont parent = cont.parent; 52 LetCont parent = cont.parent;
56 if (parent.continuations.length == 1) { 53 if (parent.continuations.length == 1) {
57 assert(cont.parent_index == 0);
58 _removeNode(parent); 54 _removeNode(parent);
59 } else { 55 } else {
60 List<Continuation> continuations = parent.continuations; 56 parent.continuations.remove(cont);
61 for (int i = cont.parent_index; i < continuations.length - 1; ++i) {
62 Continuation current = continuations[i + 1];
63 continuations[i] = current;
64 current.parent_index = i;
65 }
66 continuations.removeLast();
asgerf 2015/10/01 10:54:46 The array shift kind of defeats the purpose of the
67 } 57 }
68 cont.parent = _DELETED; 58 cont.parent = _DELETED;
69 } 59 }
70 60
71 void _processTask(_ReductionTask task) { 61 void _processTask(_ReductionTask task) {
72 // Skip tasks for deleted nodes. 62 // Skip tasks for deleted nodes.
73 if (task.node.parent == _DELETED) { 63 if (task.node.parent == _DELETED) {
74 return; 64 return;
75 } 65 }
76 66
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 // let cont k0(v0) = /* v0 is not used */ in 187 // let cont k0(v0) = /* v0 is not used */ in
198 // call foo () k0 188 // call foo () k0
199 // 189 //
200 // Where the dead parameter reduction is no longer valid because we do not 190 // Where the dead parameter reduction is no longer valid because we do not
201 // allow removing the paramter of call continuations. We disallow such eta 191 // allow removing the paramter of call continuations. We disallow such eta
202 // reductions in [_isEtaCont]. 192 // reductions in [_isEtaCont].
203 assert(_isDeadParameter(task.node)); 193 assert(_isDeadParameter(task.node));
204 194
205 Parameter parameter = task.node; 195 Parameter parameter = task.node;
206 Continuation continuation = parameter.parent; 196 Continuation continuation = parameter.parent;
207 int index = parameter.parentIndex; 197 int index = continuation.parameters.indexOf(parameter);
198 assert(index != -1);
208 199
209 // Remove the index'th argument from each invocation. 200 // Remove the index'th argument from each invocation.
210 Reference<Continuation> current = continuation.firstRef; 201 Reference<Continuation> current = continuation.firstRef;
211 while (current != null) { 202 while (current != null) {
212 InvokeContinuation invoke = current.parent; 203 InvokeContinuation invoke = current.parent;
213 Reference<Primitive> argument = invoke.arguments[index]; 204 Reference<Primitive> argument = invoke.arguments[index];
214 argument.unlink(); 205 argument.unlink();
215 // Removing an argument can create a dead parameter or dead value redex. 206 // Removing an argument can create a dead parameter or dead value redex.
216 if (argument.definition is Parameter) { 207 if (argument.definition is Parameter) {
217 if (_isDeadParameter(argument.definition)) { 208 if (_isDeadParameter(argument.definition)) {
218 _worklist.add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER, 209 _worklist.add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER,
219 argument.definition)); 210 argument.definition));
220 } 211 }
221 } else { 212 } else {
222 Node parent = argument.definition.parent; 213 Node parent = argument.definition.parent;
223 if (parent is LetPrim) { 214 if (parent is LetPrim) {
224 if (_isDeadVal(parent)) { 215 if (_isDeadVal(parent)) {
225 _worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, parent)); 216 _worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, parent));
226 } 217 }
227 } 218 }
228 } 219 }
229 invoke.arguments.removeAt(index); 220 invoke.arguments.removeAt(index);
230 current = current.next; 221 current = current.next;
231 } 222 }
232 // Copy the parameters above index down. 223 continuation.parameters.removeAt(index);
233 List<Parameter> parameters = continuation.parameters;
234 for (int i = index; i < parameters.length - 1; ++i) {
235 Parameter p = parameters[i + 1];
236 parameters[i] = p;
237 p.parentIndex = i;
238 }
239 parameters.removeLast();
asgerf 2015/10/01 10:54:46 Same as above.
240 224
241 // Removing an unused parameter can create an eta-redex. 225 // Removing an unused parameter can create an eta-redex.
242 if (_isEtaCont(continuation)) { 226 if (_isEtaCont(continuation)) {
243 _worklist.add(new _ReductionTask(_ReductionKind.ETA_CONT, continuation)); 227 _worklist.add(new _ReductionTask(_ReductionKind.ETA_CONT, continuation));
244 } 228 }
245 } 229 }
246 } 230 }
247 231
248 /// Returns true iff the bound primitive is unused, and has no effects 232 /// Returns true iff the bound primitive is unused, and has no effects
249 /// preventing it from being eliminated. 233 /// preventing it from being eliminated.
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 while (current != null) { 375 while (current != null) {
392 if (current.parent is! InvokeContinuation) return false; 376 if (current.parent is! InvokeContinuation) return false;
393 InvokeContinuation invoke = current.parent; 377 InvokeContinuation invoke = current.parent;
394 if (invoke.continuation.definition != continuation) return false; 378 if (invoke.continuation.definition != continuation) return false;
395 current = current.next; 379 current = current.next;
396 } 380 }
397 return true; 381 return true;
398 } 382 }
399 383
400 /// Traverses a term and adds any found redexes to the worklist. 384 /// Traverses a term and adds any found redexes to the worklist.
401 class _RedexVisitor extends RecursiveVisitor { 385 class _RedexVisitor extends TrampolineRecursiveVisitor {
402 final List<_ReductionTask> worklist; 386 final List<_ReductionTask> worklist;
403 387
404 _RedexVisitor(this.worklist); 388 _RedexVisitor(this.worklist);
405 389
406 void processLetPrim(LetPrim node) { 390 void processLetPrim(LetPrim node) {
407 if (_isDeadVal(node)) { 391 if (_isDeadVal(node)) {
408 worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, node)); 392 worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, node));
409 } 393 }
410 } 394 }
411 395
(...skipping 25 matching lines...) Expand all
437 } 421 }
438 } 422 }
439 } 423 }
440 424
441 /// Traverses a deleted CPS term, marking nodes that might participate in a 425 /// Traverses a deleted CPS term, marking nodes that might participate in a
442 /// redex as deleted and adding newly created redexes to the worklist. 426 /// redex as deleted and adding newly created redexes to the worklist.
443 /// 427 ///
444 /// Deleted nodes that might participate in a reduction task are marked so that 428 /// Deleted nodes that might participate in a reduction task are marked so that
445 /// any corresponding tasks can be skipped. Nodes are marked so by setting 429 /// any corresponding tasks can be skipped. Nodes are marked so by setting
446 /// their parent to the deleted sentinel. 430 /// their parent to the deleted sentinel.
447 class _RemovalVisitor extends RecursiveVisitor { 431 class _RemovalVisitor extends TrampolineRecursiveVisitor {
448 final List<_ReductionTask> worklist; 432 final List<_ReductionTask> worklist;
449 433
450 _RemovalVisitor(this.worklist); 434 _RemovalVisitor(this.worklist);
451 435
452 void processLetPrim(LetPrim node) { 436 void processLetPrim(LetPrim node) {
453 node.parent = ShrinkingReducer._DELETED; 437 node.parent = ShrinkingReducer._DELETED;
454 } 438 }
455 439
456 void processContinuation(Continuation node) { 440 void processContinuation(Continuation node) {
457 node.parent = ShrinkingReducer._DELETED; 441 node.parent = ShrinkingReducer._DELETED;
(...skipping 25 matching lines...) Expand all
483 if (_isDeadCont(cont)) { 467 if (_isDeadCont(cont)) {
484 worklist.add(new _ReductionTask(_ReductionKind.DEAD_CONT, cont)); 468 worklist.add(new _ReductionTask(_ReductionKind.DEAD_CONT, cont));
485 } else if (_isBetaContLin(cont)) { 469 } else if (_isBetaContLin(cont)) {
486 worklist.add(new _ReductionTask(_ReductionKind.BETA_CONT_LIN, cont)); 470 worklist.add(new _ReductionTask(_ReductionKind.BETA_CONT_LIN, cont));
487 } 471 }
488 } 472 }
489 } 473 }
490 } 474 }
491 } 475 }
492 476
493 /// Traverses the CPS term and sets node.parent for each visited node.
494 class ParentVisitor extends RecursiveVisitor {
495 processFunctionDefinition(FunctionDefinition node) {
496 node.body.parent = node;
497 if (node.thisParameter != null) node.thisParameter.parent = node;
498 int index = 0;
499 node.parameters.forEach((Definition parameter) {
500 parameter.parent = node;
501 if (parameter is Parameter) parameter.parentIndex = index++;
502 });
503 node.returnContinuation.parent = node;
504 node.body.parent = node;
505 }
506 477
507 processLetPrim(LetPrim node) {
508 node.primitive.parent = node;
509 node.body.parent = node;
510 }
511
512 processLetCont(LetCont node) {
513 int index = 0;
514 node.continuations.forEach((Continuation continuation) {
515 continuation.parent = node;
516 continuation.parent_index = index++;
517 });
518 node.body.parent = node;
519 }
520
521 processLetHandler(LetHandler node) {
522 node.handler.parent = node;
523 node.body.parent = node;
524 }
525
526 processLetMutable(LetMutable node) {
527 node.variable.parent = node;
528 node.value.parent = node;
529 node.body.parent = node;
530 }
531
532 processInvokeStatic(InvokeStatic node) {
533 node.arguments.forEach((Reference ref) => ref.parent = node);
534 node.continuation.parent = node;
535 }
536
537 processInvokeContinuation(InvokeContinuation node) {
538 node.continuation.parent = node;
539 node.arguments.forEach((Reference ref) => ref.parent = node);
540 }
541
542 processInvokeMethod(InvokeMethod node) {
543 node.receiver.parent = node;
544 node.continuation.parent = node;
545 node.arguments.forEach((Reference ref) => ref.parent = node);
546 }
547
548 processInvokeMethodDirectly(InvokeMethodDirectly node) {
549 node.receiver.parent = node;
550 node.continuation.parent = node;
551 node.arguments.forEach((Reference ref) => ref.parent = node);
552 }
553
554 processInvokeConstructor(InvokeConstructor node) {
555 node.continuation.parent = node;
556 node.arguments.forEach((Reference ref) => ref.parent = node);
557 }
558
559 processBranch(Branch node) {
560 node.condition.parent = node;
561 node.trueContinuation.parent = node;
562 node.falseContinuation.parent = node;
563 }
564
565 processTypeCast(TypeCast node) {
566 node.typeArguments.forEach((Reference ref) => ref.parent = node);
567 node.continuation.parent = node;
568 node.value.parent = node;
569 }
570
571 processTypeTest(TypeTest node) {
572 node.typeArguments.forEach((Reference ref) => ref.parent = node);
573 node.value.parent = node;
574 }
575
576 processSetMutable(SetMutable node) {
577 node.variable.parent = node;
578 node.value.parent = node;
579 }
580
581 processThrow(Throw node) {
582 node.value.parent = node;
583 }
584
585 processGetLazyStatic(GetLazyStatic node) {
586 node.continuation.parent = node;
587 }
588
589 processLiteralList(LiteralList node) {
590 node.values.forEach((Reference ref) => ref.parent = node);
591 }
592
593 processLiteralMap(LiteralMap node) {
594 node.entries.forEach((LiteralMapEntry entry) {
595 entry.key.parent = node;
596 entry.value.parent = node;
597 });
598 }
599
600 processCreateFunction(CreateFunction node) {
601 node.definition.parent = node;
602 }
603
604 processContinuation(Continuation node) {
605 if (node.body != null) node.body.parent = node;
606 int index = 0;
607 node.parameters.forEach((Parameter parameter) {
608 parameter.parent = node;
609 parameter.parentIndex = index++;
610 });
611 }
612
613 processInterceptor(Interceptor node) {
614 node.input.parent = node;
615 }
616
617 processSetField(SetField node) {
618 node.object.parent = node;
619 node.value.parent = node;
620 }
621
622 processGetField(GetField node) {
623 node.object.parent = node;
624 }
625
626 processGetStatic(GetStatic node) {
627 }
628
629 processSetStatic(SetStatic node) {
630 node.value.parent = node;
631 }
632
633 processGetMutable(GetMutable node) {
634 node.variable.parent = node;
635 }
636
637 processCreateInstance(CreateInstance node) {
638 node.arguments.forEach((Reference ref) => ref.parent = node);
639 node.typeInformation.forEach((Reference ref) => ref.parent = node);
640 }
641
642 processCreateBox(CreateBox node) {
643 }
644
645 processReifyRuntimeType(ReifyRuntimeType node) {
646 node.value.parent = node;
647 }
648
649 processReadTypeVariable(ReadTypeVariable node) {
650 node.target.parent = node;
651 }
652
653 processTypeExpression(TypeExpression node) {
654 node.arguments.forEach((Reference ref) => ref.parent = node);
655 }
656
657 processCreateInvocationMirror(CreateInvocationMirror node) {
658 node.arguments.forEach((Reference ref) => ref.parent = node);
659 }
660
661 processApplyBuiltinOperator(ApplyBuiltinOperator node) {
662 node.arguments.forEach((Reference ref) => ref.parent = node);
663 }
664
665 processApplyBuiltinMethod(ApplyBuiltinMethod node) {
666 node.receiver.parent = node;
667 node.arguments.forEach((Reference ref) => ref.parent = node);
668 }
669
670 processForeignCode(ForeignCode node) {
671 if (node.continuation != null) {
672 node.continuation.parent = node;
673 }
674 node.arguments.forEach((Reference ref) => ref.parent = node);
675 }
676
677 processGetLength(GetLength node) {
678 node.object.parent = node;
679 }
680
681 processGetIndex(GetIndex node) {
682 node.object.parent = node;
683 node.index.parent = node;
684 }
685
686 processSetIndex(SetIndex node) {
687 node.object.parent = node;
688 node.index.parent = node;
689 node.value.parent = node;
690 }
691
692 processAwait(Await node) {
693 node.continuation.parent = node;
694 node.input.parent = node;
695 }
696
697 processRefinement(Refinement node) {
698 node.value.parent = node;
699 }
700
701 processYield(Yield node) {
702 node.continuation.parent = node;
703 node.input.parent = node;
704 }
705 }
706 478
707 class _ReductionKind { 479 class _ReductionKind {
708 final String name; 480 final String name;
709 final int hashCode; 481 final int hashCode;
710 482
711 const _ReductionKind(this.name, this.hashCode); 483 const _ReductionKind(this.name, this.hashCode);
712 484
713 static const _ReductionKind DEAD_VAL = const _ReductionKind('dead-val', 0); 485 static const _ReductionKind DEAD_VAL = const _ReductionKind('dead-val', 0);
714 static const _ReductionKind DEAD_CONT = const _ReductionKind('dead-cont', 1); 486 static const _ReductionKind DEAD_CONT = const _ReductionKind('dead-cont', 1);
715 static const _ReductionKind BETA_CONT_LIN = 487 static const _ReductionKind BETA_CONT_LIN =
(...skipping 23 matching lines...) Expand all
739 bool operator==(_ReductionTask that) { 511 bool operator==(_ReductionTask that) {
740 return (that.kind == this.kind && that.node == this.node); 512 return (that.kind == this.kind && that.node == this.node);
741 } 513 }
742 514
743 String toString() => "$kind: $node"; 515 String toString() => "$kind: $node";
744 } 516 }
745 517
746 /// A dummy class used solely to mark nodes as deleted once they are removed 518 /// A dummy class used solely to mark nodes as deleted once they are removed
747 /// from a term. 519 /// from a term.
748 class _DeletedNode extends Node { 520 class _DeletedNode extends Node {
749 accept(_) => null; 521 accept(_) {}
522 setParentPointers() {}
750 } 523 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/share_interceptors.dart ('k') | pkg/compiler/lib/src/cps_ir/type_propagation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698