« On Why J2ME Will... | Main | Twenty Causes of a... »
http://www.jroller.com/random7/date/20040613 Sunday June 13, 2004

How the J2ME StackMap Works

All JVMs verify the class file during linking. The mostly costly part of verification is Pass 3, where the JVM does detailed data-flow analysis on the code attribute. This analysis verifies a number of things dealing with the operand stack (the work area) and the local variable array. On J2ME classes, we do pre-verification on the class files, storing information in a stack map about the local variable array and operand stack. We only need to store information in the stack map when there is a conditional statement or exception within the byte-code. Thus, the KVM uses a lot less memory than the typical JVM during Pass 3 verification because the KVM does a linear scan of the byte-code, relying on the stack map for all of the branches.

According to the CLDC 1.0 Spec, stack item types and local variables are recorded if one or more of the following conditions hold:

    1. The instruction is a target of a conditional jump (e.g., ifeq), unconditional jump (e.g.,
       goto), tableswitch, or a lookupswitch instruction.
    2. The instruction is marked by the handler_pc in the exception_table of the Code attribute.
    3. The instruction immediately follows an unconditional jump (e.g., goto), tableswitch, lookupswitch,
       athrow, or return instructions. Unless this instruction is  dead code, it must also fall into cases
       1 or 2.

The stack map attribute structure is:

StackMap_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 number_of_entries;
    {
     u2 byte_code_offset;
     u2 number_of_locals;
     ty types_of_locals[number_of_locals];
     u2 number_of_stack_items;
     ty stack_item_types[number_of_stack_items];    
    } entries[number_of_entries];
}

From the structure above, we see that the stack map attribute contains the byte_code_offset of the target, contents of the local variable array and contents of the operand stack.

Now let?s take a look at the following byte-code:

Offset	Instruction	Argument
0	aload_0  	
1	getfield	rand Ljava/util/Random;  
4	invokevirtual	java.util.Random.nextInt ()I():int
7	iload_1  	
8	irem	
9	istore_2  	
10	iload_2  	
11	ifge 	18
14	iload_2  	
15	iload_1  	
16	iadd	
17	istore_2  	
18	iload_2  	
19	ireturn	

In the code above, the KVM cannot do a linear scan of the byte-codes. Offset 11 has a conditional jump to offset 18, thus satisfying condition (1); so we need a stack map. In offset 0, the KVM loads a reference to this into the local variable array. In offsets 7 and 10, the KVM loads Integers. The pre-verifier has already recorded the stack map attribute with the local variable array containing {object, integer, integer}. You can also find the values of the operand stack within the stack map by going through the byte-code. The getfield and invokevirtual instructions each push an object onto the operand stack and so on.

That is about all there is in regards to a stack map.



Posted by random7 [J2ME] ( June 13, 2004 08:55 PM ) Permalink | Comments[0]
Comments:

Post a Comment:
  • HTML Syntax: NOT allowed