Skip to content

Commit 69c6ad8

Browse files
authored
Improving compaction heuristics + Some other tweaks while looking at compaction. (#74)
1 parent 8b4636a commit 69c6ad8

20 files changed

+984
-464
lines changed

src/coreclr/gc/satori/SatoriAllocator.cpp

Lines changed: 142 additions & 70 deletions
Large diffs are not rendered by default.

src/coreclr/gc/satori/SatoriAllocator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class SatoriAllocator
104104
DECLSPEC_ALIGN(64)
105105
volatile int32_t m_singePageAdders;
106106

107+
void UpdateAllocStatsAndHelpIfNeeded(SatoriAllocationContext * context);
107108
SatoriObject* AllocRegular(SatoriAllocationContext* context, size_t size, uint32_t flags);
108109
SatoriObject* AllocRegularShared(SatoriAllocationContext* context, size_t size, uint32_t flags);
109110
SatoriObject* AllocLarge(SatoriAllocationContext* context, size_t size, uint32_t flags);

src/coreclr/gc/satori/SatoriObject.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ void SatoriObject::DirtyCardsForContent()
104104
void SatoriObject::Validate()
105105
{
106106
#ifdef _DEBUG
107+
// min object size is the same as min free size because any hole
108+
// must be able to fit a free obj for parseability reasons
107109
_ASSERTE(this->Size() >= Satori::MIN_FREE_SIZE);
108110

109111
if (ContainingRegion()->IsEscapeTrackedByCurrentThread())

src/coreclr/gc/satori/SatoriObject.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class SatoriObject : public Object
5555

5656
size_t Size();
5757
size_t FreeObjSize();
58+
size_t FreeObjCapacity();
5859
bool SameRegion(SatoriRegion* otherRegion);
5960
bool IsFree();
6061
bool IsExternal();
@@ -111,4 +112,20 @@ class SatoriObject : public Object
111112
static void Initialize();
112113
};
113114

115+
116+
class SatoriFreeListObject : public SatoriObject
117+
{
118+
private:
119+
uint32_t m_Length;
120+
#if defined(HOST_64BIT)
121+
uint32_t m_uAlignpad;
122+
#endif // HOST_64BIT
123+
124+
public:
125+
SatoriFreeListObject() = delete;
126+
~SatoriFreeListObject() = delete;
127+
128+
SatoriFreeListObject* m_nextInFreeList;
129+
};
130+
114131
#endif

src/coreclr/gc/satori/SatoriObject.inl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,16 @@ FORCEINLINE size_t SatoriObject::FreeObjSize()
5353
_ASSERTE(IsFree());
5454
size_t size = Satori::MIN_FREE_SIZE;
5555
size += (size_t)((ArrayBase*)this)->GetNumComponents();
56-
size = ALIGN_UP(size, Satori::OBJECT_ALIGNMENT);
56+
_ASSERTE(size == ALIGN_UP(size, Satori::OBJECT_ALIGNMENT));
5757
return size;
5858
}
5959

60+
FORCEINLINE size_t SatoriObject::FreeObjCapacity()
61+
{
62+
_ASSERTE(IsFree());
63+
return (size_t)((ArrayBase*)this)->GetNumComponents();
64+
}
65+
6066
inline size_t SatoriObject::Start()
6167
{
6268
return (size_t)this;

src/coreclr/gc/satori/SatoriPage.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ void SatoriPage::WipeGroupsForRange(size_t start, size_t end)
324324

325325
size_t firstGroup = firstByteOffset / Satori::BYTES_PER_CARD_GROUP;
326326
size_t lastGroup = lastByteOffset / Satori::BYTES_PER_CARD_GROUP;
327+
// this resets both states and tickets
327328
memset((void*)&m_cardGroups[firstGroup * 2], Satori::CardState::BLANK, (lastGroup - firstGroup + 1) * 2);
328329
}
329330

src/coreclr/gc/satori/SatoriPage.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ class SatoriPage
121121
void ResetCardsForRange(size_t start, size_t end, bool isTenured);
122122

123123
volatile int8_t& CardState();
124-
volatile int8_t& ScanTicket();
124+
volatile uint8_t& ScanTicket();
125125
volatile int8_t& CardGroupState(size_t i);
126-
volatile int8_t& CardGroupScanTicket(size_t i);
126+
volatile uint8_t& CardGroupScanTicket(size_t i);
127127

128128
size_t CardGroupCount();
129129
int8_t* CardsForGroup(size_t i);
@@ -148,7 +148,7 @@ class SatoriPage
148148
struct
149149
{
150150
int8_t m_cardState;
151-
int8_t m_scanTicket;
151+
uint8_t m_scanTicket;
152152
size_t m_end;
153153
size_t m_initialCommit;
154154
size_t m_firstRegion;
@@ -170,6 +170,8 @@ class SatoriPage
170170

171171
// computed size,
172172
// 2 byte per card group (4 per region granule)
173+
// one signed byte for a state, which has negative values.
174+
// and one unsigned for a ticket, which is a wrap-around counter.
173175
// 2048 bytes per 1Gb
174176
DECLSPEC_ALIGN(128)
175177
int8_t m_cardGroups[1];

src/coreclr/gc/satori/SatoriPage.inl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ inline volatile int8_t& SatoriPage::CardState()
6363
}
6464

6565
// order is unimportant, but we want to read it only once when we read it, thus volatile.
66-
inline volatile int8_t& SatoriPage::ScanTicket()
66+
inline volatile uint8_t& SatoriPage::ScanTicket()
6767
{
6868
return m_scanTicket;
6969
}
@@ -75,9 +75,9 @@ inline volatile int8_t& SatoriPage::CardGroupState(size_t i)
7575
}
7676

7777
// order is unimportant, but we want to read it once when we read it, thus volatile.
78-
inline volatile int8_t& SatoriPage::CardGroupScanTicket(size_t i)
78+
inline volatile uint8_t& SatoriPage::CardGroupScanTicket(size_t i)
7979
{
80-
return m_cardGroups[i * 2 + 1];
80+
return (uint8_t&)m_cardGroups[i * 2 + 1];
8181
}
8282

8383
inline size_t SatoriPage::CardGroupCount()

src/coreclr/gc/satori/SatoriQueue.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,50 @@ class SatoriQueue
153153
return result;
154154
}
155155

156+
// same as TryPop, but on empty pushes the item.
157+
// emptines is checked under a lock.
158+
T* PopOrPush(T* item)
159+
{
160+
_ASSERTE(item->m_next == nullptr);
161+
_ASSERTE(item->m_prev == nullptr);
162+
_ASSERTE(item->m_containingQueue == nullptr);
163+
164+
T* result;
165+
{
166+
SatoriLockHolder holder(&m_lock);
167+
result = m_head;
168+
if (result == nullptr)
169+
{
170+
// push the item and return nullptr.
171+
_ASSERTE(m_tail == nullptr);
172+
m_count++;
173+
item->m_containingQueue = this;
174+
m_tail = item;
175+
m_head = item;
176+
return nullptr;
177+
}
178+
179+
// pop the result
180+
T* next = result->m_next;
181+
m_count--;
182+
m_head = next;
183+
result->m_containingQueue = nullptr;
184+
if (next == nullptr)
185+
{
186+
m_tail = nullptr;
187+
}
188+
else
189+
{
190+
next->m_prev = nullptr;
191+
}
192+
}
193+
194+
_ASSERTE(result->m_prev == nullptr);
195+
result->m_next = nullptr;
196+
197+
return result;
198+
}
199+
156200
T* TryPopWithTryEnter()
157201
{
158202
if (IsEmpty())

0 commit comments

Comments
 (0)