Skip to content

Commit 58cc7e0

Browse files
committed
Convert COMCustomAttribute from MDCS to UCO
1 parent 937dec6 commit 58cc7e0

File tree

3 files changed

+162
-73
lines changed

3 files changed

+162
-73
lines changed

src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -302,16 +302,16 @@ private RuntimeCustomAttributeData(RuntimeModule scope, MetadataToken caCtorToke
302302
#region Pseudo Custom Attribute Constructor
303303
internal RuntimeCustomAttributeData(Attribute attribute)
304304
{
305-
if (attribute is DllImportAttribute dllImportAttribute)
306-
Init(dllImportAttribute);
307-
else if (attribute is FieldOffsetAttribute fieldOffsetAttribute)
308-
Init(fieldOffsetAttribute);
309-
else if (attribute is MarshalAsAttribute marshalAsAttribute)
310-
Init(marshalAsAttribute);
311-
else if (attribute is TypeForwardedToAttribute typeForwardedToAttribute)
312-
Init(typeForwardedToAttribute);
313-
else
314-
Init(attribute);
305+
if (attribute is DllImportAttribute dllImportAttribute)
306+
Init(dllImportAttribute);
307+
else if (attribute is FieldOffsetAttribute fieldOffsetAttribute)
308+
Init(fieldOffsetAttribute);
309+
else if (attribute is MarshalAsAttribute marshalAsAttribute)
310+
Init(marshalAsAttribute);
311+
else if (attribute is TypeForwardedToAttribute typeForwardedToAttribute)
312+
Init(typeForwardedToAttribute);
313+
else
314+
Init(attribute);
315315
}
316316
private void Init(DllImportAttribute dllImport)
317317
{
@@ -849,24 +849,24 @@ private static CustomAttributeEncodedArgument ParseCustomAttributeValue(
849849
arg.StringValue = parser.GetString();
850850
break;
851851
case CustomAttributeEncoding.Array:
852-
{
853-
arg.ArrayValue = null;
854-
int len = parser.GetI4();
855-
if (len != -1) // indicates array is null - ECMA-335 II.23.3.
856852
{
857-
attributeType = new CustomAttributeType(
858-
attributeType.EncodedArrayType,
859-
CustomAttributeEncoding.Undefined, // Array type
860-
attributeType.EncodedEnumType,
861-
attributeType.EnumType);
862-
arg.ArrayValue = new CustomAttributeEncodedArgument[len];
863-
for (int i = 0; i < len; ++i)
853+
arg.ArrayValue = null;
854+
int len = parser.GetI4();
855+
if (len != -1) // indicates array is null - ECMA-335 II.23.3.
864856
{
865-
arg.ArrayValue[i] = ParseCustomAttributeValue(ref parser, attributeType, module);
857+
attributeType = new CustomAttributeType(
858+
attributeType.EncodedArrayType,
859+
CustomAttributeEncoding.Undefined, // Array type
860+
attributeType.EncodedEnumType,
861+
attributeType.EnumType);
862+
arg.ArrayValue = new CustomAttributeEncodedArgument[len];
863+
for (int i = 0; i < len; ++i)
864+
{
865+
arg.ArrayValue[i] = ParseCustomAttributeValue(ref parser, attributeType, module);
866+
}
866867
}
868+
break;
867869
}
868-
break;
869-
}
870870
default:
871871
throw new BadImageFormatException();
872872
}
@@ -1859,6 +1859,51 @@ private static bool ParseAttributeUsageAttribute(
18591859
return result != 0;
18601860
}
18611861

1862+
[UnmanagedCallersOnly]
1863+
[RequiresUnsafe]
1864+
private static unsafe void InvokeCustomAttributeCtor(RuntimeConstructorInfo* pCtor, NativeCtorInvokeContract* pContract, object* pResult, Exception* pException)
1865+
{
1866+
try
1867+
{
1868+
object?[]? parameters = *pContract->CtorArgs;
1869+
byte[]? argIsValueType = *pContract->ArgIsValueType;
1870+
1871+
if ((pCtor->InvocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers | InvocationFlags.NoConstructorInvoke)) != 0)
1872+
{
1873+
pCtor->ThrowNoInvokeException();
1874+
}
1875+
1876+
int argCount = pContract->ArgCount;
1877+
if (argCount < 0 || (parameters?.Length ?? 0) != argCount || argIsValueType is null || argIsValueType.Length != argCount)
1878+
{
1879+
throw new TargetParameterCountException(SR.Arg_ParmCnt);
1880+
}
1881+
1882+
if (argCount == 0 && pContract->CtorEntryPoint != IntPtr.Zero)
1883+
{
1884+
((delegate*<object, void>)pContract->CtorEntryPoint)(*pContract->CtorTarget);
1885+
*pResult = *pContract->CtorTarget;
1886+
return;
1887+
}
1888+
1889+
throw new NotSupportedException();
1890+
}
1891+
catch (Exception ex)
1892+
{
1893+
*pException = ex;
1894+
}
1895+
}
1896+
1897+
[StructLayout(LayoutKind.Sequential)]
1898+
private unsafe struct NativeCtorInvokeContract
1899+
{
1900+
public object[]* CtorArgs;
1901+
public byte[]* ArgIsValueType;
1902+
public int ArgCount;
1903+
public object* CtorTarget;
1904+
public IntPtr CtorEntryPoint;
1905+
}
1906+
18621907
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CustomAttribute_CreateCustomAttributeInstance")]
18631908
private static partial void CreateCustomAttributeInstance(
18641909
QCallModule pModule,

src/coreclr/vm/corelib.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,9 @@ DEFINE_CLASS(MEMBER, Reflection, MemberInfo)
515515

516516
DEFINE_CLASS(METHODBASEINVOKER, Reflection, MethodBaseInvoker)
517517

518+
DEFINE_CLASS(CUSTOMATTRIBUTE, Reflection, CustomAttribute)
519+
DEFINE_METHOD(CUSTOMATTRIBUTE, INVOKE_CUSTOM_ATTRIBUTE_CTOR, InvokeCustomAttributeCtor, NoSig)
520+
518521
DEFINE_CLASS(INSTANCE_CALLI_HELPER, Reflection, InstanceCalliHelper)
519522

520523
DEFINE_CLASS_U(Reflection, RuntimeMethodInfo, NoClass)

src/coreclr/vm/customattribute.cpp

Lines changed: 90 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "reflectioninvocation.h"
1616
#include "runtimehandles.h"
1717
#include "typestring.h"
18+
#include "callhelpers.h"
1819

1920
static TypeHandle GetTypeForEnum(LPCUTF8 szEnumName, COUNT_T cbEnumName, Assembly* pAssembly)
2021
{
@@ -915,23 +916,35 @@ extern "C" void QCALLTYPE CustomAttribute_CreateCustomAttributeInstance(
915916
MethodDesc* pCtorMD = ((REFLECTMETHODREF)pMethod.Get())->GetMethod();
916917
TypeHandle th = ((REFLECTCLASSBASEREF)pCaType.Get())->GetType();
917918

918-
MethodDescCallSite ctorCallSite(pCtorMD, th);
919-
MetaSig* pSig = ctorCallSite.GetMetaSig();
919+
MetaSig ctorSig(pCtorMD, th);
920+
MetaSig* pSig = &ctorSig;
920921
BYTE* pBlob = *ppBlob;
921922

922-
// get the number of arguments and allocate an array for the args
923-
ARG_SLOT *args = NULL;
924-
UINT cArgs = pSig->NumFixedArgs() + 1; // make room for the this pointer
925-
UINT i = 1; // used to flag that we actually get the right number of arg from the blob
923+
UINT cArgs = pSig->NumFixedArgs();
924+
UINT i = 0;
926925

927-
args = (ARG_SLOT*)_alloca(cArgs * sizeof(ARG_SLOT));
928-
memset((void*)args, 0, cArgs * sizeof(ARG_SLOT));
929-
930-
OBJECTREF *argToProtect = (OBJECTREF*)_alloca(cArgs * sizeof(OBJECTREF));
931-
memset((void*)argToProtect, 0, cArgs * sizeof(OBJECTREF));
932-
933-
// load the this pointer
934-
argToProtect[0] = th.GetMethodTable()->Allocate(); // this is the value to return after the ctor invocation
926+
struct
927+
{
928+
OBJECTREF ctorArgs;
929+
OBJECTREF ctorArgIsValueTypeFlags;
930+
OBJECTREF ctorObj;
931+
OBJECTREF ctorArgsObj;
932+
OBJECTREF ctorTarget;
933+
OBJECTREF ctorResult;
934+
} gc;
935+
gc.ctorArgs = NULL;
936+
gc.ctorArgIsValueTypeFlags = NULL;
937+
gc.ctorObj = NULL;
938+
gc.ctorArgsObj = NULL;
939+
gc.ctorTarget = NULL;
940+
gc.ctorResult = NULL;
941+
GCPROTECT_BEGIN(gc);
942+
943+
gc.ctorArgs = (OBJECTREF)AllocateObjectArray(cArgs, g_pObjectClass);
944+
gc.ctorArgIsValueTypeFlags = (OBJECTREF)(U1ARRAYREF)AllocatePrimitiveArray(ELEMENT_TYPE_U1, cArgs);
945+
gc.ctorTarget = th.GetMethodTable()->Allocate();
946+
947+
BYTE* argIsValueTypeFlags = ((U1ARRAYREF)gc.ctorArgIsValueTypeFlags)->GetDataPtr();
935948

936949
if (pBlob)
937950
{
@@ -947,44 +960,53 @@ extern "C" void QCALLTYPE CustomAttribute_CreateCustomAttributeInstance(
947960
pBlob += 2;
948961
}
949962

950-
if (cArgs > 1)
963+
if (cArgs > 0)
951964
{
952-
GCPROTECT_ARRAY_BEGIN(*argToProtect, cArgs);
965+
// loop through the args
966+
for (i = 0; i < cArgs; i++)
953967
{
954-
// loop through the args
955-
for (i = 1; i < cArgs; i++) {
956-
CorElementType type = pSig->NextArg();
957-
if (type == ELEMENT_TYPE_END)
958-
break;
959-
BOOL bObjectCreated = FALSE;
960-
TypeHandle th = pSig->GetLastTypeHandleThrowing();
961-
if (th.IsArray())
962-
// get the array element
963-
th = th.GetArrayElementTypeHandle();
964-
ARG_SLOT data = GetDataFromBlob(pCtorMD->GetAssembly(), (CorSerializationType)type, th, &pBlob, pEndBlob, pModule, &bObjectCreated);
965-
if (bObjectCreated)
966-
argToProtect[i] = ArgSlotToObj(data);
967-
else
968-
args[i] = data;
968+
CorElementType type = pSig->NextArg();
969+
if (type == ELEMENT_TYPE_END)
970+
break;
971+
972+
BOOL bObjectCreated = FALSE;
973+
TypeHandle argType = pSig->GetLastTypeHandleThrowing();
974+
if (argType.IsArray())
975+
argType = argType.GetArrayElementTypeHandle();
976+
977+
argIsValueTypeFlags[i] = argType.IsValueType() ? 1 : 0;
978+
979+
ARG_SLOT data = GetDataFromBlob(
980+
pCtorMD->GetAssembly(),
981+
(CorSerializationType)type,
982+
argType,
983+
&pBlob,
984+
pEndBlob,
985+
pModule,
986+
&bObjectCreated);
987+
988+
OBJECTREF argObj = NULL;
989+
if (bObjectCreated)
990+
{
991+
argObj = ArgSlotToObj(data);
969992
}
970-
}
971-
GCPROTECT_END();
972-
973-
// We have borrowed the signature from MethodDescCallSite. We have to put it back into the initial position
974-
// because of that's where MethodDescCallSite expects to find it below.
975-
pSig->Reset();
976-
977-
for (i = 1; i < cArgs; i++)
978-
{
979-
if (argToProtect[i] != NULL)
993+
else
980994
{
981-
_ASSERTE(args[i] == (ARG_SLOT)NULL);
982-
args[i] = ObjToArgSlot(argToProtect[i]);
995+
MethodTable* pMTValue = (type == ELEMENT_TYPE_VALUETYPE || type == ELEMENT_TYPE_CLASS)
996+
? argType.GetMethodTable()
997+
: CoreLibBinder::GetElementType(type);
998+
999+
_ASSERTE(pMTValue != NULL);
1000+
argObj = pMTValue->Box((void*)ArgSlotEndiannessFixup(&data, pMTValue->GetNumInstanceFieldBytes()));
9831001
}
1002+
1003+
((PTRARRAYREF)gc.ctorArgs)->SetAt(i, argObj);
9841004
}
1005+
1006+
// Reset signature enumeration before we leave argument processing.
1007+
pSig->Reset();
9851008
}
9861009
}
987-
args[0] = ObjToArgSlot(argToProtect[0]);
9881010

9891011
if (i != cArgs)
9901012
COMPlusThrow(kCustomAttributeFormatException);
@@ -1009,12 +1031,31 @@ extern "C" void QCALLTYPE CustomAttribute_CreateCustomAttributeInstance(
10091031
if (*pcNamedArgs == 0 && pBlob != pEndBlob)
10101032
COMPlusThrow(kCustomAttributeFormatException);
10111033

1012-
// make the invocation to the ctor
1013-
result.Set(ArgSlotToObj(args[0]));
1014-
if (pCtorMD->GetMethodTable()->IsValueType())
1015-
args[0] = PtrToArgSlot(OBJECTREFToObject(result.Get())->UnBox());
1034+
gc.ctorObj = pMethod.Get();
1035+
gc.ctorArgsObj = gc.ctorArgs;
1036+
PCODE ctorEntryPoint = pCtorMD->GetSingleCallableAddrOfCode();
1037+
1038+
struct NativeCtorInvokeContract
1039+
{
1040+
OBJECTREF* ctorArgs;
1041+
OBJECTREF* argIsValueType;
1042+
INT32 argCount;
1043+
OBJECTREF* ctorTarget;
1044+
PCODE ctorEntryPoint;
1045+
} contract;
1046+
1047+
contract.ctorArgs = &gc.ctorArgsObj;
1048+
contract.argIsValueType = &gc.ctorArgIsValueTypeFlags;
1049+
contract.argCount = (INT32)cArgs;
1050+
contract.ctorTarget = &gc.ctorTarget;
1051+
contract.ctorEntryPoint = ctorEntryPoint;
1052+
1053+
UnmanagedCallersOnlyCaller invokeCustomAttributeCtor(METHOD__CUSTOMATTRIBUTE__INVOKE_CUSTOM_ATTRIBUTE_CTOR);
1054+
invokeCustomAttributeCtor.InvokeThrowing(&gc.ctorObj, &contract, &gc.ctorResult);
10161055

1017-
ctorCallSite.CallWithValueTypes(args);
1056+
result.Set(gc.ctorResult);
1057+
1058+
GCPROTECT_END();
10181059

10191060
END_QCALL;
10201061
}

0 commit comments

Comments
 (0)