Some bugs fixed
This commit is contained in:
parent
a78c260dbf
commit
32b063052f
15 changed files with 396 additions and 0 deletions
|
@ -1,4 +1,14 @@
|
||||||
package ex4;
|
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 {
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
29
DiSLProject2022/src-profiler/ex4/Profiler.java
Normal file
29
DiSLProject2022/src-profiler/ex4/Profiler.java
Normal file
|
@ -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<String, LongAdder> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,21 @@
|
||||||
package ex5;
|
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 {
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
31
DiSLProject2022/src-profiler/ex5/Profiler.java
Normal file
31
DiSLProject2022/src-profiler/ex5/Profiler.java
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,32 @@
|
||||||
package ex6;
|
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 {
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
10
DiSLProject2022/src-profiler/ex6/IsLoopInstructionGuard.java
Normal file
10
DiSLProject2022/src-profiler/ex6/IsLoopInstructionGuard.java
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
21
DiSLProject2022/src-profiler/ex6/LoopContext.java
Normal file
21
DiSLProject2022/src-profiler/ex6/LoopContext.java
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
29
DiSLProject2022/src-profiler/ex6/Profiler.java
Normal file
29
DiSLProject2022/src-profiler/ex6/Profiler.java
Normal file
|
@ -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<String, LongAdder> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,35 @@
|
||||||
package ex7;
|
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 {
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
66
DiSLProject2022/src-profiler/ex7/Profiler.java
Normal file
66
DiSLProject2022/src-profiler/ex7/Profiler.java
Normal file
|
@ -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<MonitorEntry, LongAdder> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,18 @@
|
||||||
package ex8;
|
package ex8;
|
||||||
|
|
||||||
|
import ch.usi.dag.disl.annotation.Before;
|
||||||
|
import ch.usi.dag.disl.marker.BytecodeMarker;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
public class Instrumentation {
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
11
DiSLProject2022/src-profiler/ex8/InvocationContext.java
Normal file
11
DiSLProject2022/src-profiler/ex8/InvocationContext.java
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
33
DiSLProject2022/src-profiler/ex8/InvokeType.java
Normal file
33
DiSLProject2022/src-profiler/ex8/InvokeType.java
Normal file
|
@ -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<Integer, InvokeType> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
55
DiSLProject2022/src-profiler/ex8/Profiler.java
Normal file
55
DiSLProject2022/src-profiler/ex8/Profiler.java
Normal file
|
@ -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<Invocation, LongAdder> 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Reference in a new issue