Commit 6a8cc0a3 authored by Lukáš Marek's avatar Lukáš Marek

Removed unneeded extendThread target from test/build.xml

Removed unneeded Thread_jborat.jar
Added jborat in rev. 95 with custom extend thread interface
DiSL now supports custom extend thread interface for thread locals
Removed startutil - no longer needed
parent cd779908
......@@ -2,9 +2,9 @@
<classpath>
<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="lib" path="lib/jborat-agent.jar"/>
<classpathentry kind="lib" path="lib/jborat-runtime.jar"/>
<classpathentry kind="lib" path="lib/jborat.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.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
asm.path=lib/asm-debug-all-4.0_RC2.jar
jborat.path=lib/jborat-interface.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
......@@ -7,6 +7,7 @@
<pathelement location="${asm.path}"/>
<pathelement location="${jborat.path}"/>
<pathelement location="${jborat-runtime.path}"/>
<pathelement location="${jborat-interface.path}"/>
</path>
<target name="package" depends="compile">
......
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
package ch.usi.dag.disl.dislclass.localvar;
import org.objectweb.asm.Type;
public abstract class AbstractLocalVar {
public final static String NAME_DELIM = ".";
private String className;
private String fieldName;
private Type type;
public AbstractLocalVar(String className, String fieldName) {
public AbstractLocalVar(String className, String fieldName, Type type) {
super();
this.className = className;
this.fieldName = fieldName;
this.type = type;
}
public String getID() {
......@@ -24,4 +28,8 @@ public abstract class AbstractLocalVar {
public String getName() {
return fieldName;
}
public Type getType() {
return type;
}
}
......@@ -7,22 +7,16 @@ import ch.usi.dag.disl.dislclass.annotation.SyntheticLocal;
public class SyntheticLocalVar extends AbstractLocalVar {
private Type type;
private SyntheticLocal.Initialize initialize;
private InsnList initASMCode;
public SyntheticLocalVar(String className, String fieldName, Type type,
SyntheticLocal.Initialize initialize) {
super(className, fieldName);
this.type = type;
super(className, fieldName, type);
this.initialize = initialize;
}
public Type getType() {
return type;
}
public SyntheticLocal.Initialize getInitialize() {
return initialize;
}
......
package ch.usi.dag.disl.dislclass.localvar;
import org.objectweb.asm.Type;
public class ThreadLocalVar extends AbstractLocalVar {
public ThreadLocalVar(String className, String fieldName) {
private Object defaultValue;
private boolean inheritable;
public ThreadLocalVar(String className, String fieldName, Type type,
boolean inheritable) {
super(className, fieldName, type);
this.inheritable = inheritable;
}
public String getTypeAsDesc() {
return getType().getDescriptor();
}
public Object getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(Object defaultValue) {
this.defaultValue = defaultValue;
}
super(className, fieldName);
public boolean isInheritable() {
return inheritable;
}
}
......@@ -2,6 +2,7 @@ package ch.usi.dag.disl.dislclass.parser;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
......@@ -11,7 +12,13 @@ import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.SourceValue;
import ch.usi.dag.disl.dislclass.annotation.SyntheticLocal;
import ch.usi.dag.disl.dislclass.localvar.LocalVars;
......@@ -20,6 +27,8 @@ import ch.usi.dag.disl.dislclass.localvar.ThreadLocalVar;
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
......@@ -46,19 +55,25 @@ public abstract class AbstractParser {
allLocalVars.putAll(localVars);
// get static initialization code
InsnList origInitCodeIL = null;
MethodNode cinit = null;
for (MethodNode method : classNode.methods) {
// get the code
if (method.name.equals(Constants.STATIC_INIT_NAME)) {
origInitCodeIL = method.instructions;
cinit = method;
break;
}
}
// parse init code for synthetic local vars and assigns them accordingly
if (origInitCodeIL != null) {
parseInitCodeForSLV(origInitCodeIL, localVars.getSyntheticLocals());
if (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());
}
}
......@@ -118,6 +133,10 @@ public abstract class AbstractParser {
return result;
}
private static class TLAnnotationData {
public boolean inheritable = false; // default
}
private ThreadLocalVar parseThreadLocal(String className, FieldNode field,
AnnotationNode annotation) throws ParserException {
......@@ -127,10 +146,15 @@ public abstract class AbstractParser {
+ " declared as ThreadLocal but is not static");
}
// TODO ! add thread local parsing
// parse annotation
TLAnnotationData tlad = new TLAnnotationData();
ParserHelper.parseAnnotation(tlad, annotation);
// here we can ignore annotation parsing - already done by start utility
return new ThreadLocalVar(className, field.name);
Type fieldType = Type.getType(field.desc);
// default value will be set later on
return new ThreadLocalVar(className, field.name, fieldType,
tlad.inheritable);
}
private static class SLAnnotaionData {
......@@ -234,4 +258,132 @@ public abstract class AbstractParser {
return dst;
}
private void parseInitCodeForTLV(String className, MethodNode cinitMethod,
Map<String, ThreadLocalVar> tlvs) throws ParserException {
// crate analyzer
Analyzer<SourceValue> analyzer = StackUtil.getSourceAnalyzer();
try {
analyzer.analyze(className, cinitMethod);
} catch (AnalyzerException e) {
throw new ParserException(e);
}
Frame<SourceValue>[] frames = analyzer.getFrames();
// analyze instructions in each frame
// one frame should cover one field initialization
for (int i = 0; i < frames.length; i++) {
AbstractInsnNode instr = cinitMethod.instructions.get(i);
// if the last instruction puts some value into the field...
if (instr.getOpcode() != Opcodes.PUTSTATIC) {
continue;
}
FieldInsnNode fin = (FieldInsnNode) instr;
ThreadLocalVar tlv =
tlvs.get(className + ThreadLocalVar.NAME_DELIM + fin.name);
// ... and the field is thread local var
if (tlv == null) {
continue;
}
// get the instruction that put the field value on the stack
Set<AbstractInsnNode> sources = frames[i].getStack(frames[i]
.getStackSize() - 1).insns;
if (sources.size() != 1) {
throw new ParserException("Thread local variable "
+ tlv.getName()
+ " can be initialized only by single constant");
}
AbstractInsnNode source = sources.iterator().next();
// analyze oppcode and set the proper default value
switch (source.getOpcode()) {
// not supported
// case Opcodes.ACONST_NULL:
// var.setDefaultValue(null);
// break;
case Opcodes.ICONST_M1:
tlv.setDefaultValue(-1);
break;
case Opcodes.ICONST_0:
if (fin.desc.equals("Z")) {
tlv.setDefaultValue(false);
} else {
tlv.setDefaultValue(0);
}
break;
case Opcodes.LCONST_0:
tlv.setDefaultValue(0);
break;
case Opcodes.FCONST_0:
case Opcodes.DCONST_0:
tlv.setDefaultValue(0.0);
break;
case Opcodes.ICONST_1:
if (fin.desc.equals("Z")) {
tlv.setDefaultValue(true);
} else {
tlv.setDefaultValue(1);
}
break;
case Opcodes.LCONST_1:
tlv.setDefaultValue(1);
break;
case Opcodes.FCONST_1:
case Opcodes.DCONST_1:
tlv.setDefaultValue(1.0);
break;
case Opcodes.ICONST_2:
case Opcodes.FCONST_2:
tlv.setDefaultValue(2);
break;
case Opcodes.ICONST_3:
tlv.setDefaultValue(3);
break;
case Opcodes.ICONST_4:
tlv.setDefaultValue(4);
break;
case Opcodes.ICONST_5:
tlv.setDefaultValue(5);
break;
case Opcodes.BIPUSH:
case Opcodes.SIPUSH:
tlv.setDefaultValue(((IntInsnNode) source).operand);
break;
case Opcodes.LDC:
tlv.setDefaultValue(((LdcInsnNode) source).cst);
break;
default:
throw new ParserException("Initialization is not"
+ " defined for thread local variable " + tlv.getName());
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/DiSL"/>
<classpathentry kind="lib" path="/DiSL/lib/asm-debug-all-4.0_RC2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>DiSL-start</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
package ch.usi.dag.disl.startutil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.SourceValue;
import ch.usi.dag.disl.dislclass.parser.ParserHelper;
import ch.usi.dag.disl.util.stack.StackUtil;
public class ClassParser {
private static final String STATIC_INIT_METHOD = "<clinit>";
public static List<ThreadLocalVar> usedTLV(File dislClassFile)
throws FileNotFoundException, IOException, ClassParserException {
ClassReader cr = new ClassReader(new FileInputStream(dislClassFile));
ClassNode classNode = new ClassNode();
cr.accept(classNode, 0);
// parse tlvs
List<ThreadLocalVar> tlvs =
parseFields(classNode.name, classNode.fields);
// set default values
setTLVDefaultValues(classNode, tlvs);
return tlvs;
}
private static List<ThreadLocalVar> parseFields(String name,
List<FieldNode> fields) throws ClassParserException {
List<ThreadLocalVar> result = new LinkedList<ThreadLocalVar>();
for (FieldNode field : fields) {
// skip unannotated fields
if (field.invisibleAnnotations == null) {
continue;
}
// skip fields with more then one annotation
if (field.invisibleAnnotations.size() > 1) {
continue;
}
AnnotationNode annotation =
(AnnotationNode) field.invisibleAnnotations.get(0);
Type annotationType = Type.getType(annotation.desc);
// skip, it it is not thread local
if (! annotationType.equals(Type
.getType(ch.usi.dag.disl.dislclass.annotation.ThreadLocal.class))) {
continue;
}
ThreadLocalVar tlv = parseThreadLocal(field, annotation);
result.add(tlv);
}
return result;
}
private static class TLAnnotationData {
public boolean inheritable = false; // default
}
private static ThreadLocalVar parseThreadLocal(FieldNode field,
AnnotationNode annotation) throws ClassParserException {
// check if field is static
if ((field.access & Opcodes.ACC_STATIC) == 0) {
throw new ClassParserException("Field " + field.name
+ " declared as ThreadLocal but is not static");
}
// parse annotation
TLAnnotationData tlad = new TLAnnotationData();
ParserHelper.parseAnnotation(tlad, annotation);
Type fieldType = Type.getType(field.desc);
// default value will be set later on
return new ThreadLocalVar(field.name, fieldType, tlad.inheritable);
}
private static void setTLVDefaultValues(ClassNode classNode,
List<ThreadLocalVar> tlvs) throws ClassParserException {
MethodNode methodNode = null;
// search for static init
for (MethodNode method : classNode.methods) {
if (method.name.equals(STATIC_INIT_METHOD)) {
methodNode = method;
break;
}
}
if (methodNode == null) {
return;
}
// crate analyzer
Analyzer<SourceValue> analyzer = StackUtil.getSourceAnalyzer();
try {
analyzer.analyze(classNode.name, methodNode);
} catch (AnalyzerException e) {
return;
}
Frame<SourceValue>[] frames = analyzer.getFrames();
// for each thread local variable
for (ThreadLocalVar var : tlvs) {
// analyze instructions in each frame
// one frame should cover one field initialization
for (int i = 0; i < frames.length; i++) {
AbstractInsnNode instr = methodNode.instructions.get(i);
// if the last instruction puts some value into the field
if (instr.getOpcode() != Opcodes.PUTSTATIC) {
continue;
}
FieldInsnNode fin = (FieldInsnNode) instr;
// and the field is our thread local var
if (!fin.name.equals(var.getName())) {
continue;
}
// get the instruction that put the field value on the stack
Set<AbstractInsnNode> sources = frames[i].getStack(frames[i]
.getStackSize() - 1).insns;
if (sources.size() != 1) {
throw new ClassParserException("Thread local variable "
+ var.getName()
+ " can be initialized only by single constant");
}
AbstractInsnNode source = sources.iterator().next();
// analyze oppcode and set the proper default value
switch (source.getOpcode()) {
// not supported
//case Opcodes.ACONST_NULL:
// var.setDefaultValue("null");
// break;
case Opcodes.ICONST_M1:
var.setDefaultValue("-1");
break;
case Opcodes.ICONST_0:
if (fin.desc.equals("Z")) {
var.setDefaultValue("false");
} else {
var.setDefaultValue("0");
}
break;
case Opcodes.LCONST_0:
var.setDefaultValue("0");
break;
case Opcodes.FCONST_0:
case Opcodes.DCONST_0:
var.setDefaultValue("0.0");
break;
case Opcodes.ICONST_1:
if (fin.desc.equals("Z")) {
var.setDefaultValue("true");
} else {
var.setDefaultValue("1");
}
break;
case Opcodes.LCONST_1:
var.setDefaultValue("1");
break;
case Opcodes.FCONST_1:
case Opcodes.DCONST_1:
var.setDefaultValue("1.0");
break;
case Opcodes.ICONST_2:
case Opcodes.FCONST_2:
var.setDefaultValue("2");
break;
case Opcodes.ICONST_3:
var.setDefaultValue("3");
break;
case Opcodes.ICONST_4:
var.setDefaultValue("4");
break;
case Opcodes.ICONST_5:
var.setDefaultValue("5");
break;
case Opcodes.BIPUSH:
case Opcodes.SIPUSH:
var.setDefaultValue(Integer.toString(
((IntInsnNode) source).operand));
break;
case Opcodes.LDC:
var.setDefaultValue(((LdcInsnNode) source).cst.toString());
break;
default:
throw new ClassParserException("Initialization is not"
+ " defined for thread local variable "
+ var.getName());
}
}
}
}
}
package ch.usi.dag.disl.startutil;
public class ClassParserException extends Exception {
private static final long serialVersionUID = -6464336317649984655L;
public ClassParserException() {
super();
}
public ClassParserException(String message, Throwable cause) {
super(message, cause);
}
public ClassParserException(String message) {
super(message);
}
public ClassParserException(Throwable cause) {
super(cause);
}
}
package ch.usi.dag.disl.startutil;
import java.io.File;
import java.io.FileInputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
public class DiSLStartUtil {
private static final String DISL_PROPERTIES = "DiSL.properties";
public static void main(String[] args) {
try {
// TODO create more general tool - ant task?
// a) creates jar from DiSL classes + support classes
// - outputs jar file and within manifest with DiSL classes
// b1) creates thread local jar using jborat util
// b2) runs jborat + disl
// gather all DiSL classes
List<String> dislClasses = new LinkedList<String>();
int i = 0;
while (i < args.length) {
dislClasses.add(args[i]);
++i;
}
// parse thread local vars
List<ThreadLocalVar> tlv = new LinkedList<ThreadLocalVar>();
for (String dislClass : dislClasses) {
File dcFile = new File(dislClass);
tlv.addAll(ClassParser.usedTLV(dcFile));
}
// read properties file
Properties properties = new Properties();
properties.load(new FileInputStream(DISL_PROPERTIES));
// TODO ! use extend thread utility
// - usage of dynamic bypass is specified in DISL_PROPERTIES file
// - as additional fields
// - also other needed consts there
} catch (Throwable e) {
e.printStackTrace();
}