diff --git a/DiSLProject2022/src-profiler/ex10/CustomMarker.java b/DiSLProject2022/src-profiler/ex10/CustomMarker.java new file mode 100644 index 0000000..be70f6c --- /dev/null +++ b/DiSLProject2022/src-profiler/ex10/CustomMarker.java @@ -0,0 +1,2 @@ +package ex10;public class CustomMarker { +} diff --git a/DiSLProject2022/src-profiler/ex10/CustomStaticContext.java b/DiSLProject2022/src-profiler/ex10/CustomStaticContext.java new file mode 100644 index 0000000..ceb41d2 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex10/CustomStaticContext.java @@ -0,0 +1,2 @@ +package ex10;public class CustomStaticContext { +} diff --git a/DiSLProject2022/src-profiler/ex10/DeclarationGuard.java b/DiSLProject2022/src-profiler/ex10/DeclarationGuard.java new file mode 100644 index 0000000..73320d7 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex10/DeclarationGuard.java @@ -0,0 +1,2 @@ +package ex10;public class DeclarationGuard { +} diff --git a/DiSLProject2022/src-profiler/ex10/MethodDecoder.java b/DiSLProject2022/src-profiler/ex10/MethodDecoder.java new file mode 100644 index 0000000..410753f --- /dev/null +++ b/DiSLProject2022/src-profiler/ex10/MethodDecoder.java @@ -0,0 +1,2 @@ +package ex10;public class MethodDecoder { +} diff --git a/DiSLProject2022/src-profiler/ex2/IsTriviallyThreadGuard.java b/DiSLProject2022/src-profiler/ex2/IsTriviallyThreadGuard.java index 86df968..6684cf7 100644 --- a/DiSLProject2022/src-profiler/ex2/IsTriviallyThreadGuard.java +++ b/DiSLProject2022/src-profiler/ex2/IsTriviallyThreadGuard.java @@ -1,7 +1,6 @@ package ex2; import ch.usi.dag.disl.annotation.GuardMethod; -import ch.usi.dag.disl.dynamiccontext.DynamicContext; import ch.usi.dag.disl.staticcontext.ClassStaticContext; import ch.usi.dag.disl.staticcontext.MethodStaticContext; diff --git a/DiSLProject2022/src-profiler/ex2/Profiler.java b/DiSLProject2022/src-profiler/ex2/Profiler.java index 43fc668..f9cbbb6 100644 --- a/DiSLProject2022/src-profiler/ex2/Profiler.java +++ b/DiSLProject2022/src-profiler/ex2/Profiler.java @@ -1,6 +1,5 @@ package ex2; -import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.LongAdder; @@ -15,9 +14,9 @@ public final class Profiler { static { Runtime.getRuntime().addShutdownHook(new Thread(() -> { - System.out.printf("Instance field read access: %d\nInstance field write access: %d\n", - reads.longValue(), - writes.longValue()); + System.out.printf("Instance field read access: %d\nInstance field write access: %d\n", + reads.longValue(), + writes.longValue()); })); } diff --git a/DiSLProject2022/src-profiler/ex9/Instrumentation.java b/DiSLProject2022/src-profiler/ex9/Instrumentation.java index 79baf7b..86fd27d 100644 --- a/DiSLProject2022/src-profiler/ex9/Instrumentation.java +++ b/DiSLProject2022/src-profiler/ex9/Instrumentation.java @@ -1,4 +1,35 @@ package ex9; +import ch.usi.dag.disl.annotation.Before; +import ch.usi.dag.disl.marker.BodyMarker; +import ch.usi.dag.disl.marker.BytecodeMarker; +import ch.usi.dag.disl.staticcontext.InvocationStaticContext; +import ch.usi.dag.disl.staticcontext.MethodStaticContext; + public class Instrumentation { + + @Before(marker = BytecodeMarker.class, + args = "invokevirtual, invokespecial, invokeinterface, invokestatic", + guard = IsNotConstructorOrStaticGuard.class, + scope = "ex9.MainThread.*") + static void logCall(final InvocationStaticContext isc) { + // this will log calls for all types of methods (including constructors and static initializers). + // However, constructors and static initializers will not be instrumented thanks to the included guard. + // Should calls to constructors and static methods not be instrumented, add the following line: + // + // if (isc.isConstructor()) return; + // + // and remove `invokestatic` from the BytecodeMarker argument list + + Profiler.logCall(Thread.currentThread(), isc.getInternalName()); + } + + @Before(marker = BodyMarker.class, + guard = IsNotConstructorOrStaticGuard.class, + scope = "ex9.MainThread.run") + static void logThreadStart(final MethodStaticContext msc) { + // We separately instrument the Thread.run() method as there is no obvious way to instrument the caller of + // Thread.run(). Hence, we log the call at method start. + Profiler.logCall(Thread.currentThread(), msc.thisMethodFullName()); + } } diff --git a/DiSLProject2022/src-profiler/ex9/IsNotConstructorOrStaticGuard.java b/DiSLProject2022/src-profiler/ex9/IsNotConstructorOrStaticGuard.java new file mode 100644 index 0000000..18b1808 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex9/IsNotConstructorOrStaticGuard.java @@ -0,0 +1,11 @@ +package ex9; + +import ch.usi.dag.disl.annotation.GuardMethod; +import ch.usi.dag.disl.staticcontext.MethodStaticContext; + +public class IsNotConstructorOrStaticGuard { + @GuardMethod + public static boolean isNotConstructorOrStatic(final MethodStaticContext msc) { + return !msc.isMethodStatic() && !msc.isMethodConstructor(); + } +} diff --git a/DiSLProject2022/src-profiler/ex9/Profiler.java b/DiSLProject2022/src-profiler/ex9/Profiler.java new file mode 100644 index 0000000..7157950 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex9/Profiler.java @@ -0,0 +1,31 @@ +package ex9; + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public final class Profiler { + private static final ConcurrentMap> callLog = new ConcurrentHashMap<>(); + + static { + Runtime.getRuntime().addShutdownHook(new Thread(Profiler::print)); + } + + private Profiler() { + } + + public static void logCall(final Thread thread, final String methodName) { + final List list = callLog.computeIfAbsent(thread.getName(), ignored -> new LinkedList<>()); + + // thread safe, as once a thread accesses its own list access to said list is non-concurrent + list.add(methodName); + } + + private static void print() { + for (final String threadName : callLog.keySet()) { + System.out.printf("=== %s ===\n", threadName); + callLog.get(threadName).forEach(System.out::println); + } + } +}