Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inline callbacks #5081

Merged
merged 3 commits into from
May 4, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
41 changes: 41 additions & 0 deletions lib/Backend/FunctionCodeGenJitTimeData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ namespace Js
return ldFldInlinees ? ldFldInlinees[inlineCacheIndex] : nullptr;
}

const FunctionCodeGenJitTimeData * FunctionCodeGenJitTimeData::GetCallbackInlinee(const ProfileId profiledCallSiteId) const
{
Assert(GetFunctionBody());
Assert(profiledCallSiteId < GetFunctionBody()->GetProfiledCallSiteCount());

return callbackInlinees ? callbackInlinees[profiledCallSiteId] : nullptr;
}

FunctionCodeGenJitTimeData *FunctionCodeGenJitTimeData::AddInlinee(
Recycler *const recycler,
const ProfileId profiledCallSiteId,
Expand Down Expand Up @@ -165,6 +173,34 @@ namespace Js
return inlineeData;
}

FunctionCodeGenJitTimeData * FunctionCodeGenJitTimeData::AddCallbackInlinee(
Recycler *const recycler,
const ProfileId profiledCallSiteId,
FunctionInfo *const inlinee)
{
Assert(recycler != nullptr);
FunctionBody * functionBody = GetFunctionBody();
Assert(functionBody != nullptr);
Assert(profiledCallSiteId < functionBody->GetProfiledCallSiteCount());
Assert(inlinee != nullptr);

if (!callbackInlinees)
{
callbackInlinees = RecyclerNewArrayZ(recycler, Field(FunctionCodeGenJitTimeData *), functionBody->GetProfiledCallSiteCount());
}

// Polymorphic arguments are not inlined.
Assert(callbackInlinees[profiledCallSiteId] == nullptr);

FunctionCodeGenJitTimeData * inlineeData = FunctionCodeGenJitTimeData::New(recycler, inlinee, nullptr /* entryPoint */, true /*isInlined*/);
callbackInlinees[profiledCallSiteId] = inlineeData;
if (++callbackInlineeCount == 0)
{
Js::Throw::OutOfMemory();
}
return inlineeData;
}

uint FunctionCodeGenJitTimeData::InlineeCount() const
{
return inlineeCount;
Expand All @@ -175,6 +211,11 @@ namespace Js
return ldFldInlineeCount;
}

uint FunctionCodeGenJitTimeData::CallbackInlineeCount() const
{
return callbackInlineeCount;
}

#ifdef FIELD_ACCESS_STATS
void FunctionCodeGenJitTimeData::EnsureInlineCacheStats(Recycler* recycler)
{
Expand Down
11 changes: 11 additions & 0 deletions lib/Backend/FunctionCodeGenJitTimeData.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace Js
// There will be a non-null entry for each profiled call site where a function is to be inlined
Field(Field(FunctionCodeGenJitTimeData*)*) inlinees;
Field(Field(FunctionCodeGenJitTimeData*)*) ldFldInlinees;
Field(Field(FunctionCodeGenJitTimeData*)*) callbackInlinees;
Field(RecyclerWeakReference<FunctionBody>*) weakFuncRef;

Field(PolymorphicInlineCacheInfoIDL*) inlineeInfo;
Expand All @@ -46,6 +47,9 @@ namespace Js
// accurate count.
Field(uint) ldFldInlineeCount;

// Number of functions passed as arguments to be inlined.
Field(uint) callbackInlineeCount;
Copy link
Contributor

Choose a reason for hiding this comment

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

We currently have four unused bytes after globalObjTypeSpecFldInfoCount; could this go up there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This member isn't actually needed. I'm going to remove it.


// For polymorphic call site we will have linked list of FunctionCodeGenJitTimeData
// Each is differentiated by id starting from 0, 1
Field(FunctionCodeGenJitTimeData *) next;
Expand Down Expand Up @@ -90,13 +94,15 @@ namespace Js
public:
const FunctionCodeGenJitTimeData *GetInlinee(const ProfileId profiledCallSiteId) const;
const FunctionCodeGenJitTimeData *GetLdFldInlinee(const InlineCacheIndex inlineCacheIndex) const;
const FunctionCodeGenJitTimeData * GetCallbackInlinee(const ProfileId profiledCallSiteId) const;
FunctionCodeGenJitTimeData *AddInlinee(
Recycler *const recycler,
const ProfileId profiledCallSiteId,
FunctionInfo *const inlinee,
bool isInlined = true);
uint InlineeCount() const;
uint LdFldInlineeCount() const;
uint CallbackInlineeCount() const;
bool IsLdFldInlineePresent() const { return ldFldInlineeCount != 0; }

RecyclerWeakReference<FunctionBody> *GetWeakFuncRef() const { return this->weakFuncRef; }
Expand All @@ -118,6 +124,11 @@ namespace Js
const InlineCacheIndex inlineCacheIndex,
FunctionInfo *const inlinee);

FunctionCodeGenJitTimeData * AddCallbackInlinee(
Recycler *const recycler,
const ProfileId profiledCallSiteId,
FunctionInfo *const inlinee);

bool IsPolymorphicCallSite(const ProfileId profiledCallSiteId) const;
// This function walks all the chained jittimedata and returns the one which match the functionInfo.
// This can return null, if the functionInfo doesn't match.
Expand Down
49 changes: 49 additions & 0 deletions lib/Backend/FunctionJITTimeInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,24 @@ FunctionJITTimeInfo::BuildJITTimeData(
BuildJITTimeData(alloc, inlineeJITData, inlineeRuntimeData, jitData->inlinees[i], true, isForegroundJIT);
}
}

jitData->callbackInlineeCount = jitData->bodyData->profiledCallSiteCount;
jitData->callbackInlinees = AnewArrayZ(alloc, FunctionJITTimeDataIDL*, jitData->bodyData->profiledCallSiteCount);

for (Js::ProfileId i = 0; i < jitData->bodyData->profiledCallSiteCount; ++i)
{
const Js::FunctionCodeGenJitTimeData * inlineeJITData = codeGenData->GetCallbackInlinee(i);
if (inlineeJITData != nullptr)
{
const Js::FunctionCodeGenRuntimeData * inlineeRuntimeData = nullptr;
if (inlineeJITData->GetFunctionInfo()->HasBody())
{
inlineeRuntimeData = isInlinee ? targetRuntimeData->GetCallbackInlinee(i) : functionBody->GetCallbackInlineeCodeGenRuntimeData(i);
}
jitData->callbackInlinees[i] = AnewStructZ(alloc, FunctionJITTimeDataIDL);
BuildJITTimeData(alloc, inlineeJITData, inlineeRuntimeData, jitData->callbackInlinees[i], true, isForegroundJIT);
}
}
}
jitData->profiledRuntimeData = AnewStructZ(alloc, FunctionJITRuntimeIDL);
if (isInlinee && targetRuntimeData->ClonedInlineCaches()->HasInlineCaches())
Expand Down Expand Up @@ -250,6 +268,24 @@ FunctionJITTimeInfo::GetLdFldInlineeRuntimeData(const Js::InlineCacheIndex inlin
return GetLdFldInlinee(inlineCacheIndex) ? GetLdFldInlinee(inlineCacheIndex)->GetRuntimeInfo() : nullptr;
}

const FunctionJITRuntimeInfo *
FunctionJITTimeInfo::GetCallbackInlineeRuntimeData(const Js::ProfileId profiledCallSiteId) const
{
return GetCallbackInlinee(profiledCallSiteId) ? GetCallbackInlinee(profiledCallSiteId)->GetRuntimeInfo() : nullptr;
}

const FunctionJITRuntimeInfo *
FunctionJITTimeInfo::GetInlineeForCallbackInlineeRuntimeData(const Js::ProfileId profiledCallSiteId, intptr_t inlineeFuncBodyAddr) const
{
const FunctionJITTimeInfo *inlineeData = GetCallbackInlinee(profiledCallSiteId);
while (inlineeData && inlineeData->GetBody()->GetAddr() != inlineeFuncBodyAddr)
{
inlineeData = inlineeData->GetNext();
}
__analysis_assume(inlineeData != nullptr);
return inlineeData->GetRuntimeInfo();
}

const FunctionJITRuntimeInfo *
FunctionJITTimeInfo::GetRuntimeInfo() const
{
Expand Down Expand Up @@ -290,6 +326,19 @@ FunctionJITTimeInfo::GetSourceContextId() const
return GetBody()->GetSourceContextId();
}

const FunctionJITTimeInfo *
FunctionJITTimeInfo::GetCallbackInlinee(Js::ProfileId profileId) const
{
Assert(profileId < m_data.bodyData->profiledCallSiteCount);
if (!m_data.callbackInlinees)
{
return nullptr;
}
AssertOrFailFast(profileId < m_data.callbackInlineeCount);

return reinterpret_cast<const FunctionJITTimeInfo *>(m_data.callbackInlinees[profileId]);
}

const FunctionJITTimeInfo *
FunctionJITTimeInfo::GetLdFldInlinee(Js::InlineCacheIndex inlineCacheIndex) const
{
Expand Down
3 changes: 3 additions & 0 deletions lib/Backend/FunctionJITTimeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class FunctionJITTimeInfo
uint GetInlineeCount() const;
bool IsLdFldInlineePresent() const;

const FunctionJITTimeInfo * GetCallbackInlinee(Js::ProfileId profileId) const;
const FunctionJITTimeInfo * GetLdFldInlinee(Js::InlineCacheIndex inlineCacheIndex) const;
const FunctionJITTimeInfo * GetInlinee(Js::ProfileId profileId) const;
const FunctionJITTimeInfo * GetNext() const;
Expand All @@ -41,6 +42,8 @@ class FunctionJITTimeInfo
const FunctionJITRuntimeInfo * GetInlineeForTargetInlineeRuntimeData(const Js::ProfileId profiledCallSiteId, intptr_t inlineeFuncBodyAddr) const;
const FunctionJITRuntimeInfo *GetInlineeRuntimeData(const Js::ProfileId profiledCallSiteId) const;
const FunctionJITRuntimeInfo *GetLdFldInlineeRuntimeData(const Js::InlineCacheIndex inlineCacheIndex) const;
const FunctionJITRuntimeInfo * GetCallbackInlineeRuntimeData(const Js::ProfileId profiledCallSiteId) const;
const FunctionJITRuntimeInfo * GetInlineeForCallbackInlineeRuntimeData(const Js::ProfileId profiledCallSiteId, intptr_t inlineeFuncBodyAddr) const;
bool ForceJITLoopBody() const;
bool HasSharedPropertyGuards() const;
bool HasSharedPropertyGuard(Js::PropertyId id) const;
Expand Down
Loading