blob: bf4ffb78d47beeaac6d0ac371a1626765addac72 [file] [log] [blame]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
#if ENABLE_NATIVE_CODEGEN
// forward ref
struct FunctionBodyDataIDL;
namespace Js
{
// - Data generated for jitting purposes
// - Recycler-allocated, lifetime is from when a code gen work item is added to the jit queue, to when jitting is complete
// - Also keeps the function body and inlinee function bodies alive while jitting.
class FunctionCodeGenJitTimeData
{
private:
Field(FunctionInfo *) const functionInfo;
// Point's to an entry point if the work item needs the entry point alive- null for cases where the entry point isn't used
Field(EntryPointInfo *) const entryPointInfo;
// These cloned inline caches are guaranteed to have stable data while jitting, but will be collectible after jitting
Field(ObjTypeSpecFldInfoArray) objTypeSpecFldInfoArray;
// Globally ordered list of all object type specialized property access information (monomorphic and polymorphic caches combined).
Field(uint) globalObjTypeSpecFldInfoCount;
Field(Field(ObjTypeSpecFldInfo*)*) globalObjTypeSpecFldInfoArray;
// 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(Field(FunctionCodeGenJitTimeData*)*) callApplyTargetInlinees;
Field(RecyclerWeakReference<FunctionBody>*) weakFuncRef;
Field(PolymorphicInlineCacheInfoIDL*) inlineeInfo;
Field(PolymorphicInlineCacheInfoIDL*) selfInfo;
Field(PolymorphicInlineCacheIDL*) polymorphicInlineCaches;
// current value of global this object, may be changed in case of script engine invalidation
Field(Var) globalThisObject;
// Number of functions that are to be inlined (this is not the length of the 'inlinees' array above, includes getter setter inlinee count)
Field(uint) inlineeCount;
// Number of counts of getter setter to be inlined. This is not an exact count as inline caches are shared and we have no way of knowing
// accurate count.
Field(uint) ldFldInlineeCount;
// For polymorphic call site we will have linked list of FunctionCodeGenJitTimeData
// Each is differentiated by id starting from 0, 1
Field(FunctionCodeGenJitTimeData *) next;
Field(bool) isInlined;
// This indicates the function is aggressively Inlined(see NativeCodeGenerator::TryAggressiveInlining) .
Field(bool) isAggressiveInliningEnabled;
// The profiled iterations need to be determined at the time of gathering code gen data on the main thread
Field(const uint16) profiledIterations;
FunctionCodeGenJitTimeData(FunctionInfo *const functionInfo, EntryPointInfo *const entryPoint, Var globalThis, uint16 profiledIterations, bool isInlined = true);
#ifdef FIELD_ACCESS_STATS
public:
Field(FieldAccessStatsPtr) inlineCacheStats;
void EnsureInlineCacheStats(Recycler* recycler);
void AddInlineeInlineCacheStats(FunctionCodeGenJitTimeData* inlineeJitTimeData);
#endif
public:
static FunctionCodeGenJitTimeData* New(Recycler* recycler, FunctionInfo *const functionInfo, EntryPointInfo *const entryPoint, bool isInlined = true);
public:
Field(BVFixed *) inlineesBv;
Field(Js::PropertyId*) sharedPropertyGuards;
Field(uint) sharedPropertyGuardCount;
FunctionInfo *GetFunctionInfo() const;
FunctionBody *GetFunctionBody() const;
Var GetGlobalThisObject() const;
FunctionBodyDataIDL *GetJITBody() const;
FunctionCodeGenJitTimeData *GetNext() const { return next; }
const ObjTypeSpecFldInfoArray* GetObjTypeSpecFldInfoArray() const { return &this->objTypeSpecFldInfoArray; }
ObjTypeSpecFldInfoArray* GetObjTypeSpecFldInfoArray() { return &this->objTypeSpecFldInfoArray; }
EntryPointInfo* GetEntryPointInfo() const { return this->entryPointInfo; }
public:
const FunctionCodeGenJitTimeData *GetInlinee(const ProfileId profiledCallSiteId) const;
const FunctionCodeGenJitTimeData *GetLdFldInlinee(const InlineCacheIndex inlineCacheIndex) const;
const FunctionCodeGenJitTimeData * GetCallbackInlinee(const ProfileId profiledCallSiteId) const;
const FunctionCodeGenJitTimeData * GetCallApplyTargetInlinee(const ProfileId callApplyCallSiteId) const;
FunctionCodeGenJitTimeData *AddInlinee(
Recycler *const recycler,
const ProfileId profiledCallSiteId,
FunctionInfo *const inlinee,
bool isInlined = true);
uint InlineeCount() const;
uint LdFldInlineeCount() const;
bool IsLdFldInlineePresent() const { return ldFldInlineeCount != 0; }
RecyclerWeakReference<FunctionBody> *GetWeakFuncRef() const { return this->weakFuncRef; }
void SetWeakFuncRef(RecyclerWeakReference<FunctionBody> *weakFuncRef)
{
Assert(this->weakFuncRef == nullptr || weakFuncRef == nullptr || this->weakFuncRef == weakFuncRef);
this->weakFuncRef = weakFuncRef;
}
void SetPolymorphicInlineInfo(PolymorphicInlineCacheInfoIDL* inlineeInfo, PolymorphicInlineCacheInfoIDL* selfInfo, PolymorphicInlineCacheIDL* polymorphicInlineCaches)
{
this->inlineeInfo = inlineeInfo;
this->selfInfo = selfInfo;
this->polymorphicInlineCaches = polymorphicInlineCaches;
}
FunctionCodeGenJitTimeData *AddLdFldInlinee(
Recycler *const recycler,
const InlineCacheIndex inlineCacheIndex,
FunctionInfo *const inlinee);
FunctionCodeGenJitTimeData * AddCallbackInlinee(
Recycler *const recycler,
const ProfileId profiledCallSiteId,
FunctionInfo *const inlinee);
FunctionCodeGenJitTimeData * AddCallApplyTargetInlinee(
Recycler *const recycler,
const ProfileId profiledCallSiteId,
const ProfileId callApplyCallSiteId,
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.
const FunctionCodeGenJitTimeData *GetJitTimeDataFromFunctionInfo(FunctionInfo *polyFunctioInfoy) const;
uint GetGlobalObjTypeSpecFldInfoCount() const { return this->globalObjTypeSpecFldInfoCount; }
Field(ObjTypeSpecFldInfo*)* GetGlobalObjTypeSpecFldInfoArray() const {return this->globalObjTypeSpecFldInfoArray; }
ObjTypeSpecFldInfo* GetGlobalObjTypeSpecFldInfo(uint propertyInfoId) const
{
Assert(this->globalObjTypeSpecFldInfoArray != nullptr && propertyInfoId < this->globalObjTypeSpecFldInfoCount);
return this->globalObjTypeSpecFldInfoArray[propertyInfoId];
}
void SetGlobalObjTypeSpecFldInfo(uint propertyInfoId, ObjTypeSpecFldInfo* info) const
{
Assert(this->globalObjTypeSpecFldInfoArray != nullptr && propertyInfoId < this->globalObjTypeSpecFldInfoCount);
this->globalObjTypeSpecFldInfoArray[propertyInfoId] = info;
}
void SetGlobalObjTypeSpecFldInfoArray(Field(ObjTypeSpecFldInfo*)* array, uint count)
{
Assert(array != nullptr);
this->globalObjTypeSpecFldInfoArray = array;
this->globalObjTypeSpecFldInfoCount = count;
}
bool GetIsInlined() const
{
return isInlined;
}
bool GetIsAggressiveInliningEnabled() const
{
return isAggressiveInliningEnabled;
}
void SetIsAggressiveInliningEnabled()
{
isAggressiveInliningEnabled = true;
}
void SetupRecursiveInlineeChain(
Recycler *const recycler,
const ProfileId profiledCallSiteId)
{
if (!inlinees)
{
inlinees = RecyclerNewArrayZ(recycler, Field(FunctionCodeGenJitTimeData *), GetFunctionBody()->GetProfiledCallSiteCount());
}
inlinees[profiledCallSiteId] = this;
inlineeCount++;
}
uint16 GetProfiledIterations() const;
PREVENT_COPY(FunctionCodeGenJitTimeData)
};
}
#endif