public static StorageSizes computeSizes ( Frame < BasicValue > frame , int offset , int length ) { Validate . notNull ( frame ) ; Validate . isTrue ( offset >= 0 ) ; Validate . isTrue ( length >= 0 ) ; Validate . isTrue ( offset < frame . getStackSize ( ) ) ; Validate . isTrue ( offset + length <= frame . getStackSize ( ) ) ; // Count size required for each storage array int intsSize = 0 ; int longsSize = 0 ; int floatsSize = 0 ; int doublesSize = 0 ; int objectsSize = 0 ; for ( int i = offset + length - 1 ; i >= offset ; i -- ) { BasicValue basicValue = frame . getStack ( i ) ; Type type = basicValue . getType ( ) ; // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so we can avoid saving it. When we load it back up, we can simply push a null in to that slot, thereby // keeping the same 'Lnull;' type. if ( "Lnull;" . equals ( type . getDescriptor ( ) ) ) { continue ; } switch ( type . getSort ( ) ) { case Type . BOOLEAN : case Type . BYTE : case Type . SHORT : case Type . CHAR : case Type . INT : intsSize ++ ; break ; case Type . FLOAT : floatsSize ++ ; break ; case Type . LONG : longsSize ++ ; break ; case Type . DOUBLE : doublesSize ++ ; break ; case Type . ARRAY : case Type . OBJECT : objectsSize ++ ; break ; case Type . METHOD : case Type . VOID : default : throw new IllegalStateException ( ) ; } } return new StorageSizes ( intsSize , longsSize , floatsSize , doublesSize , objectsSize ) ; }
Compute sizes required for the storage arrays that will contain the operand stack at this frame .