Skip to content

Commit 7bfaf94

Browse files
committed
[MERGE chakra-core#2465 @leirocks] Float32Array memory leak problem chakra-core#2328
Merge pull request chakra-core#2465 from leirocks:2328-2 the List keeping the weakreference that from ArrayBuffer to TypedArray kept expanding, there's no clean up after the TypedArray is collected. cleanup the list while adding parent once a while.
2 parents ea32e97 + bcf4eb8 commit 7bfaf94

2 files changed

Lines changed: 25 additions & 40 deletions

File tree

lib/Runtime/Library/ArrayBuffer.cpp

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ namespace Js
9595

9696
if (this->otherParents != nullptr)
9797
{
98-
this->otherParents->Map([&](int index, RecyclerWeakReference<ArrayBufferParent>* item)
98+
this->otherParents->Map([&](RecyclerWeakReference<ArrayBufferParent>* item)
9999
{
100100
this->ClearParentsLength(item->Get());
101101
});
@@ -114,40 +114,25 @@ namespace Js
114114
{
115115
if (this->otherParents == nullptr)
116116
{
117-
this->otherParents = JsUtil::List<RecyclerWeakReference<ArrayBufferParent>*>::New(this->GetRecycler());
117+
this->otherParents = RecyclerNew(this->GetRecycler(), OtherParents, this->GetRecycler());
118118
}
119-
this->otherParents->Add(this->GetRecycler()->CreateWeakReferenceHandle(parent));
120-
}
121-
}
122119

123-
void ArrayBuffer::RemoveParent(ArrayBufferParent* parent)
124-
{
125-
if (this->primaryParent != nullptr && this->primaryParent->Get() == parent)
126-
{
127-
this->primaryParent = nullptr;
128-
}
129-
else
130-
{
131-
int foundIndex = -1;
132-
bool parentFound = this->otherParents != nullptr && this->otherParents->MapUntil([&](int index, RecyclerWeakReference<ArrayBufferParent>* item)
120+
if (this->otherParents->increasedCount >= ParentsCleanupThreshold)
133121
{
134-
if (item->Get() == parent)
122+
auto iter = this->otherParents->GetEditingIterator();
123+
while (iter.Next())
135124
{
136-
foundIndex = index;
137-
return true;
125+
if (iter.Data()->Get() == nullptr)
126+
{
127+
iter.RemoveCurrent();
128+
}
138129
}
139-
return false;
140-
141-
});
142130

143-
if (parentFound)
144-
{
145-
this->otherParents->RemoveAt(foundIndex);
146-
}
147-
else
148-
{
149-
AssertMsg(false, "We shouldn't be clearing a parent that hasn't been set.");
131+
this->otherParents->increasedCount = 0;
150132
}
133+
134+
this->otherParents->PrependNode(this->GetRecycler()->CreateWeakReferenceHandle(parent));
135+
this->otherParents->increasedCount++;
151136
}
152137
}
153138

lib/Runtime/Library/ArrayBuffer.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ namespace Js
2929
virtual ArrayBuffer * GetAsArrayBuffer() = 0;
3030
virtual SharedArrayBuffer * GetAsSharedArrayBuffer() { return nullptr; }
3131
virtual void AddParent(ArrayBufferParent* parent) { }
32-
virtual void RemoveParent(ArrayBufferParent* parent) { }
3332
virtual bool IsDetached() { return false; }
3433
virtual uint32 GetByteLength() const = 0;
3534
virtual BYTE* GetBuffer() const = 0;
@@ -122,14 +121,15 @@ namespace Js
122121
static int GetBufferOffset() { return offsetof(ArrayBuffer, buffer); }
123122

124123
virtual void AddParent(ArrayBufferParent* parent) override;
125-
virtual void RemoveParent(ArrayBufferParent* parent) override;
126124
#if _WIN64
127125
//maximum 2G -1 for amd64
128126
static const uint32 MaxArrayBufferLength = 0x7FFFFFFF;
129127
#else
130128
// maximum 1G to avoid arithmetic overflow.
131129
static const uint32 MaxArrayBufferLength = 1 << 30;
132130
#endif
131+
static const uint32 ParentsCleanupThreshold = 1000;
132+
133133
virtual bool IsValidAsmJsBufferLength(uint length, bool forceCheck = false) { return false; }
134134
virtual bool IsArrayBuffer() override { return true; }
135135
virtual bool IsSharedArrayBuffer() override { return false; }
@@ -147,8 +147,17 @@ namespace Js
147147

148148
//In most cases, the ArrayBuffer will only have one parent
149149
RecyclerWeakReference<ArrayBufferParent>* primaryParent;
150-
JsUtil::List<RecyclerWeakReference<ArrayBufferParent>*>* otherParents;
151150

151+
struct OtherParents :public SList<RecyclerWeakReference<ArrayBufferParent>*, Recycler>
152+
{
153+
OtherParents(Recycler* recycler)
154+
:SList<RecyclerWeakReference<ArrayBufferParent>*, Recycler>(recycler), increasedCount(0)
155+
{
156+
}
157+
uint increasedCount;
158+
};
159+
160+
OtherParents* otherParents;
152161

153162
BYTE *buffer; // Points to a heap allocated RGBA buffer, can be null
154163
uint32 bufferLength; // Number of bytes allocated
@@ -179,15 +188,6 @@ namespace Js
179188
arrayBuffer->AddParent(this);
180189
}
181190

182-
void ClearArrayBuffer()
183-
{
184-
if (this->arrayBuffer != nullptr)
185-
{
186-
this->arrayBuffer->RemoveParent(this);
187-
this->arrayBuffer = nullptr;
188-
}
189-
}
190-
191191
public:
192192
ArrayBufferBase* GetArrayBuffer() const
193193
{

0 commit comments

Comments
 (0)