@@ -27,6 +27,7 @@ struct Bin {
2727 ubyte sizeClass,
2828 void ** top,
2929 void ** bottom,
30+ void ** requested,
3031 size_t slotSize,
3132 ) shared {
3233 import d.gc.sizeclass;
@@ -38,6 +39,9 @@ struct Bin {
3839 assert (bottom < top, " Invalid stack boundaries!" );
3940 assert ((top - bottom) < uint .max, " Invalid stack size!" );
4041
42+ assert (bottom < requested && requested <= top,
43+ " Invalid requested slot count!" );
44+
4145 /**
4246 * When we run out of slab with free space, we allocate a fresh slab.
4347 * However, while we do so, another thread may have returned slabs to
@@ -112,8 +116,20 @@ struct Bin {
112116 assert (freshSlab is null );
113117 assert (progressed);
114118
115- freshSlab = filler.allocSlab(emap, sizeClass);
119+ /**
120+ * We want to avoid leaving partially filled slabs behind us,
121+ * so, before allocating a new slab, we make sure that it'll
122+ * either be required to meet the requested number of slot,
123+ * or that it'll be completely filled.
124+ */
125+ assert (bottom <= insert && insert < top, " Invalid insertion point!" );
126+ auto navailable = top - insert;
116127 auto nslots = binInfos[sizeClass].nslots;
128+ if (requested <= insert && navailable <= nslots) {
129+ return insert;
130+ }
131+
132+ freshSlab = filler.allocSlab(emap, sizeClass);
117133 assert (freshSlab is null || freshSlab.nfree == nslots);
118134
119135 progressed = false ;
0 commit comments