blob: dd1e443eebe28e300b463587b67f287f6c25fb2a [file] [log] [blame]
/*
* Copyright 2008 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.copy;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVariableRef;
import com.google.gwt.dev.jjs.impl.gflow.AssumptionMap;
import com.google.gwt.dev.jjs.impl.gflow.AssumptionUtil;
import com.google.gwt.dev.jjs.impl.gflow.IntegratedFlowFunction;
import com.google.gwt.dev.jjs.impl.gflow.TransformationFunction.Transformation;
import com.google.gwt.dev.jjs.impl.gflow.cfg.Cfg;
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.CfgReadNode;
import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgTransformer;
import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgUtil;
import com.google.gwt.dev.util.Preconditions;
/**
* Integrated flow function for CopyAnalysis. Tries to replace copied vars with
* original ones.
*/
public class CopyIntegratedFlowFunction implements
IntegratedFlowFunction<CfgNode<?>, CfgEdge, CfgTransformer, Cfg, CopyAssumption> {
private final class CopyTransformation implements
Transformation<CfgTransformer, Cfg> {
private final CfgNode<?> node;
private final JVariable original;
private final Cfg graph;
private CopyTransformation(CfgNode<?> node, JVariable original,
Cfg graph) {
this.node = node;
this.original = original;
this.graph = graph;
}
public CfgTransformer getGraphTransformer() {
return new CfgTransformer() {
public boolean transform(final CfgNode<?> node, Cfg cfgGraph) {
JModVisitor visitor = new JModVisitor() {
@Override
public void endVisit(JNode x, Context ctx) {
if (x == node.getJNode()) {
ctx.replaceMe(createRef(x.getSourceInfo(), original));
}
}
};
CfgNode<?> parentNode = node.getParent();
JNode parentJNode = parentNode.getJNode();
visitor.accept(parentJNode);
Preconditions.checkState(visitor.didChange());
return true;
}
};
}
public Cfg getNewSubgraph() {
CfgReadNode newNode = new CfgReadNode(node.getParent(),
createRef(node.getJNode().getSourceInfo(), original));
return CfgUtil.createSingleNodeReplacementGraph(graph, node, newNode);
}
@Override
public String toString() {
return "CopyTransformation(" + node + "," + original + ")";
}
private JVariableRef createRef(SourceInfo sourceInfo, JVariable variable) {
if (variable instanceof JLocal) {
return new JLocalRef(sourceInfo, (JLocal) variable);
} else if (variable instanceof JParameter) {
return new JParameterRef(sourceInfo, (JParameter) variable);
}
throw new IllegalArgumentException("Unsupported variable: " +
variable.getClass());
}
}
private static final CopyFlowFunction FLOW_FUNCTION = new CopyFlowFunction();
public Transformation<CfgTransformer, Cfg>
interpretOrReplace(final CfgNode<?> node, final Cfg graph,
AssumptionMap<CfgEdge, CopyAssumption> assumptionMap) {
CopyAssumption in = AssumptionUtil.join(
graph.getInEdges(node), assumptionMap);
if (in != null && node instanceof CfgReadNode) {
JVariable v = ((CfgReadNode) node).getTarget();
final JVariable original = in.getOriginal(v);
Preconditions.checkState(v != original,
"Variable is a copy of itself: %s", v);
if (original != null) {
return new CopyTransformation(node, original, graph);
}
}
FLOW_FUNCTION.interpret(node, graph, assumptionMap);
return null;
}
}