Sponsored Link •
|
Advertisement
|
The Saying Tomato applet, included below, demonstrates a Java virtual machine executing a sequence of bytecodes. This applet accompanies Chapter 16, "Control Flow," of Inside the Java 2 Virtual Machine.
The bytecode sequence in the simulation was generated by the javac
compiler for the argue()
method of the class shown below:
// On CD-ROM in file opcodes/ex1/Struggle.java class Struggle { public final static int TOMAYTO = 0; public final static int TOMAHTO = 1; static void argue() { int say = TOMAYTO; for (;;) { switch (say) { case TOMAYTO: say = TOMAHTO; break; case TOMAHTO: say = TOMAYTO; break; } } } }
The bytecodes generated by javac
for the argue()
method are shown here:
0 iconst_0 // Push constant 0 (TOMAYTO) 1 istore_0 // Pop into local var 0: int say = TOMAYTO; 2 iload_0 // Push key for switch from local var 0 // Perform switch statement: switch (say) {... // Low case value is 0, high case value is 1 // Default branch offset will goto 2 3 tableswitch 0 to 1: default=2 0: 24 // case 0 (TOMAYTO): goto 24 1: 29 // case 1 (TOMAHTO): goto 29 // Note that the next instruction starts at address // 24, which means the tableswitch took up 21 bytes 24 iconst_1 // Push constant 1 (TOMAHTO) 25 istore_0 // Pop into local var 0: say = TOMAHTO 26 goto 2 // Branch unconditionally to 2, top of while loop 29 iconst_0 // Push constant 1 (TOMAYTO) 30 istore_0 // Pop into local var 0: say = TOMAYTO 31 goto 2 // Branch unconditionally to 2, top of while loop
The argue()
method merely switches the value of say
back and forth between TOMAYTO
and TOMAHTO
. Because the values of TOMAYTO
and TOMAHTO
were consecutive (TOMAYTO
was a 0 and TOMAHTO
was a 1), the javac
compiler used a tableswitch
. The tableswitch
is a more efficient instruction than a lookupswitch
, and the equivalent lookupswitch
instruction would occupy 28 bytes--4 bytes more than tableswitch
.
It turns out that even if TOMAYTO
were a 0 and TOMAHTO
were a 2, the javac
compiler still would have used a tableswitch
, because even with the extra default branch offset in there for a 1, the tableswitch
instruction would occupy only 28 bytes--the same number of bytes as the equivalent lookupswitch
. Both instructions occupy the same number of bytes, but tableswitch
is more efficient, so it is used. As soon as you make TOMAHTO
a 3, however, javac
starts using a lookupswitch
. This is because a tableswitch
would now need two default branch offsets in its list (for 1 and 2), which would push its size up to 32 bytes. Thus, a lookupswitch
now would require fewer bytes than a tableswitch
--so javac
chooses the lookupswitch
.
The branch offsets for the case values cause the Java virtual machine to hop down to code that will change the value of the say
local variable. The value of say
will alternate between TOMAYTO
and TOMAHTO
indefinitely, until the user aborts the program, thereby calling the whole thing off.
To drive the Saying Tomato simulation, use the Step, Reset, Run, and Stop buttons. Each time you press the Step button, the simulator will execute the instruction pointed to by the pc register. If you press the Run button, the simulation will continue with no further coaxing on your part until you press the Stop button. To start the simulation over, press the Reset button. For each step of the simulation, a panel at the bottom of the applet contains an explanation of what the next instruction will do. Happy clicking.
Click here to view a page of links to the source code of the Saying Tomato applet.
Sponsored Links
|