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

Unified Diff: pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart

Issue 1313783003: dart2js cps: Generate interceptors at use-site and share afterwards. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Revert patch #3. I read Golem results backwards. Created 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart ('k') | pkg/compiler/lib/src/cps_ir/optimizers.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart
diff --git a/pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart b/pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4471019fb5dac959d7e37a507e4658bf3ad5f9e1
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.cps_ir.loop_invariant_code_motion;
+
+import 'optimizers.dart';
+import 'cps_ir_nodes.dart';
+import 'loop_hierarchy.dart';
+
+/// Lifts primitives out of loops when it is safe and profitable.
+///
+/// Currently we only do this for interceptors.
+class LoopInvariantCodeMotion extends RecursiveVisitor implements Pass {
+ String get passName => 'Loop-invariant code motion';
+
+ final Map<Primitive, Continuation> primitiveLoop =
+ <Primitive, Continuation>{};
+
+ LoopHierarchy loopHierarchy;
+ Continuation currentLoopHeader;
+
+ /// When processing the dependencies of a primitive, [referencedLoop]
+ /// refers to the innermost loop that contains one of the dependencies
+ /// seen so far (or `null` if none of the dependencies are bound in a loop).
+ ///
+ /// This is used to determine how far the primitive can be lifted without
+ /// falling out of scope of its dependencies.
+ Continuation referencedLoop;
+
+ void rewrite(FunctionDefinition node) {
+ loopHierarchy = new LoopHierarchy(node);
+ visit(node.body);
+ }
+
+ @override
+ Expression traverseContinuation(Continuation cont) {
+ Continuation oldLoopHeader = currentLoopHeader;
+ pushAction(() {
+ currentLoopHeader = oldLoopHeader;
+ });
+ currentLoopHeader = loopHierarchy.getLoopHeader(cont);
+ for (Parameter param in cont.parameters) {
+ primitiveLoop[param] = currentLoopHeader;
+ }
+ return cont.body;
+ }
+
+ @override
+ Expression traverseLetPrim(LetPrim node) {
+ primitiveLoop[node.primitive] = currentLoopHeader;
+ if (!shouldLift(node.primitive)) {
+ return node.body;
+ }
+ referencedLoop = null;
+ visit(node.primitive); // Sets referencedLoop.
+ Expression next = node.body;
+ if (referencedLoop != currentLoopHeader) {
+ // Bind the primitive inside [referencedLoop] (possibly null),
+ // immediately before the binding of the inner loop.
+
+ // Find the inner loop.
+ Continuation loop = currentLoopHeader;
+ Continuation enclosing = loopHierarchy.getEnclosingLoop(loop);
+ while (enclosing != referencedLoop) {
+ assert(loop != null);
+ loop = enclosing;
+ enclosing = loopHierarchy.getEnclosingLoop(loop);
+ }
+ assert(loop != null);
+
+ // Remove LetPrim from its current position.
+ node.parent.body = node.body;
+ node.body.parent = node.parent;
+
+ // Insert the LetPrim immediately before the loop.
+ LetCont loopBinding = loop.parent;
+ InteriorNode newParent = loopBinding.parent;
+ newParent.body = node;
+ node.body = loopBinding;
+ loopBinding.parent = node;
+ node.parent = newParent;
+
+ // A different loop now contains the primitive.
+ primitiveLoop[node.primitive] = enclosing;
+ }
+ return next;
+ }
+
+ /// Returns the the innermost loop that effectively encloses both
+ /// c1 and c2 (or `null` if there is no such loop).
+ Continuation leastCommonAncestor(Continuation c1, Continuation c2) {
+ int d1 = getDepth(c1), d2 = getDepth(c2);
+ while (c1 != c2) {
+ if (d1 <= d2) {
+ c2 = loopHierarchy.getEnclosingLoop(c2);
+ d2 = getDepth(c2);
+ } else {
+ c1 = loopHierarchy.getEnclosingLoop(c1);
+ d1 = getDepth(c1);
+ }
+ }
+ return c1;
+ }
+
+ @override
+ void processReference(Reference ref) {
+ Continuation loop =
+ leastCommonAncestor(currentLoopHeader, primitiveLoop[ref.definition]);
+ referencedLoop = getInnerLoop(loop, referencedLoop);
+ }
+
+ int getDepth(Continuation loop) {
+ if (loop == null) return -1;
+ return loopHierarchy.loopDepth[loop];
+ }
+
+ Continuation getInnerLoop(Continuation loop1, Continuation loop2) {
+ if (loop1 == null) return loop2;
+ if (loop2 == null) return loop1;
+ if (loopHierarchy.loopDepth[loop1] > loopHierarchy.loopDepth[loop2]) {
+ return loop1;
+ } else {
+ return loop2;
+ }
+ }
+
+ bool shouldLift(Primitive prim) {
+ // Interceptors are safe and almost always profitable for lifting
+ // out of loops. Several other primitive could be lifted too, but it's not
+ // always profitable to do so.
+ return prim is Interceptor;
+ }
+}
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart ('k') | pkg/compiler/lib/src/cps_ir/optimizers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698