@@ -12,12 +12,9 @@ struct Bin {
1212 import d.sync.mutex;
1313 shared Mutex mutex;
1414
15- import d.gc.extent;
16- Extent* current;
17-
1815 // XXX: We might want to consider targeting Extents
1916 // on old huge pages instead of just address.
20- import d.gc.heap;
17+ import d.gc.extent, d.gc. heap;
2118 Heap! (Extent, addrExtentCmp) slabs;
2219
2320 void * alloc (shared (Arena)* arena, shared (ExtentMap)* emap,
@@ -28,22 +25,12 @@ struct Bin {
2825
2926 // Load eagerly as prefetching.
3027 import d.gc.slab;
31- auto size = binInfos[sizeClass].itemSize;
28+ auto slotSize = binInfos[sizeClass].itemSize;
3229
3330 mutex.lock();
3431 scope (exit) mutex.unlock();
3532
36- auto slab = (cast (Bin* ) &this ).getSlab(arena, emap, sizeClass);
37- if (slab is null ) {
38- return null ;
39- }
40-
41- void * [1 ] buffer = void ;
42- if (slab.batchAllocate(buffer[0 .. 1 ], size) == 0 ) {
43- return null ;
44- }
45-
46- return buffer[0 ];
33+ return (cast (Bin* ) &this ).allocImpl(arena, emap, sizeClass, slotSize);
4734 }
4835
4936 bool free (shared (Arena)* arena, void * ptr, PageDescriptor pd) shared {
@@ -54,18 +41,39 @@ struct Bin {
5441 " Invalid arena or sizeClass!" );
5542
5643 import d.gc.slab;
44+ auto slots = binInfos[pd.sizeClass].slots;
5745 auto sg = SlabAllocGeometry(pd, ptr);
5846 assert (ptr is sg.address);
5947
60- auto slots = binInfos[pd.sizeClass].slots;
61-
6248 mutex.lock();
6349 scope (exit) mutex.unlock();
6450
6551 return (cast (Bin* ) &this ).freeImpl(pd.extent, sg.index, slots);
6652 }
6753
6854private :
55+ void * allocImpl (shared (Arena)* arena, shared (ExtentMap)* emap,
56+ ubyte sizeClass, size_t slotSize) {
57+ // FIXME: in contract.
58+ assert (mutex.isHeld(), " Mutex not held!" );
59+
60+ auto e = getSlab(arena, emap, sizeClass);
61+ if (e is null ) {
62+ return null ;
63+ }
64+
65+ void * [1 ] buffer = void ;
66+ auto count = e.batchAllocate(buffer[0 .. 1 ], slotSize);
67+ assert (count > 0 );
68+
69+ // If the slab is full, remove it from the heap.
70+ if (e.freeSlots == 0 ) {
71+ slabs.remove(e);
72+ }
73+
74+ return buffer[0 ];
75+ }
76+
6977 bool freeImpl (Extent* e, uint index, uint slots) {
7078 // FIXME: in contract.
7179 assert (mutex.isHeld(), " Mutex not held!" );
@@ -74,11 +82,6 @@ private:
7482
7583 auto nfree = e.freeSlots;
7684 if (nfree == slots) {
77- if (e is current) {
78- current = null ;
79- return true ;
80- }
81-
8285 // If we only had one slot, we never got added to the heap.
8386 if (slots > 1 ) {
8487 slabs.remove(e);
@@ -87,7 +90,7 @@ private:
8790 return true ;
8891 }
8992
90- if (nfree == 1 && e ! is current ) {
93+ if (nfree == 1 ) {
9194 // Newly non empty.
9295 assert (slots > 1 );
9396 slabs.insert(e);
@@ -96,25 +99,12 @@ private:
9699 return false ;
97100 }
98101
99- auto tryGetSlab () {
100- // FIXME: in contract.
101- assert (mutex.isHeld(), " Mutex not held!" );
102-
103- // If the current slab still have free slots, go for it.
104- if (current ! is null && current.freeSlots != 0 ) {
105- return current;
106- }
107-
108- current = slabs.pop();
109- return current;
110- }
111-
112102 auto getSlab (shared (Arena)* arena, shared (ExtentMap)* emap,
113103 ubyte sizeClass) {
114104 // FIXME: in contract.
115105 assert (mutex.isHeld(), " Mutex not held!" );
116106
117- auto slab = tryGetSlab() ;
107+ auto slab = slabs.top ;
118108 if (slab ! is null ) {
119109 return slab;
120110 }
@@ -128,23 +118,24 @@ private:
128118 slab = arena.allocSlab(emap, sizeClass);
129119 }
130120
121+ auto current = slabs.top;
131122 if (slab is null ) {
132123 // Another thread might have been successful
133124 // while we did not hold the lock.
134- return tryGetSlab () ;
125+ return current ;
135126 }
136127
137128 // We may have allocated the slab we need when the lock was released.
138- if (current is null || current.freeSlots == 0 ) {
139- current = slab;
129+ if (current is null ) {
130+ slabs.insert( slab) ;
140131 return slab;
141132 }
142133
143134 // If we have, then free the run we just allocated.
144135 assert (slab ! is current);
145136 assert (current.freeSlots > 0 );
146137
147- // In which case we put the free run back in the tree .
138+ // In which case we release the slab we just allocated .
148139 import d.gc.slab;
149140 assert (slab.freeSlots == binInfos[sizeClass].slots);
150141 arena.freeSlab(emap, slab);
0 commit comments