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

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

Issue 1426633005: dart2js cps: Better side-effect tracking in loops. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.bounds_checker; 5 library dart2js.cps_ir.bounds_checker;
6 6
7 import 'cps_ir_nodes.dart'; 7 import 'cps_ir_nodes.dart';
8 import 'optimizers.dart' show Pass; 8 import 'optimizers.dart' show Pass;
9 import 'octagon.dart'; 9 import 'octagon.dart';
10 import '../constants/values.dart'; 10 import '../constants/values.dart';
11 import 'cps_fragment.dart'; 11 import 'cps_fragment.dart';
12 import 'type_mask_system.dart'; 12 import 'type_mask_system.dart';
13 import '../world.dart'; 13 import '../world.dart';
14 import '../elements/elements.dart'; 14 import '../elements/elements.dart';
15 import 'loop_effects.dart';
16
17
15 18
16 /// Eliminates bounds checks when they can be proven safe. 19 /// Eliminates bounds checks when they can be proven safe.
17 /// 20 ///
18 /// In general, this pass will try to eliminate any branch with arithmetic 21 /// In general, this pass will try to eliminate any branch with arithmetic
19 /// in the condition, i.e. `x < y`, `x <= y`, `x == y` etc. 22 /// in the condition, i.e. `x < y`, `x <= y`, `x == y` etc.
20 /// 23 ///
21 /// The analysis uses an [Octagon] abstract domain. Unlike traditional octagon 24 /// The analysis uses an [Octagon] abstract domain. Unlike traditional octagon
22 /// analyzers, we do not use a closed matrix representation, but just maintain 25 /// analyzers, we do not use a closed matrix representation, but just maintain
23 /// a bucket of constraints. Constraints can therefore be added and removed 26 /// a bucket of constraints. Constraints can therefore be added and removed
24 /// on-the-fly without significant overhead. 27 /// on-the-fly without significant overhead.
25 /// 28 ///
26 /// We never copy the constraint system. While traversing the IR, the 29 /// We never copy the constraint system. While traversing the IR, the
27 /// constraint system is mutated to take into account the knowledge that is 30 /// constraint system is mutated to take into account the knowledge that is
28 /// valid for the current location. Constraints are added when entering a 31 /// valid for the current location. Constraints are added when entering a
29 /// branch, for instance, and removed again after the branch has been processed. 32 /// branch, for instance, and removed again after the branch has been processed.
30 /// 33 ///
31 /// Loops are analyzed in two passes. The first pass establishes monotonicity 34 /// Loops are analyzed in two passes. The first pass establishes monotonicity
32 /// of loop variables, which the second pass uses to compute upper/lower bounds. 35 /// of loop variables, which the second pass uses to compute upper/lower bounds.
33 /// The first pass also records whether any side effects occurred in the loop.
34 /// 36 ///
35 /// The two-pass scheme is suboptimal compared to a least fixed-point 37 /// The two-pass scheme is suboptimal compared to a least fixed-point
36 /// computation, but does not require repeated iteration. Repeated iteration 38 /// computation, but does not require repeated iteration. Repeated iteration
37 /// would be expensive, since we cannot perform a sparse analysis with our 39 /// would be expensive, since we cannot perform a sparse analysis with our
38 /// mutable octagon representation. 40 /// mutable octagon representation.
39 class BoundsChecker extends TrampolineRecursiveVisitor implements Pass { 41 class BoundsChecker extends TrampolineRecursiveVisitor implements Pass {
40 String get passName => 'Bounds checker'; 42 String get passName => 'Bounds checker';
41 43
42 static const int MAX_UINT32 = (1 << 32) - 1; 44 static const int MAX_UINT32 = (1 << 32) - 1;
43 45
44 /// All integers of this magnitude or less are representable as JS numbers. 46 /// All integers of this magnitude or less are representable as JS numbers.
45 static const int MAX_SAFE_INT = (1 << 53) - 1; 47 static const int MAX_SAFE_INT = (1 << 53) - 1;
46 48
47 /// Marker to indicate that a continuation should get a unique effect number. 49 /// Marker to indicate that a continuation should get a unique effect number.
48 static const int NEW_EFFECT = -1; 50 static const int NEW_EFFECT = -1;
49 51
50 final TypeMaskSystem types; 52 final TypeMaskSystem types;
51 final World world; 53 final World world;
52 54
53 /// Fields for the constraint system and its variables. 55 /// Fields for the constraint system and its variables.
54 final Octagon octagon = new Octagon(); 56 final Octagon octagon = new Octagon();
55 final Map<Primitive, SignedVariable> valueOf = {}; 57 final Map<Primitive, SignedVariable> valueOf = {};
56 final Map<Primitive, Map<int, SignedVariable>> lengthOf = {}; 58 final Map<Primitive, Map<int, SignedVariable>> lengthOf = {};
57 59
58 /// Fields for the two-pass handling of loops. 60 /// Fields for the two-pass handling of loops.
59 final Set<Continuation> loopsWithSideEffects = new Set<Continuation>();
60 final Map<Parameter, Monotonicity> monotonicity = <Parameter, Monotonicity>{}; 61 final Map<Parameter, Monotonicity> monotonicity = <Parameter, Monotonicity>{};
61 bool isStrongLoopPass; 62 bool isStrongLoopPass;
62 bool foundLoop = false; 63 bool foundLoop = false;
63 64
64 /// Fields for tracking side effects. 65 /// Fields for tracking side effects.
65 /// 66 ///
66 /// The IR is divided into regions wherein the lengths of indexable objects 67 /// The IR is divided into regions wherein the lengths of indexable objects
67 /// are known not to change. Regions are identified by their "effect number". 68 /// are known not to change. Regions are identified by their "effect number".
69 LoopSideEffects loopEffects;
68 final Map<Continuation, int> effectNumberAt = <Continuation, int>{}; 70 final Map<Continuation, int> effectNumberAt = <Continuation, int>{};
69 int currentEffectNumber = 0; 71 int currentEffectNumber = 0;
70 int effectNumberCounter = 0; 72 int effectNumberCounter = 0;
71 73
72 BoundsChecker(this.types, this.world); 74 BoundsChecker(this.types, this.world);
73 75
74 void rewrite(FunctionDefinition node) { 76 void rewrite(FunctionDefinition node) {
77 loopEffects = new LoopSideEffects(node, world);
75 isStrongLoopPass = false; 78 isStrongLoopPass = false;
76 visit(node); 79 visit(node);
77 if (foundLoop) { 80 if (foundLoop) {
78 isStrongLoopPass = true; 81 isStrongLoopPass = true;
79 effectNumberAt.clear(); 82 effectNumberAt.clear();
80 visit(node); 83 visit(node);
81 } 84 }
82 } 85 }
83 86
84 // ------------- VARIABLES ----------------- 87 // ------------- VARIABLES -----------------
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 Monotonicity mono = monotonicity[param]; 398 Monotonicity mono = monotonicity[param];
396 if (mono == null) { 399 if (mono == null) {
397 // Value never changes. This is extremely uncommon. 400 // Value never changes. This is extremely uncommon.
398 initialValue.substituteFor(param); 401 initialValue.substituteFor(param);
399 } else if (mono == Monotonicity.Increasing) { 402 } else if (mono == Monotonicity.Increasing) {
400 makeGreaterThanOrEqual(getValue(param), initialVariable); 403 makeGreaterThanOrEqual(getValue(param), initialVariable);
401 } else if (mono == Monotonicity.Decreasing) { 404 } else if (mono == Monotonicity.Decreasing) {
402 makeLessThanOrEqual(getValue(param), initialVariable); 405 makeLessThanOrEqual(getValue(param), initialVariable);
403 } 406 }
404 } 407 }
405 if (loopsWithSideEffects.contains(cont)) { 408 }
406 currentEffectNumber = makeNewEffect(); 409 if (loopEffects.loopChangesLength(cont)) {
407 }
408 } else {
409 // During the weak pass, conservatively make a new effect number in the
410 // loop body. This may be strengthened during the strong pass.
411 currentEffectNumber = effectNumberAt[cont] = makeNewEffect(); 410 currentEffectNumber = effectNumberAt[cont] = makeNewEffect();
412 } 411 }
413 push(cont); 412 push(cont);
414 } 413 }
415 414
416 void analyzeLoopContinue(InvokeContinuation node) { 415 void analyzeLoopContinue(InvokeContinuation node) {
417 Continuation cont = node.continuation.definition; 416 Continuation cont = node.continuation.definition;
418 417
419 // During the strong loop phase, there is no need to compute monotonicity, 418 // During the strong loop phase, there is no need to compute monotonicity,
420 // and we already put bounds on the loop variables when we went into the 419 // and we already put bounds on the loop variables when we went into the
(...skipping 12 matching lines...) Expand all
433 // We couldn't prove that the value does not increase, so assume 432 // We couldn't prove that the value does not increase, so assume
434 // henceforth that it might be increasing. 433 // henceforth that it might be increasing.
435 markMonotonicity(cont.parameters[i], Monotonicity.Increasing); 434 markMonotonicity(cont.parameters[i], Monotonicity.Increasing);
436 } 435 }
437 if (!isDefinitelyGreaterThanOrEqualTo(arg, paramVar)) { 436 if (!isDefinitelyGreaterThanOrEqualTo(arg, paramVar)) {
438 // We couldn't prove that the value does not decrease, so assume 437 // We couldn't prove that the value does not decrease, so assume
439 // henceforth that it might be decreasing. 438 // henceforth that it might be decreasing.
440 markMonotonicity(cont.parameters[i], Monotonicity.Decreasing); 439 markMonotonicity(cont.parameters[i], Monotonicity.Decreasing);
441 } 440 }
442 } 441 }
443
444 // If a side effect has occurred between the entry and continue, mark
445 // the loop as having side effects.
446 if (currentEffectNumber != effectNumberAt[cont]) {
447 loopsWithSideEffects.add(cont);
448 }
449 } 442 }
450 443
451 void markMonotonicity(Parameter param, Monotonicity mono) { 444 void markMonotonicity(Parameter param, Monotonicity mono) {
452 Monotonicity current = monotonicity[param]; 445 Monotonicity current = monotonicity[param];
453 if (current == null) { 446 if (current == null) {
454 monotonicity[param] = mono; 447 monotonicity[param] = mono;
455 } else if (current != mono) { 448 } else if (current != mono) {
456 monotonicity[param] = Monotonicity.NotMonotone; 449 monotonicity[param] = Monotonicity.NotMonotone;
457 } 450 }
458 } 451 }
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 } 600 }
608 return node.body; 601 return node.body;
609 } 602 }
610 } 603 }
611 604
612 /// Lattice representing the known (weak) monotonicity of a loop variable. 605 /// Lattice representing the known (weak) monotonicity of a loop variable.
613 /// 606 ///
614 /// The lattice bottom is represented by `null` and represents the case where 607 /// The lattice bottom is represented by `null` and represents the case where
615 /// the loop variable never changes value during the loop. 608 /// the loop variable never changes value during the loop.
616 enum Monotonicity { NotMonotone, Increasing, Decreasing, } 609 enum Monotonicity { NotMonotone, Increasing, Decreasing, }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/loop_effects.dart » ('j') | pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698