Just-in-time compilation: Difference between revisions

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search
imported>InternetArchiveBot
Rescuing 1 sources and tagging 0 as dead.) #IABot (v2.0.9.5
 
imported>GünniX
m v2.05 - Fix errors for CW project (Unbalanced quotes in ref name or illegal character or empty name.)
 
Line 1: Line 1:
{{short description|Dynamically compiling bytecode to machine code during runtime}}
{{short description|Dynamically compiling bytecode to machine code during runtime}}
{{Program execution}}
{{Program execution}}
In [[computing]], '''just-in-time''' ('''JIT''') '''compilation''' (also '''dynamic translation''' or '''run-time compilations''')<ref name="Michigan" /> is [[compiler|compilation]] (of [[Source code|computer code]]) during execution of a program (at [[run time (program lifecycle phase)|run time]]) rather than before execution.{{sfn|Aycock|2003}} This may consist of [[source code translation]] but is more commonly [[bytecode]] translation to [[machine code]], which is then executed directly. A system implementing a JIT compiler typically continuously analyses the code being executed and identifies parts of the code where the speedup gained from compilation or recompilation would outweigh the overhead of compiling that code.
In [[computing]], '''just-in-time''' ('''JIT''') '''compilation''' (also '''dynamic translation''' or '''run-time compilations''')<ref name="Michigan"/> is [[compiler|compilation]] (of [[Source code|computer code]]) during execution of a program (at [[run time (program lifecycle phase)|run time]]) rather than before execution.{{sfn|Aycock|2003}} This may consist of [[source code translation]] but is more commonly [[bytecode]] translation to [[machine code]], which is then executed directly. A system implementing a JIT compiler typically continuously analyses the code being executed and identifies parts of the code where the speedup gained from compilation or recompilation would outweigh the overhead of compiling that code.


JIT compilation is a combination of the two traditional approaches to translation to machine code&mdash;[[Ahead-of-time compilation|ahead-of-time compilation (AOT)]], and [[Interpreter (computing)|interpretation]]&mdash;and combines some advantages and drawbacks of both.{{sfn|Aycock|2003}} Roughly, JIT compilation combines the speed of compiled code with the flexibility of interpretation, with the overhead of an interpreter and the additional overhead of compiling and [[Linker (computing)|linking]] (not just interpreting). JIT compilation is a form of [[dynamic compilation]], and allows [[adaptive optimization]] such as [[dynamic recompilation]] and [[microarchitecture]]-specific speedups.{{refn|group=nb|Ahead-of-Time compilers can target specific microarchitectures as well, but the difference between AOT and JIT in that matter is one of portability. A JIT can render code tailored to the currently running CPU at runtime, whereas an AOT, in lieu of optimizing for a generalized subset of uarches, must know the target CPU in advance: such code may not only be not performant on other CPU types but may be outright unstable.}}<ref name="Notario" /> Interpretation and JIT compilation are particularly suited for [[dynamic programming language]]s, as the runtime system can handle [[Late binding|late-bound]] data types and enforce security guarantees.
JIT compilation is a combination of the two traditional approaches to translation to machine code: [[ahead-of-time compilation]] (AOT), and [[Interpreter (computing)|interpretation]], which combines some advantages and drawbacks of both.{{sfn|Aycock|2003}} Roughly, JIT compilation combines the speed of compiled code with the flexibility of interpretation, with the overhead of an interpreter and the additional overhead of compiling and [[Linker (computing)|linking]] (not just interpreting). JIT compilation is a form of [[dynamic compilation]], and allows [[adaptive optimization]] such as [[dynamic recompilation]] and [[microarchitecture]]-specific speedups.{{refn|group=nb|Ahead-of-Time compilers can target specific microarchitectures as well, but the difference between AOT and JIT in that matter is one of portability. A JIT can render code tailored to the currently running CPU at runtime, whereas an AOT, in lieu of optimizing for a generalized subset of uarches, must know the target CPU in advance: such code may not only be not performant on other CPU types but may be outright unstable.}}<ref name="Notario"/> Interpretation and JIT compilation are particularly suited for [[dynamic programming language]]s, as the runtime system can handle [[Late binding|late-bound]] data types and enforce security guarantees.


== History ==
== History ==


The earliest published JIT compiler is generally attributed to work on [[Lisp (programming language)|LISP]] by [[John McCarthy (computer scientist)|John McCarthy]] in 1960.{{sfn|Aycock|2003|loc=2. JIT Compilation Techniques, 2.1 Genesis, p. 98}} In his seminal paper ''Recursive functions of symbolic expressions and their computation by machine, Part I'', he mentions functions that are translated during runtime, thereby sparing the need to save the compiler output to [[punch card]]s<ref name="McCarthy1960" /> (although this would be more accurately known as a "[[Compile and go system]]"). Another early example was by [[Ken Thompson]], who in 1968 gave one of the first applications of [[regular expression]]s, here for [[pattern matching]] in the text editor [[QED (text editor)|QED]].{{sfn|Thompson|1968}} For speed, Thompson implemented regular expression matching by JITing to [[IBM 7094]] code on the [[Compatible Time-Sharing System]].{{sfn|Aycock|2003|loc=2. JIT Compilation Techniques, 2.1 Genesis, p. 98}} An influential technique for deriving compiled code from interpretation was pioneered by [[James G. Mitchell]] in 1970, which he implemented for the experimental language ''LC²''.{{sfn|Aycock|2003|loc=2. JIT Compilation Techniques, 2.2 LC², p. 98–99}}<ref name="Mitchell1970" />
The earliest published JIT compiler is generally attributed to work on [[Lisp (programming language)|LISP]] by [[John McCarthy (computer scientist)|John McCarthy]] in 1960.{{sfn|Aycock|2003|loc=2. JIT Compilation Techniques, 2.1 Genesis, p. 98}} In his seminal paper ''Recursive functions of symbolic expressions and their computation by machine, Part I'', he mentions functions that are translated during runtime, thereby sparing the need to save the compiler output to [[punch card]]s<ref name="McCarthy1960"/> (although this would be more accurately known as a "[[Compile and go system]]"). Another early example was by [[Ken Thompson]], who in 1968 gave one of the first applications of [[regular expression]]s, here for [[pattern matching]] in the text editor [[QED (text editor)|QED]].{{sfn|Thompson|1968}} For speed, Thompson implemented regular expression matching by JITing to [[IBM 7094]] code on the [[Compatible Time-Sharing System]].{{sfn|Aycock|2003|loc=2. JIT Compilation Techniques, 2.1 Genesis, p. 98}} An influential technique for deriving compiled code from interpretation was pioneered by [[James G. Mitchell]] in 1970, which he implemented for the experimental language ''LC²''.{{sfn|Aycock|2003|loc=2. JIT Compilation Techniques, 2.2 LC², p. 98–99}}<ref name="Mitchell1970"/>


[[Smalltalk]] (c. 1983) pioneered new aspects of JIT compilations. For example, translation to machine code was done on demand, and the result was cached for later use. When memory became scarce, the system would delete some of this code and regenerate it when it was needed again.{{sfn|Aycock|2003}}<ref name="Schiffman1984" /> Sun's [[Self (programming language)|Self]] language improved these techniques extensively and was at one point the fastest Smalltalk system in the world, achieving up to half the speed of optimized C<ref name="Self" /> but with a fully object-oriented language.
[[Smalltalk]] (c. 1980) pioneered new aspects of JIT compilations. For example, translation to machine code was done on demand, and the result was cached for later use. When memory became scarce, the system would delete some of this code and regenerate it when it was needed again.{{sfn|Aycock|2003}}<ref name="Schiffman1984"/> Sun's [[Self (programming language)|Self]] language improved these techniques extensively and was at one point the fastest Smalltalk system in the world, achieving up to half the speed of optimized [[C (programming language)|C]]<ref name="Self"/> but with a fully [[object-oriented programming]] language.


Self was abandoned by Sun, but the research went into the Java language. The term "Just-in-time compilation" was borrowed from the manufacturing term "[[Just in time (business)|Just in time]]" and popularized by Java, with James Gosling using the term from 1993.{{sfn|Aycock|2003|loc=2.14 Java, p. 107, footnote 13}} Currently JITing is used by most implementations of the [[Java virtual machine|Java Virtual Machine]], as [[HotSpot (virtual machine)|HotSpot]] builds on, and extensively uses, this research base.
Self was abandoned by Sun, but the research went into the Java language. The term "Just-in-time compilation" was borrowed from the manufacturing term "[[Just in time (business)|Just in time]]" and popularized by Java, with James Gosling using the term from 1993.{{sfn|Aycock|2003|loc=2.14 Java, p. 107, footnote 13}} Currently JITing is used by most implementations of the [[Java virtual machine]], as [[HotSpot (virtual machine)|HotSpot]] builds on, and extensively uses, this research base.


The HP project Dynamo was an experimental JIT compiler where the "bytecode" format and the machine code format were the same; the system optimized [[PA-8000]] machine code.<ref name="Bala" /> Counterintuitively, this resulted in speed ups, in some cases of 30% since doing this permitted optimizations at the machine code level, for example, inlining code for better cache usage and optimizations of calls to dynamic libraries and many other run-time optimizations which conventional compilers are not able to attempt.<ref name="Jannotti" /><ref name="Dynamo" />
The HP project Dynamo was an experimental JIT compiler where the "bytecode" format and the machine code format were the same; the system optimized [[PA-8000]] machine code.<ref name="Bala"/> Counterintuitively, this resulted in speed ups, in some cases of 30% since doing this permitted optimizations at the machine code level, for example, inlining code for better cache usage and optimizations of calls to dynamic libraries and many other run-time optimizations which conventional compilers are not able to attempt.<ref name="Jannotti"/><ref name="Dynamo"/>


In November 2020, [[PHP]] 8.0 introduced a JIT compiler.<ref name="Tung" /> In October 2024, [[CPython]] introduced an experimental JIT compiler.<ref>{{Cite web |title=What's New In Python 3.13 |url=https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-jit-compiler |access-date=2024-11-27 |website=Python documentation |language=en}}</ref>
In November 2020, [[PHP]] 8.0 introduced a JIT compiler.<ref name="Tung"/> In October 2024, [[CPython]] introduced an experimental JIT compiler.<ref>{{Cite web |title=What's New In Python 3.13 |url=https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-jit-compiler |access-date=2024-11-27 |website=Python documentation |language=en}}</ref>


== Design ==
== Design ==
Line 23: Line 23:
By contrast, a traditional ''interpreted virtual machine'' will simply interpret the bytecode, generally with much lower performance. Some ''interpreter''s even interpret source code, without the step of first compiling to bytecode, with even worse performance. ''Statically-compiled code'' or ''native code'' is compiled prior to deployment. A ''dynamic compilation environment'' is one in which the compiler can be used during execution. A common goal of using JIT techniques is to reach or surpass the performance of [[static compilation]], while maintaining the advantages of bytecode interpretation: Much of the "heavy lifting" of parsing the original source code and performing basic optimization is often handled at compile time, prior to deployment: compilation from bytecode to machine code is much faster than compiling from source. The deployed bytecode is portable, unlike native code. Since the runtime has control over the compilation, like interpreted bytecode, it can run in a secure sandbox. Compilers from bytecode to machine code are easier to write, because the portable bytecode compiler has already done much of the work.
By contrast, a traditional ''interpreted virtual machine'' will simply interpret the bytecode, generally with much lower performance. Some ''interpreter''s even interpret source code, without the step of first compiling to bytecode, with even worse performance. ''Statically-compiled code'' or ''native code'' is compiled prior to deployment. A ''dynamic compilation environment'' is one in which the compiler can be used during execution. A common goal of using JIT techniques is to reach or surpass the performance of [[static compilation]], while maintaining the advantages of bytecode interpretation: Much of the "heavy lifting" of parsing the original source code and performing basic optimization is often handled at compile time, prior to deployment: compilation from bytecode to machine code is much faster than compiling from source. The deployed bytecode is portable, unlike native code. Since the runtime has control over the compilation, like interpreted bytecode, it can run in a secure sandbox. Compilers from bytecode to machine code are easier to write, because the portable bytecode compiler has already done much of the work.


JIT code generally offers far better performance than interpreters. In addition, it can in some cases offer better performance than static compilation, as many optimizations are only feasible at run-time:<ref name="Croce" /><ref name="stackoverflow-1" />
JIT code generally offers far better performance than interpreters. In addition, it can in some cases offer better performance than static compilation, as many optimizations are only feasible at run-time:<ref name="Croce"/><ref name="stackoverflow-1"/>


# The compilation can be optimized to the targeted CPU and the operating system model where the application runs. For example, JIT can choose [[SSE2]] vector CPU instructions when it detects that the CPU supports them. To obtain this level of optimization specificity with a static compiler, one must either compile a binary for each intended platform/architecture, or else include multiple versions of portions of the code within a single binary.
# The compilation can be optimized to the targeted CPU and the operating system model where the application runs. For example, JIT can choose [[SSE2]] vector CPU instructions when it detects that the CPU supports them. To obtain this level of optimization specificity with a static compiler, one must either compile a binary for each intended platform/architecture, or else include multiple versions of portions of the code within a single binary.
# The system is able to collect statistics about how the program is actually running in the environment it is in, and it can rearrange and recompile for optimum performance. However, some static compilers can also take profile information as input.
# The system is able to collect statistics about how the program is actually running in the environment it is in, and it can rearrange and recompile for optimum performance. However, some static compilers can also take profile information as input.
# The system can do global code optimizations (e.g. [[inline expansion|inlining]] of library functions) without losing the advantages of dynamic linking and without the overheads inherent to static compilers and linkers. Specifically, when doing global inline substitutions, a static compilation process may need run-time checks and ensure that a virtual call would occur if the actual class of the object overrides the inlined method, and boundary condition checks on array accesses may need to be processed within loops. With just-in-time compilation in many cases this processing can be moved out of loops, often giving large increases of speed.
# The system can do global code optimizations (e.g. [[inline expansion|inlining]] of [[Library (computing)|library]] functions) without losing the advantages of dynamic linking and without the overheads inherent to static compilers and linkers. Specifically, when doing global inline substitutions, a static compilation process may need run-time checks and ensure that a virtual call would occur if the actual class of the object overrides the inlined method, and boundary condition checks on array accesses may need to be processed within loops. With just-in-time compilation in many cases this processing can be moved out of loops, often giving large increases of speed.
# Although this is possible with statically compiled garbage collected languages, a bytecode system can more easily rearrange executed code for better cache utilization.
# Although this is possible with statically compiled garbage collected languages, a bytecode system can more easily rearrange executed code for better cache utilization.


Because a JIT must render and execute a native binary image at runtime, true machine-code JITs necessitate platforms that allow for data to be executed at runtime, making using such JITs on a [[Harvard architecture]]-based machine impossible; the same can be said for certain operating systems and virtual machines as well. However, a special type of "JIT" may potentially ''not'' target the physical machine's CPU architecture, but rather an optimized VM bytecode where limitations on raw machine code prevail, especially where that bytecode's VM eventually leverages a JIT to native code.<ref name="stackoverflow-2" />
Because a JIT must render and execute a native binary image at runtime, true machine-code JITs necessitate platforms that allow for data to be executed at runtime, making using such JITs on a [[Harvard architecture]]-based machine impossible; the same can be said for certain operating systems and virtual machines as well. However, a special type of "JIT" may potentially ''not'' target the physical machine's CPU architecture, but rather an optimized VM bytecode where limitations on raw machine code prevail, especially where that bytecode's VM eventually leverages a JIT to native code.<ref name="stackoverflow-2"/>


== Performance ==
== Performance ==


JIT causes a slight to noticeable delay in the initial execution of an application, due to the time taken to load and compile the input code. Sometimes this delay is called "startup time delay" or "warm-up time". In general, the more optimization JIT performs, the better the code it will generate, but the initial delay will also increase. A JIT compiler therefore has to make a trade-off between the compilation time and the quality of the code it hopes to generate. Startup time can include increased IO-bound operations in addition to JIT compilation: for example, the ''rt.jar'' class data file for the [[Java virtual machine|Java Virtual Machine]] (JVM) is 40 MB and the JVM must seek a lot of data in this contextually huge file.<ref name="Haase" />
JIT causes a slight to noticeable delay in the initial execution of an application, due to the time taken to load and compile the input code. Sometimes this delay is called "startup time delay" or "warm-up time". In general, the more optimization JIT performs, the better the code it will generate, but the initial delay will also increase. A JIT compiler therefore has to make a trade-off between the compilation time and the quality of the code it hopes to generate. Startup time can include increased IO-bound operations in addition to JIT compilation: for example, the ''rt.jar'' class data file for the [[Java virtual machine]] (JVM) is 40 MB and the JVM must seek a lot of data in this contextually huge file.<ref name="Haase"/>


One possible optimization, used by Sun's [[HotSpot (virtual machine)|HotSpot]] Java Virtual Machine, is to combine interpretation and JIT compilation. The application code is initially interpreted, but the JVM monitors which sequences of [[bytecode]] are frequently executed and translates them to machine code for direct execution on the hardware. For bytecode which is executed only a few times, this saves the compilation time and reduces the initial latency; for frequently executed bytecode, JIT compilation is used to run at high speed, after an initial phase of slow interpretation. Additionally, since a program spends most time executing a minority of its code, the reduced compilation time is significant. Finally, during the initial code interpretation, execution statistics can be collected before compilation, which helps to perform better optimization.<ref name="HotSpot" />
One possible optimization, used by Sun's [[HotSpot (virtual machine)|HotSpot]] Java virtual machine, is to combine interpretation and JIT compilation. The application code is initially interpreted, but the JVM monitors which sequences of [[bytecode]] are frequently executed and translates them to machine code for direct execution on the hardware. For bytecode which is executed only a few times, this saves the compilation time and reduces the initial latency; for frequently executed bytecode, JIT compilation is used to run at high speed, after an initial phase of slow interpretation. Further, since a program spends most time executing a minority of its code, the reduced compilation time is significant. Finally, during the initial code interpretation, execution statistics can be collected before compilation, which helps to perform better optimization.<ref name="HotSpot"/>


The correct tradeoff can vary due to circumstances. For example, Sun's Java Virtual Machine has two major modes—client and server. In client mode, minimal compilation and optimization is performed, to reduce startup time. In server mode, extensive compilation and optimization is performed, to maximize performance once the application is running by sacrificing startup time. Other Java just-in-time compilers have used a runtime measurement of the number of times a method has executed combined with the bytecode size of a method as a heuristic to decide when to compile.<ref name="Schilling" /> Still another uses the number of times executed combined with the detection of loops.<ref name="Suganuma" /> In general, it is much harder to accurately predict which methods to optimize in short-running applications than in long-running ones.<ref name="Arnold-2000" />
The correct tradeoff can vary due to circumstances. For example, Sun's Java virtual machine has two major modes—client and server. In client mode, minimal compilation and optimization is performed, to reduce startup time. In server mode, extensive compilation and optimization is performed, to maximize performance once the application is running by sacrificing startup time. Other Java just-in-time compilers have used a runtime measurement of the number of times a method has executed combined with the bytecode size of a method as a heuristic to decide when to compile.<ref name="Schilling"/> Still another uses the number of times executed combined with the detection of loops.<ref name="Suganuma"/> In general, it is much harder to accurately predict which methods to optimize in short-running applications than in long-running ones.<ref name="Arnold-2000"/>


[[Native Image Generator]] (Ngen) by [[Microsoft]] is another approach at reducing the initial delay.<ref name="MSDN" /> Ngen pre-compiles (or "pre-JITs") bytecode in a [[Common Intermediate Language]] image into machine native code. As a result, no runtime compilation is needed. [[.NET Framework]] 2.0 shipped with [[Visual Studio 2005]] runs Ngen on all of the Microsoft library DLLs right after the installation. Pre-jitting provides a way to improve the startup time. However, the quality of code it generates might not be as good as the one that is JITed, for the same reasons why code compiled statically, without [[profile-guided optimization]], cannot be as good as JIT compiled code in the extreme case: the lack of profiling data to drive, for instance, inline caching.<ref name="Arnold-2005" />
[[Native Image Generator]] (Ngen) by [[Microsoft]] is another approach at reducing the initial delay.<ref name="MSDN"/> Ngen pre-compiles (or "pre-JITs") bytecode in a [[Common Intermediate Language]] image into machine native code. As a result, no runtime compilation is needed. [[.NET Framework]] 2.0 shipped with [[Visual Studio 2005]] runs Ngen on all of the Microsoft [[dynamic-link library]] (DLL) files right after installing. Pre-jitting provides a way to reduce startup time. However, the quality of code it generates may be lower than the one that is JITed, for the same reasons why code compiled statically, without [[profile-guided optimization]], cannot be as good as JIT compiled code in the extreme case: the lack of profiling data to drive, for instance, inline caching.<ref name="Arnold-2005"/>


There also exist Java implementations that combine an [[ahead-of-time compilation|AOT (ahead-of-time) compiler]] with either a JIT compiler ([[Excelsior JET]]) or interpreter ([[GNU Compiler for Java]]).
There also exist Java implementations that combine an [[ahead-of-time compilation|AOT (ahead-of-time) compiler]] with either a JIT compiler ([[Excelsior JET]]) or interpreter ([[GNU Compiler for Java]]).


JIT compilation may not reliably achieve its goal, namely entering a steady state of improved performance after a short initial warmup period.{{sfn|Barrett|Bolz-Tereick|Killick|Mount|2017|p=3}}{{sfn|Traini|Cortellessa|Di Pompeo|Tucci|2022|p=1}} Across eight different virtual machines, {{harvtxt|Barrett|Bolz-Tereick|Killick|Mount|Tratt|2017}} measured six widely-used [[microbenchmarks]] which are commonly used by virtual machine implementors as optimisation targets, running them repeatedly within a single process execution.{{sfn|Barrett|Bolz-Tereick|Killick|Mount|2017|p=5-6}} On [[Linux]], they found that 8.7% to 9.6% of process executions failed to reach a steady state of performance, 16.7% to 17.9% entered a steady state of ''reduced'' performance after a warmup period, and 56.5% pairings of a specific virtual machine running a specific benchmark failed to consistently see a steady-state non-degradation of performance across multiple executions (i.e., at least one execution failed to reach a steady state or saw reduced performance in the steady state). Even where an improved steady-state was reached, it sometimes took many hundreds of iterations.{{sfn|Barrett|Bolz-Tereick|Killick|Mount|2017|p=12-13}} {{harvtxt|Traini|Cortellessa|Di Pompeo|Tucci|2022}} instead focused on the HotSpot virtual machine but with a much wider array of benchmarks,{{sfn|Traini|Cortellessa|Di Pompeo|Tucci|2022|p=17-23}} finding that 10.9% of process executions failed to reach a steady state of performance, and 43.5% of benchmarks did not consistently attain a steady state across multiple executions.{{sfn|Traini|Cortellessa|Di Pompeo|Tucci|2022|p=26-29}}
JIT compilation may not reliably achieve its goal, namely entering a steady state of improved performance after a short initial warmup period.{{sfn|Barrett|Bolz-Tereick|Killick|Mount|2017|p=3}}{{sfn|Traini|Cortellessa|Di Pompeo|Tucci|2022|p=1}} Across eight different virtual machines, {{harvtxt|Barrett|Bolz-Tereick|Killick|Mount|Tratt|2017}} measured six widely used [[microbenchmarks]] which are commonly used by virtual machine implementors as optimisation targets, running them repeatedly within a single process execution.{{sfn|Barrett|Bolz-Tereick|Killick|Mount|2017|p=5-6}} On [[Linux]], they found that 8.7% to 9.6% of process executions failed to reach a steady state of performance, 16.7% to 17.9% entered a steady state of ''reduced'' performance after a warmup period, and 56.5% pairings of a specific virtual machine running a specific benchmark failed to consistently see a steady-state non-degradation of performance across multiple executions (i.e., at least one execution failed to reach a steady state or saw reduced performance in the steady state). Even where an improved steady-state was reached, it sometimes took many hundreds of iterations.{{sfn|Barrett|Bolz-Tereick|Killick|Mount|2017|p=12-13}} {{harvtxt|Traini|Cortellessa|Di Pompeo|Tucci|2022}} instead focused on the HotSpot virtual machine but with a much wider array of benchmarks,{{sfn|Traini|Cortellessa|Di Pompeo|Tucci|2022|p=17-23}} finding that 10.9% of process executions failed to reach a steady state of performance, and 43.5% of benchmarks did not consistently attain a steady state across multiple executions.{{sfn|Traini|Cortellessa|Di Pompeo|Tucci|2022|p=26-29}}


== Security ==
== Security ==
Line 50: Line 50:
JIT compilation fundamentally uses executable data, and thus poses security challenges and possible exploits.
JIT compilation fundamentally uses executable data, and thus poses security challenges and possible exploits.


Implementation of JIT compilation consists of compiling source code or byte code to machine code and executing it. This is generally done directly in memory: the JIT compiler outputs the machine code directly into memory and immediately executes it, rather than outputting it to disk and then invoking the code as a separate program, as in usual ahead of time compilation. In modern architectures this runs into a problem due to [[executable space protection]]: arbitrary memory cannot be executed, as otherwise there is a potential security hole. Thus memory must be marked as executable; for security reasons this should be done ''after'' the code has been written to memory, and marked read-only, as writable/executable memory is a security hole (see [[W^X]]).<ref name="Bendersky" /> For instance Firefox's JIT compiler for Javascript introduced this protection in a release version with Firefox 46.<ref name="De Mooij" />
Implementation of JIT compilation consists of compiling source code or byte code to machine code and executing it. This is generally done directly in memory: the JIT compiler outputs the machine code directly into memory and immediately executes it, rather than outputting it to disk and then invoking the code as a separate program, as in usual ahead of time compilation. In modern architectures this runs into a problem due to [[executable space protection]]: arbitrary memory cannot be executed, as otherwise there is a potential security hole. Thus memory must be marked as executable; for security reasons this should be done ''after'' the code has been written to memory, and marked read-only, as writable/executable memory is a security hole (see [[W^X]]).<ref name="Bendersky"/> For instance Firefox's JIT compiler for [[JavaScript]] introduced this protection in a release version with Firefox 46.<ref name="De Mooij"/>


[[JIT spraying]] is a class of [[computer security exploit]]s that use JIT compilation for [[heap spraying]]: the resulting memory is then executable, which allows an exploit if execution can be moved into the heap.
[[JIT spraying]] is a class of [[computer security exploit]]s that use JIT compilation for [[heap spraying]]: the resulting memory is then executable, which allows an exploit if execution can be moved into the heap.
Line 82: Line 82:


{{reflist|refs=
{{reflist|refs=
<ref name="Michigan">{{citation | title = Languages, Compilers, and Runtime Systems | access-date = March 15, 2018 | publisher = University of Michigan, Computer Science and Engineering | url = https://www.eecs.umich.edu/eecs/research/area.html?areaname=languages-compilers | archive-date = March 26, 2018 | archive-url = https://web.archive.org/web/20180326105004/http://eecs.umich.edu/eecs/research/area.html?areaname=languages-compilers | url-status = dead }}</ref>
<ref name="Michigan">{{citation |title=Languages, Compilers, and Runtime Systems |access-date=March 15, 2018 |publisher=University of Michigan, Computer Science and Engineering |url=https://www.eecs.umich.edu/eecs/research/area.html?areaname=languages-compilers |archive-date=March 26, 2018 |archive-url=https://web.archive.org/web/20180326105004/http://eecs.umich.edu/eecs/research/area.html?areaname=languages-compilers |url-status=dead}}</ref>
<ref name="Notario">{{ cite news | url = https://blogs.msdn.microsoft.com/davidnotario/2005/08/15/does-the-jit-take-advantage-of-my-cpu/ | title = Does the JIT take advantage of my CPU? | work = David Notario's WebLog | access-date = 2018-12-03 }}</ref>
<ref name="Notario">{{cite news |url=https://blogs.msdn.microsoft.com/davidnotario/2005/08/15/does-the-jit-take-advantage-of-my-cpu/ |title=Does the JIT take advantage of my CPU? |work=David Notario's WebLog |access-date=2018-12-03}}</ref>
<ref name="McCarthy1960">{{ cite journal | last = McCarthy | first = J. | author-link = John McCarthy (computer scientist) | title = Recursive functions of symbolic expressions and their computation by machine, Part I | journal = Communications of the ACM | date = April 1960 | volume = 3 | issue = 4 | pages = 184–195 | doi = 10.1145/367177.367199 | citeseerx = 10.1.1.111.8833| s2cid = 1489409 }}<!-- | access-date=24 May 2010--></ref>
<ref name="McCarthy1960">{{cite journal |last1=McCarthy |first1=J. |author1-link=John McCarthy (computer scientist) |date=April 1960 |title=Recursive functions of symbolic expressions and their computation by machine, Part I |journal=Communications of the ACM |volume=3 |issue=4 |pages=184–195 |doi=10.1145/367177.367199 |citeseerx=10.1.1.111.8833 |s2cid=1489409}}<!-- |access-date=24 May 2010--></ref>
<ref name=Mitchell1970>{{ cite journal | last = Mitchell | first = J.G. | title = The design and construction of flexible and efficient interactive programming systems | year = 1970 }}</ref>
<ref name=Mitchell1970>{{cite journal |last1=Mitchell |first1=J.G. |year=1970 |title=The design and construction of flexible and efficient interactive programming systems}}</ref>
<ref name="Schiffman1984">{{ Cite book | last1 = Deutsch | first1 = L.P. | last2 = Schiffman | first2 = A.M. | title = Proceedings of the 11th ACM SIGACT-SIGPLAN symposium on Principles of programming languages - POPL '84 | chapter = Efficient implementation of the smalltalk-80 system | year = 1984 | pages = 297–302 | doi = 10.1145/800017.800542 | chapter-url = http://webpages.charter.net/allanms/popl84.pdf | isbn = 0-89791-125-3 | s2cid = 3045432 | url-status = dead | archive-url = https://web.archive.org/web/20040618105930/http://webpages.charter.net/allanms/popl84.pdf | archive-date = 2004-06-18 }}</ref>
<ref name="Schiffman1984">{{Cite book |last1=Deutsch |first1=L.P. |last2=Schiffman |first2=A.M. |title=Proceedings of the 11th ACM SIGACT-SIGPLAN symposium on Principles of programming languages - POPL '84 |chapter=Efficient implementation of the smalltalk-80 system |year=1984 |pages=297–302 |doi=10.1145/800017.800542 |chapter-url=http://webpages.charter.net/allanms/popl84.pdf |isbn=0-89791-125-3 |s2cid=3045432 |url-status=dead |archive-url=https://web.archive.org/web/20040618105930/http://webpages.charter.net/allanms/popl84.pdf |archive-date=2004-06-18}}</ref>
<ref name="Self">{{cite web |url=http://research.sun.com/jtech/pubs/97-pep.ps |title=97-pep.ps |website=research.sun.com |access-date=15 January 2022 |archive-url=https://web.archive.org/web/20061124224739/http://research.sun.com/jtech/pubs/97-pep.ps |archive-date=24 November 2006 |url-status=dead}}</ref>
<ref name="Self">{{cite web |url=http://research.sun.com/jtech/pubs/97-pep.ps |title=97-pep.ps |website=research.sun.com |access-date=15 January 2022 |archive-url=https://web.archive.org/web/20061124224739/http://research.sun.com/jtech/pubs/97-pep.ps |archive-date=24 November 2006 |url-status=dead}}</ref>
<ref name="Bala">[http://cseweb.ucsd.edu/classes/sp00/cse231/dynamopldi.pdf "Dynamo: A Transparent Dynamic Optimization System". Vasanth Bala, Evelyn Duesterwald, Sanjeev Banerjia. PLDI '00 Proceedings of the ACM SIGPLAN 2000 conference on Programming language design and implementation. pages 1 to 12. DOI 10.1145/349299.349303. Retrieved March 28, 2012]</ref>
<ref name="Bala">[http://cseweb.ucsd.edu/classes/sp00/cse231/dynamopldi.pdf "Dynamo: A Transparent Dynamic Optimization System". Vasanth Bala, Evelyn Duesterwald, Sanjeev Banerjia. PLDI '00 Proceedings of the ACM SIGPLAN 2000 conference on Programming language design and implementation. pages 1 to 12. DOI 10.1145/349299.349303. Retrieved March 28, 2012]</ref>
<ref name="Jannotti">{{ cite web | author = John Jannotti | url = https://arstechnica.com/reviews/1q00/dynamo/dynamo-1.html | title = HP's Dynamo | website = Ars Technica | access-date = 2013-07-05 }}</ref>
<ref name="Jannotti">{{cite web |author=John Jannotti |url=https://arstechnica.com/reviews/1q00/dynamo/dynamo-1.html |title=HP's Dynamo |website=Ars Technica |access-date=2013-07-05}}</ref>
<ref name="Dynamo">{{ cite web | url = http://www.hpl.hp.com/cambridge/projects/Dynamo/ | title = The HP Dynamo Project | access-date = 2016-04-12 | url-status = unfit | archive-url = https://web.archive.org/web/20021019114947/http://www.hpl.hp.com/cambridge/projects/Dynamo/ | archive-date = October 19, 2002 }}</ref>
<ref name="Dynamo">{{cite web |url=http://www.hpl.hp.com/cambridge/projects/Dynamo/ |title=The HP Dynamo Project |access-date=2016-04-12 |url-status=unfit |archive-url=https://web.archive.org/web/20021019114947/http://www.hpl.hp.com/cambridge/projects/Dynamo/ |archive-date=October 19, 2002}}</ref>
<ref name="Tung">{{ cite web | url = https://www.zdnet.com/article/programming-language-php-8-is-out-this-new-jit-compiler-points-to-better-performance/ | title = Programming language PHP 8 is out: This new JIT compiler points to better performance | last = Tung | first = Liam | date = 27 November 2020 | website = [[ZDNet]] | access-date = 28 November 2020 }}</ref>
<ref name="Tung">{{cite web |url=https://www.zdnet.com/article/programming-language-php-8-is-out-this-new-jit-compiler-points-to-better-performance/ |title=Programming language PHP 8 is out: This new JIT compiler points to better performance |last1=Tung |first1=Liam |date=27 November 2020 |website=[[ZDNet]] |access-date=28 November 2020}}</ref>
<ref name="Croce">{{ cite web | url = https://www.cs.columbia.edu/~aho/cs6998/Lectures/14-09-22_Croce_JIT.pdf | title = Just in Time Compilation | last = Croce | first = Louis | website = Columbia University | archive-url = https://web.archive.org/web/20180503145240/http://www.cs.columbia.edu/~aho/cs6998/Lectures/14-09-22_Croce_JIT.pdf | archive-date = 2018-05-03 | url-status = dead }}</ref>
<ref name="Croce">{{cite web |url=https://www.cs.columbia.edu/~aho/cs6998/Lectures/14-09-22_Croce_JIT.pdf |title=Just in Time Compilation |last1=Croce |first1=Louis |website=Columbia University |archive-url=https://web.archive.org/web/20180503145240/http://www.cs.columbia.edu/~aho/cs6998/Lectures/14-09-22_Croce_JIT.pdf |archive-date=2018-05-03 |url-status=dead}}</ref>
<ref name="stackoverflow-1">{{ cite web | url = https://stackoverflow.com/q/2106380 | title = What are the advantages of JIT vs. AOT compilation | date = Jan 21, 2010 | website = Stack Overflow }}</ref>
<ref name="stackoverflow-1">{{cite web |url=https://stackoverflow.com/q/2106380 |title=What are the advantages of JIT vs. AOT compilation |date=Jan 21, 2010 |website=Stack Overflow}}</ref>
<ref name="stackoverflow-2">{{ cite web | url = https://stackoverflow.com/q/42919339 | title = Compile a JIT based lang to Webassembly | website = Stack Overflow | access-date = 2018-12-04 }}</ref>
<ref name="stackoverflow-2">{{cite web |url=https://stackoverflow.com/q/42919339 |title=Compile a JIT based lang to Webassembly |website=Stack Overflow |access-date=2018-12-04}}</ref>
<ref name="Haase">{{ cite web | url = http://java.sun.com/developer/technicalArticles/javase/consumerjre#Quickstarter | title = Consumer JRE: Leaner, Meaner Java Technology | publisher = Sun Microsystems | last = Haase | first = Chet | date = May 2007 | access-date = 2007-07-27 }}</ref>
<ref name="Haase">{{cite web |url=http://java.sun.com/developer/technicalArticles/javase/consumerjre#Quickstarter |title=Consumer JRE: Leaner, Meaner Java Technology |publisher=Sun Microsystems |last1=Haase |first1=Chet |date=May 2007 |access-date=2007-07-27}}</ref>
<ref name="HotSpot">{{ cite web | url = http://www.oracle.com/technetwork/java/whitepaper-135217.html | title = The Java HotSpot Performance Engine Architecture | publisher = Oracle.com | access-date = 2013-07-05 }}</ref>
<ref name="HotSpot">{{cite web |url=http://www.oracle.com/technetwork/java/whitepaper-135217.html |title=The Java HotSpot Performance Engine Architecture |publisher=Oracle.com |access-date=2013-07-05}}</ref>
<ref name="Schilling">{{ cite journal | title = The simplest heuristics may be the best in Java JIT compilers | last = Schilling | first = Jonathan L. | journal = [[SIGPLAN Notices]] | volume = 38 | issue = 2 | date = February 2003 | pages = 36–46 | doi = 10.1145/772970.772975 | s2cid = 15117148 | url = http://www.sco.com/developers/java/news/jit-heur.pdf | url-status = dead | archive-url = https://web.archive.org/web/20150924095409/http://www.sco.com/developers/java/news/jit-heur.pdf | archive-date = 2015-09-24 }}</ref>
<ref name="Schilling">{{cite journal |title=The simplest heuristics may be the best in Java JIT compilers |last1=Schilling |first1=Jonathan L. |journal=[[SIGPLAN Notices]] |volume=38 |issue=2 |date=February 2003 |pages=36–46 |doi=10.1145/772970.772975 |s2cid=15117148 |url=http://www.sco.com/developers/java/news/jit-heur.pdf |url-status=dead |archive-url=https://web.archive.org/web/20150924095409/http://www.sco.com/developers/java/news/jit-heur.pdf |archive-date=2015-09-24}}</ref>
<ref name="Suganuma">Toshio Suganuma, Toshiaki Yasue, Motohiro Kawahito, Hideaki Komatsu, Toshio Nakatani, "A dynamic optimization framework for a Java just-in-time compiler", ''Proceedings of the 16th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications'' (OOPSLA '01), pp. 180–195, October 14–18, 2001.</ref>
<ref name="Suganuma">Toshio Suganuma, Toshiaki Yasue, Motohiro Kawahito, Hideaki Komatsu, Toshio Nakatani, "A dynamic optimization framework for a Java just-in-time compiler", ''Proceedings of the 16th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications'' (OOPSLA '01), pp. 180–195, October 14–18, 2001.</ref>
<ref name="Arnold-2000">Matthew Arnold, Michael Hind, Barbara G. Ryder, "An Empirical Study of Selective Optimization", ''Proceedings of the 13th International Workshop on Languages and Compilers for Parallel Computing-Revised Papers'', pp. 49–67, August 10–12, 2000.</ref>
<ref name="Arnold-2000">Matthew Arnold, Michael Hind, Barbara G. Ryder, "An Empirical Study of Selective Optimization", ''Proceedings of the 13th International Workshop on Languages and Compilers for Parallel Computing-Revised Papers'', pp. 49–67, August 10–12, 2000.</ref>
<ref name="MSDN">{{ cite web | url = http://msdn2.microsoft.com/en-us/library/6t9t5wcf(VS.80).aspx | title = Native Image Generator (Ngen.exe) | date = 5 December 2006 | publisher = Msdn2.microsoft.com | access-date = 2013-07-05 }}</ref>
<ref name="MSDN">{{cite web |url=http://msdn2.microsoft.com/en-us/library/6t9t5wcf(VS.80).aspx |title=Native Image Generator (Ngen.exe) |date=5 December 2006 |publisher=Msdn2.microsoft.com |access-date=2013-07-05}}</ref>
<ref name="Arnold-2005">{{ cite journal | title = A Survey of Adaptive Optimization in Virtual Machines | last = Sweeney | first = Arnold | journal = [[Proceedings of the IEEE]] | volume = 92 | issue = 2 | date = February 2005 | pages = 449–466 | url = http://researcher.ibm.com/researcher/files/us-hindm/RC23429.pdf | url-status = dead | archive-url = https://web.archive.org/web/20160629150108/http://researcher.ibm.com/researcher/files/us-hindm/RC23429.pdf | archive-date = 2016-06-29 }}</ref>
<ref name="Arnold-2005">{{cite journal |last1=Sweeney |first1=Arnold |date=February 2005 |title=A Survey of Adaptive Optimization in Virtual Machines |journal=[[Proceedings of the IEEE]] |volume=92 |issue=2 |pages=449–466 |url=http://researcher.ibm.com/researcher/files/us-hindm/RC23429.pdf |url-status=dead |archive-url=https://web.archive.org/web/20160629150108/http://researcher.ibm.com/researcher/files/us-hindm/RC23429.pdf |archive-date=2016-06-29}}</ref>
<ref name="Bendersky">[http://eli.thegreenplace.net/2013/11/05/how-to-jit-an-introduction/ "How to JIT&nbsp;– an introduction", Eli Bendersky, November 5th, 2013 at 5:59 am]</ref>
<ref name="Bendersky">[http://eli.thegreenplace.net/2013/11/05/how-to-jit-an-introduction/ "How to JIT&nbsp;– an introduction", Eli Bendersky, November 5th, 2013 at 5:59 am]</ref>
<ref name="De Mooij">{{ cite web | last1 = De Mooij | first1 = Jan | title = W^X JIT-code enabled in Firefox | url = http://jandemooij.nl/blog/2015/12/29/wx-jit-code-enabled-in-firefox/ | website = Jan De Mooij | access-date = 11 May 2016 }}</ref>
<ref name="De Mooij">{{cite web |last1=De Mooij |first1=Jan |title=W^X JIT-code enabled in Firefox |url=http://jandemooij.nl/blog/2015/12/29/wx-jit-code-enabled-in-firefox/ |website=Jan De Mooij |access-date=11 May 2016}}</ref>
}}
}}


== Bibliography ==
== Bibliography ==


* {{ cite journal | doi = 10.1145/3133876 | arxiv = 1602.00602 | date = 12 October 2017 | title = Virtual machine warmup blows hot and cold | journal = Proceedings of the ACM on Programming Languages | last1 = Barrett | first1 = Ed | last2 = Bolz-Tereick | first2 = Carl Friedrich | last3 = Killick | first3 = Rebecca | last4 = Mount | first4 = Sarah | last5 = Tratt | first5 = Laurence | volume = 1 | pages = 1–27 | s2cid = 1036324 }}
* {{Cite journal |last1=Barrett |first1=Ed |last2=Bolz-Tereick |first2=Carl Friedrich |last3=Killick |first3=Rebecca |last4=Mount |first4=Sarah |last5=Tratt |first5=Laurence |date=12 October 2017 |title=Virtual machine warmup blows hot and cold |journal=Proceedings of the ACM on Programming Languages |volume=1 |pages=1–27 |doi=10.1145/3133876 |arxiv=1602.00602 |s2cid=1036324}}
* {{ Cite journal | arxiv = 2209.15369 | date = 30 September 2022 | title = Towards effective assessment of steady state performance in Java software: Are we there yet? | last1 = Traini | first1 = Luca | last2 = Cortellessa | first2 = Vittorio | last3 = Di Pompeo | first3 = Daniele | last4 = Tucci | first4 = Michele | journal = Empirical Software Engineering | volume = 28 | doi = 10.1007/s10664-022-10247-x | s2cid = 252668652 }}
* {{Cite journal |last1=Traini |first1=Luca |last2=Cortellessa |first2=Vittorio |last3=Di Pompeo |first3=Daniele |last4=Tucci |first4=Michele |date=30 September 2022 |arxiv=2209.15369 |title=Towards effective assessment of steady state performance in Java software: Are we there yet? |journal=Empirical Software Engineering |volume=28 |doi=10.1007/s10664-022-10247-x |s2cid=252668652}}
* {{Cite journal | last = Aycock | first = J. | title = A brief history of just-in-time | doi = 10.1145/857076.857077 | journal = ACM Computing Surveys | volume = 35 | issue = 2 | pages = 97–113 | date = June 2003  | citeseerx = 10.1.1.97.3985 | s2cid = 15345671 }}
* {{Cite journal |last1=Aycock |first1=J. |date=June 2003 |title=A brief history of just-in-time |doi=10.1145/857076.857077 |journal=ACM Computing Surveys |volume=35 |issue=2 |pages=97–113 |citeseerx=10.1.1.97.3985 |s2cid=15345671}}
* {{Cite journal | last = Thompson | first = K. | author-link = Ken Thompson | title = Programming Techniques: Regular expression search algorithm | doi = 10.1145/363347.363387 | journal = Communications of the ACM | volume = 11 | issue = 6 | pages = 419–422 | year = 1968 | s2cid = 21260384 | doi-access = free }}
* {{Cite journal |last1=Thompson |first1=K. |author1-link=Ken Thompson |year=1968 |title=Programming Techniques: Regular expression search algorithm |doi=10.1145/363347.363387 |journal=Communications of the ACM |volume=11 |issue=6 |pages=419–422 |s2cid=21260384 |doi-access=free}}


== External links ==
== External links ==


* [https://web.archive.org/web/20020905042721/http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?just-in-time Free Online Dictionary of Computing entry]
* [https://web.archive.org/web/20020905042721/http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?just-in-time Free Online Dictionary of Computing entry]
* [https://developer.mozilla.org/En/Nanojit Mozilla Nanojit] {{Webarchive|url=https://web.archive.org/web/20120509215101/https://developer.mozilla.org/En/Nanojit |date=2012-05-09 }}: A small, cross-platform C++ library that emits machine code. It is used as the JIT for the Mozilla [[Tamarin (JavaScript engine)|Tamarin]] and [[SpiderMonkey (JavaScript engine)|SpiderMonkey]] Javascript engines.
* [https://developer.mozilla.org/En/Nanojit Mozilla Nanojit] {{Webarchive|url=https://web.archive.org/web/20120509215101/https://developer.mozilla.org/En/Nanojit |date=2012-05-09}}: A small, [[cross-platform software]] [[C++]] library that emits machine code. It is used as the JIT for the Mozilla [[Tamarin (software)|Tamarin]] and [[SpiderMonkey]] [[JavaScript engine]]s.
* [http://software.intel.com/sites/products/documentation/hpc/vtune/windows/jit_profiling.pdf Profiling Runtime Generated and Interpreted Code using the VTune Performance Analyzer]
* [http://software.intel.com/sites/products/documentation/hpc/vtune/windows/jit_profiling.pdf Profiling Runtime Generated and Interpreted Code using the VTune Performance Analyzer]



Latest revision as of 04:52, 24 June 2025

Template:Short description Template:Program execution In computing, just-in-time (JIT) compilation (also dynamic translation or run-time compilations)[1] is compilation (of computer code) during execution of a program (at run time) rather than before execution.Template:Sfn This may consist of source code translation but is more commonly bytecode translation to machine code, which is then executed directly. A system implementing a JIT compiler typically continuously analyses the code being executed and identifies parts of the code where the speedup gained from compilation or recompilation would outweigh the overhead of compiling that code.

JIT compilation is a combination of the two traditional approaches to translation to machine code: ahead-of-time compilation (AOT), and interpretation, which combines some advantages and drawbacks of both.Template:Sfn Roughly, JIT compilation combines the speed of compiled code with the flexibility of interpretation, with the overhead of an interpreter and the additional overhead of compiling and linking (not just interpreting). JIT compilation is a form of dynamic compilation, and allows adaptive optimization such as dynamic recompilation and microarchitecture-specific speedups.Template:Refn[2] Interpretation and JIT compilation are particularly suited for dynamic programming languages, as the runtime system can handle late-bound data types and enforce security guarantees.

History

The earliest published JIT compiler is generally attributed to work on LISP by John McCarthy in 1960.Template:Sfn In his seminal paper Recursive functions of symbolic expressions and their computation by machine, Part I, he mentions functions that are translated during runtime, thereby sparing the need to save the compiler output to punch cards[3] (although this would be more accurately known as a "Compile and go system"). Another early example was by Ken Thompson, who in 1968 gave one of the first applications of regular expressions, here for pattern matching in the text editor QED.Template:Sfn For speed, Thompson implemented regular expression matching by JITing to IBM 7094 code on the Compatible Time-Sharing System.Template:Sfn An influential technique for deriving compiled code from interpretation was pioneered by James G. Mitchell in 1970, which he implemented for the experimental language LC².Template:Sfn[4]

Smalltalk (c. 1980) pioneered new aspects of JIT compilations. For example, translation to machine code was done on demand, and the result was cached for later use. When memory became scarce, the system would delete some of this code and regenerate it when it was needed again.Template:Sfn[5] Sun's Self language improved these techniques extensively and was at one point the fastest Smalltalk system in the world, achieving up to half the speed of optimized C[6] but with a fully object-oriented programming language.

Self was abandoned by Sun, but the research went into the Java language. The term "Just-in-time compilation" was borrowed from the manufacturing term "Just in time" and popularized by Java, with James Gosling using the term from 1993.Template:Sfn Currently JITing is used by most implementations of the Java virtual machine, as HotSpot builds on, and extensively uses, this research base.

The HP project Dynamo was an experimental JIT compiler where the "bytecode" format and the machine code format were the same; the system optimized PA-8000 machine code.[7] Counterintuitively, this resulted in speed ups, in some cases of 30% since doing this permitted optimizations at the machine code level, for example, inlining code for better cache usage and optimizations of calls to dynamic libraries and many other run-time optimizations which conventional compilers are not able to attempt.[8][9]

In November 2020, PHP 8.0 introduced a JIT compiler.[10] In October 2024, CPython introduced an experimental JIT compiler.[11]

Design

In a bytecode-compiled system, source code is translated to an intermediate representation known as bytecode. Bytecode is not the machine code for any particular computer, and may be portable among computer architectures. The bytecode may then be interpreted by, or run on a virtual machine. The JIT compiler reads the bytecodes in many sections (or in full, rarely) and compiles them dynamically into machine code so the program can run faster. This can be done per-file, per-function or even on any arbitrary code fragment; the code can be compiled when it is about to be executed (hence the name "just-in-time"), and then cached and reused later without needing to be recompiled.

By contrast, a traditional interpreted virtual machine will simply interpret the bytecode, generally with much lower performance. Some interpreters even interpret source code, without the step of first compiling to bytecode, with even worse performance. Statically-compiled code or native code is compiled prior to deployment. A dynamic compilation environment is one in which the compiler can be used during execution. A common goal of using JIT techniques is to reach or surpass the performance of static compilation, while maintaining the advantages of bytecode interpretation: Much of the "heavy lifting" of parsing the original source code and performing basic optimization is often handled at compile time, prior to deployment: compilation from bytecode to machine code is much faster than compiling from source. The deployed bytecode is portable, unlike native code. Since the runtime has control over the compilation, like interpreted bytecode, it can run in a secure sandbox. Compilers from bytecode to machine code are easier to write, because the portable bytecode compiler has already done much of the work.

JIT code generally offers far better performance than interpreters. In addition, it can in some cases offer better performance than static compilation, as many optimizations are only feasible at run-time:[12][13]

  1. The compilation can be optimized to the targeted CPU and the operating system model where the application runs. For example, JIT can choose SSE2 vector CPU instructions when it detects that the CPU supports them. To obtain this level of optimization specificity with a static compiler, one must either compile a binary for each intended platform/architecture, or else include multiple versions of portions of the code within a single binary.
  2. The system is able to collect statistics about how the program is actually running in the environment it is in, and it can rearrange and recompile for optimum performance. However, some static compilers can also take profile information as input.
  3. The system can do global code optimizations (e.g. inlining of library functions) without losing the advantages of dynamic linking and without the overheads inherent to static compilers and linkers. Specifically, when doing global inline substitutions, a static compilation process may need run-time checks and ensure that a virtual call would occur if the actual class of the object overrides the inlined method, and boundary condition checks on array accesses may need to be processed within loops. With just-in-time compilation in many cases this processing can be moved out of loops, often giving large increases of speed.
  4. Although this is possible with statically compiled garbage collected languages, a bytecode system can more easily rearrange executed code for better cache utilization.

Because a JIT must render and execute a native binary image at runtime, true machine-code JITs necessitate platforms that allow for data to be executed at runtime, making using such JITs on a Harvard architecture-based machine impossible; the same can be said for certain operating systems and virtual machines as well. However, a special type of "JIT" may potentially not target the physical machine's CPU architecture, but rather an optimized VM bytecode where limitations on raw machine code prevail, especially where that bytecode's VM eventually leverages a JIT to native code.[14]

Performance

JIT causes a slight to noticeable delay in the initial execution of an application, due to the time taken to load and compile the input code. Sometimes this delay is called "startup time delay" or "warm-up time". In general, the more optimization JIT performs, the better the code it will generate, but the initial delay will also increase. A JIT compiler therefore has to make a trade-off between the compilation time and the quality of the code it hopes to generate. Startup time can include increased IO-bound operations in addition to JIT compilation: for example, the rt.jar class data file for the Java virtual machine (JVM) is 40 MB and the JVM must seek a lot of data in this contextually huge file.[15]

One possible optimization, used by Sun's HotSpot Java virtual machine, is to combine interpretation and JIT compilation. The application code is initially interpreted, but the JVM monitors which sequences of bytecode are frequently executed and translates them to machine code for direct execution on the hardware. For bytecode which is executed only a few times, this saves the compilation time and reduces the initial latency; for frequently executed bytecode, JIT compilation is used to run at high speed, after an initial phase of slow interpretation. Further, since a program spends most time executing a minority of its code, the reduced compilation time is significant. Finally, during the initial code interpretation, execution statistics can be collected before compilation, which helps to perform better optimization.[16]

The correct tradeoff can vary due to circumstances. For example, Sun's Java virtual machine has two major modes—client and server. In client mode, minimal compilation and optimization is performed, to reduce startup time. In server mode, extensive compilation and optimization is performed, to maximize performance once the application is running by sacrificing startup time. Other Java just-in-time compilers have used a runtime measurement of the number of times a method has executed combined with the bytecode size of a method as a heuristic to decide when to compile.[17] Still another uses the number of times executed combined with the detection of loops.[18] In general, it is much harder to accurately predict which methods to optimize in short-running applications than in long-running ones.[19]

Native Image Generator (Ngen) by Microsoft is another approach at reducing the initial delay.[20] Ngen pre-compiles (or "pre-JITs") bytecode in a Common Intermediate Language image into machine native code. As a result, no runtime compilation is needed. .NET Framework 2.0 shipped with Visual Studio 2005 runs Ngen on all of the Microsoft dynamic-link library (DLL) files right after installing. Pre-jitting provides a way to reduce startup time. However, the quality of code it generates may be lower than the one that is JITed, for the same reasons why code compiled statically, without profile-guided optimization, cannot be as good as JIT compiled code in the extreme case: the lack of profiling data to drive, for instance, inline caching.[21]

There also exist Java implementations that combine an AOT (ahead-of-time) compiler with either a JIT compiler (Excelsior JET) or interpreter (GNU Compiler for Java).

JIT compilation may not reliably achieve its goal, namely entering a steady state of improved performance after a short initial warmup period.Template:SfnTemplate:Sfn Across eight different virtual machines, Template:Harvtxt measured six widely used microbenchmarks which are commonly used by virtual machine implementors as optimisation targets, running them repeatedly within a single process execution.Template:Sfn On Linux, they found that 8.7% to 9.6% of process executions failed to reach a steady state of performance, 16.7% to 17.9% entered a steady state of reduced performance after a warmup period, and 56.5% pairings of a specific virtual machine running a specific benchmark failed to consistently see a steady-state non-degradation of performance across multiple executions (i.e., at least one execution failed to reach a steady state or saw reduced performance in the steady state). Even where an improved steady-state was reached, it sometimes took many hundreds of iterations.Template:Sfn Template:Harvtxt instead focused on the HotSpot virtual machine but with a much wider array of benchmarks,Template:Sfn finding that 10.9% of process executions failed to reach a steady state of performance, and 43.5% of benchmarks did not consistently attain a steady state across multiple executions.Template:Sfn

Security

JIT compilation fundamentally uses executable data, and thus poses security challenges and possible exploits.

Implementation of JIT compilation consists of compiling source code or byte code to machine code and executing it. This is generally done directly in memory: the JIT compiler outputs the machine code directly into memory and immediately executes it, rather than outputting it to disk and then invoking the code as a separate program, as in usual ahead of time compilation. In modern architectures this runs into a problem due to executable space protection: arbitrary memory cannot be executed, as otherwise there is a potential security hole. Thus memory must be marked as executable; for security reasons this should be done after the code has been written to memory, and marked read-only, as writable/executable memory is a security hole (see W^X).[22] For instance Firefox's JIT compiler for JavaScript introduced this protection in a release version with Firefox 46.[23]

JIT spraying is a class of computer security exploits that use JIT compilation for heap spraying: the resulting memory is then executable, which allows an exploit if execution can be moved into the heap.

Uses

Script error: No such module "Unsubst".

JIT compilation can be applied to some programs, or can be used for certain capacities, particularly dynamic capacities such as regular expressions. For example, a text editor may compile a regular expression provided at runtime to machine code to allow faster matching: this cannot be done ahead of time, as the pattern is only provided at runtime. Several modern runtime environments rely on JIT compilation for high-speed code execution, including most implementations of Java, together with Microsoft's .NET. Similarly, many regular-expression libraries feature JIT compilation of regular expressions, either to bytecode or to machine code. JIT compilation is also used in some emulators, in order to translate machine code from one CPU architecture to another.

A common implementation of JIT compilation is to first have AOT compilation to bytecode (virtual machine code), known as bytecode compilation, and then have JIT compilation to machine code (dynamic compilation), rather than interpretation of the bytecode. This improves the runtime performance compared to interpretation, at the cost of lag due to compilation. JIT compilers translate continuously, as with interpreters, but caching of compiled code minimizes lag on future execution of the same code during a given run. Since only part of the program is compiled, there is significantly less lag than if the entire program were compiled prior to execution.

See also

Script error: No such module "Portal".

Notes

Template:Reflist

References

Template:Reflist

Bibliography

  • Script error: No such module "Citation/CS1".
  • Script error: No such module "Citation/CS1".
  • Script error: No such module "Citation/CS1".
  • Script error: No such module "Citation/CS1".

External links

  1. Cite error: Invalid <ref> tag; no text was provided for refs named Michigan
  2. Cite error: Invalid <ref> tag; no text was provided for refs named Notario
  3. Cite error: Invalid <ref> tag; no text was provided for refs named McCarthy1960
  4. Cite error: Invalid <ref> tag; no text was provided for refs named Mitchell1970
  5. Cite error: Invalid <ref> tag; no text was provided for refs named Schiffman1984
  6. Cite error: Invalid <ref> tag; no text was provided for refs named Self
  7. Cite error: Invalid <ref> tag; no text was provided for refs named Bala
  8. Cite error: Invalid <ref> tag; no text was provided for refs named Jannotti
  9. Cite error: Invalid <ref> tag; no text was provided for refs named Dynamo
  10. Cite error: Invalid <ref> tag; no text was provided for refs named Tung
  11. Script error: No such module "citation/CS1".
  12. Cite error: Invalid <ref> tag; no text was provided for refs named Croce
  13. Cite error: Invalid <ref> tag; no text was provided for refs named stackoverflow-1
  14. Cite error: Invalid <ref> tag; no text was provided for refs named stackoverflow-2
  15. Cite error: Invalid <ref> tag; no text was provided for refs named Haase
  16. Cite error: Invalid <ref> tag; no text was provided for refs named HotSpot
  17. Cite error: Invalid <ref> tag; no text was provided for refs named Schilling
  18. Cite error: Invalid <ref> tag; no text was provided for refs named Suganuma
  19. Cite error: Invalid <ref> tag; no text was provided for refs named Arnold-2000
  20. Cite error: Invalid <ref> tag; no text was provided for refs named MSDN
  21. Cite error: Invalid <ref> tag; no text was provided for refs named Arnold-2005
  22. Cite error: Invalid <ref> tag; no text was provided for refs named Bendersky
  23. Cite error: Invalid <ref> tag; no text was provided for refs named De Mooij