From 32b063052f6ad7b53812bc901dc0399f9e840134 Mon Sep 17 00:00:00 2001 From: tripparsugo Date: Mon, 9 Jan 2023 08:01:15 +0100 Subject: [PATCH] Some bugs fixed --- .../src-profiler/ex4/Instrumentation.java | 10 +++ .../src-profiler/ex4/Profiler.java | 29 ++++++++ .../src-profiler/ex5/Instrumentation.java | 17 +++++ .../src-profiler/ex5/Profiler.java | 31 +++++++++ .../src-profiler/ex6/Instrumentation.java | 28 ++++++++ .../ex6/IsLoopInstructionGuard.java | 10 +++ .../src-profiler/ex6/LoopContext.java | 21 ++++++ .../src-profiler/ex6/Profiler.java | 29 ++++++++ .../src-profiler/ex7/Instrumentation.java | 31 +++++++++ .../ex7/IsSynchronizedMethodGuard.java | 11 ++++ .../src-profiler/ex7/Profiler.java | 66 +++++++++++++++++++ .../src-profiler/ex8/Instrumentation.java | 14 ++++ .../src-profiler/ex8/InvocationContext.java | 11 ++++ .../src-profiler/ex8/InvokeType.java | 33 ++++++++++ .../src-profiler/ex8/Profiler.java | 55 ++++++++++++++++ 15 files changed, 396 insertions(+) create mode 100644 DiSLProject2022/src-profiler/ex4/Profiler.java create mode 100644 DiSLProject2022/src-profiler/ex5/Profiler.java create mode 100644 DiSLProject2022/src-profiler/ex6/IsLoopInstructionGuard.java create mode 100644 DiSLProject2022/src-profiler/ex6/LoopContext.java create mode 100644 DiSLProject2022/src-profiler/ex6/Profiler.java create mode 100644 DiSLProject2022/src-profiler/ex7/IsSynchronizedMethodGuard.java create mode 100644 DiSLProject2022/src-profiler/ex7/Profiler.java create mode 100644 DiSLProject2022/src-profiler/ex8/InvocationContext.java create mode 100644 DiSLProject2022/src-profiler/ex8/InvokeType.java create mode 100644 DiSLProject2022/src-profiler/ex8/Profiler.java diff --git a/DiSLProject2022/src-profiler/ex4/Instrumentation.java b/DiSLProject2022/src-profiler/ex4/Instrumentation.java index 4bd3be4..99d8950 100644 --- a/DiSLProject2022/src-profiler/ex4/Instrumentation.java +++ b/DiSLProject2022/src-profiler/ex4/Instrumentation.java @@ -1,4 +1,14 @@ package ex4; +import ch.usi.dag.disl.annotation.Before; +import ch.usi.dag.disl.dynamiccontext.DynamicContext; +import ch.usi.dag.disl.marker.BytecodeMarker; + public class Instrumentation { + @Before(marker = BytecodeMarker.class, args = "athrow", scope = "ex4.MainThread.*") + static void beforeThrowing(final DynamicContext dc) { + final Throwable throwableThrown = dc.getStackValue(0, Throwable.class); + Profiler.countException(throwableThrown); + } + } diff --git a/DiSLProject2022/src-profiler/ex4/Profiler.java b/DiSLProject2022/src-profiler/ex4/Profiler.java new file mode 100644 index 0000000..d5712d9 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex4/Profiler.java @@ -0,0 +1,29 @@ +package ex4; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.LongAdder; + +public final class Profiler { + + private static final Map exceptionNameToCount = new ConcurrentHashMap<>(); + + static { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + for (final var entry : exceptionNameToCount.entrySet()) { + System.out.printf("Exception: %s - occurrences: %d%n", entry.getKey(), entry.getValue().intValue()); + } + })); + } + + private Profiler() { + } + + public static void countException(Throwable e) { + final String exceptionName = e.getClass().getName(); + exceptionNameToCount.computeIfAbsent(exceptionName, k -> new LongAdder()); + exceptionNameToCount.get(exceptionName).increment(); + } + + +} diff --git a/DiSLProject2022/src-profiler/ex5/Instrumentation.java b/DiSLProject2022/src-profiler/ex5/Instrumentation.java index 6ef7782..3ed21f8 100644 --- a/DiSLProject2022/src-profiler/ex5/Instrumentation.java +++ b/DiSLProject2022/src-profiler/ex5/Instrumentation.java @@ -1,4 +1,21 @@ package ex5; +import ch.usi.dag.disl.annotation.Before; +import ch.usi.dag.disl.dynamiccontext.DynamicContext; +import ch.usi.dag.disl.marker.BodyMarker; +import ch.usi.dag.disl.marker.BytecodeMarker; +import ch.usi.dag.disl.staticcontext.MethodStaticContext; +//import jdk.internal.misc.Unsafe; + public class Instrumentation { + @Before(marker = BytecodeMarker.class, args = "new,newarray,anewarray,multianewarray", scope = "*") + static void handleSafeAllocation() { + Profiler.addSafeAllocation(); + } + +// TODO why is it always 0 + @Before(marker = BodyMarker.class, scope = "jdk.internal.misc.Unsafe.allocateInstance") + static void handleUnsafeAllocation() { + Profiler.addUnsafeAllocation(); + } } diff --git a/DiSLProject2022/src-profiler/ex5/Profiler.java b/DiSLProject2022/src-profiler/ex5/Profiler.java new file mode 100644 index 0000000..4c1e4b7 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex5/Profiler.java @@ -0,0 +1,31 @@ +package ex5; + +import java.util.concurrent.atomic.LongAdder; + +public final class Profiler { + + private static final LongAdder safeAllocations = new LongAdder(); + private static final LongAdder unsafeAllocation = new LongAdder(); + + static { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + System.out.printf("Safe allocation: %d%n", safeAllocations.intValue()); + System.out.printf("Unsafe allocation: %d%n", unsafeAllocation.intValue()); + })); + } + + private Profiler() { + } + + + public static void addSafeAllocation(){ + safeAllocations.increment(); + } + + public static void addUnsafeAllocation(){ + unsafeAllocation.increment(); + } + + + +} diff --git a/DiSLProject2022/src-profiler/ex6/Instrumentation.java b/DiSLProject2022/src-profiler/ex6/Instrumentation.java index 6857793..e9e90da 100644 --- a/DiSLProject2022/src-profiler/ex6/Instrumentation.java +++ b/DiSLProject2022/src-profiler/ex6/Instrumentation.java @@ -1,4 +1,32 @@ package ex6; +import ch.usi.dag.disl.annotation.Before; +import ch.usi.dag.disl.marker.BytecodeMarker; +import ch.usi.dag.disl.staticcontext.MethodStaticContext; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.util.Printer; + public class Instrumentation { + + final static String[] BRANCH_OP_NAMES = new String[]{ + Printer.OPCODES[Opcodes.GOTO], + Printer.OPCODES[Opcodes.IF_ACMPEQ], + Printer.OPCODES[Opcodes.IF_ACMPNE], + Printer.OPCODES[Opcodes.IF_ICMPEQ], + Printer.OPCODES[Opcodes.IF_ICMPGE], + Printer.OPCODES[Opcodes.IF_ICMPLE], + Printer.OPCODES[Opcodes.IF_ICMPGT], + Printer.OPCODES[Opcodes.IF_ICMPLT], + Printer.OPCODES[Opcodes.IF_ICMPNE] + }; +// static final String BRANCH_OP_NAMES_STRING = String.join(",", BRANCH_OP_NAMES); + static final String BRANCH_OP_NAMES_STRING = "GOTO,IF_ACMPEQ,IF_ACMPNE,IF_ICMPEQ,IF_ICMPGE,IF_ICMPLE,IF_ICMPGT,IF_ICMPLT,IF_ICMPNE"; + + + @Before(marker = BytecodeMarker.class, args = BRANCH_OP_NAMES_STRING, scope = "ex6.MainThread.*", guard = IsLoopInstructionGuard.class) + static void handleLoopInstruction(MethodStaticContext mc) { + final String methodName = mc.thisMethodFullName(); + Profiler.countLoop(methodName); + + } } diff --git a/DiSLProject2022/src-profiler/ex6/IsLoopInstructionGuard.java b/DiSLProject2022/src-profiler/ex6/IsLoopInstructionGuard.java new file mode 100644 index 0000000..d2aecf2 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex6/IsLoopInstructionGuard.java @@ -0,0 +1,10 @@ +package ex6; + +import ch.usi.dag.disl.annotation.GuardMethod; + +public class IsLoopInstructionGuard { + @GuardMethod + public static boolean isLoopInstruction(LoopContext lc) { + return lc.isLoopInstruction(); + } +} diff --git a/DiSLProject2022/src-profiler/ex6/LoopContext.java b/DiSLProject2022/src-profiler/ex6/LoopContext.java new file mode 100644 index 0000000..9ab64ac --- /dev/null +++ b/DiSLProject2022/src-profiler/ex6/LoopContext.java @@ -0,0 +1,21 @@ +package ex6; + +import ch.usi.dag.disl.staticcontext.AbstractStaticContext; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.JumpInsnNode; + +public class LoopContext extends AbstractStaticContext { +// considered loop instruction if loop footer. + public boolean isLoopInstruction() { + final InsnList insList = staticContextData.getMethodNode().instructions; + final AbstractInsnNode ins = staticContextData.getRegionStart(); + if (ins instanceof final JumpInsnNode jIns) { + final int nextInsOffset = insList.indexOf(jIns.label); + final int insOffset = insList.indexOf(jIns); + return nextInsOffset < insOffset; + } + return false; + } +} + diff --git a/DiSLProject2022/src-profiler/ex6/Profiler.java b/DiSLProject2022/src-profiler/ex6/Profiler.java new file mode 100644 index 0000000..54f8a5c --- /dev/null +++ b/DiSLProject2022/src-profiler/ex6/Profiler.java @@ -0,0 +1,29 @@ +package ex6; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.LongAdder; + +public final class Profiler { + + private static final Map methodToLoopCount = new ConcurrentHashMap<>(); + + static { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + for (final var entry : methodToLoopCount.entrySet()) { + System.out.printf("Method name: %s - # executed loops: %d%n", entry.getKey(), entry.getValue().intValue()); + } + })); + } + + private Profiler() { + } + + + public static void countLoop(String methodName) { + methodToLoopCount.computeIfAbsent(methodName, k -> new LongAdder()); + methodToLoopCount.get(methodName).increment(); + } + + +} diff --git a/DiSLProject2022/src-profiler/ex7/Instrumentation.java b/DiSLProject2022/src-profiler/ex7/Instrumentation.java index 25e5226..f62bcf6 100644 --- a/DiSLProject2022/src-profiler/ex7/Instrumentation.java +++ b/DiSLProject2022/src-profiler/ex7/Instrumentation.java @@ -1,4 +1,35 @@ package ex7; +import ch.usi.dag.disl.annotation.After; +import ch.usi.dag.disl.annotation.Before; +import ch.usi.dag.disl.dynamiccontext.DynamicContext; +import ch.usi.dag.disl.marker.BodyMarker; +import ch.usi.dag.disl.marker.BytecodeMarker; +import ch.usi.dag.disl.staticcontext.ClassStaticContext; +import ch.usi.dag.disl.staticcontext.MethodStaticContext; + + public class Instrumentation { + @Before(marker = BytecodeMarker.class, args = "MONITORENTER", scope = "ex7.MainThread.*") + static void handleMonitorAccess(final DynamicContext dc) { + final Object monitor = dc.getStackValue(0, Object.class); + Profiler.countMonitorAccess(monitor); + } + + @After(marker = BodyMarker.class, scope = "ex7.MainThread.*", guard = IsSynchronizedMethodGuard.class) + static void handledSynchronizedAccess(final MethodStaticContext mc, final DynamicContext dc, final ClassStaticContext cc) { + if (mc.isMethodStatic()) { + try { + Class methodClass = Class.forName(cc.getName()); + Profiler.countMonitorAccess(methodClass); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Class " + cc.getName() + " not found"); + } + + } else { + Profiler.countMonitorAccess(dc.getThis()); + } + } + + } diff --git a/DiSLProject2022/src-profiler/ex7/IsSynchronizedMethodGuard.java b/DiSLProject2022/src-profiler/ex7/IsSynchronizedMethodGuard.java new file mode 100644 index 0000000..980dd16 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex7/IsSynchronizedMethodGuard.java @@ -0,0 +1,11 @@ +package ex7; + +import ch.usi.dag.disl.annotation.GuardMethod; +import ch.usi.dag.disl.staticcontext.MethodStaticContext; + +public class IsSynchronizedMethodGuard { + @GuardMethod + public static boolean isSynchronizedMethod(MethodStaticContext mc) { + return mc.isMethodSynchronized(); + } +} diff --git a/DiSLProject2022/src-profiler/ex7/Profiler.java b/DiSLProject2022/src-profiler/ex7/Profiler.java new file mode 100644 index 0000000..a98e9de --- /dev/null +++ b/DiSLProject2022/src-profiler/ex7/Profiler.java @@ -0,0 +1,66 @@ +package ex7; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.LongAdder; + +public final class Profiler { + + private static final class MonitorEntry { + private final int hashCode; + private final String name; + + public MonitorEntry(int hashCode, String name) { + this.hashCode = hashCode; + this.name = name; + } + + public int getHashCode() { + return hashCode; + } + + public String getName() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MonitorEntry that = (MonitorEntry) o; + return hashCode == that.hashCode && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(hashCode, name); + } + } + + private static final Map monitorToAccessCount = new ConcurrentHashMap<>(); + + static { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + for (final var entry : monitorToAccessCount.entrySet()) { + System.out.printf("%d - %s - #Locks: %d%n", + entry.getKey().getHashCode(), + entry.getKey().getName(), + entry.getValue().intValue() + ); + } + })); + } + + private Profiler() { + } + + + public static void countMonitorAccess(final Object obj) { + final MonitorEntry monitorEntry = new MonitorEntry(obj.hashCode(), obj.getClass().getName()); + monitorToAccessCount.computeIfAbsent(monitorEntry, k -> new LongAdder()); + monitorToAccessCount.get(monitorEntry).increment(); + } + + +} diff --git a/DiSLProject2022/src-profiler/ex8/Instrumentation.java b/DiSLProject2022/src-profiler/ex8/Instrumentation.java index d51ca10..ad94de9 100644 --- a/DiSLProject2022/src-profiler/ex8/Instrumentation.java +++ b/DiSLProject2022/src-profiler/ex8/Instrumentation.java @@ -1,4 +1,18 @@ package ex8; +import ch.usi.dag.disl.annotation.Before; +import ch.usi.dag.disl.marker.BytecodeMarker; +import org.objectweb.asm.Opcodes; + public class Instrumentation { + + @Before(marker = BytecodeMarker.class, args = "invokestatic,invokespecial,invokevirtual,invokedynamic", scope = "*") + static void handleInvoke(InvocationContext ic) { + switch (ic.getInvocationOp()){ + case Opcodes.INVOKEDYNAMIC -> Profiler.countInvoke(Thread.currentThread().getName(), "dynamic"); + case Opcodes.INVOKEVIRTUAL -> Profiler.countInvoke(Thread.currentThread().getName(), "virtual"); + case Opcodes.INVOKESTATIC -> Profiler.countInvoke(Thread.currentThread().getName(), "static"); + case Opcodes.INVOKESPECIAL -> Profiler.countInvoke(Thread.currentThread().getName(), "special"); + } + } } diff --git a/DiSLProject2022/src-profiler/ex8/InvocationContext.java b/DiSLProject2022/src-profiler/ex8/InvocationContext.java new file mode 100644 index 0000000..d4ce4b7 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex8/InvocationContext.java @@ -0,0 +1,11 @@ +package ex8; + +import ch.usi.dag.disl.staticcontext.AbstractStaticContext; +import org.objectweb.asm.tree.AbstractInsnNode; + +public class InvocationContext extends AbstractStaticContext { + public int getInvocationOp(){ + final AbstractInsnNode ins = staticContextData.getRegionStart(); + return ins.getOpcode(); + } +} diff --git a/DiSLProject2022/src-profiler/ex8/InvokeType.java b/DiSLProject2022/src-profiler/ex8/InvokeType.java new file mode 100644 index 0000000..78b6c86 --- /dev/null +++ b/DiSLProject2022/src-profiler/ex8/InvokeType.java @@ -0,0 +1,33 @@ +package ex8; + +import org.objectweb.asm.Opcodes; + +import java.util.HashMap; + +public enum InvokeType { + STATIC("static"), + DYNAMIC("dynamic"), + SPECIAL("special"), + VIRTUAL("virtual"); + + final String name; + + final static HashMap opcodeToInvokeType = new HashMap<>() { + { + put(Opcodes.INVOKESTATIC, InvokeType.STATIC); + put(Opcodes.INVOKEDYNAMIC, InvokeType.DYNAMIC); + put(Opcodes.INVOKESPECIAL, InvokeType.SPECIAL); + put(Opcodes.INVOKEVIRTUAL, InvokeType.VIRTUAL); + } + }; + + InvokeType(String name) { + this.name = name; + } + + static InvokeType fromOpcode(int opCode) { + return opcodeToInvokeType.get(opCode); + } + + +} diff --git a/DiSLProject2022/src-profiler/ex8/Profiler.java b/DiSLProject2022/src-profiler/ex8/Profiler.java new file mode 100644 index 0000000..c66b15c --- /dev/null +++ b/DiSLProject2022/src-profiler/ex8/Profiler.java @@ -0,0 +1,55 @@ +package ex8; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.LongAdder; + +public final class Profiler { + + + private record Invocation(String threadName, String invokeType) { + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Invocation that = (Invocation) o; + return Objects.equals(threadName, that.threadName) && Objects.equals(invokeType, that.invokeType); + } + + @Override + public int hashCode() { + return Objects.hash(threadName, invokeType); + } + + } + + + private Profiler() { + } + + private static final Map invocationToCount = new ConcurrentHashMap<>(); + + // TODO change format to match assignment + static { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + for (final var entry : invocationToCount.entrySet()) { + System.out.printf("Thread: %s Type: %s Count: %d%n", + entry.getKey().threadName, + entry.getKey().invokeType, + entry.getValue().intValue() + ); + } + })); + } + + public static void countInvoke(final String threadName, final String invokeType) { + final Invocation invocation = new Invocation(threadName, invokeType); + invocationToCount.computeIfAbsent(invocation, k -> new LongAdder()); + invocationToCount.get(invocation).increment(); + + } + + +}