When recompiling a function that has an IC making a native call on the stack, we need code for the native to return to which will readjust the machine stack and test the return value. Currently, we just steal the native stub from the original code and reuse it for the new code. This doesn't always work on x64 since the jumps to/from the stub could be out of range, and we end up crashing.
This can be fixed in several ways:
1) Still steal the natives, but use far jumps so that we can always steal the stub.
2) Use a more general mechanism to ensure the jumps will be in range, like code motion or restricting the code address space.
3) Emit the tail of the native stub when doing on-stack recompilation of opcodes with old native stubs, but do not steal the whole stub.
2) would apply to all ICs on x64, with or without type inference, and is tricky but something that should be done regardless (as a separate bug) as it hurts our x64 perf. 3) is probably simplest and the best approach for this bug.
The needs here changed with bug 650163, where instead of stealing a native stub and giving it to the recompiled script, we steal the stub and orphan it (with a vector and refcount attached to the compartment of orphaned native stubs, after references go to zero all orphaned stubs are destroyed).
Now the jump at the end of the stub has been patched to go to the interpoline, which is more likely to be out of range from the ExecutableAllocator code. The fix below uses an indirect jump at the end of native stubs, which can be patched to go to any address (this is the only place where such far jumps are needed with recompilation).