diff --git a/.classpath b/.classpath
index a12cfef288939ff19d9091290813cc4c7e17ed24..104ebc64b78bf9a235b8ac0213244ad19c8e592a 100644
--- a/.classpath
+++ b/.classpath
@@ -2,9 +2,8 @@
-
-
+
diff --git a/build.properties b/build.properties
index b523c95affbc0e101f41b599481f688746f0e3a3..7013017034e28614b2ab62b7229f58e3c385fd43 100644
--- a/build.properties
+++ b/build.properties
@@ -1,5 +1,4 @@
asm.path=lib/asm-debug-all-4.0_RC2.jar
-jborat.path=lib/jborat.jar
jborat-runtime.path=lib/jborat-runtime.jar
jborat-interface.path=lib/jborat-interface.jar
instr.jar.name=dislinstr.jar
diff --git a/build.xml b/build.xml
index 6732d83cc6c30110e32fffe417a807918c10c00a..6bc0496b9cc2f03fac855696e9af587d7d518c04 100644
--- a/build.xml
+++ b/build.xml
@@ -5,7 +5,6 @@
-
diff --git a/src/ch/usi/dag/disl/DiSL.java b/src/ch/usi/dag/disl/DiSL.java
index d7c0ef0d1495467c7147e3d55bed55a18be35c0e..389a1af958d664d50f09c4ce5c155cf5b3be5dc9 100644
--- a/src/ch/usi/dag/disl/DiSL.java
+++ b/src/ch/usi/dag/disl/DiSL.java
@@ -17,6 +17,7 @@ import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.dislclass.loader.ClassByteLoader;
import ch.usi.dag.disl.dislclass.localvar.SyntheticLocalVar;
+import ch.usi.dag.disl.dislclass.localvar.ThreadLocalVar;
import ch.usi.dag.disl.dislclass.parser.ClassParser;
import ch.usi.dag.disl.dislclass.processor.Proc;
import ch.usi.dag.disl.dislclass.snippet.Snippet;
@@ -33,6 +34,8 @@ import ch.usi.dag.disl.processor.generator.ProcGenerator;
import ch.usi.dag.disl.processor.generator.ProcInstance;
import ch.usi.dag.disl.processor.generator.ProcMethodInstance;
import ch.usi.dag.disl.staticinfo.StaticInfo;
+import ch.usi.dag.disl.util.Constants;
+import ch.usi.dag.disl.weaver.TLVInserter;
import ch.usi.dag.disl.weaver.Weaver;
import ch.usi.dag.jborat.agent.Instrumentation;
@@ -269,16 +272,16 @@ public class DiSL implements Instrumentation {
}
// this method is thread safe after initialization
- private boolean instrument(ClassNode classNode) throws DiSLException {
+ private ClassNode instrument(ClassNode classNode) throws DiSLException {
- if (snippets == null) {
- throw new DiSLFatalException("DiSL was not initialized");
- }
-
- boolean classChanged = false;
-
// report every exception within our code - don't let anyone mask it
try {
+
+ if (snippets == null) {
+ throw new DiSLFatalException("DiSL was not initialized");
+ }
+
+ boolean classChanged = false;
// list of static analysis instances
// validity of an instance is for one instrumented class
@@ -291,7 +294,34 @@ public class DiSL implements Instrumentation {
classChanged = classChanged || methodChanged;
}
-
+
+ String className = classNode.name.replace(
+ Constants.PACKAGE_ASM_DELIM, Constants.PACKAGE_STD_DELIM);
+
+ // instrument thread local fields
+ if(Thread.class.getName().equals(className)) {
+
+ Set insertTLVs = new HashSet();
+
+ // get all thread locals in snippets
+ for(Snippet snippet : snippets) {
+ insertTLVs.addAll(snippet.getCode().getReferencedTLVs());
+ }
+
+ // instrument fields
+ ClassNode cnWithFields = new ClassNode(Opcodes.ASM4);
+ classNode.accept(new TLVInserter(cnWithFields, insertTLVs));
+
+ // replace original code with instrumented one
+ classNode = cnWithFields;
+ classChanged = true;
+ }
+
+ if(classChanged) {
+ return classNode;
+ }
+
+ return null;
}
catch (DiSLException e) {
@@ -304,8 +334,6 @@ public class DiSL implements Instrumentation {
// signal error
throw e;
}
-
- return classChanged;
}
private byte[] instrument(ClassReader classReader) throws DiSLException {
@@ -316,27 +344,27 @@ public class DiSL implements Instrumentation {
classReader.accept(classNode, ClassReader.SKIP_DEBUG
| ClassReader.EXPAND_FRAMES);
+ ClassNode insrCN = instrument(classNode);
+
+ if(insrCN == null) {
+ return null;
+ }
- if(instrument(classNode)) {
+ // DiSL uses some instructions available only in higher versions
+ final int REQUIRED_VERSION = Opcodes.V1_5;
+ final int MAJOR_V_MASK = 0xFFFF;
- // DiSL uses some instructions available only in higher versions
- final int REQUIRED_VERSION = Opcodes.V1_5;
- final int MAJOR_V_MASK = 0xFFFF;
-
- int requiredMajorVersion = REQUIRED_VERSION & MAJOR_V_MASK;
- int classMajorVersion = classNode.version & MAJOR_V_MASK;
-
- if (classMajorVersion < requiredMajorVersion) {
- classNode.version = REQUIRED_VERSION;
- }
-
- // return as bytes
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- classNode.accept(cw);
- return cw.toByteArray();
+ int requiredMajorVersion = REQUIRED_VERSION & MAJOR_V_MASK;
+ int classMajorVersion = insrCN.version & MAJOR_V_MASK;
+
+ if (classMajorVersion < requiredMajorVersion) {
+ insrCN.version = REQUIRED_VERSION;
}
- return null;
+ // return as bytes
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ insrCN.accept(cw);
+ return cw.toByteArray();
}
public byte[] instrument(byte[] classAsBytes) throws Exception {
diff --git a/src/ch/usi/dag/disl/dislclass/parser/AbstractParser.java b/src/ch/usi/dag/disl/dislclass/parser/AbstractParser.java
index fc3b12d4bccd3a74f9f511d05cc3b07a777198a7..56041c73f6b0374a9c40d07e5e21d7189bddd842 100644
--- a/src/ch/usi/dag/disl/dislclass/parser/AbstractParser.java
+++ b/src/ch/usi/dag/disl/dislclass/parser/AbstractParser.java
@@ -28,7 +28,6 @@ import ch.usi.dag.disl.exception.ParserException;
import ch.usi.dag.disl.util.AsmHelper;
import ch.usi.dag.disl.util.Constants;
import ch.usi.dag.disl.util.stack.StackUtil;
-import ch.usi.dag.jborat.tools.thread.ExtendThread;
/**
* Parses DiSL class with local variables
@@ -65,16 +64,11 @@ public abstract class AbstractParser {
}
}
- // parse init code for synthetic local vars and assigns them accordingly
+ // parse init code for local vars and assigns them accordingly
if (cinit != null && cinit.instructions != null) {
parseInitCodeForSLV(cinit.instructions, localVars.getSyntheticLocals());
parseInitCodeForTLV(classNode.name, cinit, localVars.getThreadLocals());
}
-
- for(ThreadLocalVar tlv : localVars.getThreadLocals().values()) {
- ExtendThread.addField(tlv.getName(), tlv.getTypeAsDesc(),
- tlv.getDefaultValue(), tlv.isInheritable());
- }
}
private LocalVars parseLocalVars(String className, List fields)
diff --git a/src/ch/usi/dag/disl/dislclass/snippet/scope/ScopeImpl.java b/src/ch/usi/dag/disl/dislclass/snippet/scope/ScopeImpl.java
index 23734a9fc0acfdc8324ced890833de2052e5cb16..cd6a750d120c5dad0cd92d1e1ecbc3fbeef4f63c 100644
--- a/src/ch/usi/dag/disl/dislclass/snippet/scope/ScopeImpl.java
+++ b/src/ch/usi/dag/disl/dislclass/snippet/scope/ScopeImpl.java
@@ -8,6 +8,7 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.exception.ScopeParserException;
+import ch.usi.dag.disl.util.Constants;
public class ScopeImpl implements Scope {
@@ -17,8 +18,6 @@ public class ScopeImpl implements Scope {
private final String METHOD_DELIM = ".";
private final String PACKAGE_DELIM = ".";
private final String PARAM_MATCH_REST = "...";
- private final char PACKAGE_INNER_DELIM = '/';
- private final char PACKAGE_STD_DELIM = '.';
private String classWildCard;
private String methodWildCard;
@@ -194,7 +193,8 @@ public class ScopeImpl implements Scope {
*/
// replace delimiters for matching
- className = className.replace(PACKAGE_INNER_DELIM, PACKAGE_STD_DELIM);
+ className = className.replace(
+ Constants.PACKAGE_ASM_DELIM, Constants.PACKAGE_STD_DELIM);
if(classWildCard != null
&& ! WildCard.match(className, classWildCard)) {
diff --git a/src/ch/usi/dag/disl/util/Constants.java b/src/ch/usi/dag/disl/util/Constants.java
index 3c6684964bc0cb6fe870a6646f74c3d90a95c981..5edb31ff92d054744d22754d40f63009d591e21a 100644
--- a/src/ch/usi/dag/disl/util/Constants.java
+++ b/src/ch/usi/dag/disl/util/Constants.java
@@ -4,7 +4,8 @@ public class Constants {
final public static String STATIC_ANALYSIS_METHOD_DELIM = ".";
- final public static String INTERNAL_PACKAGE_DELIM = "/";
+ final public static char PACKAGE_ASM_DELIM = '/';
+ final public static char PACKAGE_STD_DELIM = '.';
final public static String CONSTRUCTOR_NAME = "";
final public static String STATIC_INIT_NAME = "";
diff --git a/src/ch/usi/dag/disl/weaver/TLVInserter.java b/src/ch/usi/dag/disl/weaver/TLVInserter.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5c8f21ee78faa489fdbc58564754d12481cf069
--- /dev/null
+++ b/src/ch/usi/dag/disl/weaver/TLVInserter.java
@@ -0,0 +1,122 @@
+package ch.usi.dag.disl.weaver;
+
+import java.util.Set;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.commons.AdviceAdapter;
+
+import ch.usi.dag.disl.dislclass.localvar.ThreadLocalVar;
+import ch.usi.dag.disl.util.Constants;
+
+public final class TLVInserter extends ClassVisitor {
+
+ private final Set threadLocalVars;
+
+ public TLVInserter(ClassVisitor cv, Set tlvs) {
+ super(Opcodes.ASM4, cv);
+ this.threadLocalVars = tlvs;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc,
+ String sig, String[] exceptions) {
+
+ // add field initialization
+ if (Constants.CONSTRUCTOR_NAME.equals(name)) {
+ return new TLVInitializer(super.visitMethod(access, name, desc,
+ sig, exceptions), access, name, desc);
+ }
+
+ return super.visitMethod(access, name, desc, sig, exceptions);
+ }
+
+ @Override
+ public void visitEnd() {
+
+ // add fields
+ for (ThreadLocalVar tlv : threadLocalVars) {
+ super.visitField(Opcodes.ACC_PUBLIC, tlv.getName(),
+ tlv.getTypeAsDesc(), null, null);
+ }
+
+ super.visitEnd();
+ }
+
+ private class TLVInitializer extends AdviceAdapter {
+
+ private TLVInitializer(MethodVisitor mv, int access, String name,
+ String desc) {
+
+ super(Opcodes.ASM4, mv, access, name, desc);
+ }
+
+ @Override
+ protected void onMethodEnter() {
+
+ final String THREAD_CLASS_NAME = Thread.class.getName().replace(
+ Constants.PACKAGE_STD_DELIM, Constants.PACKAGE_ASM_DELIM);
+ final String CURRENTTHREAD_METHOD_NAME = "currentThread";
+ final String CURRENTTHREAD_METHOD_SIG =
+ "()L" + THREAD_CLASS_NAME + ";";
+
+ // for each thread local var insert initialization
+ for (ThreadLocalVar tlv : threadLocalVars) {
+
+ Label getDefaultValue = new Label();
+ Label putValue = new Label();
+
+ // put this on the stack - for putfield
+ visitVarInsn(ALOAD, 0);
+
+ // -- inherited value --
+ if (tlv.isInheritable()) {
+
+ // put current thread instance on the stack
+ visitMethodInsn(INVOKESTATIC,
+ THREAD_CLASS_NAME,
+ CURRENTTHREAD_METHOD_NAME,
+ CURRENTTHREAD_METHOD_SIG);
+
+ // if null, go to "get default value"
+ visitJumpInsn(IFNULL, getDefaultValue);
+
+ // put current thread instance on the stack
+ visitMethodInsn(INVOKESTATIC,
+ THREAD_CLASS_NAME,
+ CURRENTTHREAD_METHOD_NAME,
+ CURRENTTHREAD_METHOD_SIG);
+
+ // get value from parent thread ant put it on the stack
+ visitFieldInsn(GETFIELD, THREAD_CLASS_NAME, tlv.getName(),
+ tlv.getTypeAsDesc());
+
+ // go to "put value"
+ visitJumpInsn(GOTO, putValue);
+ }
+
+ // -- default value --
+ visitLabel(getDefaultValue);
+
+ // put the default value on the stack
+ Object defaultVal = tlv.getDefaultValue();
+ if (defaultVal != null) {
+ // default value
+ visitLdcInsn(defaultVal);
+ }
+ else {
+ // null
+ visitInsn(ACONST_NULL);
+ }
+
+ // -- put value to the field --
+ visitLabel(putValue);
+
+ visitFieldInsn(PUTFIELD, THREAD_CLASS_NAME, tlv.getName(),
+ tlv.getTypeAsDesc());
+ }
+ }
+ }
+}