This repository has been archived on 2024-10-22. You can view files and clone it, but cannot push or open issues or pull requests.
AJP/DiSLProject2022/src-profiler/ex11/Profiler.java

67 lines
2.2 KiB
Java
Raw Normal View History

package ex11;
import org.objectweb.asm.Opcodes;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public final class Profiler {
private static final Map<CallInfo, long[]> count = new HashMap<>();
private static boolean stop = false;
static {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
stop = true;
for (final var entry : count.entrySet()) {
System.out.println(entry.getKey().toString() + "\n#invokes " + entry.getValue()[0] + "\n");
}
}));
}
private Profiler() {
}
public static void registerCall(final CallInfo info) {
if (stop) return;
count.computeIfAbsent(info, ignored -> new long[1])[0]++;
}
public record CallInfo(int instruction, long index, String caller, String callee, String callTarget) {
private static final String FORMAT = "CallerMethodFQIN %s\nCallerBCI %d\ninvoketype %s\nCalleeMethodFQIN %s\nCallTargetFQIN %s";
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CallInfo callInfo = (CallInfo) o;
return index == callInfo.index && instruction == callInfo.instruction &&
caller.equals(callInfo.caller) && callee.equals(callInfo.callee) &&
callTarget.equals(callInfo.callTarget);
}
@Override
public int hashCode() {
return Objects.hash(instruction, index, caller, callee, callTarget);
}
public String invokeType() {
return switch (instruction) {
case Opcodes.INVOKEDYNAMIC -> "dynamic";
case Opcodes.INVOKESTATIC -> "static";
case Opcodes.INVOKEINTERFACE -> "interface";
case Opcodes.INVOKESPECIAL -> "special";
case Opcodes.INVOKEVIRTUAL -> "virtual";
default -> throw new IllegalStateException("Not an INVOKE* bytecode instruction: " + instruction);
};
}
@Override
public String toString() {
return String.format(FORMAT, caller, index, invokeType(), callee, callTarget);
}
}
}