Skip to content

Commit cfa0cc5

Browse files
authored
Inject IJW Copy Constructor calls in the JIT instead of in the IL stubs (#106424)
1 parent 631778a commit cfa0cc5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1458
-800
lines changed

docs/design/datacontracts/RuntimeTypeSystem.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ internal enum CorElementType
2323
// Values defined in ECMA-335 - II.23.1.16 Element types used in signatures
2424
// +
2525
Internal = 0x21, // Indicates that the next pointer sized number of bytes is the address of a TypeHandle. Signatures that contain the Internal CorElementType cannot exist in metadata that is saved into a serialized format.
26+
CModInternal = 0x22, // Indicates that the next byte specifies if the modifier is required and the next pointer sized number of bytes after that is the address of a TypeHandle. Signatures that contain the CModInternal CorElementType cannot exist in metadata that is saved into a seralized format.
2627
}
2728
```
2829

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,11 @@ internal static int EnumCompareTo<T>(T x, T y) where T : struct, Enum
360360
return x.CompareTo(y);
361361
}
362362

363+
// The body of this function will be created by the EE for the specific type.
364+
// See getILIntrinsicImplementation for how this happens.
365+
[Intrinsic]
366+
internal static extern unsafe void CopyConstruct<T>(T* dest, T* src) where T : unmanaged;
367+
363368
internal static ref byte GetRawData(this object obj) =>
364369
ref Unsafe.As<RawData>(obj).Data;
365370

src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,75 +1315,6 @@ public IntPtr AddRef()
13151315
}
13161316
} // class CleanupWorkListElement
13171317

1318-
internal unsafe struct CopyConstructorCookie
1319-
{
1320-
private void* m_source;
1321-
1322-
private nuint m_destinationOffset;
1323-
1324-
public delegate*<void*, void*, void> m_copyConstructor;
1325-
1326-
public delegate*<void*, void> m_destructor;
1327-
1328-
public CopyConstructorCookie* m_next;
1329-
1330-
[StackTraceHidden]
1331-
public void ExecuteCopy(void* destinationBase)
1332-
{
1333-
if (m_copyConstructor != null)
1334-
{
1335-
m_copyConstructor((byte*)destinationBase + m_destinationOffset, m_source);
1336-
}
1337-
1338-
if (m_destructor != null)
1339-
{
1340-
m_destructor(m_source);
1341-
}
1342-
}
1343-
}
1344-
1345-
internal unsafe struct CopyConstructorChain
1346-
{
1347-
public void* m_realTarget;
1348-
public CopyConstructorCookie* m_head;
1349-
1350-
public void Add(CopyConstructorCookie* cookie)
1351-
{
1352-
cookie->m_next = m_head;
1353-
m_head = cookie;
1354-
}
1355-
1356-
[ThreadStatic]
1357-
private static CopyConstructorChain s_copyConstructorChain;
1358-
1359-
public void Install(void* realTarget)
1360-
{
1361-
m_realTarget = realTarget;
1362-
s_copyConstructorChain = this;
1363-
}
1364-
1365-
[StackTraceHidden]
1366-
private void ExecuteCopies(void* destinationBase)
1367-
{
1368-
for (CopyConstructorCookie* current = m_head; current != null; current = current->m_next)
1369-
{
1370-
current->ExecuteCopy(destinationBase);
1371-
}
1372-
}
1373-
1374-
[UnmanagedCallersOnly]
1375-
[StackTraceHidden]
1376-
public static void* ExecuteCurrentCopiesAndGetTarget(void* destinationBase)
1377-
{
1378-
void* target = s_copyConstructorChain.m_realTarget;
1379-
s_copyConstructorChain.ExecuteCopies(destinationBase);
1380-
// Reset this instance to ensure we don't accidentally execute the copies again.
1381-
// All of the pointers point to the stack, so we don't need to free any memory.
1382-
s_copyConstructorChain = default;
1383-
return target;
1384-
}
1385-
}
1386-
13871318
internal static partial class StubHelpers
13881319
{
13891320
[MethodImpl(MethodImplOptions.InternalCall)]

src/coreclr/ildasm/dasm.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,6 +2088,9 @@ BYTE* PrettyPrintCABlobValue(PCCOR_SIGNATURE &typePtr,
20882088

20892089
#ifdef LOGGING
20902090
case ELEMENT_TYPE_INTERNAL :
2091+
case ELEMENT_TYPE_CMOD_INTERNAL :
2092+
typePtr += 1;
2093+
Reiterate = TRUE;
20912094
#endif // LOGGING
20922095
return NULL;
20932096

src/coreclr/inc/corhdr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,9 +911,10 @@ typedef enum CorElementType
911911

912912
// This is for signatures generated internally (which will not be persisted in any way).
913913
ELEMENT_TYPE_INTERNAL = 0x21, // INTERNAL <typehandle>
914+
ELEMENT_TYPE_CMOD_INTERNAL = 0x22, // CMOD_INTERNAL <required (1 byte: non-zero if required, 0 if optional)> <typehandle>
914915

915916
// Note that this is the max of base type excluding modifiers
916-
ELEMENT_TYPE_MAX = 0x22, // first invalid element type
917+
ELEMENT_TYPE_MAX = 0x23, // first invalid element type
917918

918919

919920
ELEMENT_TYPE_MODIFIER = 0x40,

src/coreclr/inc/corinfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,7 @@ enum CorInfoTypeWithMod
644644
{
645645
CORINFO_TYPE_MASK = 0x3F, // lower 6 bits are type mask
646646
CORINFO_TYPE_MOD_PINNED = 0x40, // can be applied to CLASS, or BYREF to indicate pinned
647+
CORINFO_TYPE_MOD_COPY_WITH_HELPER = 0x80 // can be applied to VALUECLASS to indicate 'needs helper to copy'
647648
};
648649

649650
inline CorInfoType strip(CorInfoTypeWithMod val) {
@@ -3325,6 +3326,8 @@ class ICorDynamicInfo : public ICorStaticInfo
33253326
// but for tailcalls, the contract is that JIT leaves the indirection cell in
33263327
// a register during tailcall.
33273328
virtual void updateEntryPointForTailCall(CORINFO_CONST_LOOKUP* entryPoint) = 0;
3329+
3330+
virtual CORINFO_METHOD_HANDLE getSpecialCopyHelper(CORINFO_CLASS_HANDLE type) = 0;
33283331
};
33293332

33303333
/**********************************************************************************/

src/coreclr/inc/cortypeinfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ TYPEINFO(ELEMENT_TYPE_MVAR, NULL, NULL, TARGET_POINTER_SI
5454
TYPEINFO(ELEMENT_TYPE_CMOD_REQD, NULL, NULL, 0, TYPE_GC_NONE, false, false, false, false, false) // 0x1f
5555
TYPEINFO(ELEMENT_TYPE_CMOD_OPT, NULL, NULL, 0, TYPE_GC_NONE, false, false, false, false, false) // 0x20
5656
TYPEINFO(ELEMENT_TYPE_INTERNAL, NULL, NULL, 0, TYPE_GC_OTHER, false, false, false, false, false) // 0x21
57+
TYPEINFO(ELEMENT_TYPE_CMOD_INTERNAL,NULL, NULL, 0, TYPE_GC_NONE, false, false, false, false, false) // 0x22

src/coreclr/inc/formattype.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,44 @@ PCCOR_SIGNATURE PrettyPrintType(
694694
appendStr(out, sz);
695695
break;
696696
}
697+
case ELEMENT_TYPE_CMOD_INTERNAL :
698+
{
699+
// ELEMENT_TYPE_CMOD_INTERNAL <required> <TypeHandle>
700+
bool required = *typePtr++ != 0;
701+
_ASSERTE(sizeof(TypeHandle) == sizeof(void *));
702+
TypeHandle typeHandle;
703+
typePtr += CorSigUncompressPointer(typePtr, (void **)&typeHandle);
704+
705+
MethodTable *pMT = NULL;
706+
if (typeHandle.IsTypeDesc())
707+
{
708+
pMT = typeHandle.AsTypeDesc()->GetMethodTable();
709+
if (pMT)
710+
{
711+
PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport());
712+
713+
// It could be a "native version" of the managed type used in interop
714+
if (typeHandle.AsTypeDesc()->IsNativeValueType())
715+
appendStr(out, "_NativeValueType");
716+
}
717+
else
718+
appendStr(out, "(null)");
719+
}
720+
else
721+
{
722+
pMT = typeHandle.AsMethodTable();
723+
if (pMT)
724+
PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport());
725+
else
726+
appendStr(out, "(null)");
727+
}
728+
729+
const char fmt[] = " mod%s(/* MT: %p */)";
730+
char sz[Max64BitHexString + ARRAY_SIZE(fmt) + ARRAY_SIZE("req")];
731+
sprintf_s(sz, ARRAY_SIZE(sz), fmt, required ? "req" : "opt", pMT);
732+
appendStr(out, sz);
733+
break;
734+
}
697735
#endif
698736

699737

src/coreclr/inc/icorjitinfoimpl_generated.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,9 @@ uint32_t getJitFlags(
742742
CORJIT_FLAGS* flags,
743743
uint32_t sizeInBytes) override;
744744

745+
CORINFO_METHOD_HANDLE getSpecialCopyHelper(
746+
CORINFO_CLASS_HANDLE type) override;
747+
745748
/**********************************************************************************/
746749
// clang-format on
747750
/**********************************************************************************/

src/coreclr/inc/jiteeversionguid.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
4343
#define GUID_DEFINED
4444
#endif // !GUID_DEFINED
4545

46-
constexpr GUID JITEEVersionIdentifier = { /* f43f9022-8795-4791-ba55-c450d76cfeb9 */
47-
0xf43f9022,
48-
0x8795,
49-
0x4791,
50-
{0xba, 0x55, 0xc4, 0x50, 0xd7, 0x6c, 0xfe, 0xb9}
46+
constexpr GUID JITEEVersionIdentifier = { /* 62865a69-7c84-4ba5-8636-a7dec55c05a7 */
47+
0x62865a69,
48+
0x7c84,
49+
0x4ba5,
50+
{0x86, 0x36, 0xa7, 0xde, 0xc5, 0x5c, 0x05, 0xa7}
5151
};
5252

5353
//////////////////////////////////////////////////////////////////////////////////////////////////////////

src/coreclr/inc/sigparser.h

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -582,19 +582,32 @@ class SigParser
582582
return hr;
583583

584584
while ((ELEMENT_TYPE_CMOD_REQD == bElementType) ||
585-
(ELEMENT_TYPE_CMOD_OPT == bElementType))
585+
(ELEMENT_TYPE_CMOD_OPT == bElementType) ||
586+
(ELEMENT_TYPE_CMOD_INTERNAL == bElementType))
586587
{
587588
sigTemp.SkipBytes(1);
589+
if (ELEMENT_TYPE_CMOD_INTERNAL == bElementType)
590+
{
591+
void * pMT;
592+
// If this custom modifier is required or optional
593+
uint8_t required;
594+
if (FAILED(hr = sigTemp.GetByte(&required)))
595+
return hr;
596+
597+
if (FAILED(hr = sigTemp.GetPointer(&pMT)))
598+
return hr;
599+
}
600+
else
601+
{
602+
mdToken token;
588603

589-
mdToken token;
590-
591-
hr = sigTemp.GetToken(&token);
604+
hr = sigTemp.GetToken(&token);
592605

593-
if (FAILED(hr))
594-
return hr;
606+
if (FAILED(hr))
607+
return hr;
608+
}
595609

596-
hr = sigTemp.PeekByte(&bElementType);
597-
if (FAILED(hr))
610+
if (FAILED(hr = sigTemp.PeekByte(&bElementType)))
598611
return hr;
599612
}
600613

@@ -643,19 +656,31 @@ class SigParser
643656
while (ELEMENT_TYPE_CMOD_REQD == bElementType ||
644657
ELEMENT_TYPE_CMOD_OPT == bElementType ||
645658
ELEMENT_TYPE_MODIFIER == bElementType ||
646-
ELEMENT_TYPE_PINNED == bElementType)
659+
ELEMENT_TYPE_PINNED == bElementType ||
660+
ELEMENT_TYPE_CMOD_INTERNAL == bElementType)
647661
{
648662
sigTemp.SkipBytes(1);
663+
if (ELEMENT_TYPE_CMOD_INTERNAL == bElementType)
664+
{
665+
void * pMT;
666+
uint8_t required;
667+
if (FAILED(hr = sigTemp.GetByte(&required)))
668+
return hr;
669+
670+
if (FAILED(hr = sigTemp.GetPointer(&pMT)))
671+
return hr;
672+
}
673+
else
674+
{
675+
mdToken token;
649676

650-
mdToken token;
651-
652-
hr = sigTemp.GetToken(&token);
677+
hr = sigTemp.GetToken(&token);
653678

654-
if (FAILED(hr))
655-
return hr;
679+
if (FAILED(hr))
680+
return hr;
681+
}
656682

657-
hr = sigTemp.PeekByte(&bElementType);
658-
if (FAILED(hr))
683+
if (FAILED(hr = sigTemp.PeekByte(&bElementType)))
659684
return hr;
660685
}
661686

src/coreclr/jit/ICorJitInfo_names_generated.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,5 +180,6 @@ DEF_CLR_API(recordRelocation)
180180
DEF_CLR_API(getRelocTypeHint)
181181
DEF_CLR_API(getExpectedTargetArchitecture)
182182
DEF_CLR_API(getJitFlags)
183+
DEF_CLR_API(getSpecialCopyHelper)
183184

184185
#undef DEF_CLR_API

src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,6 +1742,15 @@ uint32_t WrapICorJitInfo::getJitFlags(
17421742
return temp;
17431743
}
17441744

1745+
CORINFO_METHOD_HANDLE WrapICorJitInfo::getSpecialCopyHelper(
1746+
CORINFO_CLASS_HANDLE type)
1747+
{
1748+
API_ENTER(getSpecialCopyHelper);
1749+
CORINFO_METHOD_HANDLE temp = wrapHnd->getSpecialCopyHelper(type);
1750+
API_LEAVE(getSpecialCopyHelper);
1751+
return temp;
1752+
}
1753+
17451754
/**********************************************************************************/
17461755
// clang-format on
17471756
/**********************************************************************************/

src/coreclr/jit/compiler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,6 +1989,10 @@ void Compiler::compInit(ArenaAllocator* pAlloc,
19891989
m_fpStructLoweringCache = nullptr;
19901990
#endif
19911991

1992+
#if defined(TARGET_X86) && defined(FEATURE_IJW)
1993+
m_specialCopyArgs = nullptr;
1994+
#endif
1995+
19921996
// check that HelperCallProperties are initialized
19931997

19941998
assert(s_helperCallProperties.IsPure(CORINFO_HELP_GET_GCSTATIC_BASE));

src/coreclr/jit/compiler.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5703,6 +5703,36 @@ class Compiler
57035703
const CORINFO_SWIFT_LOWERING* GetSwiftLowering(CORINFO_CLASS_HANDLE clsHnd);
57045704
#endif
57055705

5706+
#if defined(TARGET_X86) && defined(FEATURE_IJW)
5707+
bool* m_specialCopyArgs;
5708+
bool recordArgRequiresSpecialCopy(unsigned argNum)
5709+
{
5710+
if (argNum >= info.compArgsCount)
5711+
{
5712+
return false;
5713+
}
5714+
5715+
if (m_specialCopyArgs == nullptr)
5716+
{
5717+
m_specialCopyArgs = new (getAllocator()) bool[info.compArgsCount];
5718+
memset(m_specialCopyArgs, 0, info.compArgsCount * sizeof(bool));
5719+
}
5720+
5721+
m_specialCopyArgs[argNum] = true;
5722+
return true;
5723+
}
5724+
5725+
bool argRequiresSpecialCopy(unsigned argNum)
5726+
{
5727+
return argNum < info.compArgsCount && m_specialCopyArgs != nullptr && m_specialCopyArgs[argNum];
5728+
}
5729+
5730+
bool compHasSpecialCopyArgs()
5731+
{
5732+
return m_specialCopyArgs != nullptr;
5733+
}
5734+
#endif
5735+
57065736
void optRecordLoopMemoryDependence(GenTree* tree, BasicBlock* block, ValueNum memoryVN);
57075737
void optCopyLoopMemoryDependence(GenTree* fromTree, GenTree* toTree);
57085738

src/coreclr/jit/gentree.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16599,6 +16599,7 @@ GenTree* Compiler::gtNewTempStore(
1659916599
valTyp = lvaGetRealType(val->AsLclVar()->GetLclNum());
1660016600
val->gtType = valTyp;
1660116601
}
16602+
1660216603
var_types dstTyp = varDsc->TypeGet();
1660316604

1660416605
/* If the variable's lvType is not yet set then set it here */

0 commit comments

Comments
 (0)