Commit 11504037 authored by Lubomir Bulej's avatar Lubomir Bulej

ExtendThread: take the output directory as an argument.

parent 6081a78c
......@@ -26,9 +26,10 @@
</target>
<target name="prepare-extendedthread" depends="compile-tlvinserter">
<mkdir dir="bin-thread/java/lang" />
<mkdir dir="bin-thread" />
<java fork="true" classname="ch.usi.dag.disl.utilinstr.tlvinserter.ExtendThread">
<classpath refid="buildpath" />
<arg value="${basedir}/bin-thread" />
</java>
<mkdir dir="${build}" />
<jar basedir="bin-thread" destfile="${extendedthread.path}" />
......
package ch.usi.dag.disl.utilinstr.tlvinserter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
......@@ -11,52 +13,76 @@ import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import ch.usi.dag.disl.localvar.ThreadLocalVar;
import ch.usi.dag.disl.util.Constants;
/**
* This is just a utility class for disl compilation
* Extends {@link Thread} with a "bypass" variable and writes its new bytecode
* to a class file in a given directory. This is required to compile DiSL bypass
* code, which checks the state of the "bypass" variable.
*/
public final class ExtendThread {
private static final String THREAD_BIN_DIR = "./bin-thread/";
public static void main(String[] args) throws Exception {
Class<?> tc = Thread.class;
// get thread class as resource
InputStream tis = tc.getResourceAsStream("Thread.class");
// prepare dynamic bypass variable
ThreadLocalVar tlv = new ThreadLocalVar(null, "bypass",
Type.getType(boolean.class), false);
tlv.setDefaultValue(0);
public static void main (final String ... args) throws Exception {
if (args.length < 1) {
System.err.println ("usage: ExtendThread <output-directory>");
System.exit (1);
}
final File outputDir = new File (args [0]);
if (!outputDir.isDirectory ()) {
System.err.printf ("error: %s does not exist or is not a directory!\n", outputDir);
System.exit (1);
}
//
// Define a thread-local non-inheritable boolean variable named
// "bypass", with a default value of false,
//
final ThreadLocalVar tlBypass = new ThreadLocalVar (
null, "bypass", Type.getType (boolean.class), false
);
tlBypass.setDefaultValue (0);
//
// Extend Thread with a "bypass" variable and dump the new Thread
// bytecode into given directory.
//
__writeThread (outputDir, __extendThread (tlBypass));
}
// prepare Set with dynamic bypass
Set<ThreadLocalVar> tlvs = new HashSet<ThreadLocalVar>();
tlvs.add(tlv);
// parse Thread in ASM
ClassReader cr = new ClassReader(tis);
ClassWriter cw = new ClassWriter(cr, 0);
private static byte [] __extendThread (
final ThreadLocalVar ... tlvs
) throws IOException {
final InputStream is = Thread.class.getResourceAsStream ("Thread.class");
final ClassReader cr = new ClassReader (is);
final ClassWriter cw = new ClassWriter (cr, 0);
final Set <ThreadLocalVar> vars = new HashSet <ThreadLocalVar> (Arrays.asList (tlvs));
cr.accept (new TLVInserter (cw, vars), 0);
return cw.toByteArray ();
}
// put dynamic bypass into Thread using TLVInserter
cr.accept(new TLVInserter(cw, tlvs), 0);
// prepare Thread file name
String threadFileName = tc.getName();
threadFileName = threadFileName.replace(
Constants.PACKAGE_STD_DELIM, Constants.PACKAGE_INTERN_DELIM);
threadFileName += Constants.CLASS_EXT;
private static void __writeThread (
final File baseDir, final byte [] bytes
) throws IOException {
final Class <Thread> tc = Thread.class;
final String pkgName = tc.getPackage ().getName ();
final String dirName = pkgName.replace ('.', File.separatorChar);
// output Thread code into special thread bin directory
write(THREAD_BIN_DIR + threadFileName, cw.toByteArray());
}
final File outputDir = new File (baseDir, dirName);
outputDir.mkdirs ();
final String fileName = String.format ("%s.class", tc.getSimpleName ());
final File outputFile = new File (outputDir, fileName);
private static void write(String outputFile, byte[] data) throws IOException {
FileOutputStream fos = new FileOutputStream(outputFile);
fos.write(data);
fos.close();
final FileOutputStream fos = new FileOutputStream (outputFile);
try {
fos.write (bytes);
} finally {
fos.close ();
}
}
}
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