Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions lib/Runtime/Base/FunctionBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7170,13 +7170,11 @@ namespace Js
}
}

if (!IsScriptContextShutdown)
if (unregisteredInlineCacheCount > 0)
{
AssertMsg(!IsScriptContextShutdown, "Unregistration of inlineCache should only be done if this is not scriptContext shutdown.");
ThreadContext* threadContext = this->m_scriptContext->GetThreadContext();
if (unregisteredInlineCacheCount > 0)
{
threadContext->NotifyInlineCacheBatchUnregistered(unregisteredInlineCacheCount);
}
threadContext->NotifyInlineCacheBatchUnregistered(unregisteredInlineCacheCount);
}

while (this->GetPolymorphicInlineCachesHead())
Expand Down
19 changes: 19 additions & 0 deletions lib/Runtime/Base/ThreadContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2865,6 +2865,7 @@ ThreadContext::InvalidateAndDeleteInlineCacheList(InlineCacheList* inlineCacheLi
Assert(inlineCacheList != nullptr);

uint cacheCount = 0;
uint nullCacheCount = 0;
FOREACH_SLISTBASE_ENTRY(Js::InlineCache*, inlineCache, inlineCacheList)
{
cacheCount++;
Expand All @@ -2878,22 +2879,32 @@ ThreadContext::InvalidateAndDeleteInlineCacheList(InlineCacheList* inlineCacheLi

memset(inlineCache, 0, sizeof(Js::InlineCache));
}
else
{
nullCacheCount++;
}
}
NEXT_SLISTBASE_ENTRY;
Adelete(&this->inlineCacheThreadInfoAllocator, inlineCacheList);
this->registeredInlineCacheCount = this->registeredInlineCacheCount > cacheCount ? this->registeredInlineCacheCount - cacheCount : 0;
this->unregisteredInlineCacheCount = this->unregisteredInlineCacheCount > nullCacheCount ? this->unregisteredInlineCacheCount - nullCacheCount : 0;
}

void
ThreadContext::CompactInlineCacheInvalidationLists()
{
#if DBG
uint countOfNodesToCompact = this->unregisteredInlineCacheCount;
this->totalUnregisteredCacheCount = 0;
#endif
Assert(this->unregisteredInlineCacheCount > 0);
CompactProtoInlineCaches();

if (this->unregisteredInlineCacheCount > 0)
{
CompactStoreFieldInlineCaches();
}
Assert(countOfNodesToCompact == this->totalUnregisteredCacheCount);
}

void
Expand Down Expand Up @@ -2931,10 +2942,18 @@ ThreadContext::CompactInlineCacheList(InlineCacheList* inlineCacheList)
}
NEXT_SLISTBASE_ENTRY_EDITING;

#if DBG
this->totalUnregisteredCacheCount += cacheCount;
#endif
if (cacheCount > 0)
{
AssertMsg(this->unregisteredInlineCacheCount >= cacheCount, "Some codepaths didn't unregistered the inlineCaches which might leak memory.");
this->unregisteredInlineCacheCount = this->unregisteredInlineCacheCount > cacheCount ?
this->unregisteredInlineCacheCount - cacheCount : 0;

AssertMsg(this->registeredInlineCacheCount >= cacheCount, "Some codepaths didn't registered the inlineCaches which might leak memory.");
this->registeredInlineCacheCount = this->registeredInlineCacheCount > cacheCount ?
this->registeredInlineCacheCount - cacheCount : 0;
}
}

Expand Down
3 changes: 3 additions & 0 deletions lib/Runtime/Base/ThreadContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,9 @@ class ThreadContext sealed :

uint registeredInlineCacheCount;
uint unregisteredInlineCacheCount;
#if DBG
uint totalUnregisteredCacheCount;
#endif

typedef JsUtil::BaseDictionary<Js::Var, Js::IsInstInlineCache*, ArenaAllocator> IsInstInlineCacheListMapByFunction;
IsInstInlineCacheListMapByFunction isInstInlineCacheByFunction;
Expand Down
11 changes: 10 additions & 1 deletion lib/Runtime/Language/JavascriptOperators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9374,6 +9374,8 @@ namespace Js
return;
}

uint unregisteredInlineCacheCount = 0;

Assert(inlineCaches && size > 0);

// If we're not shutting down (as in closing the script context), we need to remove our inline caches from
Expand All @@ -9390,7 +9392,10 @@ namespace Js
{
for (int i = 0; i < size; i++)
{
inlineCaches[i].RemoveFromInvalidationList();
if (inlineCaches[i].RemoveFromInvalidationList())
{
unregisteredInlineCacheCount++;
}
}

AllocatorDeleteArray(InlineCacheAllocator, functionBody->GetScriptContext()->GetInlineCacheAllocator(), size, inlineCaches);
Expand Down Expand Up @@ -9426,6 +9431,10 @@ namespace Js
prev = next = nullptr;
inlineCaches = nullptr;
size = 0;
if (unregisteredInlineCacheCount > 0)
{
functionBody->GetScriptContext()->GetThreadContext()->NotifyInlineCacheBatchUnregistered(unregisteredInlineCacheCount);
}
}

JavascriptString * JavascriptOperators::Concat3(Var aLeft, Var aCenter, Var aRight, ScriptContext * scriptContext)
Expand Down
14 changes: 12 additions & 2 deletions lib/Runtime/Library/RootObjectBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,13 @@ namespace Js
void
RootObjectBase::ReleaseInlineCache(Js::PropertyId propertyId, bool isLoadMethod, bool isStore, bool isShutdown)
{
uint unregisteredInlineCacheCount = 0;

RootObjectInlineCacheMap * inlineCacheMap = isStore ? storeInlineCacheMap :
isLoadMethod ? loadMethodInlineCacheMap : loadInlineCacheMap;
bool found = false;
inlineCacheMap->RemoveIfWithKey(propertyId,
[this, isShutdown, &found](PropertyRecord const * propertyRecord, RootObjectInlineCache * rootObjectInlineCache)
[this, isShutdown, &unregisteredInlineCacheCount, &found](PropertyRecord const * propertyRecord, RootObjectInlineCache * rootObjectInlineCache)
{
found = true;
if (rootObjectInlineCache->Release() == 0)
Expand All @@ -114,7 +116,11 @@ namespace Js
// Close called) and thus the invalidation lists are safe to keep references to caches from this script context.
if (!isShutdown)
{
rootObjectInlineCache->GetInlineCache()->RemoveFromInvalidationList();
if (rootObjectInlineCache->GetInlineCache()->RemoveFromInvalidationList())
{
unregisteredInlineCacheCount++;

}
AllocatorDelete(InlineCacheAllocator, this->GetScriptContext()->GetInlineCacheAllocator(), rootObjectInlineCache->GetInlineCache());
}
return true; // Remove from the map
Expand All @@ -123,6 +129,10 @@ namespace Js
}
);
Assert(found);
if (unregisteredInlineCacheCount > 0)
{
this->GetScriptContext()->GetThreadContext()->NotifyInlineCacheBatchUnregistered(unregisteredInlineCacheCount);
}
}

BOOL
Expand Down
3 changes: 2 additions & 1 deletion lib/Runtime/Library/ScriptFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,8 +753,9 @@ namespace Js
}
}

if (!isShutdown && unregisteredInlineCacheCount > 0 && !scriptContext->IsClosed())
if (unregisteredInlineCacheCount > 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is it okay to remove the shutdown and scriptContext closed conditions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you see above, we call RemoveFromInvalidationList() only if !isShutdown and !scriptContext->IsClosed which means unregisteredInlineCacheCount > 0 only if this 2 conditions are met. So the check here was redundant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it be replaced with an assert?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced.

{
AssertMsg(!isShutdown && !scriptContext->IsClosed(), "Unregistration of inlineCache should only be done if this is not shutdown or scriptContext closing.");
scriptContext->GetThreadContext()->NotifyInlineCacheBatchUnregistered(unregisteredInlineCacheCount);
}
}
Expand Down