dislproj: ex2 done

This commit is contained in:
Claudio Maggioni 2023-01-02 15:18:34 +01:00
parent 3eefaaba0a
commit 6274bebf70
4 changed files with 101 additions and 0 deletions

View file

@ -1,4 +1,43 @@
package ex2;
import ch.usi.dag.disl.annotation.After;
import ch.usi.dag.disl.annotation.Before;
import ch.usi.dag.disl.annotation.ThreadLocal;
import ch.usi.dag.disl.dynamiccontext.DynamicContext;
import ch.usi.dag.disl.marker.BodyMarker;
import ch.usi.dag.disl.marker.BytecodeMarker;
public class Instrumentation {
@ThreadLocal
static long readCount;
@ThreadLocal
static long writeCount;
@Before(marker = BytecodeMarker.class, args = "getfield")
static void beforeGetField() {
readCount++;
}
@Before(marker = BytecodeMarker.class, args = "putfield")
static void beforePutField() {
writeCount++;
}
@After(marker = BodyMarker.class,
scope = "void run()",
guard = IsTriviallyThreadGuard.class)
static void onThreadExit() {
Profiler.increment(readCount, writeCount);
}
@After(marker = BodyMarker.class,
scope = "void run()",
guard = IsNotTriviallyThreadGuard.class)
static void onThreadExit(final DynamicContext dc) {
if (Profiler.isThread(dc.getThis().getClass())) {
Profiler.increment(readCount, writeCount);
}
}
}

View file

@ -0,0 +1,12 @@
package ex2;
import ch.usi.dag.disl.annotation.GuardMethod;
import ch.usi.dag.disl.staticcontext.ClassStaticContext;
public class IsNotTriviallyThreadGuard {
@GuardMethod
public static boolean isNotTriviallyThread(final ClassStaticContext csc) {
return !IsTriviallyThreadGuard.isThread(csc);
}
}

View file

@ -0,0 +1,12 @@
package ex2;
import ch.usi.dag.disl.annotation.GuardMethod;
import ch.usi.dag.disl.staticcontext.ClassStaticContext;
public class IsTriviallyThreadGuard {
@GuardMethod
public static boolean isThread(ClassStaticContext csc) {
return csc.getInternalName().equals("java/lang/Thread") ||
csc.getSuperClassInternalName().equals("java/lang/Thread");
}
}

View file

@ -0,0 +1,38 @@
package ex2;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.LongAdder;
public final class Profiler {
// not concurrent on purpose, since the value of the map is computed with a pure function
// on the map key, and thus we don't care if the value is overwritten as a result of a
// race condition
private static final Map<Class<?>, Boolean> isThread = new HashMap<>();
private static final LongAdder reads = new LongAdder();
private static final LongAdder writes = new LongAdder();
static {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.printf("Instance field read access: %d\nInstance field write access: %d\n",
reads.longValue(),
writes.longValue());
}));
}
private Profiler() {
}
public static boolean isThread(final Class<?> clazz) {
return isThread.computeIfAbsent(clazz, Thread.class::isAssignableFrom);
}
public static void increment(long readCount, long writeCount) {
reads.add(readCount);
writes.add(writeCount);
}
}