ex11 minus invokedynamic handling and return type for call target

This commit is contained in:
Claudio Maggioni 2023-01-11 15:17:18 +01:00
parent 6a7bf23a9d
commit 38c67580ae
4 changed files with 157 additions and 0 deletions

View file

@ -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;
}
}
}

View file

@ -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()
));
}
}

View 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);
}
}
}

View 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.");
}
}