Commit 850061fd authored by Lukáš Marek's avatar Lukáš Marek

Removed ExtendThread interface usage

Added tread local inserting - not tested
parent c5285343
...@@ -2,9 +2,8 @@ ...@@ -2,9 +2,8 @@
<classpath> <classpath>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="lib" path="lib/jborat-runtime.jar"/>
<classpathentry kind="lib" path="lib/asm-debug-all-4.0_RC2.jar"/> <classpathentry kind="lib" path="lib/asm-debug-all-4.0_RC2.jar"/>
<classpathentry kind="lib" path="lib/jborat-interface.jar"/> <classpathentry kind="lib" path="lib/jborat-interface.jar"/>
<classpathentry kind="lib" path="lib/jborat.jar"/> <classpathentry kind="lib" path="lib/jborat-runtime.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>
asm.path=lib/asm-debug-all-4.0_RC2.jar asm.path=lib/asm-debug-all-4.0_RC2.jar
jborat.path=lib/jborat.jar
jborat-runtime.path=lib/jborat-runtime.jar jborat-runtime.path=lib/jborat-runtime.jar
jborat-interface.path=lib/jborat-interface.jar jborat-interface.path=lib/jborat-interface.jar
instr.jar.name=dislinstr.jar instr.jar.name=dislinstr.jar
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
<path id="buildpath"> <path id="buildpath">
<pathelement location="${asm.path}"/> <pathelement location="${asm.path}"/>
<pathelement location="${jborat.path}"/>
<pathelement location="${jborat-runtime.path}"/> <pathelement location="${jborat-runtime.path}"/>
<pathelement location="${jborat-interface.path}"/> <pathelement location="${jborat-interface.path}"/>
</path> </path>
......
...@@ -17,6 +17,7 @@ import org.objectweb.asm.tree.MethodNode; ...@@ -17,6 +17,7 @@ import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.dislclass.loader.ClassByteLoader; import ch.usi.dag.disl.dislclass.loader.ClassByteLoader;
import ch.usi.dag.disl.dislclass.localvar.SyntheticLocalVar; 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.parser.ClassParser;
import ch.usi.dag.disl.dislclass.processor.Proc; import ch.usi.dag.disl.dislclass.processor.Proc;
import ch.usi.dag.disl.dislclass.snippet.Snippet; import ch.usi.dag.disl.dislclass.snippet.Snippet;
...@@ -33,6 +34,8 @@ import ch.usi.dag.disl.processor.generator.ProcGenerator; ...@@ -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.ProcInstance;
import ch.usi.dag.disl.processor.generator.ProcMethodInstance; import ch.usi.dag.disl.processor.generator.ProcMethodInstance;
import ch.usi.dag.disl.staticinfo.StaticInfo; 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.disl.weaver.Weaver;
import ch.usi.dag.jborat.agent.Instrumentation; import ch.usi.dag.jborat.agent.Instrumentation;
...@@ -269,16 +272,16 @@ public class DiSL implements Instrumentation { ...@@ -269,16 +272,16 @@ public class DiSL implements Instrumentation {
} }
// this method is thread safe after initialization // 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 // report every exception within our code - don't let anyone mask it
try { try {
if (snippets == null) {
throw new DiSLFatalException("DiSL was not initialized");
}
boolean classChanged = false;
// list of static analysis instances // list of static analysis instances
// validity of an instance is for one instrumented class // validity of an instance is for one instrumented class
...@@ -291,7 +294,34 @@ public class DiSL implements Instrumentation { ...@@ -291,7 +294,34 @@ public class DiSL implements Instrumentation {
classChanged = classChanged || methodChanged; 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<ThreadLocalVar> insertTLVs = new HashSet<ThreadLocalVar>();
// 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) { catch (DiSLException e) {
...@@ -304,8 +334,6 @@ public class DiSL implements Instrumentation { ...@@ -304,8 +334,6 @@ public class DiSL implements Instrumentation {
// signal error // signal error
throw e; throw e;
} }
return classChanged;
} }
private byte[] instrument(ClassReader classReader) throws DiSLException { private byte[] instrument(ClassReader classReader) throws DiSLException {
...@@ -316,27 +344,27 @@ public class DiSL implements Instrumentation { ...@@ -316,27 +344,27 @@ public class DiSL implements Instrumentation {
classReader.accept(classNode, ClassReader.SKIP_DEBUG classReader.accept(classNode, ClassReader.SKIP_DEBUG
| ClassReader.EXPAND_FRAMES); | 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 int requiredMajorVersion = REQUIRED_VERSION & MAJOR_V_MASK;
final int REQUIRED_VERSION = Opcodes.V1_5; int classMajorVersion = insrCN.version & MAJOR_V_MASK;
final int MAJOR_V_MASK = 0xFFFF;
if (classMajorVersion < requiredMajorVersion) {
int requiredMajorVersion = REQUIRED_VERSION & MAJOR_V_MASK; insrCN.version = REQUIRED_VERSION;
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();
} }
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 { public byte[] instrument(byte[] classAsBytes) throws Exception {
......
...@@ -28,7 +28,6 @@ import ch.usi.dag.disl.exception.ParserException; ...@@ -28,7 +28,6 @@ import ch.usi.dag.disl.exception.ParserException;
import ch.usi.dag.disl.util.AsmHelper; import ch.usi.dag.disl.util.AsmHelper;
import ch.usi.dag.disl.util.Constants; import ch.usi.dag.disl.util.Constants;
import ch.usi.dag.disl.util.stack.StackUtil; import ch.usi.dag.disl.util.stack.StackUtil;
import ch.usi.dag.jborat.tools.thread.ExtendThread;
/** /**
* Parses DiSL class with local variables * Parses DiSL class with local variables
...@@ -65,16 +64,11 @@ public abstract class AbstractParser { ...@@ -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) { if (cinit != null && cinit.instructions != null) {
parseInitCodeForSLV(cinit.instructions, localVars.getSyntheticLocals()); parseInitCodeForSLV(cinit.instructions, localVars.getSyntheticLocals());
parseInitCodeForTLV(classNode.name, cinit, localVars.getThreadLocals()); 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<FieldNode> fields) private LocalVars parseLocalVars(String className, List<FieldNode> fields)
......
...@@ -8,6 +8,7 @@ import org.objectweb.asm.Type; ...@@ -8,6 +8,7 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MethodNode;
import ch.usi.dag.disl.exception.ScopeParserException; import ch.usi.dag.disl.exception.ScopeParserException;
import ch.usi.dag.disl.util.Constants;
public class ScopeImpl implements Scope { public class ScopeImpl implements Scope {
...@@ -17,8 +18,6 @@ public class ScopeImpl implements Scope { ...@@ -17,8 +18,6 @@ public class ScopeImpl implements Scope {
private final String METHOD_DELIM = "."; private final String METHOD_DELIM = ".";
private final String PACKAGE_DELIM = "."; private final String PACKAGE_DELIM = ".";
private final String PARAM_MATCH_REST = "..."; private final String PARAM_MATCH_REST = "...";
private final char PACKAGE_INNER_DELIM = '/';
private final char PACKAGE_STD_DELIM = '.';
private String classWildCard; private String classWildCard;
private String methodWildCard; private String methodWildCard;
...@@ -194,7 +193,8 @@ public class ScopeImpl implements Scope { ...@@ -194,7 +193,8 @@ public class ScopeImpl implements Scope {
*/ */
// replace delimiters for matching // 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 if(classWildCard != null
&& ! WildCard.match(className, classWildCard)) { && ! WildCard.match(className, classWildCard)) {
......
...@@ -4,7 +4,8 @@ public class Constants { ...@@ -4,7 +4,8 @@ public class Constants {
final public static String STATIC_ANALYSIS_METHOD_DELIM = "."; 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 = "<init>"; final public static String CONSTRUCTOR_NAME = "<init>";
final public static String STATIC_INIT_NAME = "<clinit>"; final public static String STATIC_INIT_NAME = "<clinit>";
......
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<ThreadLocalVar> threadLocalVars;
public TLVInserter(ClassVisitor cv, Set<ThreadLocalVar> 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());
}
}
}
}
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