56

Both of them pretty much do the same thing. Identify that the method is hot and compile it instead of interpreting. With OSR, you just move to the compiled version right after it gets compiled, unlike with JIT, where the compiled code gets called when the method is called for the second time.

Other than this, are there any other differences?

Seki
  • 11,135
  • 7
  • 46
  • 70
Chander Shivdasani
  • 9,878
  • 20
  • 76
  • 107
  • This blog is another good resource... http://www.azulsystems.com/blog/cliff/2011-11-22-what-the-heck-is-osr-and-why-is-it-bad-or-good – Chander Shivdasani Feb 02 '12 at 04:23
  • working link: https://web.archive.org/web/20140126120326/http://www.azulsystems.com/blog/cliff/2011-11-22-what-the-heck-is-osr-and-why-is-it-bad-or-good – Dan M. May 26 '22 at 07:03

3 Answers3

79

In general, Just-in-time compilation refers to compiling native code at runtime and executing it instead of (or in addition to) interpreting. Some VMs, such as Google V8, don't even have an interpreter; they JIT compile every function that gets executed (with varying degrees of optimization).

On Stack Replacement (OSR) is a technique for switching between different implementations of the same function. For example, you could use OSR to switch from interpreted or unoptimized code to JITed code as soon as it finishes compiling.

OSR is useful in situations where you identify a function as "hot" while it is running. This might not necessarily be because the function gets called frequently; it might be called only once, but it spends a lot of time in a big loop which could benefit from optimization. When OSR occurs, the VM is paused, and the stack frame for the target function is replaced by an equivalent frame which may have variables in different locations.

OSR can also occur in the other direction: from optimized code to unoptimized code or interpreted code. Optimized code may make some assumptions about the runtime behavior of the program based on past behavior. For instance, you could convert a virtual or dynamic method call into a static call if you've only ever seen one type of receiver object. If it turns out later that these assumptions were wrong, OSR can be used to fall back to a more conservative implementation: the optimized stack frame gets converted into an unoptimized stack frame. If the VM supports inlining, you might even end up converting an optimized stack frame into several unoptimized stack frames.

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Jay Conrod
  • 28,943
  • 19
  • 98
  • 110
16

Yes, that's pretty much it. Just-in-time compilation can improve performance by compiling "hot spots" (spots of bytecode that are known / supposed to execute very often) of bytecode to native instructions. On-Stack Replacement complements JIT capabilities by replacing long running interpreted "hot" bytecode by it's compiled version when it becomes available. The mentioned On-Stack Replacement article shows a nice example where JIT compilation would not be very useful without OSR.

jocull
  • 20,008
  • 22
  • 105
  • 149
Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118
  • 5
    Unfortunately, article link doesn't work anymore. Here is another post on OSR: http://xmlandmore.blogspot.com/2012/06/on-stack-replacement-in-hotspot-jvm.html – Tvaroh May 08 '13 at 12:49
  • 1
    I've updated the dead link with a snapshot from the web archive. Do note that this article is from 2012 :) – jocull Oct 28 '19 at 13:22
0

JIT is just.. looks for number of method invocations, and if it crosses a threshold, (-XX:CompileThreshold=) it compiles (to machine code/ native) and caches the method. On next invocation, the compiled version will invoke.
OSR is interesting. Supposing a gigantic for loop is running in interpret mode. JVM decides to compile at some point of time when it has crossed the compile threshold. So while the loop is still running, its interpreted version can get replaced with a compiled to native version while the code is still running!
So essentially it is exactly what it says. Replacing interpreted code, which is still running on stack, while it is running, with compiled code.
This can also result in an interesting but benign issue called 'who ate my variable'. See who ate my variable

Apurva Singh
  • 4,534
  • 4
  • 33
  • 42