Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/optimize.dart |
| =================================================================== |
| --- sdk/lib/_internal/compiler/implementation/ssa/optimize.dart (revision 17466) |
| +++ sdk/lib/_internal/compiler/implementation/ssa/optimize.dart (working copy) |
| @@ -58,6 +58,7 @@ |
| // Previous optimizations may have generated new |
| // opportunities for constant folding. |
| new SsaConstantFolder(constantSystem, backend, work, types), |
| + new SsaSimplifyInterceptors(constantSystem), |
| new SsaDeadCodeEliminator(types)]; |
| runPhases(graph, phases); |
| if (!speculative) { |
| @@ -1445,3 +1446,47 @@ |
| // TODO(ngeoffray): Also implement it for non-intercepted calls. |
| } |
| + |
| +/** |
| + * This phase changes all interceptors that are used only once with |
|
sra1
2013/01/23 21:21:30
/changes/replaces/
ngeoffray
2013/01/24 08:39:15
Done.
|
| + * one-shot interceptors. It saves code size and makes the receiver of |
| + * an intercepted call a candidate for being generated at use site. |
| + */ |
| +class SsaSimplifyInterceptors extends HBaseVisitor |
| + implements OptimizationPhase { |
| + final String name = "SsaSimplifyInterceptors"; |
| + final ConstantSystem constantSystem; |
| + HGraph graph; |
| + |
| + SsaSimplifyInterceptors(this.constantSystem); |
| + |
| + void visitGraph(HGraph graph) { |
| + this.graph = graph; |
| + visitDominatorTree(graph); |
| + } |
| + |
| + void visitInterceptor(HInterceptor node) { |
| + if (node.usedBy.length != 1) return; |
| + // [HBailoutTarget] instructions might have the interceptor as |
| + // input. In such situation we let the dead code analyzer find out |
| + // the interceptor is not needed. |
|
sra1
2013/01/23 21:21:30
Does this lead to unreferenced one-shots?
ngeoffray
2013/01/24 08:39:15
One-shots have side effects, so there's nothing we
|
| + if (node.usedBy[0] is !HInvokeDynamic) return; |
| + |
| + // Replace the user with a [HOneShotInterceptor]. |
| + HInvokeDynamic user = node.usedBy[0]; |
| + HConstant nullConstant = graph.addConstantNull(constantSystem); |
| + List<HInstruction> inputs = new List<HInstruction>.from(user.inputs); |
| + inputs[0] = nullConstant; |
| + HOneShotInterceptor interceptor = new HOneShotInterceptor( |
| + user.selector, inputs, node.interceptedClasses); |
| + |
| + HBasicBlock block = user.block; |
| + block.addAfter(user, interceptor); |
| + block.rewrite(user, interceptor); |
| + block.remove(user); |
| + |
| + // The interceptor will be removed in the dead code elimination |
| + // phase. Note that removing it here would not work because of how |
| + // the [visitBasicBlock] is implemented. |
| + } |
| +} |