Skip to content

Commit 7a3eaba

Browse files
committed
Convert COMCustomAttribute from MDCS to UCO
1 parent 937dec6 commit 7a3eaba

3 files changed

Lines changed: 428 additions & 73 deletions

File tree

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

Lines changed: 200 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,182 @@ private static bool ParseAttributeUsageAttribute(
18591859
return result != 0;
18601860
}
18611861

1862+
[UnmanagedCallersOnly]
1863+
[RequiresUnsafe]
1864+
private static unsafe void InvokeCustomAttributeCtor(NativeCtorInvokeContract* pContract, object* pResult, Exception* pException)
1865+
{
1866+
try
1867+
{
1868+
object?[]? parameters = *pContract->CtorArgs;
1869+
byte[]? argIsValueType = *pContract->ArgIsValueType;
1870+
object? target = *pContract->CtorTarget;
1871+
1872+
int argCount = pContract->ArgCount;
1873+
if (argCount < 0 || parameters is null || argIsValueType is null || parameters.Length != argCount || argIsValueType.Length != argCount)
1874+
{
1875+
throw new TargetParameterCountException(SR.Arg_ParmCnt);
1876+
}
1877+
1878+
if (target is null)
1879+
{
1880+
throw new InvalidOperationException("Invalid constructor target.");
1881+
}
1882+
1883+
object ctorTarget = target;
1884+
object?[] ctorArgs = parameters;
1885+
byte[] argIsValueTypeFlags = argIsValueType;
1886+
1887+
if (pContract->CtorEntryPoint == IntPtr.Zero)
1888+
{
1889+
throw new InvalidOperationException("Invalid constructor entry point.");
1890+
}
1891+
1892+
if (argCount == 0)
1893+
{
1894+
((delegate*<object, void>)pContract->CtorEntryPoint)(ctorTarget);
1895+
*pResult = ctorTarget;
1896+
return;
1897+
}
1898+
1899+
if (argCount == 1)
1900+
{
1901+
object? arg0 = ctorArgs[0];
1902+
if (argIsValueTypeFlags[0] == 0)
1903+
{
1904+
InstanceCalliHelper.Call((delegate*<object, object?, void>)pContract->CtorEntryPoint, ctorTarget, arg0);
1905+
}
1906+
else
1907+
{
1908+
if (arg0 is null)
1909+
{
1910+
throw new InvalidOperationException("Value-type custom attribute ctor argument cannot be null.");
1911+
}
1912+
1913+
Type argType = arg0.GetType();
1914+
if (argType.IsEnum)
1915+
{
1916+
argType = Enum.GetUnderlyingType(argType);
1917+
}
1918+
1919+
switch (Type.GetTypeCode(argType))
1920+
{
1921+
case TypeCode.Boolean:
1922+
InstanceCalliHelper.Call((delegate*<object, bool, void>)pContract->CtorEntryPoint, ctorTarget, (bool)arg0);
1923+
break;
1924+
case TypeCode.Char:
1925+
InstanceCalliHelper.Call((delegate*<object, char, void>)pContract->CtorEntryPoint, ctorTarget, (char)arg0);
1926+
break;
1927+
case TypeCode.SByte:
1928+
InstanceCalliHelper.Call((delegate*<object, sbyte, void>)pContract->CtorEntryPoint, ctorTarget, (sbyte)arg0);
1929+
break;
1930+
case TypeCode.Byte:
1931+
InstanceCalliHelper.Call((delegate*<object, byte, void>)pContract->CtorEntryPoint, ctorTarget, (byte)arg0);
1932+
break;
1933+
case TypeCode.Int16:
1934+
InstanceCalliHelper.Call((delegate*<object, short, void>)pContract->CtorEntryPoint, ctorTarget, (short)arg0);
1935+
break;
1936+
case TypeCode.UInt16:
1937+
InstanceCalliHelper.Call((delegate*<object, ushort, void>)pContract->CtorEntryPoint, ctorTarget, (ushort)arg0);
1938+
break;
1939+
case TypeCode.Int32:
1940+
InstanceCalliHelper.Call((delegate*<object, int, void>)pContract->CtorEntryPoint, ctorTarget, (int)arg0);
1941+
break;
1942+
case TypeCode.UInt32:
1943+
InstanceCalliHelper.Call((delegate*<object, uint, void>)pContract->CtorEntryPoint, ctorTarget, (uint)arg0);
1944+
break;
1945+
case TypeCode.Int64:
1946+
InstanceCalliHelper.Call((delegate*<object, long, void>)pContract->CtorEntryPoint, ctorTarget, (long)arg0);
1947+
break;
1948+
case TypeCode.UInt64:
1949+
InstanceCalliHelper.Call((delegate*<object, ulong, void>)pContract->CtorEntryPoint, ctorTarget, (ulong)arg0);
1950+
break;
1951+
case TypeCode.Single:
1952+
InstanceCalliHelper.Call((delegate*<object, float, void>)pContract->CtorEntryPoint, ctorTarget, (float)arg0);
1953+
break;
1954+
case TypeCode.Double:
1955+
InstanceCalliHelper.Call((delegate*<object, double, void>)pContract->CtorEntryPoint, ctorTarget, (double)arg0);
1956+
break;
1957+
default:
1958+
throw new InvalidOperationException("Unsupported value-type custom attribute ctor argument.");
1959+
}
1960+
}
1961+
1962+
*pResult = ctorTarget;
1963+
return;
1964+
}
1965+
1966+
if (argCount <= 6)
1967+
{
1968+
bool hasValueTypeArg = false;
1969+
for (int i = 0; i < argCount; i++)
1970+
{
1971+
if (argIsValueTypeFlags[i] != 0)
1972+
{
1973+
hasValueTypeArg = true;
1974+
}
1975+
}
1976+
1977+
if (hasValueTypeArg)
1978+
{
1979+
if (pContract->CtorInvokeStubEntryPoint == IntPtr.Zero)
1980+
{
1981+
throw new InvalidOperationException("Invalid constructor invoke stub entry point.");
1982+
}
1983+
1984+
((delegate*<object, object?[], IntPtr, void>)pContract->CtorInvokeStubEntryPoint)(ctorTarget, ctorArgs, pContract->CtorEntryPoint);
1985+
*pResult = ctorTarget;
1986+
return;
1987+
}
1988+
1989+
switch (argCount)
1990+
{
1991+
case 2:
1992+
InstanceCalliHelper.Call((delegate*<object, object?, object?, void>)pContract->CtorEntryPoint, ctorTarget, ctorArgs[0], ctorArgs[1]);
1993+
break;
1994+
case 3:
1995+
InstanceCalliHelper.Call((delegate*<object, object?, object?, object?, void>)pContract->CtorEntryPoint, ctorTarget, ctorArgs[0], ctorArgs[1], ctorArgs[2]);
1996+
break;
1997+
case 4:
1998+
InstanceCalliHelper.Call((delegate*<object, object?, object?, object?, object?, void>)pContract->CtorEntryPoint, ctorTarget, ctorArgs[0], ctorArgs[1], ctorArgs[2], ctorArgs[3]);
1999+
break;
2000+
case 5:
2001+
InstanceCalliHelper.Call((delegate*<object, object?, object?, object?, object?, object?, void>)pContract->CtorEntryPoint, ctorTarget, ctorArgs[0], ctorArgs[1], ctorArgs[2], ctorArgs[3], ctorArgs[4]);
2002+
break;
2003+
case 6:
2004+
InstanceCalliHelper.Call((delegate*<object, object?, object?, object?, object?, object?, object?, void>)pContract->CtorEntryPoint, ctorTarget, ctorArgs[0], ctorArgs[1], ctorArgs[2], ctorArgs[3], ctorArgs[4], ctorArgs[5]);
2005+
break;
2006+
}
2007+
2008+
*pResult = ctorTarget;
2009+
return;
2010+
}
2011+
2012+
if (pContract->CtorInvokeStubEntryPoint == IntPtr.Zero)
2013+
{
2014+
throw new InvalidOperationException("Invalid constructor invoke stub entry point.");
2015+
}
2016+
2017+
((delegate*<object, object?[], IntPtr, void>)pContract->CtorInvokeStubEntryPoint)(ctorTarget, ctorArgs, pContract->CtorEntryPoint);
2018+
*pResult = ctorTarget;
2019+
return;
2020+
}
2021+
catch (Exception ex)
2022+
{
2023+
*pException = ex;
2024+
}
2025+
}
2026+
2027+
[StructLayout(LayoutKind.Sequential)]
2028+
private unsafe struct NativeCtorInvokeContract
2029+
{
2030+
public object[]* CtorArgs;
2031+
public byte[]* ArgIsValueType;
2032+
public int ArgCount;
2033+
public object* CtorTarget;
2034+
public IntPtr CtorEntryPoint;
2035+
public IntPtr CtorInvokeStubEntryPoint;
2036+
}
2037+
18622038
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CustomAttribute_CreateCustomAttributeInstance")]
18632039
private static partial void CreateCustomAttributeInstance(
18642040
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)

0 commit comments

Comments
 (0)