From 850061fd8f03988ff5d32db859e82f95b5374f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Marek?= Date: Fri, 16 Sep 2011 13:40:49 +0000 Subject: [PATCH] Removed ExtendThread interface usage Added tread local inserting - not tested --- .classpath | 3 +- build.properties | 1 - build.xml | 1 - src/ch/usi/dag/disl/DiSL.java | 82 ++++++++---- .../disl/dislclass/parser/AbstractParser.java | 8 +- .../dislclass/snippet/scope/ScopeImpl.java | 6 +- src/ch/usi/dag/disl/util/Constants.java | 3 +- src/ch/usi/dag/disl/weaver/TLVInserter.java | 122 ++++++++++++++++++ 8 files changed, 184 insertions(+), 42 deletions(-) create mode 100644 src/ch/usi/dag/disl/weaver/TLVInserter.java diff --git a/.classpath b/.classpath index a12cfef2..104ebc64 100644 --- a/.classpath +++ b/.classpath @@ -2,9 +2,8 @@ - - + diff --git a/build.properties b/build.properties index b523c95a..70130170 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 6732d83c..6bc0496b 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 d7c0ef0d..389a1af9 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 fc3b12d4..56041c73 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 23734a9f..cd6a750d 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 3c668496..5edb31ff 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 00000000..a5c8f21e --- /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()); + } + } + } +} -- GitLab