Skip to content

JIT: lay groundwork for custom layouts #111942

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

Closed
wants to merge 1 commit into from
Closed
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
18 changes: 6 additions & 12 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -11041,24 +11041,18 @@ class Compiler
#endif // DEBUG

private:
class ClassLayoutTable* m_classLayoutTable = nullptr;

class ClassLayoutTable* typCreateClassLayoutTable();
class ClassLayoutTable* typGetClassLayoutTable();
class ClassLayoutBuilder* m_classLayoutBuilder = nullptr;
class ClassLayoutBuilder* typGetClassLayoutBuilder();

public:
// Get the layout having the specified layout number.
ClassLayout* typGetLayoutByNum(unsigned layoutNum);
// Get the layout number of the specified layout.
unsigned typGetLayoutNum(ClassLayout* layout);
// Get the layout having the specified size but no class handle.
ClassLayout* typGetBlkLayout(unsigned blockSize);
// Get the number of a layout having the specified size but no class handle.
unsigned typGetBlkLayoutNum(unsigned blockSize);
// Get the layout for the specified class handle.
ClassLayout* typGetObjLayout(CORINFO_CLASS_HANDLE classHandle);
// Get the number of a layout for the specified class handle.
unsigned typGetObjLayoutNum(CORINFO_CLASS_HANDLE classHandle);
// Get the layout for a boxed instance
ClassLayout* typGetBoxLayout(ClassLayout* payloadLayout);
// Get the layout for the specified array of known length
ClassLayout* typGetArrayLayout(ClassLayout* elementLayout, unsigned length);

var_types TypeHandleToVarType(CORINFO_CLASS_HANDLE handle, ClassLayout** pLayout = nullptr);
var_types TypeHandleToVarType(CorInfoType jitType, CORINFO_CLASS_HANDLE handle, ClassLayout** pLayout = nullptr);
Expand Down
180 changes: 96 additions & 84 deletions src/coreclr/jit/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ class ClassLayoutTable
// Each layout is assigned a number, starting with TYP_UNKNOWN + 1. This way one could use a single
// unsigned value to represent the notion of type - values below TYP_UNKNOWN are var_types and values
// above it are struct layouts.
static constexpr unsigned ZeroSizedBlockLayoutNum = TYP_UNKNOWN + 1;
static constexpr unsigned FirstLayoutNum = TYP_UNKNOWN + 2;
static constexpr unsigned FirstLayoutNum = TYP_UNKNOWN + 1;

typedef JitHashTable<unsigned, JitSmallPrimitiveKeyFuncs<unsigned>, unsigned> BlkLayoutIndexMap;
typedef JitHashTable<CORINFO_CLASS_HANDLE, JitPtrKeyFuncs<CORINFO_CLASS_STRUCT_>, unsigned> ObjLayoutIndexMap;
Expand All @@ -38,62 +37,40 @@ class ClassLayoutTable
unsigned m_layoutCount;
// The capacity of m_layoutLargeArray (when more than 3 layouts are stored).
unsigned m_layoutLargeCapacity;
// We furthermore fast-path the 0-sized block layout which is used for
// block locals that may grow (e.g. the outgoing arg area in every non-x86
// compilation).
ClassLayout m_zeroSizedBlockLayout;

// Associated layout builder
ClassLayoutBuilder* m_layoutBuilder;

public:
ClassLayoutTable()
ClassLayoutTable(ClassLayoutBuilder* builder)
: m_layoutCount(0)
, m_layoutLargeCapacity(0)
, m_zeroSizedBlockLayout(0)
, m_layoutBuilder(builder)
{
}

// Get a number that uniquely identifies the specified layout.
unsigned GetLayoutNum(ClassLayout* layout) const
{
if (layout == &m_zeroSizedBlockLayout)
{
return ZeroSizedBlockLayoutNum;
}

return GetLayoutIndex(layout) + FirstLayoutNum;
}

// Get the layout that corresponds to the specified identifier number.
ClassLayout* GetLayoutByNum(unsigned num) const
{
if (num == ZeroSizedBlockLayoutNum)
{
// Fine to cast away const as ClassLayout is immutable
return const_cast<ClassLayout*>(&m_zeroSizedBlockLayout);
}

assert(num >= FirstLayoutNum);
return GetLayoutByIndex(num - FirstLayoutNum);
}

// Get the layout having the specified size but no class handle.
ClassLayout* GetBlkLayout(Compiler* compiler, unsigned blockSize)
{
if (blockSize == 0)
{
return &m_zeroSizedBlockLayout;
}

return GetLayoutByIndex(GetBlkLayoutIndex(compiler, blockSize));
}

// Get a number that uniquely identifies a layout having the specified size but no class handle.
unsigned GetBlkLayoutNum(Compiler* compiler, unsigned blockSize)
{
if (blockSize == 0)
{
return ZeroSizedBlockLayoutNum;
}

return GetBlkLayoutIndex(compiler, blockSize) + FirstLayoutNum;
}

Expand Down Expand Up @@ -132,7 +109,6 @@ class ClassLayoutTable
unsigned GetLayoutIndex(ClassLayout* layout) const
{
assert(layout != nullptr);
assert(layout != &m_zeroSizedBlockLayout);

if (HasSmallCapacity())
{
Expand All @@ -159,9 +135,6 @@ class ClassLayoutTable

unsigned GetBlkLayoutIndex(Compiler* compiler, unsigned blockSize)
{
// The 0-sized block layout has its own fast path.
assert(blockSize != 0);

if (HasSmallCapacity())
{
for (unsigned i = 0; i < m_layoutCount; i++)
Expand All @@ -186,7 +159,7 @@ class ClassLayoutTable

ClassLayout* CreateBlkLayout(Compiler* compiler, unsigned blockSize)
{
return new (compiler, CMK_ClassLayout) ClassLayout(blockSize);
return m_layoutBuilder->NewBlock(blockSize);
}

unsigned AddBlkLayout(Compiler* compiler, ClassLayout* layout)
Expand Down Expand Up @@ -230,7 +203,7 @@ class ClassLayoutTable

ClassLayout* CreateObjLayout(Compiler* compiler, CORINFO_CLASS_HANDLE classHandle)
{
return ClassLayout::Create(compiler, classHandle);
return m_layoutBuilder->New(classHandle);
}

unsigned AddObjLayout(Compiler* compiler, ClassLayout* layout)
Expand Down Expand Up @@ -291,99 +264,91 @@ class ClassLayoutTable
}
};

ClassLayoutTable* Compiler::typCreateClassLayoutTable()
{
assert(m_classLayoutTable == nullptr);

if (compIsForInlining())
{
m_classLayoutTable = impInlineInfo->InlinerCompiler->m_classLayoutTable;
//
// --------------------- Compiler ----------------
//

if (m_classLayoutTable == nullptr)
{
m_classLayoutTable = new (this, CMK_ClassLayout) ClassLayoutTable();
ClassLayoutBuilder* Compiler::typGetClassLayoutBuilder()
{
Compiler* const rootCompiler = impInlineRoot();

impInlineInfo->InlinerCompiler->m_classLayoutTable = m_classLayoutTable;
}
}
else
if (rootCompiler->m_classLayoutBuilder == nullptr)
{
m_classLayoutTable = new (this, CMK_ClassLayout) ClassLayoutTable();
rootCompiler->m_classLayoutBuilder = new (this, CMK_ClassLayout) ClassLayoutBuilder(rootCompiler);
}

return m_classLayoutTable;
return rootCompiler->m_classLayoutBuilder;
}

ClassLayoutTable* Compiler::typGetClassLayoutTable()
ClassLayout* Compiler::typGetBlkLayout(unsigned blockSize)
{
if (m_classLayoutTable == nullptr)
{
return typCreateClassLayoutTable();
}

return m_classLayoutTable;
return typGetClassLayoutBuilder()->CreateBlock(blockSize);
}

ClassLayout* Compiler::typGetLayoutByNum(unsigned layoutNum)
ClassLayout* Compiler::typGetBoxLayout(ClassLayout* payloadLayout)
{
return typGetClassLayoutTable()->GetLayoutByNum(layoutNum);
return typGetClassLayoutBuilder()->CreateBox(payloadLayout);
}

unsigned Compiler::typGetLayoutNum(ClassLayout* layout)
ClassLayout* Compiler::typGetObjLayout(CORINFO_CLASS_HANDLE classHandle)
{
return typGetClassLayoutTable()->GetLayoutNum(layout);
return typGetClassLayoutBuilder()->Create(classHandle);
}

unsigned Compiler::typGetBlkLayoutNum(unsigned blockSize)
ClassLayout* Compiler::typGetArrayLayout(ClassLayout* elementLayout, unsigned length)
{
return typGetClassLayoutTable()->GetBlkLayoutNum(this, blockSize);
return typGetClassLayoutBuilder()->CreateArray(elementLayout, length);
}

ClassLayout* Compiler::typGetBlkLayout(unsigned blockSize)
{
return typGetClassLayoutTable()->GetBlkLayout(this, blockSize);
}
//
// --------------------- Class Layout Builder ----------------
//

unsigned Compiler::typGetObjLayoutNum(CORINFO_CLASS_HANDLE classHandle)
ClassLayoutBuilder::ClassLayoutBuilder(Compiler* compiler)
: m_compiler(compiler)
, m_layoutTable(nullptr)
{
return typGetClassLayoutTable()->GetObjLayoutNum(this, classHandle);
assert(!m_compiler->compIsForInlining());

m_layoutTable = new (m_compiler, CMK_ClassLayout) ClassLayoutTable(this);
}

ClassLayout* Compiler::typGetObjLayout(CORINFO_CLASS_HANDLE classHandle)
ClassLayout* ClassLayoutBuilder::Create(CORINFO_CLASS_HANDLE classHandle)
{
return typGetClassLayoutTable()->GetObjLayout(this, classHandle);
return m_layoutTable->GetObjLayout(m_compiler, classHandle);
}

ClassLayout* ClassLayout::Create(Compiler* compiler, CORINFO_CLASS_HANDLE classHandle)
ClassLayout* ClassLayoutBuilder::New(CORINFO_CLASS_HANDLE classHandle)
{
bool isValueClass = compiler->eeIsValueClass(classHandle);
bool isValueClass = m_compiler->eeIsValueClass(classHandle);
unsigned size;

if (isValueClass)
{
size = compiler->info.compCompHnd->getClassSize(classHandle);
size = m_compiler->info.compCompHnd->getClassSize(classHandle);
}
else
{
size = compiler->info.compCompHnd->getHeapClassSize(classHandle);
size = m_compiler->info.compCompHnd->getHeapClassSize(classHandle);
}

var_types type = compiler->impNormStructType(classHandle);
var_types type = m_compiler->impNormStructType(classHandle);

INDEBUG(const char* className = compiler->eeGetClassName(classHandle);)
INDEBUG(const char* shortClassName = compiler->eeGetShortClassName(classHandle);)
INDEBUG(const char* className = m_compiler->eeGetClassName(classHandle);)
INDEBUG(const char* shortClassName = m_compiler->eeGetShortClassName(classHandle);)

ClassLayout* layout = new (compiler, CMK_ClassLayout)
ClassLayout* layout = new (m_compiler, CMK_ClassLayout)
ClassLayout(classHandle, isValueClass, size, type DEBUGARG(className) DEBUGARG(shortClassName));
layout->InitializeGCPtrs(compiler);

layout->InitializeGCPtrs(m_compiler);
layout->Finalize();

return layout;
}

void ClassLayout::InitializeGCPtrs(Compiler* compiler)
{
assert(!m_gcPtrsInitialized);
assert(!IsBlockLayout());
assert(!m_finalized);

if (m_size < TARGET_POINTER_SIZE)
{
Expand Down Expand Up @@ -416,10 +381,55 @@ void ClassLayout::InitializeGCPtrs(Compiler* compiler)

m_gcPtrCount = gcPtrCount;
}
}

ClassLayout* ClassLayoutBuilder::CreateBlock(unsigned blockSize)
{
return m_layoutTable->GetBlkLayout(m_compiler, blockSize);
}

ClassLayout* ClassLayoutBuilder::NewBlock(unsigned blockSize)
{
ClassLayout* layout = new (m_compiler, CMK_ClassLayout) ClassLayout(blockSize);
layout->Finalize();
return layout;
}

ClassLayout* ClassLayoutBuilder::CreateBox(ClassLayout* payloadLayout)
{
return nullptr;
}

ClassLayout* ClassLayoutBuilder::CreateArray(ClassLayout* elementLayout, unsigned elementCount)
{
return nullptr;
}

ClassLayout* ClassLayoutBuilder::CreateCustom(unsigned length)
{
return nullptr;
}

void ClassLayoutBuilder::AddRepeatingElements(ClassLayout* customLayout,
unsigned offset,
ClassLayout* elementLayout,
unsigned count)
{
}

INDEBUG(m_gcPtrsInitialized = true;)
void ClassLayoutBuilder::AddGCFields(ClassLayout* customLayout, unsigned offset, unsigned count)
{
}

void ClassLayoutBuilder::Finalize(ClassLayout* customLayout)
{
customLayout->Finalize();
}

//
// --------------------- Class Layout ----------------
//

//------------------------------------------------------------------------
// IsStackOnly: does the layout represent a block that can never be on the heap?
//
Expand Down Expand Up @@ -497,6 +507,8 @@ bool ClassLayout::AreCompatible(const ClassLayout* layout1, const ClassLayout* l
CORINFO_CLASS_HANDLE clsHnd1 = layout1->GetClassHandle();
CORINFO_CLASS_HANDLE clsHnd2 = layout2->GetClassHandle();

// validate elemcount

if ((clsHnd1 != NO_CLASS_HANDLE) && (clsHnd1 == clsHnd2))
{
return true;
Expand Down
Loading
Loading