13.10.2014 Views

OPTIMIZING THE JAVA VIRTUAL MACHINE INSTRUCTION SET BY ...

OPTIMIZING THE JAVA VIRTUAL MACHINE INSTRUCTION SET BY ...

OPTIMIZING THE JAVA VIRTUAL MACHINE INSTRUCTION SET BY ...

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

21<br />

piled into machine language instructions that are executed directly by the central<br />

processing unit. In an interpreter, the loop structure, fetch and decode operations<br />

are all implemented in software, each represented by a sequence of machine language<br />

instructions that must also be executed using the central processing unit. Only the<br />

single line shown in italics in figure 2.4 represents work performed directly toward<br />

progressing the user’s application. Consequently, interpreted implementations generally<br />

show far poorer performance than code executed using a traditional model of<br />

compilation and execution. Some studies have shown this performance gap to be as<br />

large as an order of magnitude [62].<br />

The following sections describe techniques that can be used to construct a Java<br />

interpreter. Each section includes a figure that shows the implementation of a portion<br />

of the interpreter’s main execution loop in C-like pseudo code. The code shown uses<br />

stack to refer to the array of slots which represents the operand stack. The symbol<br />

sp is the index of the top element on the stack. The array of slots used to store<br />

the local variables for the method is denoted by local vars. The bytecodes that<br />

implement the method are stored in the array named code with pc indicating the<br />

index of the next instruction to execute.<br />

2.4.1 Implementing an Interpreter with a Switch Statement<br />

Many implementation options are possible for a Java interpreter. In the simplest<br />

case, a while loop is used with a standard switch/case statement. This structure is<br />

shown in Figure 2.5. It offers poor performance for a number of reasons. First, the<br />

use of a while loop requires that a condition be tested for every iteration of the loop.<br />

Fortunately, if the condition is structured using only constant values, most optimizing<br />

compilers will recognize the fact that the condition is always true, avoiding the need<br />

to test the condition each time through the loop.<br />

The use of a standard switch/case statement also results in poor performance. In<br />

Figure 2.5, arrows are used to show the branches performed when the aload 0 case<br />

is executed. Notice that there is a branch from the break statement at the end of the<br />

codelet for aload 0, which transfers control to the bottom of the loop. However, no<br />

work is performed between the switch/case statement and the bottom of the loop. As<br />

a result, a second unconditional branch is immediately performed to return control<br />

to the top of the loop.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!