Java Reference
In-Depth Information
by known lower and upper bounds. With this information, arrays indexed
by the loop index may be known to be β€œin range,” eliminating any need
for explicit checking. Similarly, once an array bound is checked, subsequent
checks of the same bound are unnecessary until the index is changed. Thus,
in a[i] = 100 - a[i], a[i] needs to be checked only once.
If array bounds checks are optimized away, or simply suppressed, array
indexing is much more e
cient, typically three (or fewer) instructions (a shift
or multiply, an add, and a load or store). In the case where the array index is a
compile-time constant (e.g., a[100]), we can reduce this to a single instruction
by doing the computation of size βˆ— index + o ff set at compile-time and using
it directly in a load or store instruction. If the array index is a loop index
variable, then reduction in strength (Section 14.1.1 on page 549) can increment
the index variable by the appropriate amount each time around the loop, thus
eliminating the multiply instruction.
13.1.3 Method Calls
The JVM makes method calls very simple. Many of the details of a call are
hidden. In implementing an invokestatic or invokevirtual bytecode, we
must make such hidden details explicit.
Let us look at invokestatic first. In the bytecode version of the call,
parameters are pushed onto the stack, and a static method, qualified by its
class and type (to support overloading ) is accessed. In our MIPS translation,
the parameters will be in registers, which is fine since that is howmost current
architectures pass scalar (word-sized) parameters.
We will need to guarantee that parameters are placed in the correct reg-
isters. On the MIPS, the first four scalar parameters are passed in registers
$a0 to $a3; remaining parameters and non-scalar parameters are pushed onto
the runtime stack. In our translation, we can generate explicit register copy
instructions to move argument values (already in registers) to the correct reg-
isters. If we wish to avoid these extra copy instructions, we can compute the
parameters directly into the correct registers. This is called register targeting .
Essentially, when the parameter is computed, we mark the target register into
which the parameter will be computed to be the appropriate argument regis-
ter. Graph coloring (as discussed in Section 13.3.2) makes targeting fairly easy
to do. For parameters that are to be passed on the runtime stack, we simply
extend the stack (by adjusting the top-of-stack register, $sp)andthenstore
excess parameters into the locations just added.
To transfer control to the subprogram, we issue a jal (jump and link)
instruction. This instruction transfers control to the start of the method to be
called, using an address recorded when the subprogram was translated and
stores a return address in the return address register $ra.
 
 
Search WWH ::




Custom Search