Instrumenting call sites.
Mark Roos
mroos at roos.com
Mon Dec 3 11:08:13 PST 2012
Hi Duncan, Here is what I have been using to profile.
Some notes.
I create all of my Smalltalk methods in an intermediate byte code format
and then use ASM
to create the Java class JIT. Each of my methods results in a single Java
class which may have
more than one method if there are blocks.
I also have two flags, debug and profile. These are used to limit the
time impact. However I see less than
10% impact so its not as important to me right now and I leave it on.
To find my classes in the java stack trace I give them a unique identifier
( due to illegal chars in ST method names )
String cName = "rtPbc/r"+ Integer.toString(_classCounter);
So I can locate the callsites and manipulate them I use the source code
file name
to hold the class-methodName and the line number to hold the Smalltalk
bytecode index
for that callsite.
cw.visitSource(sourceName, null);
mv.visitLineNumber(lineNumber, tmpLabel);
I also pass them as bootstrap arguments for the callsite to hold to help
some of my
profiling tools.
bsmArgs=new String[2];
bsmArgs[0]=sourceName;
bsmArgs[1]= ((Integer) lineNumber).toString();
mv.visitInvokeDynamicInsn(selName, descriptor,
new Handle(Opcodes.H_INVOKESTATIC,
"ri/core/rtalk/RtCallSite",
"bootStrapSelf",
bsmType.toMethodDescriptorString()),
(Object[])bsmArgs);
For the actual profiling I add an additional callsite target pair to the
standard callsite.
So instead of the initial callsite pointing at the actual target it points
at some profiling
handles which then hold the real target. My profiling methodHandles
update a list of the receivers
for that site and the total time for the site plus number of entries.
site._depth = site._depth + 1;
int last=args.length;
RtObject rcvr=(RtObject)args[last - 1];
if(RtDebugger._profileEnable){
site.addReceiver(rcvr);
}
Mutating the mh sequence to add the profile looks like this
if( RtDebugger._profileEnable){
// have to catch the non local return as well
// MethodHandles.catchException(target, RtNonLocalReturn.class,
catchMH);
// catchMH needs to add exit time and throw the exception
mt=MethodType.methodType(RtObject[].class, RtCallSite.class,
RtObject[].class);
try {
profileEntry = lookup.findStatic(RtDebugger.class,
"profileEntry", mt);
}
catch (Throwable e) {
e.printStackTrace();
}
profileEntry = MethodHandles.insertArguments(profileEntry, 0,
this);
// I have to collect the invoker, bind the call site to the entry
filter
// filter the invoker and then spread the invoker
invoker = invoker.asSpreader(RtObject[].class, _airity);
invoker = MethodHandles.filterArguments(invoker , 0,
profileEntry);
invoker = invoker.asCollector(RtObject[].class, _airity);
// now the profile exit
mt=MethodType.methodType(RtObject.class, RtCallSite.class,
RtObject.class);
try {
profileExit = lookup.findStatic(RtDebugger.class, "profileExit",
mt);
}
catch (Throwable e) {
e.printStackTrace();
}
profileExit = MethodHandles.insertArguments(profileExit, 0, this);
invoker = MethodHandles.filterReturnValue(invoker , profileExit);
}
_realSite.setTarget(mh);
this.setTarget(invoker);
I actually convert the Java side to Smalltalk objects so I can do my
debuggers etc
in Smalltalk.
Probably can do better but I am focused on some usability issues and the
code runs
fine
regards
mark
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20121203/b8d64468/attachment.html
More information about the mlvm-dev
mailing list