Okay ... so, attached are the two bytecodes that I would like to insert into method bodies. Only the "impdep1" bytecode as I've described it needs inserting beforehand. In the simplest model, I would like to do the following transformation with Soot:
non-native method call
return point
--->
impdep1 (operand = return point)
non-native method call
nop
return point
... and then when a non-speculative thread encounters the impdep1 bytecode, it tries to fork a speculative thread starting at the return point. If successful, it changes the code at run-time using one word replacement (which is atomic) to:
impdep1 (operand = return point)
non-native method call
impdep2 (count = 1)
return point
... and then when the non-speculative thread returns from the method call, it encounters the impdep2 bytecode, checks to see if it has started a speculative thread at the return point, and if so asks that thread to commit. If the commit is successful, it joins it somehow (to be determined). Either way, as long as it has started a spec. thread, it decrements the count by 1, and if the count = 0 then replaces it with a nop instruction again.
So in an attribute, I would need to give enough information to the VM to enable it to insert this special "impdep1" bytecode at specific points (we won't want to speculate on the return from _all_ methods) within a method body. However, if Soot currently destroys the code attribute, that sounds like you can't even run it on a VM at all.
I agree that attributes are a cleaner solution, because the bytecode will only get modified on a VM that recognizes / supports them.
Anyway, let me know what you think of my plan and if you can see a better way. Tips on getting started using attributes to do what I want to do are very much appreciated :-)
Cheers,
Chris
Ondrej Lhotak wrote:
Soot reads the following attributes: SourceFile ConstantValue Code Exceptions LineNumberTable LocalVariableTable However, only LineNumberTable has a corresponding Tag implementation allowing it to be represented as a Soot attribute. If you need to preserve anything else, you need to implement a Tag to represent it, and a TagAggregator to convert it from a Soot attribute into a bytecode attribute. Ondrej On Sun, Mar 16, 2003 at 09:54:27PM -0500, Chris Pickett wrote:From the Soot tutorials ... Known shortcomings: Soot cannot currently preserve existing attributes in a class file when transforming and annotating it. In the foo example, any debug information from javac would be lost after annotation. ==== Is this still the case? Chris
impdep1 bytecode specification
impdep1
Operation
fork speculative thread at bytecode offset specified
Format
impdep1 branchbyte1 branchbyte2
Forms
impdep1 = 254 (0xfe)Operand Stack
......
Description
The unsigned branchbyte1 and branchbyte2 are used to construct a signed 16-bit offset, where the offset is calculated to be (branchbyte1 << 8) | branchbyte2.
If there is an available processor for speculative multithreading, then execution proceeds in a new speculative thread at that offset from the address of the opcode of this impdep1 instruction. The target address must be that of an opcode of an instruction within the method that contains this impdep1 instruction. The opcode preceding the target address will be a nop instruction, and if a speculative thread is successfully started, should be patched with an impdep2 instruction with a count of 1. If the preceding instruction is already an impdep2 instruction, then its use count is incremented by 1. The use count is the first operand of the impdep2 instruction.
Otherwise, a new speculative thread is not started. In either case, execution proceeds at the address of the instruction following this impdep1 instruction.
Linking Exceptions
This needs to be determined. For now, there are none.
Runtime Exceptions
This needs to be determined. For now, there are none.Notes
This instruction works in conjunction with the impdep2 instruction. The two implementation dependent instructions are used so that a static compiler can
determine the fork and join points for speculative execution. However, this impdep2 opcode might foreseeably be replaced by another internal SableVM instruction, as it is not strictly needed by static analysis under the current design.
The design / implementation is not complete. For now, this bytecode will actually cause the current thread to switch into a speculative execution mode, and the target address will not be used. Commit will occur at a GC checkpoint. Also, this design may change in the future such that the target instruction need not be inside the current method.
impdep2
Operation
join a speculative thread forked by the current thread
Format
impdep2 count
Forms
impdep2 = 255 (0xff)Operand Stack
......
Description
The current thread first checks if it has forked a speculative thread at the address of the opcode that follows this impdep2 instruction. If it has, then it replaces the count operand in the bytecode (not on the operand stack) with count - 1. If this results in count == 0, then the opcode is replaced with a nop instruction.
Then the current thread asks the speculative thread to validate and commit the results of its execution. If the commit is successful, then non-speculative execution continues at the next bytecode of the speculative thread. If the commit operation fails, then the speculative thread aborts and execution continues at the address of the opcode that follows this impdep2 instruction.
Otherwise, if the current thread has not forked a speculative thread, then execution also proceeds at the address of the instruction following this impdep2 instruction.
Linking Exceptions
This needs to be determined. For now, there are none.
Runtime Exceptions
This needs to be determined. For now, there are none.Notes
This instruction works in conjunction with the impdep1 instruction. The two implementation dependent instructions are used so that a static compiler can
determine the fork and join points for speculative execution. However, this impdep2 opcode might foreseeably be replaced by another internal SableVM instruction, as it is not strictly needed by static analysis under the current design.
The design / implementation is not complete. For now, this bytecode will actually cause the current thread to switch into a non-speculative execution mode. Commit may also occur at a GC checkpoint. Furthermore, it has not been determined whether the speculative thread or the non-speculative thread starts executing at the next bytecode in the event of a successful commit operation, nor what happens to the thread objects.