Commit d28501bb authored by Yudi Zheng's avatar Yudi Zheng

Markers now define their own weaving location.

parent 22fb3da3
......@@ -4,19 +4,17 @@ import java.util.List;
import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.marker.AbstractMarker.MarkedRegion;
public abstract class AbstractDWRMarker extends AbstractMarker{
public abstract class AbstractDWRMarker {
public final List<MarkedRegion> mark(MethodNode methodNode) {
public List<MarkedRegion> mark(MethodNode methodNode) {
List<MarkedRegion> mrs = markWithDefaultWeavingReg(methodNode);
// automatically compute default weaving region
for(MarkedRegion mr : mrs) {
for (MarkedRegion mr : mrs) {
mr.setWeavingRegion(mr.computeDefaultWeavingRegion(methodNode));
}
return mrs;
}
......
......@@ -7,12 +7,15 @@ import java.util.Set;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import ch.usi.dag.disl.exception.MarkerException;
import ch.usi.dag.disl.snippet.Shadow;
import ch.usi.dag.disl.snippet.Shadow.WeavingRegion;
import ch.usi.dag.disl.snippet.Snippet;
import ch.usi.dag.disl.util.AsmHelper;
public abstract class AbstractMarker implements Marker {
......@@ -75,16 +78,28 @@ public abstract class AbstractMarker implements Marker {
public boolean valid() {
return start != null && ends != null && weavingRegion != null;
}
public WeavingRegion computeDefaultWeavingRegion(MethodNode methodNode) {
// skip branch instruction at the end
AbstractInsnNode wstart = null;
AbstractInsnNode wstart = start;
// can be null - see WeavingRegion for details
List<AbstractInsnNode> wends = null;
// TODO ! skip branch
if (!ends.contains(wstart)) {
wends = new LinkedList<AbstractInsnNode>();
for (AbstractInsnNode instr : ends) {
if (AsmHelper.isBranch(instr)) {
wends.add(instr.getPrevious());
} else {
wends.add(instr);
}
}
}
// compute after throwing region
......@@ -95,6 +110,7 @@ public abstract class AbstractMarker implements Marker {
// get end that is the latest in the method instructions
Set<AbstractInsnNode> endsSet = new HashSet<AbstractInsnNode>(ends);
// get end that is the latest in the method instructions
AbstractInsnNode instr = methodNode.instructions.getLast();
while(instr != null) {
......@@ -104,7 +120,21 @@ public abstract class AbstractMarker implements Marker {
break;
}
instr.getPrevious();
instr = instr.getPrevious();
}
// skip the label nodes which are the end of try-catch blocks
if (afterThrowEnd instanceof LabelNode) {
Set<AbstractInsnNode> tcb_ends = new HashSet<AbstractInsnNode>();
for (TryCatchBlockNode tcb : methodNode.tryCatchBlocks) {
tcb_ends.add(tcb.end);
}
while (tcb_ends.contains(afterThrowEnd)) {
afterThrowEnd = afterThrowEnd.getPrevious();
}
}
return new WeavingRegion(wstart, wends, afterThrowStart,
......
......@@ -7,6 +7,7 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.snippet.Shadow.WeavingRegion;
import ch.usi.dag.disl.util.AsmHelper;
public class AfterInitBodyMarker extends AbstractMarker {
......@@ -28,6 +29,9 @@ public class AfterInitBodyMarker extends AbstractMarker {
}
}
WeavingRegion wregion = region.computeDefaultWeavingRegion(method);
wregion.setAfterThrowEnd(method.instructions.getLast());
region.setWeavingRegion(wregion);
regions.add(region);
return regions;
}
......
......@@ -9,19 +9,19 @@ import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.util.AsmHelper;
import ch.usi.dag.disl.util.BasicBlockCalc;
public class BasicBlockMarker extends AbstractMarker {
public class BasicBlockMarker extends AbstractDWRMarker {
protected boolean isPrecise = false;
@Override
public List<MarkedRegion> mark(MethodNode method) {
public List<MarkedRegion> markWithDefaultWeavingReg(MethodNode methodNode) {
List<MarkedRegion> regions = new LinkedList<MarkedRegion>();
List<AbstractInsnNode> seperators = BasicBlockCalc.getAll(
method.instructions, method.tryCatchBlocks, isPrecise);
methodNode.instructions, methodNode.tryCatchBlocks, isPrecise);
AbstractInsnNode last = AsmHelper.skipVirualInsns(
method.instructions.getLast(), false);
methodNode.instructions.getLast(), false);
seperators.add(last);
......@@ -34,8 +34,8 @@ public class BasicBlockMarker extends AbstractMarker {
end = end.getPrevious();
}
regions.add(new MarkedRegion(start, AsmHelper.skipVirualInsns(
end, false)));
regions.add(new MarkedRegion(start, AsmHelper.skipVirualInsns(end,
false)));
}
return regions;
......
......@@ -7,6 +7,8 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.snippet.Shadow.WeavingRegion;
public class BodyMarker extends AbstractMarker {
@Override
......@@ -25,6 +27,9 @@ public class BodyMarker extends AbstractMarker {
}
}
WeavingRegion wregion = region.computeDefaultWeavingRegion(method);
wregion.setAfterThrowEnd(method.instructions.getLast());
region.setWeavingRegion(wregion);
regions.add(region);
return regions;
}
......
......@@ -10,6 +10,7 @@ import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.exception.MarkerException;
import ch.usi.dag.disl.snippet.Shadow.WeavingRegion;
import ch.usi.dag.disl.util.AsmOpcodes;
public class BytecodeMarker extends AbstractMarker {
......@@ -55,10 +56,13 @@ public class BytecodeMarker extends AbstractMarker {
InsnList ilst = method.instructions;
for (AbstractInsnNode instruction : ilst.toArray()) {
if (searchedInstrNums.contains(instruction.getOpcode())) {
regions.add(new MarkedRegion(instruction, instruction));
MarkedRegion region = new MarkedRegion(instruction, instruction);
region.setWeavingRegion(new WeavingRegion(instruction, null,
instruction, instruction));
regions.add(region);
}
}
......
......@@ -10,10 +10,10 @@ import org.objectweb.asm.tree.TryCatchBlockNode;
import ch.usi.dag.disl.util.AsmHelper;
import ch.usi.dag.disl.util.cfg.CtrlFlowGraph;
public class ExceptionHandlerMarker extends AbstractMarker {
public class ExceptionHandlerMarker extends AbstractDWRMarker {
@Override
public List<MarkedRegion> mark(MethodNode method) {
public List<MarkedRegion> markWithDefaultWeavingReg(MethodNode method) {
List<MarkedRegion> regions = new LinkedList<MarkedRegion>();
......@@ -22,10 +22,10 @@ public class ExceptionHandlerMarker extends AbstractMarker {
cfg.visit(method.instructions.getFirst());
for (TryCatchBlockNode tcb : method.tryCatchBlocks) {
List<AbstractInsnNode> exits = cfg.visit(tcb.handler);
regions.add(new MarkedRegion(AsmHelper.skipVirualInsns(
tcb.handler, true), exits));
regions.add(new MarkedRegion(AsmHelper.skipVirualInsns(tcb.handler,
true), exits));
}
return regions;
......
......@@ -11,39 +11,36 @@ import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.util.Constants;
public class NewObjMarker extends AbstractMarker {
protected boolean isPrecise = false;
public class NewObjMarker extends AbstractDWRMarker {
// NOTE: does not work for arrays
@Override
public List<MarkedRegion> mark(MethodNode method) {
public List<MarkedRegion> markWithDefaultWeavingReg(MethodNode method) {
List<MarkedRegion> regions = new LinkedList<MarkedRegion>();
InsnList ilst = method.instructions;
int invokedNews = 0;
// find invocation of constructor after new instruction
for (AbstractInsnNode instruction : ilst.toArray()) {
// track new instruction
if(instruction.getOpcode() == Opcodes.NEW) {
if (instruction.getOpcode() == Opcodes.NEW) {
++invokedNews;
}
// if it is invoke special and there are new pending
if(instruction.getOpcode() == Opcodes.INVOKESPECIAL
if (instruction.getOpcode() == Opcodes.INVOKESPECIAL
&& invokedNews > 0) {
MethodInsnNode min = (MethodInsnNode) instruction;
if(min.name.equals(Constants.CONSTRUCTOR_NAME)) {
regions.add(
new MarkedRegion(instruction, instruction));
if (min.name.equals(Constants.CONSTRUCTOR_NAME)) {
regions.add(new MarkedRegion(instruction, instruction));
}
}
}
......
......@@ -7,22 +7,29 @@ import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import ch.usi.dag.disl.snippet.Shadow.WeavingRegion;
import ch.usi.dag.disl.util.AsmHelper;
public class TryClauseMarker extends AbstractMarker {
@Override
public List<MarkedRegion> mark(MethodNode method) {
List<MarkedRegion> regions = new LinkedList<MarkedRegion>();
for (TryCatchBlockNode tcb : method.tryCatchBlocks){
for (TryCatchBlockNode tcb : method.tryCatchBlocks) {
AbstractInsnNode start = AsmHelper.skipVirualInsns(tcb.start, true);
AbstractInsnNode end = AsmHelper.skipVirualInsns(tcb.end, false);
regions.add(new MarkedRegion(start, end));
MarkedRegion region = new MarkedRegion(start, end);
region.setWeavingRegion(new WeavingRegion(start,
new LinkedList<AbstractInsnNode>(region.getEnds()), start,
end));
regions.add(region);
}
return regions;
}
......
......@@ -30,6 +30,7 @@ public class Shadow {
// "ends" containing null notifies the weaver about this situation.
private AbstractInsnNode start;
private List<AbstractInsnNode> ends;
private AbstractInsnNode afterThrowStart;
......@@ -60,6 +61,23 @@ public class Shadow {
public AbstractInsnNode getAfterThrowEnd() {
return afterThrowEnd;
}
public void setStart(AbstractInsnNode start) {
this.start = start;
}
public void setEnds(List<AbstractInsnNode> ends) {
this.ends = ends;
}
public void setAfterThrowStart(AbstractInsnNode afterThrowStart) {
this.afterThrowStart = afterThrowStart;
}
public void setAfterThrowEnd(AbstractInsnNode afterThrowEnd) {
this.afterThrowEnd = afterThrowEnd;
}
}
public Shadow(ClassNode classNode, MethodNode methodNode, Snippet snippet,
......
......@@ -28,6 +28,7 @@ import ch.usi.dag.disl.processor.generator.PIResolver;
import ch.usi.dag.disl.snippet.Shadow;
import ch.usi.dag.disl.snippet.Snippet;
import ch.usi.dag.disl.snippet.SnippetCode;
import ch.usi.dag.disl.snippet.Shadow.WeavingRegion;
import ch.usi.dag.disl.staticcontext.generator.SCGenerator;
import ch.usi.dag.disl.util.AsmHelper;
......@@ -210,6 +211,35 @@ public class Weaver {
return new TryCatchBlockNode(startLabel, endLabel, endLabel, null);
}
private static void insert(MethodNode methodNode,
SCGenerator staticInfoHolder, PIResolver piResolver,
WeavingInfo info, Snippet snippet, SnippetCode code, Shadow shadow,
AbstractInsnNode loc) throws DynamicInfoException {
// exception handler will discard the stack and push the
// exception object. Thus, before entering this snippet,
// weaver must backup the stack and restore when exiting
if (code.containsHandledException()
&& info.stackNotEmpty(loc)) {
InsnList backup = info.backupStack(loc,
methodNode.maxLocals);
InsnList restore = info.restoreStack(loc,
methodNode.maxLocals);
methodNode.maxLocals += info.getStackHeight(loc);
methodNode.instructions.insertBefore(loc, backup);
methodNode.instructions.insert(loc, restore);
}
WeavingCode wCode = new WeavingCode(info, methodNode,
code, snippet, shadow, loc);
wCode.transform(staticInfoHolder, piResolver, false);
methodNode.instructions.insert(loc, wCode.getiList());
methodNode.tryCatchBlocks.addAll(wCode.getTCBs());
}
public static void instrument(ClassNode classNode, MethodNode methodNode,
Map<Snippet, List<Shadow>> snippetMarkings,
List<SyntheticLocalVar> syntheticLocalVars,
......@@ -234,38 +264,9 @@ public class Weaver {
if (snippet.getAnnotationClass().equals(Before.class)) {
for (Shadow shadow : shadows) {
AbstractInsnNode loc = info.getWeavingStart().get(
shadow.getRegionStart());
int index = info.getStackStart().get(
shadow.getRegionStart());
// exception handler will discard the stack and push the
// exception object. Thus, before entering this snippet,
// weaver must backup the stack and restore when exiting
if (code.containsHandledException()
&& info.stackNotEmpty(index)) {
InsnList backup = info.backupStack(index,
methodNode.maxLocals);
InsnList restore = info.restoreStack(index,
methodNode.maxLocals);
methodNode.maxLocals += info.getStackHeight(index);
AbstractInsnNode temp = restore.getFirst();
methodNode.instructions.insertBefore(loc, backup);
methodNode.instructions.insertBefore(loc, restore);
loc = temp;
}
WeavingCode wCode = new WeavingCode(info, methodNode, code,
snippet, shadow, index);
wCode.transform(staticInfoHolder, piResolver, false);
methodNode.instructions.insertBefore(loc, wCode.getiList());
methodNode.tryCatchBlocks.addAll(wCode.getTCBs());
AbstractInsnNode loc = shadow.getWeavingRegion().getStart();
insert(methodNode, staticInfoHolder, piResolver, info,
snippet, code, shadow, loc);
}
}
......@@ -273,38 +274,12 @@ public class Weaver {
// after each adjusted exit of a region.
if (snippet.getAnnotationClass().equals(AfterReturning.class)
|| snippet.getAnnotationClass().equals(After.class)) {
for (Shadow region : shadows) {
for (AbstractInsnNode exit : region.getRegionEnds()) {
AbstractInsnNode loc = info.getWeavingEnd().get(exit);
int index = info.getStackEnd().get(exit);
// backup and restore the stack
if (code.containsHandledException()
&& info.stackNotEmpty(index)) {
InsnList backup = info.backupStack(index,
methodNode.maxLocals);
InsnList restore = info.restoreStack(index,
methodNode.maxLocals);
methodNode.maxLocals += info.getStackHeight(index);
AbstractInsnNode temp = backup.getLast();
methodNode.instructions.insert(loc, restore);
methodNode.instructions.insert(loc, backup);
loc = temp;
}
for (Shadow shadow : shadows) {
WeavingCode wCode = new WeavingCode(info, methodNode,
code, snippet, region, index);
wCode.transform(staticInfoHolder, piResolver, false);
for (AbstractInsnNode loc : shadow.getWeavingRegion().getEnds()) {
methodNode.instructions.insert(loc, wCode.getiList());
methodNode.tryCatchBlocks.addAll(wCode.getTCBs());
insert(methodNode, staticInfoHolder, piResolver, info,
snippet, code, shadow, loc);
}
}
}
......@@ -315,34 +290,20 @@ public class Weaver {
if (snippet.getAnnotationClass().equals(AfterThrowing.class)
|| snippet.getAnnotationClass().equals(After.class)) {
for (Shadow region : shadows) {
for (Shadow shadow : shadows) {
WeavingRegion region = shadow.getWeavingRegion();
// after-throwing inserts the snippet once, and marks
// the start and the very end as the scope
AbstractInsnNode last = info.getWeavingThrow().get(region);
int last_index = -1;
for (AbstractInsnNode exit : region.getRegionEnds()) {
int index = info.getStackEnd().get(exit);
if (last_index < index) {
last_index = index;
}
}
if (last_index == -1) {
last_index = info.getStackEnd().get(last);
}
AbstractInsnNode loc = region.getAfterThrowEnd();
WeavingCode wCode = new WeavingCode(info, methodNode, code,
snippet, region, last_index);
snippet, shadow, loc);
wCode.transform(staticInfoHolder, piResolver, true);
// Create a try-catch clause
TryCatchBlockNode tcb = getTryCatchBlock(methodNode, info
.getWeavingStart().get(region.getRegionStart()),
last);
TryCatchBlockNode tcb = getTryCatchBlock(methodNode,
region.getAfterThrowStart(), loc);
methodNode.instructions.insert(tcb.handler,
wCode.getiList());
......
......@@ -51,18 +51,19 @@ public class WeavingCode {
private AbstractInsnNode[] iArray;
private Snippet snippet;
private Shadow shadow;
private int index;
private AbstractInsnNode weavingLoc;
private int maxLocals;
public WeavingCode(WeavingInfo weavingInfo, MethodNode method,
SnippetCode src, Snippet snippet, Shadow shadow, int index) {
SnippetCode src, Snippet snippet, Shadow shadow,
AbstractInsnNode loc) {
this.info = weavingInfo;
this.method = method;
this.code = src.clone();
this.snippet = snippet;
this.shadow = shadow;
this.index = index;
this.weavingLoc = loc;
this.iList = code.getInstructions();
this.iArray = iList.toArray();
......@@ -222,8 +223,8 @@ public class WeavingCode {
preFixDynamicInfoCheck();
Frame<BasicValue> basicframe = info.getBasicFrame(index);
Frame<SourceValue> sourceframe = info.getSourceFrame(index);
Frame<BasicValue> basicframe = info.getBasicFrame(weavingLoc);
Frame<SourceValue> sourceframe = info.getSourceFrame(weavingLoc);
int exceptionslot = INVALID_SLOT;
if (throwing) {
......@@ -562,9 +563,9 @@ public class WeavingCode {
// combine processors into an instruction list
// NOTE that these processors are for the callee
private InsnList procBeforeInvoke(ProcInstance processor, int index) {
private InsnList procBeforeInvoke(ProcInstance processor) {
Frame<SourceValue> frame = info.getSourceFrame(index);
Frame<SourceValue> frame = info.getSourceFrame(weavingLoc);
InsnList ilist = new InsnList();
for (ProcMethodInstance processorMethod : processor.getMethods()) {
......@@ -612,7 +613,7 @@ public class WeavingCode {
if (processor.getProcApplyType() == ArgumentProcessorMode.METHOD_ARGS) {
iList.insert(instr, procInMethod(processor));
} else {
iList.insert(instr, procBeforeInvoke(processor, index));
iList.insert(instr, procBeforeInvoke(processor));
}
}
......
......@@ -2,12 +2,10 @@ package ch.usi.dag.disl.weaver;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
......@@ -18,26 +16,17 @@ import org.objectweb.asm.tree.analysis.BasicValue;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.SourceValue;
import ch.usi.dag.disl.marker.BodyMarker;
import ch.usi.dag.disl.snippet.Shadow;
import ch.usi.dag.disl.snippet.Shadow.WeavingRegion;
import ch.usi.dag.disl.snippet.Snippet;
import ch.usi.dag.disl.util.AsmHelper;
import ch.usi.dag.disl.util.FrameHelper;
import ch.usi.dag.disl.util.cfg.CtrlFlowGraph;
public class WeavingInfo {
private Map<AbstractInsnNode, AbstractInsnNode> weavingStart;
private Map<AbstractInsnNode, AbstractInsnNode> weavingEnd;
private Map<Shadow, AbstractInsnNode> weavingThrow;
private Map<AbstractInsnNode, Integer> stackStart;
private Map<AbstractInsnNode, Integer> stackEnd;
private ArrayList<Snippet> sortedSnippets;
private Frame<BasicValue>[] basicFrames;
private Frame<SourceValue>[] sourceFrames;
private Map<AbstractInsnNode, Frame<BasicValue>> basicFrameMap;
private Map<AbstractInsnNode, Frame<SourceValue>> sourceFrameMap;
private Frame<BasicValue> retFrame;
......@@ -45,13 +34,6 @@ public class WeavingInfo {
public WeavingInfo(ClassNode classNode, MethodNode methodNode,
Map<Snippet, List<Shadow>> snippetMarkings) {
weavingStart = new HashMap<AbstractInsnNode, AbstractInsnNode>();
weavingEnd = new HashMap<AbstractInsnNode, AbstractInsnNode>();
weavingThrow = new HashMap<Shadow, AbstractInsnNode>();
stackStart = new HashMap<AbstractInsnNode, Integer>();
stackEnd = new HashMap<AbstractInsnNode, Integer>();
sortedSnippets = new ArrayList<Snippet>(snippetMarkings.keySet());
Collections.sort(sortedSnippets);
......@@ -62,173 +44,113 @@ public class WeavingInfo {
for (TryCatchBlockNode tcb : methodNode.tryCatchBlocks) {
tcb_ends.add(tcb.end);
}
AbstractInsnNode lastIntruction = instructions.getLast();
// initialize weaving start
for (Snippet snippet : sortedSnippets) {
for (Shadow region : snippetMarkings.get(snippet)) {
AbstractInsnNode start = region.getRegionStart();
if (weavingStart.get(start) == null) {
for (Shadow shadow : snippetMarkings.get(snippet)) {
LabelNode lstart = new LabelNode();
instructions.insertBefore(start, lstart);
weavingStart.put(start, lstart);
}
WeavingRegion region = shadow.getWeavingRegion();
AbstractInsnNode start = region.getStart();
LabelNode lstart = new LabelNode();
instructions.insertBefore(start, lstart);
region.setStart(lstart);
}
}
// first pass: adjust weaving end for one-instruction shadow
for (Snippet snippet : sortedSnippets) {
for (Shadow region : snippetMarkings.get(snippet)) {
AbstractInsnNode last = region.getRegionStart();
for (Shadow shadow : snippetMarkings.get(snippet)) {
for (AbstractInsnNode end : region.getRegionEnds()) {
// initialize weaving end
AbstractInsnNode wend = end;
WeavingRegion region = shadow.getWeavingRegion();
if (AsmHelper.isBranch(wend)) {
wend = wend.getPrevious();
}
if (region.getEnds() == null) {
LabelNode lend = new LabelNode();
instructions.insert(wend, lend);
weavingEnd.put(end, lend);
List<AbstractInsnNode> ends = new LinkedList<AbstractInsnNode>();
// initialize weaving athrow
AbstractInsnNode iter = last;
for (AbstractInsnNode end : shadow.getRegionEnds()) {
while (iter != null) {
iter = iter.getNext();
if (iter == end) {
last = end;
break;
if (AsmHelper.isBranch(end)) {
end = end.getPrevious();
}
}
}
if (snippet.getMarker() instanceof BodyMarker) {
last = lastIntruction;
} else {
if (AsmHelper.isBranch(last)
&& last.getOpcode() != Opcodes.ATHROW) {
last = last.getPrevious();
}
while (tcb_ends.contains(last)) {
last = last.getPrevious();
ends.add(end);
}