| Index: pkg/compiler/lib/src/cps_ir/loop_effects.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/loop_effects.dart b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
|
| index c7680b006ec2769a3bbae98e15bebad073843e06..4a73e5dcac3a035b550bc552cccecd572956e670 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/loop_effects.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
|
| @@ -2,25 +2,16 @@ library dart2js.cps_ir.loop_effects;
|
|
|
| import 'cps_ir_nodes.dart';
|
| import 'loop_hierarchy.dart';
|
| -import '../universe/side_effects.dart';
|
| -import '../elements/elements.dart';
|
| import '../world.dart';
|
| +import 'effects.dart';
|
|
|
| -/// Determines which the [SideEffects] that may occur during each loop in
|
| -/// a given function, in addition to whether the loop may change the length
|
| -/// of an indexable object.
|
| -///
|
| -/// TODO(asgerf): Make length a flag on [SideEffects] for better precision and
|
| -/// so we don't need to special case the length in this class.
|
| +/// Determines the side effects that may occur in each loop.
|
| class LoopSideEffects extends TrampolineRecursiveVisitor {
|
| LoopHierarchy loopHierarchy;
|
| final World world;
|
| final Map<Continuation, List<Continuation>> exitContinuations = {};
|
| - final Map<Continuation, SideEffects> loopSideEffects = {};
|
| - final Set<Continuation> loopsChangingLength = new Set<Continuation>();
|
| + final Map<Continuation, int> loopSideEffects = {};
|
| Continuation currentLoopHeader;
|
| - SideEffects currentLoopSideEffects = new SideEffects.empty();
|
| - bool currentLoopChangesLength = false;
|
|
|
| LoopSideEffects(FunctionDefinition node, this.world, {this.loopHierarchy}) {
|
| if (loopHierarchy == null) {
|
| @@ -31,30 +22,25 @@ class LoopSideEffects extends TrampolineRecursiveVisitor {
|
|
|
| /// Returns the accumulated effects and dependencies on all paths from the
|
| /// loop entry to any recursive invocation of the loop.
|
| - SideEffects getSideEffectsInLoop(Continuation loop) {
|
| + int getSideEffectsInLoop(Continuation loop) {
|
| return loopSideEffects[loop];
|
| }
|
|
|
| /// True if the length of an indexable object may change between the loop
|
| /// entry and a recursive invocation of the loop.
|
| - bool loopChangesLength(Continuation loop) {
|
| - return loopsChangingLength.contains(loop);
|
| + bool changesIndexableLength(Continuation loop) {
|
| + return loopSideEffects[loop] & Effects.changesIndexableLength != 0;
|
| }
|
|
|
| @override
|
| Expression traverseContinuation(Continuation cont) {
|
| if (cont.isRecursive) {
|
| - SideEffects oldEffects = currentLoopSideEffects;
|
| - bool oldChangesLength = currentLoopChangesLength;
|
| - loopSideEffects[cont] = currentLoopSideEffects = new SideEffects.empty();
|
| + loopSideEffects[cont] = Effects.none;
|
| exitContinuations[cont] = <Continuation>[];
|
| pushAction(() {
|
| - oldEffects.add(currentLoopSideEffects);
|
| - if (currentLoopChangesLength) {
|
| - loopsChangingLength.add(cont);
|
| + if (currentLoopHeader != null) {
|
| + loopSideEffects[currentLoopHeader] |= loopSideEffects[cont];
|
| }
|
| - currentLoopChangesLength = currentLoopChangesLength || oldChangesLength;
|
| - currentLoopSideEffects = oldEffects;
|
| exitContinuations[cont].forEach(push);
|
| });
|
| }
|
| @@ -78,6 +64,14 @@ class LoopSideEffects extends TrampolineRecursiveVisitor {
|
| return node.body;
|
| }
|
|
|
| + @override
|
| + Expression traverseLetPrim(LetPrim node) {
|
| + if (currentLoopHeader != null) {
|
| + loopSideEffects[currentLoopHeader] |= node.primitive.effects;
|
| + }
|
| + return node.body;
|
| + }
|
| +
|
| void enqueueContinuation(Continuation cont) {
|
| Continuation loop = loopHierarchy.getEnclosingLoop(cont);
|
| if (loop == currentLoopHeader) {
|
| @@ -101,85 +95,4 @@ class LoopSideEffects extends TrampolineRecursiveVisitor {
|
| exitContinuations[inner].add(cont);
|
| }
|
| }
|
| -
|
| - void addSideEffects(SideEffects effects) {
|
| - currentLoopSideEffects.add(effects);
|
| - if (effects.changesIndex()) {
|
| - currentLoopChangesLength = true;
|
| - }
|
| - }
|
| -
|
| - void addAllSideEffects() {
|
| - currentLoopSideEffects.setAllSideEffects();
|
| - currentLoopSideEffects.setDependsOnSomething();
|
| - currentLoopChangesLength = true;
|
| - }
|
| -
|
| - void visitInvokeMethod(InvokeMethod node) {
|
| - addSideEffects(world.getSideEffectsOfSelector(node.selector, node.mask));
|
| - }
|
| -
|
| - void visitInvokeStatic(InvokeStatic node) {
|
| - addSideEffects(world.getSideEffectsOfElement(node.target));
|
| - }
|
| -
|
| - void visitInvokeMethodDirectly(InvokeMethodDirectly node) {
|
| - FunctionElement target = node.target;
|
| - if (target is ConstructorBodyElement) {
|
| - ConstructorBodyElement body = target;
|
| - target = body.constructor;
|
| - }
|
| - addSideEffects(world.getSideEffectsOfElement(target));
|
| - }
|
| -
|
| - void visitInvokeConstructor(InvokeConstructor node) {
|
| - addSideEffects(world.getSideEffectsOfElement(node.target));
|
| - }
|
| -
|
| - void visitSetStatic(SetStatic node) {
|
| - currentLoopSideEffects.setChangesStaticProperty();
|
| - }
|
| -
|
| - void visitGetStatic(GetStatic node) {
|
| - currentLoopSideEffects.setDependsOnStaticPropertyStore();
|
| - }
|
| -
|
| - void visitGetField(GetField node) {
|
| - currentLoopSideEffects.setDependsOnInstancePropertyStore();
|
| - }
|
| -
|
| - void visitSetField(SetField node) {
|
| - currentLoopSideEffects.setChangesInstanceProperty();
|
| - }
|
| -
|
| - void visitGetIndex(GetIndex node) {
|
| - currentLoopSideEffects.setDependsOnIndexStore();
|
| - }
|
| -
|
| - void visitSetIndex(SetIndex node) {
|
| - // Set the change index flag without setting the change length flag.
|
| - currentLoopSideEffects.setChangesIndex();
|
| - }
|
| -
|
| - void visitForeignCode(ForeignCode node) {
|
| - addSideEffects(node.nativeBehavior.sideEffects);
|
| - }
|
| -
|
| - void visitGetLazyStatic(GetLazyStatic node) {
|
| - // TODO(asgerf): How do we get the side effects of a lazy field initializer?
|
| - addAllSideEffects();
|
| - }
|
| -
|
| - void visitAwait(Await node) {
|
| - addAllSideEffects();
|
| - }
|
| -
|
| - void visitYield(Yield node) {
|
| - addAllSideEffects();
|
| - }
|
| -
|
| - void visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
|
| - currentLoopSideEffects.setChangesIndex();
|
| - currentLoopChangesLength = true; // Push and pop.
|
| - }
|
| }
|
|
|