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

Convert pointers in a couple tables to relative #78801

Merged
merged 1 commit into from
Nov 28, 2022
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ private static unsafe void InitializeGlobalTablesForModule(TypeManagerHandle typ
IntPtr staticsSection = RuntimeImports.RhGetModuleSection(typeManager, ReadyToRunSectionType.GCStaticRegion, out length);
if (staticsSection != IntPtr.Zero)
{
Debug.Assert(length % IntPtr.Size == 0);
Debug.Assert(length % (MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint)) == 0);

object[] spine = InitializeStatics(staticsSection, length);

Expand Down Expand Up @@ -170,31 +170,39 @@ internal static void RunModuleInitializers()

private static unsafe void RunInitializers(TypeManagerHandle typeManager, ReadyToRunSectionType section)
{
var initializers = (delegate*<void>*)RuntimeImports.RhGetModuleSection(typeManager, section, out int length);
Debug.Assert(length % IntPtr.Size == 0);
int count = length / IntPtr.Size;
for (int i = 0; i < count; i++)
var pInitializers = (byte*)RuntimeImports.RhGetModuleSection(typeManager, section, out int length);
Debug.Assert(length % (MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint)) == 0);

for (byte* pCurrent = pInitializers;
pCurrent < (pInitializers + length);
pCurrent += MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint))
Copy link
Contributor

Choose a reason for hiding this comment

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

Extracting this logic into a property instead of c&p?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, we still need to switch on the size of the element later in the loop, so while it would be fewer characters, whoever is reading the code would now need to scroll to the definition to match it with the inner logic.

The ultimate improvement would be to split the code that reads the data structures from the code that interprets it with a struct iterator. But this is code that we only touch once every few years and mostly just forget it exists, so I didn't spend time to make it pretty.

{
initializers[i]();
var initializer = MethodTable.SupportsRelativePointers ? (delegate*<void>)ReadRelPtr32(pCurrent) : (delegate*<void>)pCurrent;
initializer();
}

static void* ReadRelPtr32(void* address)
=> (byte*)address + *(int*)address;
}

private static unsafe object[] InitializeStatics(IntPtr gcStaticRegionStart, int length)
{
IntPtr gcStaticRegionEnd = (IntPtr)((byte*)gcStaticRegionStart + length);
byte* gcStaticRegionEnd = (byte*)gcStaticRegionStart + length;

object[] spine = new object[length / IntPtr.Size];
object[] spine = new object[length / (MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint))];

ref object rawSpineData = ref Unsafe.As<byte, object>(ref Unsafe.As<RawArrayData>(spine).Data);

int currentBase = 0;
for (IntPtr** block = (IntPtr**)gcStaticRegionStart; block < (IntPtr**)gcStaticRegionEnd; block++)
for (byte* block = (byte*)gcStaticRegionStart;
block < gcStaticRegionEnd;
block += MethodTable.SupportsRelativePointers ? sizeof(int) : sizeof(nint))
{
// Gc Static regions can be shared by modules linked together during compilation. To ensure each
// is initialized once, the static region pointer is stored with lowest bit set in the image.
// The first time we initialize the static region its pointer is replaced with an object reference
// whose lowest bit is no longer set.
IntPtr* pBlock = *block;
IntPtr* pBlock = MethodTable.SupportsRelativePointers ? (IntPtr*)ReadRelPtr32(block) : *(IntPtr**)block;
nint blockAddr = MethodTable.SupportsRelativePointers ? (nint)ReadRelPtr32(pBlock) : *pBlock;
if ((blockAddr & GCStaticRegionConstants.Uninitialized) == GCStaticRegionConstants.Uninitialized)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,10 @@ internal DispatchMap* DispatchMap
return DynamicTemplateType->DispatchMap;
}

return ((DispatchMap**)TypeManager.DispatchMap)[idxDispatchMap];
if (SupportsRelativePointers)
return (DispatchMap*)FollowRelativePointer((int*)TypeManager.DispatchMap + idxDispatchMap);
else
return ((DispatchMap**)TypeManager.DispatchMap)[idxDispatchMap];
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,16 @@ protected internal EmbeddedPointerIndirectionNode(TTarget target)

public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
{
dataBuilder.RequireInitialPointerAlignment();
dataBuilder.EmitPointerReloc(Target);
if (factory.Target.SupportsRelativePointers)
{
dataBuilder.RequireInitialAlignment(sizeof(int));
dataBuilder.EmitReloc(Target, RelocType.IMAGE_REL_BASED_RELPTR32);
}
else
{
dataBuilder.RequireInitialPointerAlignment();
dataBuilder.EmitPointerReloc(Target);
}
}

// At minimum, Target needs to be reported as a static dependency by inheritors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)

foreach (var module in sortedModules)
{
builder.EmitPointerReloc(factory.MethodEntrypoint(module.GetGlobalModuleType().GetStaticConstructor()));
IMethodNode entrypoint = factory.MethodEntrypoint(module.GetGlobalModuleType().GetStaticConstructor());
if (factory.Target.SupportsRelativePointers)
builder.EmitReloc(entrypoint, RelocType.IMAGE_REL_BASED_RELPTR32);
else
builder.EmitPointerReloc(entrypoint);
}

var result = builder.ToObjectData();
Expand Down