Added Instrumentor for Inlining monitorEnter, monitorExit, isOldThread, and setOldThread

Now I’ve written an instrumentor, MarkerInlineStrategy that inlines the respective bytecode snippets for monitorEnter, monitorExit, isOldThread, and setOldThread. I didn’t limit it to just SyncPointBuffer, instead I’m currently employing it with a ConditionalStrategy as decorator that only invokes the decoree if the class to be instrumented happens to be SyncPointBuffer.

I also did a lot of house cleaning. I removed the parameters of type ChangeCallTargetStrategy and CreateDecoratorStrategy from instrumentors that can be invoked from FileInstrumentor‘s command line interface, and now I also allow zeroary constructors, even though the constructor accepting a MethodHashTableStrategy is still favored.

I improved the @DoNotInstrument annotation. It is now possible to specify which instrumentation strategies should not be run. The default still is that no instrumentation is performed at all:

1
2
3
4
@DoNotInstrument
public class Foo {
    ...
}

However, the SyncPointBuffer class now has to be instrumented by the MarkerInlineStrategy, but may not be instrumented by any of the *Synchronized*, ObjectCallStrategy, or AssignObjectIDStrategy instrumentors. I specify that this way:

1
2
3
4
5
@DoNotInstrument(instrumentors =
   "\*\*\*.\*Synchronized\*;\*\*\*.ObjectCallStrategy;\*\*\*.AssignObjectIDStrategy")
public class Foo {
    ...
}

The string is a semicolon-separated list of class name patterns for ClassFileTools.classNameMatches().

Furthermore, I’ve just split the “method index” long transmitted in the CompactSynchronizedBlockDebugStrategy in a “method index & program counter” value. The method index occupies the upper 32 bit, the program counter where the monitorenter or monitorexit instruction was found resides in the lower 32 bit. This fits very well with the JVM’s own limitations. Now it’s possible to exactly pinpoint a monitorenter or monitorexit in the modified class files. I have to note that this leads to quite a bit more “bloating”, since every pair of method index-program counter that occurs in a class file will now have to be put in the constant pool (i.e. 0x00010000 and 0x00010001 for a monitorenter; monitorexit; return method instead of just 0x00000001), but since this is just for debugging, that’s probably acceptable.

I’m running a few tests now to make sure that the recording stage still works after these relatively extensive modifications, then I have to focus on the replay stage again.

One major item still missing is the compact treatment of wait, sleep, notify, and notifyAll. That might cause some more headache when it comes to the replay algorithm.

Update

I also need to write an instrumentor that inserts a call to SyncPointBuffer.compactThreadExit at the end of java.lang.Thread.exit.

Update

Done.

Share

About Mathias

Software development engineer. Principal developer of DrJava. Recent Ph.D. graduate from the Department of Computer Science at Rice University.
This entry was posted in Concurrent Unit Testing. Bookmark the permalink.

Leave a Reply