Java Reference
In-Depth Information
Chapter6
TranslatingJVMCodetoMIPSCode
6.1 Introduction
6.1.1 What Happens to JVM Code?
Compilation is not necessarily over with after the class le is constructed. At \execution,"
the class is loaded into the JVM and then interpreted. In the Oracle HotSpot
TM
VM, once
a method has been executed several times, it is compiled to native code|code that can
be directly executed by the underlying computer. Once these hotspots in the code are
compiled, the native code is cached so that it may be re-used in subsequent invocations of
the method. So at run-time, control shifts back and forth between JVM code and native
code. Of course, the native code runs much faster than the interpreted JVM code. This
regimen takes advantage of the fact that nearly all programs spend most of their time
executing small regions of code.
This scenario is further complicated by the existence of at least two run-time environ-
ments. The VM that runs on a server performs many optimizations on the native code.
While these optimizations are expensive, they produce very fast code that, on a server,
runs over and over again. On the other hand, the VM that runs on a client computer,
such as a user's personal workstation, performs fewer optimizations and thus minimizes the
one-time cost of compiling the method to native code.
Compiling JVM code to native code involves the following:
Register allocation. In the JVM code, all local variables, transients and instruction
operands are stored on the run-time stack. But the computer architectures we are
compiling to have a fixed number of (often eight or thirty-two) high-speed registers.
The native instructions often require that operands be in registers and permanently
assigning as many local variables and transients to registers makes for faster running
programs. When all registers are in use and the computation requires another, one
register must be spilled to memory. Register spilling, in turn, degrades performance,
so we want to minimize that.
Optimization. The code produced can be improved so as to run faster. In some instances,
invocations of methods having short bodies can be in lined, that is, replaced by the
bodies' code.
Instruction selection. We must choose and generate the native code instructions su-
cient to perform the computations.
Run-time support. A certain amount of functional support is required at run-time. For
example, we need support for creating new objects on the heap. We also implement a
class that gives us basic input and output functionality for testing our programs.
One might reasonably ask, \Why don't we simply compile the entire JVM program to
205
Search WWH ::
Custom Search