| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "Backend.h"
- FunctionJITTimeInfo::FunctionJITTimeInfo(FunctionJITTimeDataIDL * data) : m_data(*data)
- {
- // we will cast the data (i.e. midl struct) pointers into info pointers so we can extend with methods
- CompileAssert(sizeof(FunctionJITTimeDataIDL) == sizeof(FunctionJITTimeInfo));
- }
- /* static */
- void
- FunctionJITTimeInfo::BuildJITTimeData(
- __in ArenaAllocator * alloc,
- __in const Js::FunctionCodeGenJitTimeData * codeGenData,
- __in_opt const Js::FunctionCodeGenRuntimeData * runtimeData,
- __out FunctionJITTimeDataIDL * jitData,
- bool isInlinee,
- bool isForegroundJIT)
- {
- jitData->functionInfoAddr = (intptr_t)codeGenData->GetFunctionInfo();
- jitData->localFuncId = codeGenData->GetFunctionInfo()->GetLocalFunctionId();
- jitData->isAggressiveInliningEnabled = codeGenData->GetIsAggressiveInliningEnabled();
- jitData->isInlined = codeGenData->GetIsInlined();
- jitData->weakFuncRef = (intptr_t)codeGenData->GetWeakFuncRef();
- jitData->inlineesBv = (BVFixedIDL*)(const BVFixed*)codeGenData->inlineesBv;
- if (!codeGenData->GetFunctionBody() || !codeGenData->GetFunctionBody()->GetByteCode())
- {
- // outermost function must have a body, but inlinees may not (if they are builtins)
- Assert(isInlinee);
- return;
- }
- Js::FunctionBody * body = codeGenData->GetFunctionInfo()->GetParseableFunctionInfo()->GetFunctionBody();
- jitData->bodyData = AnewStructZ(alloc, FunctionBodyDataIDL);
- JITTimeFunctionBody::InitializeJITFunctionData(alloc, body, jitData->bodyData);
- Assert(isInlinee == !!runtimeData);
- const Js::FunctionCodeGenRuntimeData * targetRuntimeData = nullptr;
- if (runtimeData)
- {
- // may be polymorphic, so seek the runtime data matching our JIT time data
- targetRuntimeData = runtimeData->GetForTarget(codeGenData->GetFunctionInfo()->GetFunctionBody());
- }
- Js::FunctionBody * functionBody = codeGenData->GetFunctionBody();
- if (functionBody->HasDynamicProfileInfo())
- {
- ProfileDataIDL * profileData = AnewStruct(alloc, ProfileDataIDL);
- JITTimeProfileInfo::InitializeJITProfileData(alloc, functionBody->GetAnyDynamicProfileInfo(), functionBody, profileData, isForegroundJIT);
- jitData->bodyData->profileData = profileData;
- if (isInlinee)
- {
- // if not inlinee, NativeCodeGenerator will provide the address
- // REVIEW: OOP JIT, for inlinees, is this actually necessary?
- Js::ProxyEntryPointInfo *defaultEntryPointInfo = functionBody->GetDefaultEntryPointInfo();
- Assert(defaultEntryPointInfo->IsFunctionEntryPointInfo());
- Js::FunctionEntryPointInfo *functionEntryPointInfo = static_cast<Js::FunctionEntryPointInfo*>(defaultEntryPointInfo);
- jitData->callsCountAddress = (intptr_t)&functionEntryPointInfo->callsCount;
-
- jitData->sharedPropertyGuards = codeGenData->sharedPropertyGuards;
- jitData->sharedPropGuardCount = codeGenData->sharedPropertyGuardCount;
- }
- }
- if (jitData->bodyData->profiledCallSiteCount > 0)
- {
- jitData->inlineeCount = jitData->bodyData->profiledCallSiteCount;
- // using arena because we can't recycler allocate (may be on background), and heap freeing this is slightly complicated
- jitData->inlinees = AnewArrayZ(alloc, FunctionJITTimeDataIDL*, jitData->bodyData->profiledCallSiteCount);
- jitData->inlineesRecursionFlags = AnewArrayZ(alloc, boolean, jitData->bodyData->profiledCallSiteCount);
- for (Js::ProfileId i = 0; i < jitData->bodyData->profiledCallSiteCount; ++i)
- {
- const Js::FunctionCodeGenJitTimeData * inlineeJITData = codeGenData->GetInlinee(i);
- if (inlineeJITData == codeGenData)
- {
- jitData->inlineesRecursionFlags[i] = TRUE;
- }
- else if (inlineeJITData != nullptr)
- {
- const Js::FunctionCodeGenRuntimeData * inlineeRuntimeData = nullptr;
- if (inlineeJITData->GetFunctionInfo()->HasBody())
- {
- inlineeRuntimeData = isInlinee ? targetRuntimeData->GetInlinee(i) : functionBody->GetInlineeCodeGenRuntimeData(i);
- }
- jitData->inlinees[i] = AnewStructZ(alloc, FunctionJITTimeDataIDL);
- BuildJITTimeData(alloc, inlineeJITData, inlineeRuntimeData, jitData->inlinees[i], true, isForegroundJIT);
- }
- }
- }
- jitData->profiledRuntimeData = AnewStructZ(alloc, FunctionJITRuntimeIDL);
- if (isInlinee && targetRuntimeData->ClonedInlineCaches()->HasInlineCaches())
- {
- jitData->profiledRuntimeData->clonedCacheCount = jitData->bodyData->inlineCacheCount;
- jitData->profiledRuntimeData->clonedInlineCaches = AnewArray(alloc, intptr_t, jitData->profiledRuntimeData->clonedCacheCount);
- for (uint j = 0; j < jitData->bodyData->inlineCacheCount; ++j)
- {
- jitData->profiledRuntimeData->clonedInlineCaches[j] = (intptr_t)targetRuntimeData->ClonedInlineCaches()->GetInlineCache(j);
- }
- }
- if (jitData->bodyData->inlineCacheCount > 0)
- {
- jitData->ldFldInlineeCount = jitData->bodyData->inlineCacheCount;
- jitData->ldFldInlinees = AnewArrayZ(alloc, FunctionJITTimeDataIDL*, jitData->bodyData->inlineCacheCount);
- Field(ObjTypeSpecFldInfo*)* objTypeSpecInfo = codeGenData->GetObjTypeSpecFldInfoArray()->GetInfoArray();
- if(objTypeSpecInfo)
- {
- jitData->objTypeSpecFldInfoCount = jitData->bodyData->inlineCacheCount;
- jitData->objTypeSpecFldInfoArray = (ObjTypeSpecFldIDL**)objTypeSpecInfo;
- }
- for (Js::InlineCacheIndex i = 0; i < jitData->bodyData->inlineCacheCount; ++i)
- {
- const Js::FunctionCodeGenJitTimeData * inlineeJITData = codeGenData->GetLdFldInlinee(i);
- const Js::FunctionCodeGenRuntimeData * inlineeRuntimeData = isInlinee ? targetRuntimeData->GetLdFldInlinee(i) : functionBody->GetLdFldInlineeCodeGenRuntimeData(i);
- if (inlineeJITData != nullptr)
- {
- jitData->ldFldInlinees[i] = AnewStructZ(alloc, FunctionJITTimeDataIDL);
- BuildJITTimeData(alloc, inlineeJITData, inlineeRuntimeData, jitData->ldFldInlinees[i], true, isForegroundJIT);
- }
- }
- }
- if (!isInlinee && codeGenData->GetGlobalObjTypeSpecFldInfoCount() > 0)
- {
- Field(ObjTypeSpecFldInfo*)* globObjTypeSpecInfo = codeGenData->GetGlobalObjTypeSpecFldInfoArray();
- Assert(globObjTypeSpecInfo != nullptr);
- jitData->globalObjTypeSpecFldInfoCount = codeGenData->GetGlobalObjTypeSpecFldInfoCount();
- jitData->globalObjTypeSpecFldInfoArray = (ObjTypeSpecFldIDL**)globObjTypeSpecInfo;
- }
- const Js::FunctionCodeGenJitTimeData * nextJITData = codeGenData->GetNext();
- if (nextJITData != nullptr)
- {
- // only inlinee should be polymorphic
- Assert(isInlinee);
- jitData->next = AnewStructZ(alloc, FunctionJITTimeDataIDL);
- BuildJITTimeData(alloc, nextJITData, runtimeData, jitData->next, true, isForegroundJIT);
- }
- }
- uint
- FunctionJITTimeInfo::GetInlineeCount() const
- {
- return m_data.inlineeCount;
- }
- bool
- FunctionJITTimeInfo::IsLdFldInlineePresent() const
- {
- return m_data.ldFldInlineeCount != 0;
- }
- bool
- FunctionJITTimeInfo::HasSharedPropertyGuards() const
- {
- return m_data.sharedPropGuardCount != 0;
- }
- bool
- FunctionJITTimeInfo::HasSharedPropertyGuard(Js::PropertyId id) const
- {
- for (uint i = 0; i < m_data.sharedPropGuardCount; ++i)
- {
- if (m_data.sharedPropertyGuards[i] == id)
- {
- return true;
- }
- }
- return false;
- }
- intptr_t
- FunctionJITTimeInfo::GetFunctionInfoAddr() const
- {
- return m_data.functionInfoAddr;
- }
- intptr_t
- FunctionJITTimeInfo::GetWeakFuncRef() const
- {
- return m_data.weakFuncRef;
- }
- uint
- FunctionJITTimeInfo::GetLocalFunctionId() const
- {
- return m_data.localFuncId;
- }
- bool
- FunctionJITTimeInfo::IsAggressiveInliningEnabled() const
- {
- return m_data.isAggressiveInliningEnabled != FALSE;
- }
- bool
- FunctionJITTimeInfo::IsInlined() const
- {
- return m_data.isInlined != FALSE;
- }
- const BVFixed *
- FunctionJITTimeInfo::GetInlineesBV() const
- {
- return reinterpret_cast<const BVFixed *>(m_data.inlineesBv);
- }
- const FunctionJITTimeInfo *
- FunctionJITTimeInfo::GetJitTimeDataFromFunctionInfoAddr(intptr_t polyFuncInfo) const
- {
- const FunctionJITTimeInfo *next = this;
- while (next && next->GetFunctionInfoAddr() != polyFuncInfo)
- {
- next = next->GetNext();
- }
- return next;
- }
- const FunctionJITRuntimeInfo *
- FunctionJITTimeInfo::GetInlineeForTargetInlineeRuntimeData(const Js::ProfileId profiledCallSiteId, intptr_t inlineeFuncBodyAddr) const
- {
- const FunctionJITTimeInfo *inlineeData = GetInlinee(profiledCallSiteId);
- while (inlineeData && inlineeData->GetBody()->GetAddr() != inlineeFuncBodyAddr)
- {
- inlineeData = inlineeData->GetNext();
- }
- __analysis_assume(inlineeData != nullptr);
- return inlineeData->GetRuntimeInfo();
- }
- const FunctionJITRuntimeInfo *
- FunctionJITTimeInfo::GetInlineeRuntimeData(const Js::ProfileId profiledCallSiteId) const
- {
- return GetInlinee(profiledCallSiteId) ? GetInlinee(profiledCallSiteId)->GetRuntimeInfo() : nullptr;
- }
- const FunctionJITRuntimeInfo *
- FunctionJITTimeInfo::GetLdFldInlineeRuntimeData(const Js::InlineCacheIndex inlineCacheIndex) const
- {
- return GetLdFldInlinee(inlineCacheIndex) ? GetLdFldInlinee(inlineCacheIndex)->GetRuntimeInfo() : nullptr;
- }
- const FunctionJITRuntimeInfo *
- FunctionJITTimeInfo::GetRuntimeInfo() const
- {
- return reinterpret_cast<const FunctionJITRuntimeInfo*>(m_data.profiledRuntimeData);
- }
- ObjTypeSpecFldInfo *
- FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
- {
- Assert(index < GetBody()->GetInlineCacheCount());
- if (m_data.objTypeSpecFldInfoArray == nullptr)
- {
- return nullptr;
- }
- return reinterpret_cast<ObjTypeSpecFldInfo *>(m_data.objTypeSpecFldInfoArray[index]);
- }
- ObjTypeSpecFldInfo *
- FunctionJITTimeInfo::GetGlobalObjTypeSpecFldInfo(uint index) const
- {
- Assert(index < m_data.globalObjTypeSpecFldInfoCount);
- return reinterpret_cast<ObjTypeSpecFldInfo *>(m_data.globalObjTypeSpecFldInfoArray[index]);
- }
- uint
- FunctionJITTimeInfo::GetGlobalObjTypeSpecFldInfoCount() const
- {
- return m_data.globalObjTypeSpecFldInfoCount;
- }
- uint
- FunctionJITTimeInfo::GetSourceContextId() const
- {
- Assert(HasBody());
- return GetBody()->GetSourceContextId();
- }
- const FunctionJITTimeInfo *
- FunctionJITTimeInfo::GetLdFldInlinee(Js::InlineCacheIndex inlineCacheIndex) const
- {
- Assert(inlineCacheIndex < m_data.bodyData->inlineCacheCount);
- if (!m_data.ldFldInlinees)
- {
- return nullptr;
- }
- Assert(inlineCacheIndex < m_data.ldFldInlineeCount);
- return reinterpret_cast<const FunctionJITTimeInfo*>(m_data.ldFldInlinees[inlineCacheIndex]);
- }
- const FunctionJITTimeInfo *
- FunctionJITTimeInfo::GetInlinee(Js::ProfileId profileId) const
- {
- Assert(profileId < m_data.bodyData->profiledCallSiteCount);
- if (!m_data.inlinees)
- {
- return nullptr;
- }
- Assert(profileId < m_data.inlineeCount);
- auto inlinee = reinterpret_cast<const FunctionJITTimeInfo *>(m_data.inlinees[profileId]);
- if (inlinee == nullptr && m_data.inlineesRecursionFlags[profileId])
- {
- inlinee = this;
- }
- return inlinee;
- }
- const FunctionJITTimeInfo *
- FunctionJITTimeInfo::GetNext() const
- {
- return reinterpret_cast<const FunctionJITTimeInfo *>(m_data.next);
- }
- JITTimeFunctionBody *
- FunctionJITTimeInfo::GetBody() const
- {
- return reinterpret_cast<JITTimeFunctionBody *>(m_data.bodyData);
- }
- bool
- FunctionJITTimeInfo::HasBody() const
- {
- return m_data.bodyData != nullptr;
- }
- bool
- FunctionJITTimeInfo::IsPolymorphicCallSite(Js::ProfileId profiledCallSiteId) const
- {
- Assert(profiledCallSiteId < m_data.bodyData->profiledCallSiteCount);
- if (!m_data.inlinees)
- {
- return false;
- }
- Assert(profiledCallSiteId < m_data.inlineeCount);
- return ((FunctionJITTimeDataIDL*)this->GetInlinee(profiledCallSiteId))->next != nullptr;
- }
- bool
- FunctionJITTimeInfo::ForceJITLoopBody() const
- {
- return
- !PHASE_OFF(Js::JITLoopBodyPhase, this) &&
- !PHASE_OFF(Js::FullJitPhase, this) &&
- !GetBody()->IsGenerator() &&
- !GetBody()->HasTry() &&
- (
- PHASE_FORCE(Js::JITLoopBodyPhase, this)
- #ifdef ENABLE_PREJIT
- || Js::Configuration::Global.flags.Prejit
- #endif
- );
- }
- char16*
- FunctionJITTimeInfo::GetDisplayName() const
- {
- return GetBody()->GetDisplayName();
- }
- char16*
- FunctionJITTimeInfo::GetDebugNumberSet(wchar(&bufferToWriteTo)[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE]) const
- {
- // (#%u.%u), #%u --> (source file Id . function Id) , function Number
- int len = swprintf_s(bufferToWriteTo, MAX_FUNCTION_BODY_DEBUG_STRING_SIZE, _u(" (#%d.%u), #%u"),
- (int)GetSourceContextId(), GetLocalFunctionId(), GetBody()->GetFunctionNumber());
- Assert(len > 8);
- return bufferToWriteTo;
- }
|