Java Reference
In-Depth Information
iload 2
; Push int b onto stack
iload 3
; Push int c onto stack
iadd
; Add top two stack values
iload 4
; Push int d onto stack
isub
; Subtract top two stack values
istore 1
; Store top stack value into a
Figure 13.1: Bytecodes for a=b+c-d;
Most bytecodes map directly into one or two MIPS instructions. Thus an
iadd instruction corresponds directly to the MIPS add instruction. The biggest
di
erence in the design of bytecodes and the MIPS (or any other modern
architecture) is that bytecodes are stack-oriented whereas the MIPS is register-
oriented .
The most obvious approach to handling stack-based operands is to load
top-of-stack values into registers when they are used, and to push registers
onto the stack when values are computed. This unfortunately is also one of
the worst approaches. The problem is that explicit pop and push operations
imply memory load and store instructions which can be slow and bulky.
Instead, we will make a few simple, but important, observations on how
stack operands are used. First, note that no operands are left on the stack
between source-level statements. If they were, a statement placed in a loop
could cause stack overflow. Thus, the stack is used only to hold operandswhile
parts of a statement are executed. Moreover, each stack operand is “touched”
twice—when it is created (pushed) and when it is used (popped).
These observations allow us to map stack operands directly into regis-
ters; no pushes or pops of a machine's runtime stack are really needed. We
can imagine the JVM operand stack as containing register names rather than
values. When a particular value is at the top of the stack, we will use the
corresponding “top register” as the source of our operand. This may seem
complex, but it really is quite simple. Consider the Java TM assignment state-
ment a=b+c-d;(where a, b, c,andd are integers, indexed as locals 1
to 4). The corresponding bytecodes are shown in Figure 13.1 (“;” begins a
one-line comment in JVM code).
Whenever a value is pushed, we will create a temporary location to hold
it. This temporary location (usually just called a temporary) will normally be
allocated to a register. We will track the names of the temporaries associated
with stack locations as bytecodes are processed. At any point, we will know
exactly what temporaries are logically on the stack. We say logically because
these values are not pushed and popped at run time. Rather, values are directly
accessed from the registers that hold them.
ff
 
Search WWH ::




Custom Search