On 2011-05-06, at 12:48 PM, chevalma@iro.umontreal.ca wrote:
For example, a "jump to function in the global object" IR instruction could be initially implemented as a call to a handler that looks up the name of the function in the global object, and when it is found, the call to the handler is replaced by a direct jump to the function
I don't really like that idea because it seems to me to be rather tightly coupled with both the IR and the backend. It seems to me that you're suggesting having one or more specific IR instructions with corresponding backend support just for that one optimization. Not to mention wanting to perhaps have code directly in the global object or special function entry points again just for that one optimization.
"That one optimization" is slowing down our code enormously. I would estimate that implementing this optimization will make calling global functions 10 to 20 times faster. The only instruction that needs special support is the call instruction (and the putprop/getprop primitives).
I'm not sure what you have in mind as a "generic code patching functionality in the IR". The problem is that code patching is very low level (in the end you have to write real machine instructions). You need to know the size of the machine instructions, because code patching overwrites existing machine instructions with new machine instructions.
I'm not suggesting we directly have a mechanism to write over a sequence of IR instructions.
OK.
I would propose that we instead brainstorm over what kinds of things we may want to do with code patching, and implement a small set of "patchable" IR instructions, so to speak.
This seems to contradict what you said above. I suggested that we make the call instruction patchable and you said you don't like the idea. Can you explain your point better?
Some potential ideas:
- An IR value that can be patched/updated later. This might allow making a
call site call a different functions at different times, or replacing a "constant" in a piece of code.
Don't you think this is a "limited" form of code patching that will not allow us to do all the things that can be done with a lower level code patching. For example, for the optimization of function call, it is desirable to eliminate the setup of the argument count register, and skip the argument count check at the beginning of the function. So this means that some instructions need to be removed, which is more that changing a parameter/constant of an instruction.
- A conditional branch (like an if instruction) that doesn't test any
values and always branches the same way, until we toggle it to branch the other way instead (a patchable jump inside a function). Such patchable jumps could have more than two possible targets. This image comes to mind: http://visual.merriam-webster.com/images/transport-machinery/rail-transport/...
This is easy enough. By the way I wouldn't call it a conditional branch... it is a changeable unconditional branch. What use do you have for this? Note that the branch will have a run-time cost, wherever the branch points to. So when generating the IR we have to consciously introduce a changeable branch (and be willing to pay the run-time cost), in the hope that it will save time later on. So... what kind of optimization do you want to do with this?
Marc