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);
    }
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 ( ) ) ; 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 ( "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.
@param frame frame to compute for
@param offset the position within the operand stack to start calculating
@param length the number of stack items to include in calculation
@return size required by each storage array
@throws NullPointerException if any argument is {@code null}
@throws IllegalArgumentException if any numeric argument is negative, or if {@code offset + length} is larger than the size of the
operand stack