ex11 minus invokedynamic handling and return type for call target
This commit is contained in:
parent
6a7bf23a9d
commit
38c67580ae
4 changed files with 157 additions and 0 deletions
|
@ -0,0 +1,38 @@
|
|||
package ex11;
|
||||
|
||||
import ch.usi.dag.disl.staticcontext.InvocationStaticContext;
|
||||
import org.objectweb.asm.signature.SignatureReader;
|
||||
import org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
public class ArgumentLengthStaticContext extends InvocationStaticContext {
|
||||
|
||||
public String getInternalNameWithDescriptor() {
|
||||
return getInternalName() + getDescriptor();
|
||||
}
|
||||
|
||||
public int getArgumentLength() {
|
||||
final String descriptor = getDescriptor();
|
||||
final ArgumentLengthVisitor av = new ArgumentLengthVisitor();
|
||||
final SignatureReader sv = new SignatureReader(descriptor);
|
||||
sv.accept(av);
|
||||
return av.getLength();
|
||||
}
|
||||
|
||||
private static class ArgumentLengthVisitor extends SignatureVisitor {
|
||||
private int length = 0;
|
||||
|
||||
public ArgumentLengthVisitor() {
|
||||
super(589824);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVisitor visitParameterType() {
|
||||
length++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,46 @@
|
|||
package ex11;
|
||||
|
||||
import ch.usi.dag.disl.annotation.Before;
|
||||
import ch.usi.dag.disl.dynamiccontext.DynamicContext;
|
||||
import ch.usi.dag.disl.guardcontext.ReflectionStaticContext;
|
||||
import ch.usi.dag.disl.marker.BytecodeMarker;
|
||||
import ch.usi.dag.disl.staticcontext.InstructionStaticContext;
|
||||
import ch.usi.dag.disl.staticcontext.MethodStaticContext;
|
||||
|
||||
public class Instrumentation {
|
||||
@Before(marker = BytecodeMarker.class, args = "invokevirtual, invokespecial, invokeinterface", guard = TemporaryGuard.class)
|
||||
static void atObjectRefCallSite(final InstructionStaticContext isc,
|
||||
final MethodStaticContext msc,
|
||||
final ArgumentLengthStaticContext ivc,
|
||||
final DynamicContext dc) {
|
||||
final Object objectRef = dc.getStackValue(ivc.getArgumentLength(), Object.class);
|
||||
|
||||
|
||||
final String callTarget = objectRef.getClass().getName().replace('.', '/')
|
||||
.concat(".")
|
||||
.concat(ivc.getName());
|
||||
|
||||
// TODO: call target signature (handle covariant return types)
|
||||
|
||||
Profiler.registerCall(new Profiler.CallInfo(
|
||||
isc.getOpcode(),
|
||||
isc.getIndex(),
|
||||
msc.thisMethodFullName().concat(msc.thisMethodDescriptor()),
|
||||
ivc.getInternalNameWithDescriptor(),
|
||||
callTarget
|
||||
));
|
||||
}
|
||||
|
||||
@Before(marker = BytecodeMarker.class, args = "invokestatic", guard = TemporaryGuard.class)
|
||||
static void atStaticCallSite(final InstructionStaticContext isc,
|
||||
final MethodStaticContext msc,
|
||||
final ArgumentLengthStaticContext ivc) {
|
||||
Profiler.registerCall(new Profiler.CallInfo(
|
||||
isc.getOpcode(),
|
||||
isc.getIndex(),
|
||||
msc.thisMethodFullName().concat(msc.thisMethodDescriptor()),
|
||||
ivc.getInternalNameWithDescriptor(),
|
||||
ivc.getInternalNameWithDescriptor()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
66
DiSLProject2022/src-profiler/ex11/Profiler.java
Normal file
66
DiSLProject2022/src-profiler/ex11/Profiler.java
Normal file
|
@ -0,0 +1,66 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
11
DiSLProject2022/src-profiler/ex11/TemporaryGuard.java
Normal file
11
DiSLProject2022/src-profiler/ex11/TemporaryGuard.java
Normal file
|
@ -0,0 +1,11 @@
|
|||
package ex11;
|
||||
|
||||
import ch.usi.dag.disl.annotation.GuardMethod;
|
||||
import ch.usi.dag.disl.staticcontext.ClassStaticContext;
|
||||
|
||||
public class TemporaryGuard {
|
||||
@GuardMethod
|
||||
public static boolean isEx11(final ClassStaticContext csc) {
|
||||
return csc.getName().startsWith("ex11.");
|
||||
}
|
||||
}
|
Reference in a new issue