Skip to content

Commit a59dd87

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

3 files changed

Lines changed: 301 additions & 73 deletions

File tree

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

Lines changed: 211 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,193 @@ 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+
// DecimalConstantAttribute: .ctor(byte scale, byte sign, uint hi, uint mid, uint low)
1980+
if (ctorArgs.Length == 5
1981+
&& ctorArgs[0] is byte scale
1982+
&& ctorArgs[1] is byte sign
1983+
&& ctorArgs[2] is uint uHi
1984+
&& ctorArgs[3] is uint uMid
1985+
&& ctorArgs[4] is uint uLow)
1986+
{
1987+
((delegate*<object, byte, byte, uint, uint, uint, void>)pContract->CtorEntryPoint)(ctorTarget, scale, sign, uHi, uMid, uLow);
1988+
*pResult = ctorTarget;
1989+
return;
1990+
}
1991+
1992+
// DecimalConstantAttribute: .ctor(byte scale, byte sign, int hi, int mid, int low)
1993+
if (ctorArgs.Length == 5
1994+
&& ctorArgs[0] is byte scaleInt
1995+
&& ctorArgs[1] is byte signInt
1996+
&& ctorArgs[2] is int hi
1997+
&& ctorArgs[3] is int mid
1998+
&& ctorArgs[4] is int low)
1999+
{
2000+
((delegate*<object, byte, byte, int, int, int, void>)pContract->CtorEntryPoint)(ctorTarget, scaleInt, signInt, hi, mid, low);
2001+
*pResult = ctorTarget;
2002+
return;
2003+
}
2004+
2005+
throw new InvalidOperationException("Unsupported multi-argument value-type custom attribute ctor signature.");
2006+
}
2007+
2008+
switch (argCount)
2009+
{
2010+
case 2:
2011+
InstanceCalliHelper.Call((delegate*<object, object?, object?, void>)pContract->CtorEntryPoint, ctorTarget, ctorArgs[0], ctorArgs[1]);
2012+
break;
2013+
case 3:
2014+
InstanceCalliHelper.Call((delegate*<object, object?, object?, object?, void>)pContract->CtorEntryPoint, ctorTarget, ctorArgs[0], ctorArgs[1], ctorArgs[2]);
2015+
break;
2016+
case 4:
2017+
InstanceCalliHelper.Call((delegate*<object, object?, object?, object?, object?, void>)pContract->CtorEntryPoint, ctorTarget, ctorArgs[0], ctorArgs[1], ctorArgs[2], ctorArgs[3]);
2018+
break;
2019+
case 5:
2020+
InstanceCalliHelper.Call((delegate*<object, object?, object?, object?, object?, object?, void>)pContract->CtorEntryPoint, ctorTarget, ctorArgs[0], ctorArgs[1], ctorArgs[2], ctorArgs[3], ctorArgs[4]);
2021+
break;
2022+
case 6:
2023+
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]);
2024+
break;
2025+
}
2026+
2027+
*pResult = ctorTarget;
2028+
return;
2029+
}
2030+
2031+
throw new InvalidOperationException("Custom attribute ctor has too many arguments for UCO invoke path.");
2032+
}
2033+
catch (Exception ex)
2034+
{
2035+
*pException = ex;
2036+
}
2037+
}
2038+
2039+
[StructLayout(LayoutKind.Sequential)]
2040+
private unsafe struct NativeCtorInvokeContract
2041+
{
2042+
public object[]* CtorArgs;
2043+
public byte[]* ArgIsValueType;
2044+
public int ArgCount;
2045+
public object* CtorTarget;
2046+
public IntPtr CtorEntryPoint;
2047+
}
2048+
18622049
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CustomAttribute_CreateCustomAttributeInstance")]
18632050
private static partial void CreateCustomAttributeInstance(
18642051
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)