next up previous contents
Next: Function Returns Up: Other Conditional Statements Previous: For

Case

The JVM has two instructions to handle case statements, the tableswitch and the lookupswitch instruction. The tableswitch instruction is used when the case values can be efficiently used as indices into the table of target offsets. When the values are more sparse, it is better to use the lookupswitch instruction. This instruction looks up the value of the case in its table of case values and jumps to the offset where the code of that value is. If the value is not in the table, it takes a default offset.

Because the lookupswitch instruction will always work, I will use that. The operands of the instruction contain an offset for every case label of the case statement. How the list of operands is exactly structured can be found in [JVM]; a short description of the instruction is given in subsection 4.2.7. I will only give an idea on how to compute and fill in the correct offsets when they are known.

The bytecode for a case statement may be structured the following way:

As you do not know in advance at what offset the code for a specific case label begins, you can not fill them in in the table. What you can do is allocate the entries in the table, i.e. allocate the params structures in the parameterlist of the instruct structure containing the lookupswitch instruction, and leave the entries for the offsets empty. This way you do know the indexes of the instructions following the lookupswitch instruction, so you can fill the offsets in when they are known.

To use the labeling algorithm used with the other conditional statements, we have to change the jmp_label field. Instead of containing an int value, it must now contain a list of int values. When an instruction is added to the list, it is now inserted before the first instruct structure of which the jmp_label field has a value other than the null pointer, instead of a value other than -1.

A case statement may now be compiled as follows:

  1. Add the code to load the value of the selector of the case statement on the operand stack;
  2. Add the lookupswitch instruction, leaving all the entries for the offsets empty;
  3. Save the index of the lookupswitch instruction, so you know where to find it when you want to fill in the offsets;
  4. Add an empty instruct structure to the list, which will serve as the label for the goto instructions of all the pieces of code for the case labels. The index of the lookupswitch instruction can be added as entry in the label list;
  5. For each of the case labels do the following:
    1. Compute the offset for the case label by subtracting the index of the lookupswitch from the index of the next instruction to add, because that is the first instruction of the code for the case label. Fill in the resulting offset at the appropriate entry in the table in the parameterlist of the lookupswitch instruction;
    2. Add the code for the case label, which is inserted before the label of the goto instructions;
    3. Add the goto instruction with an empty parameterlist to jump to the first instruction of the code following the case statement when the code of this case label has been executed (no goto for the last case label). This goto instruction is also inserted before the label of the goto instructions;
    4. Add the index of the goto instruction to the label list of the first labeled instruct structure in the list, which is the structure containing the label list for the goto instructions;
  6. Resolve the labels of the goto instructions by going through the label list and for every entry subtract the index from the current index of the instruct structure containing the label list. The resulting index is constructed into a parameterlist which is added to the goto instruction at the index contained in the entry in the label list. When the index of the lookupswitch instruction is encountered in the label list, compute the offset the same way as usual and insert it into the table in the parameterlist of the lookupswitch instruction for the default case label. After all offsets are computed, remove the instruct structure from the list.


next up previous contents
Next: Function Returns Up: Other Conditional Statements Previous: For



mark@bottom.xs4all.nl