#ifndef MRT_TYPE_INFO_MANAGER_H
#define MRT_TYPE_INFO_MANAGER_H
#include <unordered_map>
#include "ObjectModel/MClass.h"
#include "Base/SysCall.h"
#include "Base/RwLock.h"
#if defined(__linux__) || defined(hongmeng) || defined(__APPLE__)
#include <sys/mman.h>
#endif
#include "Base/HashUtils.h"
#include "Base/ImmortalWrapper.h"
namespace MapleRuntime {
class TypeGCInfo {
public:
CString GetGCTibStr(TypeInfo* ti);
private:
void FillTypeGCInfo(TypeInfo* ti, CString &gcTibStr, U32 &curSize);
void FillArrayTypeGCInfo(TypeInfo* ti, CString &gcTibStr, U32 &curSize);
};
class TypeInfoManager {
friend class TypeInfo;
friend class CJFileLoader;
public:
explicit TypeInfoManager() : genericTypeInfoDescMap(1024) {}
~TypeInfoManager() = default;
void Init();
void Fini();
void NewMMap(size_t size);
void FreeMMap(uintptr_t address, size_t size);
static TypeInfoManager& GetTypeInfoManager();
TypeInfo* GetOrCreateTypeInfo(TypeTemplate* tt, U32 argSize, TypeInfo* args[]);
void AddTypeInfo(TypeInfo* ti);
static U32 GetTypeSize(TypeInfo* ti);
void ParseEnumInfo(TypeTemplate* tt, U32 argSize, TypeInfo* args[], TypeInfo* ti);
void RecordMTableDesc(U32 uuid, MTableDesc* mTableDesc) { mTableList.emplace(uuid, mTableDesc); }
MTableDesc* GetMTableDesc(U32 uuid)
{
auto it = mTableList.find(uuid);
if (it != mTableList.end()) {
return it->second;
}
return nullptr;
}
U16 GetTypeTemplateUUID(TypeTemplate* tt);
void FillReflectInfo(TypeTemplate* tt, TypeInfo* ti);
void InitAnyAndObjectType();
TypeInfo* GetAnyTypeInfo() { return anyTi; }
TypeInfo* GetObjectTypeInfo() { return objectTi; }
void FillOffsets(TypeInfo* newTypeInfo, TypeTemplate* tt, U32 argSize, TypeInfo* args[]);
void CalculateGCTib(TypeInfo* typeInfo);
private:
uintptr_t Allocate(size_t size);
CString GetGCTibStr(TypeInfo* typeInfo);
void AddMTable(TypeTemplate* tt, TypeInfo* newTypeInfo, U32 argSize, TypeInfo* args[]);
void CopyParameterInfos(MethodInfo* ttMethodInfo, MethodInfo* tiMethodInfo);
void CopyMethodInfo(MethodInfo* ttMethodInfo, MethodInfo* tiMethodInfo, TypeInfo* ti);
bool IsEnumInfoReady(TypeTemplate* tt, TypeInfo* ti);
void HandleEnumCtorReflectInfo(TypeTemplate* tt, TypeInfo* ti);
EnumInfo* AllocateEnumInfo(EnumInfo* ttEnumInfo);
EnumDebugInfo* AllocateEnumDebugInfo(EnumInfo* ttEnumInfo);
void SetEnumConstructors(EnumDebugInfo* enumDebugInfo, EnumInfo* ttEnumInfo, U32 argSize, TypeInfo* args[]);
void SetMethodInfos(EnumInfo* enumInfo, EnumInfo* ttEnumInfo, TypeInfo* ti);
enum TypeInfoStatus : uint8_t {
TYPEINFO_NOT_CREATED = 0,
TYPEINFO_INITING,
TYPEINFO_INITED,
};
class GenericTiDesc {
public:
GenericTiDesc(TypeTemplate* pTypeTemplate, U32 pArgSize, TypeInfo* pArgs[])
: tt(pTypeTemplate), argSize(pArgSize), args(pArgs), hash(computeHash()) {
}
GenericTiDesc(GenericTiDesc &desc)
{
tt = desc.tt;
argSize = desc.argSize;
hash = desc.hash;
argsVector.assign(desc.args, desc.args + desc.argSize);
tid.store(GetTid());
}
GenericTiDesc& operator=(const GenericTiDesc& other) = delete;
bool operator==(const GenericTiDesc &other) const;
U32 GetHash() const { return hash; }
TypeInfo* typeInfo { nullptr };
bool IsNotCreated() { return typeInfo == nullptr; }
bool IsIniting() { return status.load(std::memory_order_acquire) == TypeInfoStatus::TYPEINFO_INITING; }
bool IsInited() { return status.load(std::memory_order_acquire) == TypeInfoStatus::TYPEINFO_INITED; }
void SetTypeInfoStatus(TypeInfoStatus tiStatus) { status.store(tiStatus, std::memory_order_release); }
TypeInfoStatus GetTypeInfoStatus() { return status.load(std::memory_order_acquire); }
std::atomic<U32> tid = { 0 };
U32 computeHash();
TypeTemplate* tt;
U32 argSize;
TypeInfo** args;
U32 hash;
private:
std::vector<TypeInfo*> argsVector = { };
std::atomic<TypeInfoStatus> status { TypeInfoStatus::TYPEINFO_NOT_CREATED };
};
class GenericTiDescHashMap {
public:
explicit GenericTiDescHashMap(size_t numBuckets)
: buckets(numBuckets) {}
~GenericTiDescHashMap()
{
for (auto &bucket : buckets) {
for (auto &vec : bucket.maps) {
for (auto desc : vec.second) {
delete desc;
desc = nullptr;
}
}
}
buckets.clear();
}
GenericTiDesc* InsertGenericTiDesc(GenericTiDesc& desc);
GenericTiDesc* GetGenericTiDesc(GenericTiDesc& desc);
private:
struct Bucket {
std::unordered_map<U32, std::vector<GenericTiDesc*>> maps;
RwLock rwLock;
};
std::vector<Bucket> buckets;
};
GenericTiDesc* InsertGenericTiDesc(GenericTiDesc& desc);
GenericTiDesc* GetGenericTiDesc(GenericTiDesc& desc);
GenericTiDesc* GetTypeInfo(TypeTemplate* tt, U32 argSize, TypeInfo* args[]);
void CreatedTypeInfo(GenericTiDesc* &tiDesc, TypeTemplate* tt, U32 argSize, TypeInfo* args[]);
void CreatedTypeInfoImpl(GenericTiDesc* &tiDesc, TypeTemplate* tt, U32 argSize, TypeInfo* args[]);
void FillRemainingField(GenericTiDesc* &tiDesc, TypeTemplate* tt, U32 argSize, TypeInfo* args[]);
size_t mapMemory = 1 * MB;
std::atomic<uintptr_t> position;
std::mutex ttMutex;
std::recursive_mutex tiMutex;
std::unordered_map<const char*, TypeInfo*, HashString, EqualString> nonGenericTypeInfos;
std::unordered_map<const char*, TypeInfo*, HashString, EqualString> genericTypeInfos;
std::unordered_map<const char*, TypeTemplate*, HashString, EqualString> typeTemplates;
GenericTiDescHashMap genericTypeInfoDescMap;
uintptr_t startAddress;
uintptr_t endAddress;
std::atomic<U32> tiMaxUUID { 1 };
std::atomic<U16> ttMaxUUID { 1 };
TypeGCInfo typeGCInfo;
std::vector<std::pair<uintptr_t, size_t>> mmapList;
std::unordered_map<U32, MTableDesc*> mTableList;
TypeInfo* anyTi = nullptr;
TypeInfo* objectTi = nullptr;
};
}
#endif