Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jvm: At what locations in the method bytecode does a compiler need to necessarily specify stack map frames?

This is an excerpt from the asm user guide:

In order to save space, a compiled method does not contain one frame per instruction: in fact it contains only the frames for the instructions that correspond to jump targets or exception handlers, or that follow unconditional jump instructions. Indeed the other frames can be easily and quickly inferred from these ones.

I can understand why the jvm needs stack map frames at jump targets and for exception handlers, but isn't the need to have a stack map frame after a goto a needless requirement, since there must be a jump instruction somewhere in the method bytecode which points to the instruction just after the goto instruction, and that case will be handled by the first requirement. It has to be that way or otherwise the instruction after goto will be unreachable, and hence discardable.

Example:

A method and it's bytecode are given below:

public class t {
    public static void main(String[] s) {
        int i = 10;
        while ( i > 0 ) {
            i = i + 1;
        }
        int j = 10;
    }
}



  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: bipush        10
         2: istore_1
         3: iload_1
         4: ifle          14
         7: iload_1
         8: iconst_1
         9: iadd
        10: istore_1
        11: goto          3
        14: bipush        10
        16: istore_2
        17: return
      LineNumberTable:
        line 9: 0
        line 10: 3
        line 11: 7
        line 13: 14
        line 14: 17
      StackMapTable: number_of_entries = 2
        frame_type = 252 /* append */
          offset_delta = 3
          locals = [ int ]
        frame_type = 10 /* same */
}

Instruction at index 11 is a goto instruction and the instruction at index 4 has 14, the instruction just after 11 as it's jump target.

What's the rational behind requiring a stack map frame following an unconditional jump?

like image 651
saga Avatar asked Jun 10 '18 06:06

saga


People also ask

What does the JVM store in the stack?

A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local variables and partial results, and plays a part in method invocation and return.

What does JVM do with bytecode?

The JVM is what takes the bytecode and translates it into machine code. The point of bytecode is that you get better performance than a strictly interpreted language (like PHP for example) because the bytecode is already partially compiled and optimized.

How does JVM run bytecode?

The bytecode format When a JVM loads a class file, it gets one stream of bytecodes for each method in the class. The bytecodes streams are stored in the method area of the JVM. The bytecodes for a method are executed when that method is invoked during the course of running the program.

What is bytecode in Java machine specific code?

Byte code is an intermediate code between the source code and machine code. It is a low-level code that is the result of the compilation of a source code which is written in a high-level language. It is processed by a virtual machine like Java Virtual Machine (JVM).


1 Answers

The goal of stack maps is to allow verification to be performed in a single linear pass through the code.

If the code following a goto has no jumps pointing to it, then the code is dead and theoretically does not need to be verified. However, the verifier does not know this. Since it is performing a single pass through the code, it is impossible to know ahead of time whether the code is dead or not. Therefore, it has to verify everything, and this means that it needs a stack frame to start with.

Note that this is different from the legacy non-stack map verifier. Prior to the introduction of stack maps, the verifier would simply iterate through all the code it found, (effectively) following jumps, and iterate until convergence. This means that under the old verifier, dead code is never touched at all.

like image 59
Antimony Avatar answered Sep 28 '22 06:09

Antimony