Skip to content

Commit 9565870

Browse files
committed
[MERGE chakra-core#2172 @pleath] 2 redeferral-related fixes in Recycler
Merge pull request chakra-core#2172 from pleath:10017672 1. Do not try to take special mark actions in BackgroundScanStack, only in ScanStack, as memory may be unstable in the background case. 2. In marking, if MarkInternal returns true (indicating no further work is necessary), and if we're required to take special mark actions, detect finalizable object and take the action.
2 parents 2cec92c + 08c9e0e commit 9565870

7 files changed

Lines changed: 137 additions & 36 deletions

File tree

lib/Common/Memory/HeapBlockMap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ class HeapBlockMap32
188188
template <bool interlocked>
189189
bool MarkInternal(L2MapChunk * chunk, void * candidate);
190190

191+
void OnSpecialMark(L2MapChunk * chunk, void * candidate);
192+
191193
template <bool interlocked, bool updateChunk>
192194
bool MarkInteriorInternal(MarkContext * markContext, L2MapChunk *& chunk, void * originalCandidate, void * realCandidate);
193195

lib/Common/Memory/HeapBlockMap.inl

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ HeapBlockMap32::Mark(void * candidate, MarkContext * markContext)
6868

6969
if (MarkInternal<interlocked>(chunk, candidate))
7070
{
71+
if (doSpecialMark)
72+
{
73+
this->OnSpecialMark(chunk, candidate);
74+
}
7175
return;
7276
}
7377

@@ -153,6 +157,59 @@ HeapBlockMap32::Mark(void * candidate, MarkContext * markContext)
153157
}
154158
}
155159

160+
inline
161+
void
162+
HeapBlockMap32::OnSpecialMark(L2MapChunk * chunk, void * candidate)
163+
{
164+
uint id2 = GetLevel2Id(candidate);
165+
HeapBlock::HeapBlockType blockType = chunk->blockInfo[id2].blockType;
166+
167+
Assert(blockType == HeapBlock::HeapBlockType::FreeBlockType || chunk->map[id2]->GetHeapBlockType() == blockType);
168+
169+
unsigned char attributes = ObjectInfoBits::NoBit;
170+
bool success = false;
171+
172+
// If the block is finalizable, we may still have to take special mark action.
173+
switch (blockType)
174+
{
175+
case HeapBlock::HeapBlockType::SmallFinalizableBlockType:
176+
#ifdef RECYCLER_WRITE_BARRIER
177+
case HeapBlock::HeapBlockType::SmallFinalizableBlockWithBarrierType:
178+
#endif
179+
{
180+
SmallFinalizableHeapBlock *smallBlock = (SmallFinalizableHeapBlock*)chunk->map[id2];
181+
success = smallBlock->TryGetAttributes(candidate, &attributes);
182+
break;
183+
}
184+
185+
case HeapBlock::HeapBlockType::MediumFinalizableBlockType:
186+
#ifdef RECYCLER_WRITE_BARRIER
187+
case HeapBlock::HeapBlockType::MediumFinalizableBlockWithBarrierType:
188+
#endif
189+
{
190+
MediumFinalizableHeapBlock *mediumBlock = (MediumFinalizableHeapBlock*)chunk->map[id2];
191+
success = mediumBlock->TryGetAttributes(candidate, &attributes);
192+
break;
193+
}
194+
195+
case HeapBlock::HeapBlockType::LargeBlockType:
196+
{
197+
LargeHeapBlock *largeBlock = (LargeHeapBlock*)chunk->map[id2];
198+
success = largeBlock->TryGetAttributes(candidate, &attributes);
199+
break;
200+
}
201+
202+
default:
203+
break;
204+
}
205+
206+
if (success && (attributes & FinalizeBit))
207+
{
208+
FinalizableObject *trackedObject = (FinalizableObject*)candidate;
209+
trackedObject->OnMark();
210+
}
211+
}
212+
156213
template <bool interlocked, bool largeBlockType>
157214
inline
158215
bool

lib/Common/Memory/LargeHeapBlock.cpp

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,44 @@ LargeHeapBlock::IsFreeObject(void * objectAddress)
378378
return ((char *)header >= this->address && header->objectIndex < this->allocCount && this->GetHeader(header->objectIndex) == nullptr);
379379
}
380380
#endif
381+
382+
bool
383+
LargeHeapBlock::TryGetAttributes(void* objectAddress, unsigned char * pAttr)
384+
{
385+
return this->TryGetAttributes(GetHeader(objectAddress), pAttr);
386+
}
387+
388+
bool
389+
LargeHeapBlock::TryGetAttributes(LargeObjectHeader * header, unsigned char * pAttr)
390+
{
391+
if ((char *)header < this->address)
392+
{
393+
return false;
394+
}
395+
396+
uint index = header->objectIndex;
397+
398+
if (index >= this->allocCount)
399+
{
400+
// Not allocated yet.
401+
return false;
402+
}
403+
404+
if (this->HeaderList()[index] != header)
405+
{
406+
// header doesn't match, not a real object
407+
return false;
408+
}
409+
410+
if (this->InPageHeapMode())
411+
{
412+
this->VerifyPageHeapPattern();
413+
}
414+
415+
*pAttr = header->GetAttributes(this->heapInfo->recycler->Cookie);
416+
return true;
417+
}
418+
381419
size_t
382420
LargeHeapBlock::GetPagesNeeded(size_t size, bool multiplyRequest)
383421
{
@@ -563,33 +601,14 @@ LargeHeapBlock::Mark(void* objectAddress, MarkContext * markContext)
563601
{
564602
LargeObjectHeader * header = GetHeader(objectAddress);
565603

566-
if ((char *)header < this->address)
604+
unsigned char attributes = ObjectInfoBits::NoBit;
605+
if (!this->TryGetAttributes(header, &attributes))
567606
{
568607
return;
569608
}
570609

571-
uint index = header->objectIndex;
572-
573-
if (index >= this->allocCount)
574-
{
575-
// Not allocated yet.
576-
return;
577-
}
578-
579-
if (this->HeaderList()[index] != header)
580-
{
581-
// header doesn't match, not a real object
582-
return;
583-
}
584-
585-
if (this->InPageHeapMode())
586-
{
587-
this->VerifyPageHeapPattern();
588-
}
589-
590610
DUMP_OBJECT_REFERENCE(markContext->GetRecycler(), objectAddress);
591611

592-
unsigned char attributes = header->GetAttributes(this->heapInfo->recycler->Cookie);
593612
size_t objectSize = header->objectSize;
594613
if (this->InPageHeapMode())
595614
{

lib/Common/Memory/LargeHeapBlock.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ class LargeHeapBlock sealed : public HeapBlock
149149
char* GetBeginAddress() const { return address; }
150150
char* GetEndAddress() const { return addressEnd; }
151151

152+
bool TryGetAttributes(void* objectAddress, unsigned char * pAttr);
153+
bool TryGetAttributes(LargeObjectHeader *objectHeader, unsigned char * pAttr);
154+
152155
char * Alloc(DECLSPEC_GUARD_OVERFLOW size_t size, ObjectInfoBits attributes);
153156
char * TryAllocFromFreeList(DECLSPEC_GUARD_OVERFLOW size_t size, ObjectInfoBits attributes);
154157

lib/Common/Memory/Recycler.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4974,15 +4974,7 @@ Recycler::BackgroundScanStack()
49744974
if (stackTop != nullptr)
49754975
{
49764976
size_t size = (char *)stackBase - stackTop;
4977-
bool doSpecialMark = collectionWrapper->DoSpecialMarkOnScanStack();
4978-
if (doSpecialMark)
4979-
{
4980-
ScanMemoryInline<true>((void **)stackTop, size);
4981-
}
4982-
else
4983-
{
4984-
ScanMemoryInline<false>((void **)stackTop, size);
4985-
}
4977+
ScanMemoryInline<false>((void **)stackTop, size);
49864978
return size;
49874979
}
49884980

lib/Common/Memory/SmallFinalizableHeapBlock.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,45 @@ SmallFinalizableHeapBlockT<TBlockAttributes>::SetAttributes(void * address, unsi
104104
}
105105

106106
template <class TBlockAttributes>
107-
template <bool doSpecialMark>
108-
_NOINLINE
109-
void
110-
SmallFinalizableHeapBlockT<TBlockAttributes>::ProcessMarkedObject(void* objectAddress, MarkContext * markContext)
107+
bool
108+
SmallFinalizableHeapBlockT<TBlockAttributes>::TryGetAttributes(void* objectAddress, unsigned char * pAttr)
109+
{
110+
unsigned char * attributes = nullptr;
111+
if (this->TryGetAddressOfAttributes(objectAddress, &attributes))
112+
{
113+
*pAttr = *attributes;
114+
return true;
115+
}
116+
return false;
117+
}
118+
119+
template <class TBlockAttributes>
120+
bool
121+
SmallFinalizableHeapBlockT<TBlockAttributes>::TryGetAddressOfAttributes(void* objectAddress, unsigned char ** ppAttrs)
111122
{
112123
ushort objectIndex = this->GetAddressIndex(objectAddress);
113124

114125
if (objectIndex == SmallHeapBlockT<TBlockAttributes>::InvalidAddressBit)
115126
{
116127
// Not a valid offset within the block. No further processing necessary.
117-
return;
128+
return false;
118129
}
119130

120-
unsigned char * attributes = &this->ObjectInfo(objectIndex);
131+
*ppAttrs = &this->ObjectInfo(objectIndex);
132+
return true;
133+
}
134+
135+
template <class TBlockAttributes>
136+
template <bool doSpecialMark>
137+
_NOINLINE
138+
void
139+
SmallFinalizableHeapBlockT<TBlockAttributes>::ProcessMarkedObject(void* objectAddress, MarkContext * markContext)
140+
{
141+
unsigned char * attributes = nullptr;
142+
if (!this->TryGetAddressOfAttributes(objectAddress, &attributes))
143+
{
144+
return;
145+
}
121146

122147
if (!this->template UpdateAttributesOfMarkedObjects<doSpecialMark>(markContext, objectAddress, this->objectSize, *attributes,
123148
[&](unsigned char _attributes) { *attributes = _attributes; }))

lib/Common/Memory/SmallFinalizableHeapBlock.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ class SmallFinalizableHeapBlockT : public SmallNormalHeapBlockT<TBlockAttributes
3030
}
3131
void SetNextBlock(SmallFinalizableHeapBlockT * next) { Base::SetNextBlock(next); }
3232

33+
bool TryGetAddressOfAttributes(void* objectAddress, unsigned char **ppAttr);
34+
bool TryGetAttributes(void* objectAddress, unsigned char *pAttr);
35+
3336
template <bool doSpecialMark>
3437
void ProcessMarkedObject(void* candidate, MarkContext * markContext);
3538

0 commit comments

Comments
 (0)