package org.codehaus.groovy.gjit;
import java.util.ListIterator;
import java.util.Map;
import org.codehaus.groovy.gjit.MyBasicInterpreter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Value;
public class BaseTransformer implements Opcodes {
private String owner;
//private Interpreter interpreter;
protected MethodNode node;
protected InsnList units;
protected Map<AbstractInsnNode, Value[]> use;
protected int callSiteVar;
protected Map<AbstractInsnNode, Frame> frames;
protected boolean preTransformationOnly=false;
protected Interpreter interpreter;
public BaseTransformer(String owner, MethodNode mn) {
super();
this.owner = owner;
this.node = mn;
this.units = node.instructions;
}
public BaseTransformer(Interpreter interpreter, String owner, MethodNode mn) {
//super(interpreter);
this.interpreter = interpreter;
this.owner = owner;
this.node = mn;
this.units = node.instructions;
}
public void transform() throws AnalyzerException {
if(interpreter instanceof MyBasicInterpreter) {
this.use = ((MyBasicInterpreter)interpreter).use;
}
pretransform();
if(preTransformationOnly) return;
// frames = this.analyze(this.owner, this.node);
posttransform();
}
protected void posttransform() {
}
private enum Phase {
PHASE_CALLSITE,
PHASE_NEXT_1,
PHASE_NEXT_2,
PHASE_ERROR
}
private enum CallSiteState {
START,
FOUND_CALLSITE_INST,
END,
ERROR,
};
private Phase phase = Phase.PHASE_CALLSITE;
protected void pretransform() {
ListIterator<?> stmts = units.iterator();
while(stmts.hasNext()) {
AbstractInsnNode s = (AbstractInsnNode)stmts.next();
switch(phase) {
case PHASE_CALLSITE: phase = processPhaseCallSite(s); break;
}
}
}
private Phase processPhaseCallSite(AbstractInsnNode s0) {
CallSiteState state = CallSiteState.START;
AbstractInsnNode s = s0;
while(true) {
switch(state) {
case START:
state = detectCallSiteInst(state, s);
break;
case FOUND_CALLSITE_INST:
state = detectCallSiteVar(state, s);
break;
case END: return Phase.PHASE_NEXT_1;
case ERROR: return Phase.PHASE_ERROR;
}
s = s.getNext();
if(s == null) state = CallSiteState.ERROR;
}
}
private CallSiteState detectCallSiteVar(CallSiteState state, AbstractInsnNode s) {
if(s.getOpcode() != ASTORE) return state;
VarInsnNode v = (VarInsnNode)s;
callSiteVar = v.var;
return CallSiteState.END;
}
private CallSiteState detectCallSiteInst(CallSiteState state, AbstractInsnNode s) {
if(s.getOpcode() != INVOKESTATIC) return state;
MethodInsnNode m = (MethodInsnNode)s;
if(m.name.equals("$getCallSiteArray")) return CallSiteState.FOUND_CALLSITE_INST;
return state;
}
}