This was very cool, adding a profiler using MH

John Rose john.r.rose at oracle.com
Thu Feb 16 21:29:01 PST 2012


On Feb 16, 2012, at 8:43 PM, Mark Roos wrote:

> The key code is below and it shows the power of methodHandles is ways one may not expect.  And it 
> added almost nothing to the run time ( maybe a few %).  It inserts itself into each callsite target and 
> collect entry and exit data. 

Nice!

As a bonus, your profile points are given a chance to modify the arguments and return value.

If you don't want to pass the arguments and return value, you can use a void-returning combiner with foldArguments (instead of filterArguments).  The combiner will "see" the arguments and then "return nothing", allowing the invoker to continue as before.

A different use of foldArguments would also let you pass both the original arguments and the return value to the profileExit routine, so it could see the whole call.  Something like this:

   invoker = {spreader which takes standard RtObject[] array};
   profileExit = {method of type (RtCallSite, RtObject, RtObject[]) => RtObject};
   profileExit = insertArguments(profileExit, 0, thisCallSite);  // (RtObject, RtObject[]) => RtObject
   invoker = foldArguments(profileExit, invoker);  // note that invoker serves as *combiner*

   // add entry profiling last, so that profileExit will see (possibly) transformed arguments:
   profileEntry = {method of type (RtCallSite, RtObject[]) => RtObject[]};
   profileEntry = insertArguments(0, thisCallSite);  // (RtObject[]) => RtObject[]
   invoker = filterArguments(invoker, profileEntry);

You could also interpose on abnormal termination (exceptions), using guardWithCatch.

A relatively simple way to do take full control of traced calls is to delegate the actual calling to the profile routine, but this might (presently) hurt performance, since it will make all calls go through one hot point, profileWrapper:

  invoker = {spreader which takes standard RtObject[] array};
  profileWrapper = {method of type (RTCallSite, MethodHandle, RtObject[]) => RtObject};
  // wrapped call will execute this: profileWrapper(thisCallSite, unwrappedInvoker, arg...)
  invoker = insertArguments(profileWrapper, 0, thisCallSite, invoker);

I'm glad you are enjoying the toolkit!

-- John


More information about the mlvm-dev mailing list