Commit 7a3b1658 authored by Lukáš Marek's avatar Lukáš Marek

Added support for skipping to long methods in CodeMerger

parent cc72f368
......@@ -52,9 +52,14 @@ public class DiSL {
private final boolean debug = Boolean.getBoolean(PROP_DEBUG);
// default is that exception handler is inserted
// this is the reason for double negation in assignment
// this is the reason for "double" negation in assignment
private final String PROP_NO_EXCEPT_HANDLER = "disl.noexcepthandler";
private final boolean exceptHandler = ! Boolean.getBoolean(PROP_NO_EXCEPT_HANDLER);
private final boolean exceptHandler =
! Boolean.getBoolean(PROP_NO_EXCEPT_HANDLER);
private final String PROP_SPLIT_LONG_METHODS = "disl.splitmethods";
private final boolean splitLongMethods =
Boolean.getBoolean(PROP_SPLIT_LONG_METHODS);
private final boolean useDynamicBypass;
......@@ -435,7 +440,7 @@ public class DiSL {
// origCN and instrCN are destroyed during the merging
instrCN = CodeMerger.mergeClasses(origCN, instrCN,
instrClass.getChangedMethods());
instrClass.getChangedMethods(), splitLongMethods);
}
// DiSL uses some instructions available only in higher versions
......
......@@ -2,16 +2,15 @@ package ch.usi.dag.disl.coderep;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import ch.usi.dag.disl.localvar.SyntheticLocalVar;
import ch.usi.dag.disl.localvar.ThreadLocalVar;
import ch.usi.dag.disl.util.AsmHelper;
import ch.usi.dag.disl.util.AsmHelper.ClonedCode;
public class Code {
......@@ -78,11 +77,11 @@ public class Code {
public Code clone() {
Map<LabelNode, LabelNode> map =
AsmHelper.createLabelMap(instructions);
// clone code first
ClonedCode cc =
AsmHelper.cloneCode(instructions, tryCatchBlocks);
return new Code(AsmHelper.cloneInsnList(instructions, map),
AsmHelper.cloneTryCatchBlocks(tryCatchBlocks, map),
return new Code(cc.getInstructions(), cc.getTryCatchBlocks(),
new HashSet<SyntheticLocalVar>(referencedSLVs),
new HashSet<ThreadLocalVar>(referencedTLVs),
new HashSet<StaticContextMethod>(staticContexts),
......
......@@ -2,11 +2,9 @@ package ch.usi.dag.disl.processor;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import ch.usi.dag.disl.coderep.Code;
......@@ -14,6 +12,7 @@ import ch.usi.dag.disl.coderep.StaticContextMethod;
import ch.usi.dag.disl.localvar.SyntheticLocalVar;
import ch.usi.dag.disl.localvar.ThreadLocalVar;
import ch.usi.dag.disl.util.AsmHelper;
import ch.usi.dag.disl.util.AsmHelper.ClonedCode;
public class ProcCode extends Code {
......@@ -42,11 +41,11 @@ public class ProcCode extends Code {
public ProcCode clone() {
Map<LabelNode, LabelNode> map =
AsmHelper.createLabelMap(getInstructions());
// clone code first
ClonedCode cc =
AsmHelper.cloneCode(getInstructions(), getTryCatchBlocks());
return new ProcCode(AsmHelper.cloneInsnList(getInstructions(), map),
AsmHelper.cloneTryCatchBlocks(getTryCatchBlocks(), map),
return new ProcCode(cc.getInstructions(), cc.getTryCatchBlocks(),
new HashSet<SyntheticLocalVar>(getReferencedSLVs()),
new HashSet<ThreadLocalVar>(getReferencedTLVs()),
containsHandledException(),
......
......@@ -7,7 +7,6 @@ import java.util.Map;
import java.util.Set;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import ch.usi.dag.disl.coderep.Code;
......@@ -15,6 +14,7 @@ import ch.usi.dag.disl.coderep.StaticContextMethod;
import ch.usi.dag.disl.localvar.SyntheticLocalVar;
import ch.usi.dag.disl.localvar.ThreadLocalVar;
import ch.usi.dag.disl.util.AsmHelper;
import ch.usi.dag.disl.util.AsmHelper.ClonedCode;
public class SnippetCode extends Code {
......@@ -48,11 +48,11 @@ public class SnippetCode extends Code {
public SnippetCode clone() {
Map<LabelNode, LabelNode> map =
AsmHelper.createLabelMap(getInstructions());
// clone code first
ClonedCode cc =
AsmHelper.cloneCode(getInstructions(), getTryCatchBlocks());
return new SnippetCode(AsmHelper.cloneInsnList(getInstructions(), map),
AsmHelper.cloneTryCatchBlocks(getTryCatchBlocks(), map),
return new SnippetCode(cc.getInstructions(), cc.getTryCatchBlocks(),
new HashSet<SyntheticLocalVar>(getReferencedSLVs()),
new HashSet<ThreadLocalVar>(getReferencedTLVs()),
containsHandledException(),
......
......@@ -328,6 +328,40 @@ public abstract class AsmHelper {
}
}
public static class ClonedCode {
private InsnList instructions;
private List<TryCatchBlockNode> tryCatchBlocks;
public ClonedCode(InsnList instructions,
List<TryCatchBlockNode> tryCatchBlocks) {
super();
this.instructions = instructions;
this.tryCatchBlocks = tryCatchBlocks;
}
public InsnList getInstructions() {
return instructions;
}
public List<TryCatchBlockNode> getTryCatchBlocks() {
return tryCatchBlocks;
}
}
public static ClonedCode cloneCode(InsnList instructions, List<TryCatchBlockNode> tryCatchBlocks) {
Map<LabelNode, LabelNode> tmpLblMap =
AsmHelper.createLabelMap(instructions);
InsnList clonedInstructions =
AsmHelper.cloneInsnList(instructions, tmpLblMap);
List<TryCatchBlockNode> clonedTryCatchBlocks =
AsmHelper.cloneTryCatchBlocks(tryCatchBlocks, tmpLblMap);
return new ClonedCode(clonedInstructions, clonedTryCatchBlocks);
}
// makes a clone of an instruction list
public static InsnList cloneInsnList(InsnList src) {
......@@ -335,7 +369,7 @@ public abstract class AsmHelper {
return cloneInsnList(src, map);
}
public static Map<LabelNode, LabelNode> createLabelMap(InsnList src) {
private static Map<LabelNode, LabelNode> createLabelMap(InsnList src) {
Map<LabelNode, LabelNode> map = new HashMap<LabelNode, LabelNode>();
......@@ -350,7 +384,7 @@ public abstract class AsmHelper {
return map;
}
public static InsnList cloneInsnList(InsnList src,
private static InsnList cloneInsnList(InsnList src,
Map<LabelNode, LabelNode> map) {
InsnList dst = new InsnList();
......@@ -377,7 +411,7 @@ public abstract class AsmHelper {
return dst;
}
public static List<TryCatchBlockNode> cloneTryCatchBlocks(
private static List<TryCatchBlockNode> cloneTryCatchBlocks(
List<TryCatchBlockNode> src, Map<LabelNode, LabelNode> map) {
List<TryCatchBlockNode> dst = new LinkedList<TryCatchBlockNode>();
......
package ch.usi.dag.disl.utilinstr.codemerger;
import java.util.List;
import java.util.Set;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.CodeSizeEvaluator;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import ch.usi.dag.disl.dynamicbypass.DynamicBypassCheck;
import ch.usi.dag.disl.exception.DiSLFatalException;
import ch.usi.dag.disl.util.AsmHelper;
import ch.usi.dag.disl.util.AsmHelper.ClonedCode;
public abstract class CodeMerger {
......@@ -20,12 +25,15 @@ public abstract class CodeMerger {
DynamicBypassCheck.class);
private static final String DBCHECK_METHOD = "executeUninstrumented";
private static final String DBCHECK_DESC = "()Z";
private static final int ALLOWED_SIZE = 64 * 1024; // 64KB limit
// NOTE: the originalCN and instrumentedCN will be destroyed in the process
// NOTE: abstract or native methods should not be included in the
// changedMethods list
public static ClassNode mergeClasses(ClassNode originalCN,
ClassNode instrumentedCN, Set<String> changedMethods) {
ClassNode instrumentedCN, Set<String> changedMethods,
boolean splitLongMethods) {
// NOTE: that instrumentedCN can contain added fields
// - has to be returned
......@@ -36,22 +44,17 @@ public abstract class CodeMerger {
}
// no changed method - no merging
if(changedMethods.isEmpty()) {
return instrumentedCN;
}
// TODO jb ! add splitting for to long methods
// - splitting is off by default
// - measure the length of the resulting method and split if necessary
// - ignore clinit - output warning
// - output warning if splitted is to large and ignore
if (changedMethods.isEmpty()) {
return instrumentedCN;
}
// merge methods one by one
for (MethodNode instrMN : instrumentedCN.methods) {
// We will construct the merged method node in the instrumented
// class node
// skip unchanged methods
// skip unchanged methods
if(! changedMethods.contains(instrMN.name + instrMN.desc)) {
continue;
}
......@@ -60,6 +63,15 @@ public abstract class CodeMerger {
instrMN.desc);
InsnList ilist = instrMN.instructions;
List<TryCatchBlockNode> tcblist = instrMN.tryCatchBlocks;
// create copy of the lists for splitting
ClonedCode splitCopy = null;
if(splitLongMethods) {
splitCopy = AsmHelper.cloneCode(ilist, tcblist);
}
// add reference to the original code
LabelNode origCodeL = new LabelNode();
......@@ -68,18 +80,56 @@ public abstract class CodeMerger {
// add original code
ilist.add(origMN.instructions);
// add exception handlers of the original code
instrMN.tryCatchBlocks.addAll(origMN.tryCatchBlocks);
tcblist.addAll(origMN.tryCatchBlocks);
// if the dynamic bypass is activated (non-zero value returned)
// then jump to original code
ilist.insert(new JumpInsnNode(Opcodes.IFNE, origCodeL));
ilist.insert(new MethodInsnNode(Opcodes.INVOKESTATIC,
DBCHECK_CLASS, DBCHECK_METHOD, DBCHECK_DESC));
// calculate the code size and if it is larger then allowed size,
// skip it
CodeSizeEvaluator cse = new CodeSizeEvaluator(null);
instrMN.accept(cse);
if (cse.getMaxSize() > ALLOWED_SIZE) {
if(splitLongMethods) {
// return originally instrumented code back to the instrMN
origMN.instructions = splitCopy.getInstructions();
origMN.tryCatchBlocks = splitCopy.getTryCatchBlocks();
// split methods
splitLongMethods(origMN, instrMN);
}
// insert original code into the instrumented method node
instrMN.instructions = origMN.instructions;
instrMN.tryCatchBlocks = origMN.tryCatchBlocks;
// print error msg
System.err.println("WARNING: code of the method"
+ instrumentedCN.name + "." + instrMN.name
+ "is larger ("
+ cse.getMaxSize()
+ ") then allowed size (" +
+ ALLOWED_SIZE
+ ") - skipping");
}
}
return instrumentedCN;
}
private static void splitLongMethods(MethodNode origMN, MethodNode instrMN) {
// TODO jb ! add splitting for to long methods
// - ignore clinit - output warning
// - output warning if splitted is to large and ignore
}
private static MethodNode getMethodNode(ClassNode cnToSearch,
String methodName, String methodDesc) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment