Skip to content

Commit ed34abd

Browse files
davidwrightonsirntar
authored andcommitted
Remove JitGenericHandleCache (dotnet#106843)
- It was only used for overflow scenarios from the generic dictionary (which don't happen), virtual resolution scenarios for creating delegates, and a few other rare R2R scenarios - Replace the virtual resolution scenarios with a cache of the affected data in managed code, and move the helpers to managed - Use the GenericCache type which was previously only used on NativeAOT for Generic Virtual method resolution paths. - Just remove the pointless checks from within the various normal generic lookup paths, and since they no longer do anything interesting in their hot paths except erect a helper method frame and call a worker routine, move those jit helpers to managed as well.
1 parent 9d17f3d commit ed34abd

File tree

29 files changed

+582
-502
lines changed

29 files changed

+582
-502
lines changed

src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,9 @@
196196
<Compile Include="$(BclSourcesRoot)\System\Reflection\TypeNameResolver.CoreCLR.cs" />
197197
<Compile Include="$(BclSourcesRoot)\System\Reflection\Metadata\RuntimeTypeMetadataUpdateHandler.cs" />
198198
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CastHelpers.cs" />
199+
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\GenericsHelpers.cs" />
199200
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeHelpers.CoreCLR.cs" />
201+
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\VirtualDispatchHelpers.cs" />
200202
<Compile Include="$(BclSourcesRoot)\System\Runtime\ControlledExecution.CoreCLR.cs" />
201203
<Compile Include="$(BclSourcesRoot)\System\Runtime\DependentHandle.cs" />
202204
<Compile Include="$(MSBuildThisFileDirectory)..\nativeaot\Common\src\System\Runtime\RhFailFastReason.cs" />
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.Runtime.InteropServices;
7+
8+
namespace System.Runtime.CompilerServices;
9+
10+
[StackTraceHidden]
11+
[DebuggerStepThrough]
12+
internal static unsafe partial class GenericsHelpers
13+
{
14+
[LibraryImport(RuntimeHelpers.QCall)]
15+
private static partial IntPtr GenericHandleWorker(IntPtr pMD, IntPtr pMT, IntPtr signature, uint dictionaryIndexAndSlot, IntPtr pModule);
16+
17+
public struct GenericHandleArgs
18+
{
19+
public IntPtr signature;
20+
public IntPtr module;
21+
public uint dictionaryIndexAndSlot;
22+
};
23+
24+
[DebuggerHidden]
25+
public static IntPtr Method(IntPtr methodHnd, IntPtr signature)
26+
{
27+
return GenericHandleWorker(methodHnd, IntPtr.Zero, signature, 0xFFFFFFFF, IntPtr.Zero);
28+
}
29+
30+
[DebuggerHidden]
31+
public static unsafe IntPtr MethodWithSlotAndModule(IntPtr methodHnd, GenericHandleArgs * pArgs)
32+
{
33+
return GenericHandleWorker(methodHnd, IntPtr.Zero, pArgs->signature, pArgs->dictionaryIndexAndSlot, pArgs->module);
34+
}
35+
36+
[DebuggerHidden]
37+
public static IntPtr Class(IntPtr classHnd, IntPtr signature)
38+
{
39+
return GenericHandleWorker(IntPtr.Zero, classHnd, signature, 0xFFFFFFFF, IntPtr.Zero);
40+
}
41+
42+
[DebuggerHidden]
43+
public static unsafe IntPtr ClassWithSlotAndModule(IntPtr classHnd, GenericHandleArgs * pArgs)
44+
{
45+
return GenericHandleWorker(IntPtr.Zero, classHnd, pArgs->signature, pArgs->dictionaryIndexAndSlot, pArgs->module);
46+
}
47+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Collections.Generic;
5+
using System.Diagnostics;
6+
using System.Numerics;
7+
using System.Runtime.InteropServices;
8+
9+
namespace System.Runtime.CompilerServices;
10+
11+
[StackTraceHidden]
12+
[DebuggerStepThrough]
13+
internal static unsafe partial class VirtualDispatchHelpers
14+
{
15+
private struct VirtualResolutionData : IEquatable<VirtualResolutionData>
16+
{
17+
public int _hashCode;
18+
public MethodTable* _objectMethodTable;
19+
public IntPtr _classHandle;
20+
public IntPtr _methodHandle;
21+
22+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
23+
public VirtualResolutionData(MethodTable* objectMethodTable, IntPtr classHandle, IntPtr methodHandle)
24+
{
25+
_hashCode = (int) ((uint)objectMethodTable + (BitOperations.RotateLeft((uint)classHandle, 5)) + (BitOperations.RotateRight((uint)methodHandle, 5)));
26+
_objectMethodTable = objectMethodTable;
27+
_classHandle = classHandle;
28+
_methodHandle = methodHandle;
29+
}
30+
31+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
32+
public bool Equals(VirtualResolutionData other) =>
33+
_hashCode == other._hashCode &&
34+
(((nint)_objectMethodTable - (nint)other._objectMethodTable) |
35+
(_classHandle - other._classHandle) |
36+
(_methodHandle - other._methodHandle)) == 0;
37+
38+
public override bool Equals(object? obj) => obj is VirtualResolutionData other && Equals(other);
39+
40+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
41+
public override int GetHashCode() => _hashCode;
42+
}
43+
44+
private struct VirtualFunctionPointerArgs
45+
{
46+
public IntPtr classHnd;
47+
public IntPtr methodHnd;
48+
};
49+
50+
#if DEBUG
51+
// use smaller numbers to hit resizing/preempting logic in debug
52+
private const int InitialCacheSize = 8; // MUST BE A POWER OF TWO
53+
private const int MaximumCacheSize = 512;
54+
#else
55+
private const int InitialCacheSize = 128; // MUST BE A POWER OF TWO
56+
private const int MaximumCacheSize = 8 * 1024;
57+
#endif // DEBUG
58+
59+
private static GenericCache<VirtualResolutionData, IntPtr> s_virtualFunctionPointerCache = new GenericCache<VirtualResolutionData, IntPtr>(InitialCacheSize, MaximumCacheSize);
60+
61+
[LibraryImport(RuntimeHelpers.QCall)]
62+
private static unsafe partial IntPtr ResolveVirtualFunctionPointer(ObjectHandleOnStack obj, IntPtr classHandle, IntPtr methodHandle);
63+
64+
[MethodImpl(MethodImplOptions.NoInlining)]
65+
[DebuggerHidden]
66+
private static unsafe IntPtr VirtualFunctionPointerSlow(object obj, IntPtr classHandle, IntPtr methodHandle)
67+
{
68+
IntPtr result = ResolveVirtualFunctionPointer(ObjectHandleOnStack.Create(ref obj), classHandle, methodHandle);
69+
s_virtualFunctionPointerCache.TrySet(new VirtualResolutionData(RuntimeHelpers.GetMethodTable(obj), classHandle, methodHandle), result);
70+
GC.KeepAlive(obj);
71+
return result;
72+
}
73+
74+
[DebuggerHidden]
75+
private static unsafe IntPtr VirtualFunctionPointer(object obj, IntPtr classHandle, IntPtr methodHandle)
76+
{
77+
if (s_virtualFunctionPointerCache.TryGet(new VirtualResolutionData(RuntimeHelpers.GetMethodTable(obj), classHandle, methodHandle), out IntPtr result))
78+
{
79+
return result;
80+
}
81+
return VirtualFunctionPointerSlow(obj, classHandle, methodHandle);
82+
}
83+
84+
[DebuggerHidden]
85+
private static unsafe IntPtr VirtualFunctionPointer_Dynamic(object obj, ref VirtualFunctionPointerArgs virtualFunctionPointerArgs)
86+
{
87+
IntPtr classHandle = virtualFunctionPointerArgs.classHnd;
88+
IntPtr methodHandle = virtualFunctionPointerArgs.methodHnd;
89+
90+
if (s_virtualFunctionPointerCache.TryGet(new VirtualResolutionData(RuntimeHelpers.GetMethodTable(obj), classHandle, methodHandle), out IntPtr result))
91+
{
92+
return result;
93+
}
94+
return VirtualFunctionPointerSlow(obj, classHandle, methodHandle);
95+
}
96+
}

src/coreclr/inc/CrstTypes.def

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ End
255255

256256
Crst Interop
257257
AcquiredBefore PinnedHeapHandleTable AvailableParamTypes ClassInit DeadlockDetection GenericDictionaryExpansion
258-
HandleTable InstMethodHashTable InteropData JitGenericHandleCache LoaderHeap SigConvert
258+
HandleTable InstMethodHashTable InteropData LoaderHeap SigConvert
259259
StubDispatchCache StubUnwindInfoHeapSegments SyncBlockCache TypeIDMap UnresolvedClassLock
260260
PendingTypeLoadEntry
261261
End
@@ -276,9 +276,6 @@ Crst Jit
276276
SameLevelAs ClassInit
277277
End
278278

279-
Crst JitGenericHandleCache
280-
End
281-
282279
Crst JitPatchpoint
283280
AcquiredBefore LoaderHeap
284281
End
@@ -446,7 +443,7 @@ End
446443
Crst ThreadStore
447444
AcquiredBefore AvailableParamTypes DeadlockDetection DebuggerController
448445
DebuggerHeapLock DebuggerJitInfo DynamicIL HandleTable IbcProfile
449-
JitGenericHandleCache JumpStubCache LoaderHeap ModuleLookupTable ProfilerGCRefDataFreeList
446+
JumpStubCache LoaderHeap ModuleLookupTable ProfilerGCRefDataFreeList
450447
SingleUseLock SyncBlockCache SystemDomainDelayedUnloadList ThreadIdDispenser DebuggerMutex
451448
JitInlineTrackingMap
452449
End

src/coreclr/inc/crsttypes_generated.h

Lines changed: 56 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -65,63 +65,62 @@ enum CrstType
6565
CrstIsJMCMethod = 47,
6666
CrstISymUnmanagedReader = 48,
6767
CrstJit = 49,
68-
CrstJitGenericHandleCache = 50,
69-
CrstJitInlineTrackingMap = 51,
70-
CrstJitPatchpoint = 52,
71-
CrstJumpStubCache = 53,
72-
CrstLeafLock = 54,
73-
CrstListLock = 55,
74-
CrstLoaderAllocator = 56,
75-
CrstLoaderAllocatorReferences = 57,
76-
CrstLoaderHeap = 58,
77-
CrstManagedObjectWrapperMap = 59,
78-
CrstMethodDescBackpatchInfoTracker = 60,
79-
CrstMethodTableExposedObject = 61,
80-
CrstModule = 62,
81-
CrstModuleLookupTable = 63,
82-
CrstMulticoreJitHash = 64,
83-
CrstMulticoreJitManager = 65,
84-
CrstNativeImageEagerFixups = 66,
85-
CrstNativeImageLoad = 67,
86-
CrstNotifyGdb = 68,
87-
CrstPEImage = 69,
88-
CrstPendingTypeLoadEntry = 70,
89-
CrstPerfMap = 71,
90-
CrstPgoData = 72,
91-
CrstPinnedByrefValidation = 73,
92-
CrstPinnedHeapHandleTable = 74,
93-
CrstProfilerGCRefDataFreeList = 75,
94-
CrstProfilingAPIStatus = 76,
95-
CrstRCWCache = 77,
96-
CrstRCWCleanupList = 78,
97-
CrstReadyToRunEntryPointToMethodDescMap = 79,
98-
CrstReflection = 80,
99-
CrstReJITGlobalRequest = 81,
100-
CrstRetThunkCache = 82,
101-
CrstSigConvert = 83,
102-
CrstSingleUseLock = 84,
103-
CrstStressLog = 85,
104-
CrstStubCache = 86,
105-
CrstStubDispatchCache = 87,
106-
CrstStubUnwindInfoHeapSegments = 88,
107-
CrstSyncBlockCache = 89,
108-
CrstSyncHashLock = 90,
109-
CrstSystemDomain = 91,
110-
CrstSystemDomainDelayedUnloadList = 92,
111-
CrstThreadIdDispenser = 93,
112-
CrstThreadLocalStorageLock = 94,
113-
CrstThreadStore = 95,
114-
CrstTieredCompilation = 96,
115-
CrstTypeEquivalenceMap = 97,
116-
CrstTypeIDMap = 98,
117-
CrstUMEntryThunkCache = 99,
118-
CrstUMEntryThunkFreeListLock = 100,
119-
CrstUniqueStack = 101,
120-
CrstUnresolvedClassLock = 102,
121-
CrstUnwindInfoTableLock = 103,
122-
CrstVSDIndirectionCellLock = 104,
123-
CrstWrapperTemplate = 105,
124-
kNumberOfCrstTypes = 106
68+
CrstJitInlineTrackingMap = 50,
69+
CrstJitPatchpoint = 51,
70+
CrstJumpStubCache = 52,
71+
CrstLeafLock = 53,
72+
CrstListLock = 54,
73+
CrstLoaderAllocator = 55,
74+
CrstLoaderAllocatorReferences = 56,
75+
CrstLoaderHeap = 57,
76+
CrstManagedObjectWrapperMap = 58,
77+
CrstMethodDescBackpatchInfoTracker = 59,
78+
CrstMethodTableExposedObject = 60,
79+
CrstModule = 61,
80+
CrstModuleLookupTable = 62,
81+
CrstMulticoreJitHash = 63,
82+
CrstMulticoreJitManager = 64,
83+
CrstNativeImageEagerFixups = 65,
84+
CrstNativeImageLoad = 66,
85+
CrstNotifyGdb = 67,
86+
CrstPEImage = 68,
87+
CrstPendingTypeLoadEntry = 69,
88+
CrstPerfMap = 70,
89+
CrstPgoData = 71,
90+
CrstPinnedByrefValidation = 72,
91+
CrstPinnedHeapHandleTable = 73,
92+
CrstProfilerGCRefDataFreeList = 74,
93+
CrstProfilingAPIStatus = 75,
94+
CrstRCWCache = 76,
95+
CrstRCWCleanupList = 77,
96+
CrstReadyToRunEntryPointToMethodDescMap = 78,
97+
CrstReflection = 79,
98+
CrstReJITGlobalRequest = 80,
99+
CrstRetThunkCache = 81,
100+
CrstSigConvert = 82,
101+
CrstSingleUseLock = 83,
102+
CrstStressLog = 84,
103+
CrstStubCache = 85,
104+
CrstStubDispatchCache = 86,
105+
CrstStubUnwindInfoHeapSegments = 87,
106+
CrstSyncBlockCache = 88,
107+
CrstSyncHashLock = 89,
108+
CrstSystemDomain = 90,
109+
CrstSystemDomainDelayedUnloadList = 91,
110+
CrstThreadIdDispenser = 92,
111+
CrstThreadLocalStorageLock = 93,
112+
CrstThreadStore = 94,
113+
CrstTieredCompilation = 95,
114+
CrstTypeEquivalenceMap = 96,
115+
CrstTypeIDMap = 97,
116+
CrstUMEntryThunkCache = 98,
117+
CrstUMEntryThunkFreeListLock = 99,
118+
CrstUniqueStack = 100,
119+
CrstUnresolvedClassLock = 101,
120+
CrstUnwindInfoTableLock = 102,
121+
CrstVSDIndirectionCellLock = 103,
122+
CrstWrapperTemplate = 104,
123+
kNumberOfCrstTypes = 105
125124
};
126125

127126
#endif // __CRST_TYPES_INCLUDED
@@ -182,7 +181,6 @@ int g_rgCrstLevelMap[] =
182181
0, // CrstIsJMCMethod
183182
6, // CrstISymUnmanagedReader
184183
10, // CrstJit
185-
0, // CrstJitGenericHandleCache
186184
11, // CrstJitInlineTrackingMap
187185
3, // CrstJitPatchpoint
188186
5, // CrstJumpStubCache
@@ -293,7 +291,6 @@ LPCSTR g_rgCrstNameMap[] =
293291
"CrstIsJMCMethod",
294292
"CrstISymUnmanagedReader",
295293
"CrstJit",
296-
"CrstJitGenericHandleCache",
297294
"CrstJitInlineTrackingMap",
298295
"CrstJitPatchpoint",
299296
"CrstJumpStubCache",

src/coreclr/inc/jithelpers.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,16 @@
221221
JITHELPER(CORINFO_HELP_NATIVE_MEMSET, Jit_NativeMemSet, METHOD__NIL)
222222

223223
// Generics
224-
JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_METHOD, JIT_GenericHandleMethod, METHOD__NIL)
225-
JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_CLASS, JIT_GenericHandleClass, METHOD__NIL)
224+
DYNAMICJITHELPER(CORINFO_HELP_RUNTIMEHANDLE_METHOD, NULL, METHOD__GENERICSHELPERS__METHOD)
225+
DYNAMICJITHELPER(CORINFO_HELP_RUNTIMEHANDLE_CLASS, NULL, METHOD__GENERICSHELPERS__CLASS)
226226
JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, JIT_GetRuntimeType, METHOD__NIL)
227227
JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL, JIT_GetRuntimeType_MaybeNull, METHOD__NIL)
228228
JITHELPER(CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD, JIT_GetRuntimeMethodStub,METHOD__NIL)
229229
JITHELPER(CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD, JIT_GetRuntimeFieldStub, METHOD__NIL)
230230
JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE, JIT_GetRuntimeType, METHOD__NIL)
231231
JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL, JIT_GetRuntimeType_MaybeNull, METHOD__NIL)
232232

233-
JITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR, JIT_VirtualFunctionPointer, METHOD__NIL)
233+
DYNAMICJITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR, NULL, METHOD__VIRTUALDISPATCHHELPERS__VIRTUALFUNCTIONPOINTER)
234234

235235
JITHELPER(CORINFO_HELP_READYTORUN_NEW, NULL, METHOD__NIL)
236236
JITHELPER(CORINFO_HELP_READYTORUN_NEWARR_1, NULL, METHOD__NIL)

src/coreclr/vm/JitQCallHelpers.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
/*============================================================
5+
**
6+
** Header: JitQCallHelpers.h
7+
**
8+
**
9+
===========================================================*/
10+
11+
#ifndef _JITQCALLHELPERS_H
12+
#define _JITQCALLHELPERS_H
13+
14+
#include "qcall.h"
15+
#include "corinfo.h"
16+
17+
class Module;
18+
class MethodTable;
19+
class MethodDesc;
20+
21+
extern "C" void * QCALLTYPE ResolveVirtualFunctionPointer(QCall::ObjectHandleOnStack obj, CORINFO_CLASS_HANDLE classHnd, CORINFO_METHOD_HANDLE methodHnd);
22+
extern "C" CORINFO_GENERIC_HANDLE QCALLTYPE GenericHandleWorker(MethodDesc * pMD, MethodTable * pMT, LPVOID signature, DWORD dictionaryIndexAndSlot, Module* pModule);
23+
24+
#endif //_JITQCALLHELPERS_H

src/coreclr/vm/amd64/cgenamd64.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -992,9 +992,7 @@ PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator,
992992
{
993993
STANDARD_VM_CONTRACT;
994994

995-
PCODE helperAddress = (pLookup->helper == CORINFO_HELP_RUNTIMEHANDLE_METHOD ?
996-
GetEEFuncEntryPoint(JIT_GenericHandleMethodWithSlotAndModule) :
997-
GetEEFuncEntryPoint(JIT_GenericHandleClassWithSlotAndModule));
995+
PCODE helperAddress = GetDictionaryLookupHelper(pLookup->helper);
998996

999997
GenericHandleArgs * pArgs = (GenericHandleArgs *)(void *)pAllocator->GetDynamicHelpersHeap()->AllocAlignedMem(sizeof(GenericHandleArgs), DYNAMIC_HELPER_ALIGNMENT);
1000998
ExecutableWriterHolder<GenericHandleArgs> argsWriterHolder(pArgs, sizeof(GenericHandleArgs));

src/coreclr/vm/arm/stubs.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,9 +2018,7 @@ PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator,
20182018
{
20192019
STANDARD_VM_CONTRACT;
20202020

2021-
PCODE helperAddress = (pLookup->helper == CORINFO_HELP_RUNTIMEHANDLE_METHOD ?
2022-
GetEEFuncEntryPoint(JIT_GenericHandleMethodWithSlotAndModule) :
2023-
GetEEFuncEntryPoint(JIT_GenericHandleClassWithSlotAndModule));
2021+
PCODE helperAddress = GetDictionaryLookupHelper(pLookup->helper);
20242022

20252023
GenericHandleArgs * pArgs = (GenericHandleArgs *)(void *)pAllocator->GetDynamicHelpersHeap()->AllocAlignedMem(sizeof(GenericHandleArgs), DYNAMIC_HELPER_ALIGNMENT);
20262024
ExecutableWriterHolder<GenericHandleArgs> argsWriterHolder(pArgs, sizeof(GenericHandleArgs));

src/coreclr/vm/arm64/stubs.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,9 +1946,7 @@ PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator,
19461946
{
19471947
STANDARD_VM_CONTRACT;
19481948

1949-
PCODE helperAddress = (pLookup->helper == CORINFO_HELP_RUNTIMEHANDLE_METHOD ?
1950-
GetEEFuncEntryPoint(JIT_GenericHandleMethodWithSlotAndModule) :
1951-
GetEEFuncEntryPoint(JIT_GenericHandleClassWithSlotAndModule));
1949+
PCODE helperAddress = GetDictionaryLookupHelper(pLookup->helper);
19521950

19531951
GenericHandleArgs * pArgs = (GenericHandleArgs *)(void *)pAllocator->GetDynamicHelpersHeap()->AllocAlignedMem(sizeof(GenericHandleArgs), DYNAMIC_HELPER_ALIGNMENT);
19541952
ExecutableWriterHolder<GenericHandleArgs> argsWriterHolder(pArgs, sizeof(GenericHandleArgs));

0 commit comments

Comments
 (0)