#!/bin/sh

# The following limits are chosen such that they cover all supported platforms.

# Range of quanta.
lg_qmin=3
lg_qmax=4

# The range of tiny size classes is [2^lg_tmin..2^(lg_q-1)].
lg_tmin=3

# Range of page sizes.
lg_pmin=12
lg_pmax=16

pow2() {
  e=$1
  pow2_result=1
  while [ ${e} -gt 0 ] ; do
    pow2_result=$((${pow2_result} + ${pow2_result}))
    e=$((${e} - 1))
  done
}

cat <<EOF
/* This file was automatically generated by size_classes.sh. */
/******************************************************************************/
#ifdef JEMALLOC_H_TYPES

EOF

lg_q=${lg_qmin}
while [ ${lg_q} -le ${lg_qmax} ] ; do
  lg_t=${lg_tmin}
  while [ ${lg_t} -le ${lg_q} ] ; do
    lg_p=${lg_pmin}
    while [ ${lg_p} -le ${lg_pmax} ] ; do
      echo "#if (LG_TINY_MIN == ${lg_t} && LG_QUANTUM == ${lg_q} && LG_PAGE == ${lg_p})"
      echo "#define	SIZE_CLASSES_DEFINED"
      pow2 ${lg_q}; q=${pow2_result}
      pow2 ${lg_t}; t=${pow2_result}
      pow2 ${lg_p}; p=${pow2_result}
      bin=0
      psz=0
      sz=${t}
      delta=$((${sz} - ${psz}))
      echo "/*  SIZE_CLASS(bin,	delta,	sz) */"
      echo "#define	SIZE_CLASSES							\\"

      # Tiny size classes.
      while [ ${sz} -lt ${q} ] ; do
        echo "    SIZE_CLASS(${bin},	${delta},	${sz})					\\"
        bin=$((${bin} + 1))
        psz=${sz}
        sz=$((${sz} + ${sz}))
        delta=$((${sz} - ${psz}))
      done
      # Quantum-multiple size classes.  For each doubling of sz, as many as 4
      # size classes exist.  Their spacing is the greater of:
      # - q
      # - sz/4, where sz is a power of 2
      while [ ${sz} -lt ${p} ] ; do
        if [ ${sz} -ge $((${q} * 4)) ] ; then
          i=$((${sz} / 4))
        else
          i=${q}
        fi
        next_2pow=$((${sz} * 2))
        while [ ${sz} -lt $next_2pow ] ; do
          echo "    SIZE_CLASS(${bin},	${delta},	${sz})					\\"
          bin=$((${bin} + 1))
          psz=${sz}
          sz=$((${sz} + ${i}))
          delta=$((${sz} - ${psz}))
        done
      done
      echo
      echo "#define	NBINS		${bin}"
      echo "#define	SMALL_MAXCLASS	${psz}"
      echo "#endif"
      echo
      lg_p=$((${lg_p} + 1))
    done
    lg_t=$((${lg_t} + 1))
  done
  lg_q=$((${lg_q} + 1))
done

cat <<EOF
#ifndef SIZE_CLASSES_DEFINED
#  error "No size class definitions match configuration"
#endif
#undef SIZE_CLASSES_DEFINED
/*
 * The small_size2bin lookup table uses uint8_t to encode each bin index, so we
 * cannot support more than 256 small size classes.  Further constrain NBINS to
 * 255 to support prof_promote, since all small size classes, plus a "not
 * small" size class must be stored in 8 bits of arena_chunk_map_t's bits
 * field.
 */
#if (NBINS > 255)
#  error "Too many small size classes"
#endif

#endif /* JEMALLOC_H_TYPES */
/******************************************************************************/
#ifdef JEMALLOC_H_STRUCTS


#endif /* JEMALLOC_H_STRUCTS */
/******************************************************************************/
#ifdef JEMALLOC_H_EXTERNS


#endif /* JEMALLOC_H_EXTERNS */
/******************************************************************************/
#ifdef JEMALLOC_H_INLINES


#endif /* JEMALLOC_H_INLINES */
/******************************************************************************/
EOF