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
_______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev