blob: 2a2c4ee7efd46f9f414394306dee0aeb123cac65 [file] [log] [blame]
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.dev.jjs.impl.gflow;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.impl.DeadCodeElimination;
import com.google.gwt.dev.jjs.impl.OptimizerStats;
import com.google.gwt.dev.jjs.impl.gflow.cfg.Cfg;
import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgBuilder;
import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgEdge;
import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgNode;
import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgTransformer;
import com.google.gwt.dev.jjs.impl.gflow.constants.ConstantsAnalysis;
import com.google.gwt.dev.jjs.impl.gflow.copy.CopyAnalysis;
import com.google.gwt.dev.jjs.impl.gflow.liveness.LivenessAnalysis;
import com.google.gwt.dev.jjs.impl.gflow.unreachable.UnreachableAnalysis;
import com.google.gwt.dev.util.Preconditions;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
/**
*/
public class DataflowOptimizer {
public static String NAME = DataflowOptimizer.class.getSimpleName();
public static OptimizerStats exec(JProgram jprogram, JNode node) {
Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "optimizer", NAME);
OptimizerStats stats = new DataflowOptimizer(jprogram).execImpl(node);
optimizeEvent.end();
return stats;
}
public static OptimizerStats exec(JProgram jprogram) {
return exec(jprogram, jprogram);
}
private final JProgram program;
public DataflowOptimizer(JProgram program) {
this.program = program;
}
private class DataflowOptimizerVisitor extends JModVisitor {
@Override
public boolean visit(JMethodBody methodBody, Context ctx) {
Cfg cfg = CfgBuilder.build(program, methodBody.getBlock());
JMethod method = methodBody.getMethod();
JDeclaredType enclosingType = method.getEnclosingType();
String methodName = enclosingType.getName() + "." + method.getName();
// AnalysisSolver.debug = methodName.equals("<some method>");
Preconditions.checkNotNull(cfg, "Can't build flow for %s", methodName);
try {
CombinedIntegratedAnalysis<CfgNode<?>, CfgEdge, CfgTransformer, Cfg>
fwdAnalysis = CombinedIntegratedAnalysis.createAnalysis();
fwdAnalysis.addAnalysis(new UnreachableAnalysis());
fwdAnalysis.addAnalysis(new ConstantsAnalysis());
fwdAnalysis.addAnalysis(new CopyAnalysis());
// fwdAnalysis.addAnalysis(new InlineVarAnalysis(program));
boolean madeChanges = false;
madeChanges = AnalysisSolver.solveIntegrated(cfg, fwdAnalysis, true)
|| madeChanges;
cfg = CfgBuilder.build(program, methodBody.getBlock());
Preconditions.checkNotNull(cfg);
CombinedIntegratedAnalysis<CfgNode<?>, CfgEdge, CfgTransformer, Cfg>
bkwAnalysis = CombinedIntegratedAnalysis.createAnalysis();
bkwAnalysis.addAnalysis(new LivenessAnalysis());
madeChanges = AnalysisSolver.solveIntegrated(cfg, bkwAnalysis, false)
|| madeChanges;
if (madeChanges) {
madeChanges();
DeadCodeElimination.exec(program, methodBody);
}
} catch (Throwable t) {
throw new RuntimeException("Error optimizing: " + methodName, t);
}
return true;
}
}
private OptimizerStats execImpl(JNode node) {
DataflowOptimizerVisitor visitor = new DataflowOptimizerVisitor();
visitor.accept(node);
return new OptimizerStats(NAME).recordModified(visitor.getNumMods());
}
}