add mi_stats_get_bin_size and chunk counters
diff --git a/include/mimalloc-stats.h b/include/mimalloc-stats.h
index 44c4886..93b728b 100644
--- a/include/mimalloc-stats.h
+++ b/include/mimalloc-stats.h
@@ -11,7 +11,7 @@
 #include <mimalloc.h>
 #include <stdint.h>
 
-#define MI_STAT_VERSION   1   // increased on every backward incompatible change
+#define MI_STAT_VERSION   2   // increased on every backward incompatible change
 
 // count allocation over time
 typedef struct mi_stat_count_s {
@@ -65,6 +65,17 @@
   MI_STAT_COUNTER(pages_unabandon_busy_wait) \
 
 
+// Size bins for chunks
+typedef enum mi_bbin_e {
+  MI_BBIN_SMALL,    // slice_count == 1
+  MI_BBIN_OTHER,    // slice_count: any other from the other bins, and 1 <= slice_count <= MI_BCHUNK_BITS
+  MI_BBIN_MEDIUM,   // slice_count == 8
+  MI_BBIN_LARGE,    // slice_count == MI_SIZE_BITS  (only used if MI_ENABLE_LARGE_PAGES is 1)
+  MI_BBIN_NONE,     // no bin assigned yet (the chunk is completely free)
+  MI_BBIN_COUNT
+} mi_bbin_t;
+
+
 // Define the statistics structure
 #define MI_BIN_HUGE             (73U)   // see types.h
 #define MI_STAT_COUNT(stat)     mi_stat_count_t stat;
@@ -83,6 +94,7 @@
   // size segregated statistics
   mi_stat_count_t   malloc_bins[MI_BIN_HUGE+1];   // allocation per size bin
   mi_stat_count_t   page_bins[MI_BIN_HUGE+1];     // pages allocated per size bin
+  mi_stat_count_t   chunk_bins[MI_BBIN_COUNT];    // chunks per page sizes
 } mi_stats_t;
 
 #undef MI_STAT_COUNT
@@ -93,8 +105,9 @@
 extern "C" {
 #endif
 
-mi_decl_export void  mi_stats_get( size_t stats_size, mi_stats_t* stats ) mi_attr_noexcept;
-mi_decl_export char* mi_stats_get_json( size_t buf_size, char* buf ) mi_attr_noexcept;    // use mi_free to free the result if the input buf == NULL
+mi_decl_export void    mi_stats_get( size_t stats_size, mi_stats_t* stats ) mi_attr_noexcept;
+mi_decl_export char*   mi_stats_get_json( size_t buf_size, char* buf ) mi_attr_noexcept;    // use mi_free to free the result if the input buf == NULL
+mi_decl_export size_t  mi_stats_get_bin_size(size_t bin) mi_attr_noexcept;
 
 #ifdef __cplusplus
 }
diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h
index 8a880b8..f57f108 100644
--- a/include/mimalloc/internal.h
+++ b/include/mimalloc/internal.h
@@ -299,7 +299,9 @@
 #define MI_INIT64(x)  MI_INIT32(x),MI_INIT32(x)
 #define MI_INIT128(x) MI_INIT64(x),MI_INIT64(x)
 #define MI_INIT256(x) MI_INIT128(x),MI_INIT128(x)
+
 #define MI_INIT74(x)  MI_INIT64(x),MI_INIT8(x),x(),x()
+#define MI_INIT5(x)   MI_INIT4(x),x()
 
 #include <string.h>
 // initialize a local variable to zero; use memset as compilers optimize constant sized memset's
diff --git a/src/bitmap.c b/src/bitmap.c
index f7f94dd..f010a42 100644
--- a/src/bitmap.c
+++ b/src/bitmap.c
@@ -1415,10 +1415,12 @@
   mi_assert_internal(chunk_idx < mi_bbitmap_chunk_count(bbitmap));
   for (mi_bbin_t ibin = MI_BBIN_SMALL; ibin < MI_BBIN_NONE; ibin = mi_bbin_inc(ibin)) {
     if (ibin == bin) {
-      mi_bchunk_set(& bbitmap->chunkmap_bins[ibin], chunk_idx, NULL);
+      const bool was_clear = mi_bchunk_set(& bbitmap->chunkmap_bins[ibin], chunk_idx, NULL);
+      if (was_clear) { mi_os_stat_increase(chunk_bins[ibin],1); }
     }
     else {
-      mi_bchunk_clear(&bbitmap->chunkmap_bins[ibin], chunk_idx, NULL);
+      const bool was_set = mi_bchunk_clear(&bbitmap->chunkmap_bins[ibin], chunk_idx, NULL);
+      if (was_set) { mi_os_stat_decrease(chunk_bins[ibin],1); }
     }
   }  
 }
diff --git a/src/bitmap.h b/src/bitmap.h
index 0237d00..83af74e 100644
--- a/src/bitmap.h
+++ b/src/bitmap.h
@@ -212,16 +212,7 @@
   much fragmentation since we keep chunks for larger blocks separate.
 ---------------------------------------------------------------------------- */
 
-// Size bins; larger bins are allowed to go into smaller bins.
-// SMALL can only be in small (and NONE), so they cannot fragment the larger bins.
-typedef enum mi_bbin_e {
-  MI_BBIN_SMALL,    // slice_count == 1
-  MI_BBIN_OTHER,    // slice_count: any other from the other bins, and 1 <= slice_count <= MI_BCHUNK_BITS
-  MI_BBIN_MEDIUM,   // slice_count == 8
-  MI_BBIN_LARGE,    // slice_count == MI_BFIELD_BITS  -- only used if MI_ENABLE_LARGE_PAGES is 1
-  MI_BBIN_NONE,     // no bin assigned yet (the chunk is completely free)
-  MI_BBIN_COUNT
-} mi_bbin_t;
+// mi_bbin_t is defined in mimalloc-stats.h
 
 static inline mi_bbin_t mi_bbin_inc(mi_bbin_t bbin) {
   mi_assert_internal(bbin < MI_BBIN_COUNT);
diff --git a/src/init.c b/src/init.c
index 54905dc..6d4ce65 100644
--- a/src/init.c
+++ b/src/init.c
@@ -83,7 +83,8 @@
   { { 0 }, { 0 }, { 0 }, { 0 } }, \
   \
   { MI_INIT74(MI_STAT_COUNT_NULL) }, \
-  { MI_INIT74(MI_STAT_COUNT_NULL) }
+  { MI_INIT74(MI_STAT_COUNT_NULL) }, \
+  { MI_INIT5(MI_STAT_COUNT_NULL) }
 
 // --------------------------------------------------------
 // Statically allocate an empty heap as the initial
diff --git a/src/page-queue.c b/src/page-queue.c
index 4c30c97..3e2315c 100644
--- a/src/page-queue.c
+++ b/src/page-queue.c
@@ -106,6 +106,7 @@
 }
 
 size_t _mi_bin_size(size_t bin) {
+  mi_assert_internal(bin <= MI_BIN_HUGE);
   return _mi_heap_empty.pages[bin].block_size;
 }
 
diff --git a/src/stats.c b/src/stats.c
index 27dc69d..7a761d8 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -479,6 +479,11 @@
 // Return statistics
 // --------------------------------------------------------
 
+size_t mi_stats_get_bin_size(size_t bin) mi_attr_noexcept {
+  if (bin > MI_BIN_HUGE) return 0;
+  return _mi_bin_size(bin);
+}
+
 void mi_stats_get(size_t stats_size, mi_stats_t* stats) mi_attr_noexcept {
   if (stats == NULL || stats_size == 0) return;
   _mi_memzero(stats, stats_size);
@@ -529,7 +534,7 @@
 }
 
 static void mi_heap_buf_print_count_bin(mi_heap_buf_t* hbuf, const char* prefix, mi_stat_count_t* stat, size_t bin, bool add_comma) {
-  const size_t binsize = _mi_bin_size(bin);
+  const size_t binsize = mi_stats_get_bin_size(bin);
   const size_t pagesize = (binsize <= MI_SMALL_MAX_OBJ_SIZE ? MI_SMALL_PAGE_SIZE :
                             (binsize <= MI_MEDIUM_MAX_OBJ_SIZE ? MI_MEDIUM_PAGE_SIZE :
                               (binsize <= MI_LARGE_MAX_OBJ_SIZE ? MI_LARGE_PAGE_SIZE : 0)));