Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Implement RuntimeHelpers.SizeOf#100618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
jkoritzinsky merged 17 commits intodotnet:mainfromjkoritzinsky:sizeof
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from11 commits
Commits
Show all changes
17 commits
Select commitHold shift + click to select a range
3362c4a
Implement RuntimeHelpers.SizeOf
jkoritzinskyApr 3, 2024
47c6a24
Add tests and add various fixes.
jkoritzinskyApr 3, 2024
16ea830
PR feedback
jkoritzinskyApr 3, 2024
cb7ec92
Apply suggestions from code review
jkoritzinskyApr 4, 2024
47d3b54
Update src/libraries/System.Runtime/tests/System.Runtime.Tests/System…
jkoritzinskyApr 4, 2024
c086418
Add more tests and throw for more invalid cases.
jkoritzinskyApr 4, 2024
84b4c0f
Generic parameter types don't have MethodTables in NativeAOT.
jkoritzinskyApr 4, 2024
49e6521
Update src/coreclr/vm/reflectioninvocation.cpp
jkotasApr 4, 2024
f93baee
Fix CoreCLR
jkoritzinskyApr 4, 2024
6898911
Separate out case to skip on NativeAOT as it's not relavant on the pl…
jkoritzinskyApr 4, 2024
3423a52
Check ContainsGenericVariables
jkoritzinskyApr 4, 2024
1c473f6
Update RuntimeHelpers.NativeAot.cs
jkoritzinskyApr 5, 2024
21fde4e
Add doc comments
jkoritzinskyApr 5, 2024
51a93b2
Separate out partially-specialized type test
jkoritzinskyApr 5, 2024
ec81d77
Merge branch 'sizeof' of github.com:jkoritzinsky/runtime into sizeof
jkoritzinskyApr 5, 2024
ed05d1a
Update doc comment to refer to `Unsafe.SizeOf`
jkoritzinskyApr 5, 2024
7908cf6
Merge branch 'main' of github.com:dotnet/runtime into sizeof
jkoritzinskyApr 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -416,6 +416,23 @@ private static unsafe void DispatchTailCalls(
}
}
}

[LibraryImport(QCall, EntryPoint = "ReflectionInvocation_SizeOf")]
[SuppressGCTransition]
private static partial int SizeOf(QCallTypeHandle handle);

public static unsafe int SizeOf(RuntimeTypeHandle type)
{
if (type.IsNullHandle())
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.type);

int result = SizeOf(new QCallTypeHandle(ref type));

if (result <= 0)
throw new ArgumentException(SR.Arg_TypeNotSupported);

return result;
}
}
// Helper class to assist with unsafe pinning of arbitrary objects.
// It's used by VM code.
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -87,6 +87,11 @@ internal bool IsNullHandle()
return m_type == null;
}

internal TypeHandle GetNativeTypeHandle()
{
return m_type.GetNativeTypeHandle();
}

internal static bool IsTypeDefinition(RuntimeType type)
{
CorElementType corElemType = GetCorElementType(type);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -361,6 +361,27 @@ public static unsafe object GetUninitializedObject(

return RuntimeImports.RhNewObject(mt);
}

public static unsafe int SizeOf(RuntimeTypeHandle type)
{
if (type.IsNull)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.type);

MethodTable* mt = type.ToMethodTable();

if (mt->ElementType == EETypeElementType.Void
|| mt->ContainsGenericParameters)
{
throw new ArgumentException(SR.Arg_TypeNotSupported);
}

if (mt->IsValueType)
{
return (int)mt->ValueTypeSize;
}

return nint.Size;
}
}

// CLR arrays are laid out in memory as follows (multidimensional array bounds are optional):
Expand Down
1 change: 1 addition & 0 deletionssrc/coreclr/vm/qcallentrypoints.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -337,6 +337,7 @@ static const Entry s_QCall[] =
DllImportEntry(ReflectionInvocation_RunModuleConstructor)
DllImportEntry(ReflectionInvocation_CompileMethod)
DllImportEntry(ReflectionInvocation_PrepareMethod)
DllImportEntry(ReflectionInvocation_SizeOf)
DllImportEntry(ReflectionSerialization_GetCreateUninitializedObjectInfo)
#if defined(FEATURE_COMWRAPPERS)
DllImportEntry(ComWrappers_GetIUnknownImpl)
Expand Down
13 changes: 13 additions & 0 deletionssrc/coreclr/vm/reflectioninvocation.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2120,3 +2120,16 @@ FCIMPL2_IV(Object*, ReflectionEnum::InternalBoxEnum, ReflectClassBaseObject* tar
return OBJECTREFToObject(ret);
}
FCIMPLEND

extern "C" int32_t QCALLTYPE ReflectionInvocation_SizeOf(QCall::TypeHandle pType)
{
QCALL_CONTRACT_NO_GC_TRANSITION;

TypeHandle handle = pType.AsTypeHandle();

// -1 is the same sentinel value returned by GetSize for an invalid type.
if (handle.ContainsGenericVariables())
return -1;

return handle.GetSize();
}
2 changes: 2 additions & 0 deletionssrc/coreclr/vm/reflectioninvocation.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -82,4 +82,6 @@ class ReflectionEnum {

extern "C" void QCALLTYPE Enum_GetValuesAndNames(QCall::TypeHandle pEnumType, QCall::ObjectHandleOnStack pReturnValues, QCall::ObjectHandleOnStack pReturnNames, BOOL fGetNames);

extern "C" int32_t QCALLTYPE ReflectionInvocation_SizeOf(QCall::TypeHandle pType);

#endif // _REFLECTIONINVOCATION_H_
1 change: 1 addition & 0 deletionssrc/libraries/System.Runtime/ref/System.Runtime.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -13175,6 +13175,7 @@ public static void ProbeForSufficientStack() { }
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimmer can't guarantee existence of class constructor")]
public static void RunClassConstructor(System.RuntimeTypeHandle type) { }
public static void RunModuleConstructor(System.ModuleHandle module) { }
public static int SizeOf(System.RuntimeTypeHandle type) { throw null; }
public static bool TryEnsureSufficientExecutionStack() { throw null; }
public delegate void CleanupCode(object? userData, bool exceptionThrown);
public delegate void TryCode(object? userData);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -437,6 +437,44 @@ public static void FixedAddressValueTypeTest()

Assert.Equal(fixedPtr1, fixedPtr2);
}

[InlineArray(3)]
private struct Byte3
{
public byte b1;
}

[Fact]
public static unsafe void SizeOf()
{
Assert.Equal(1, RuntimeHelpers.SizeOf(typeof(sbyte).TypeHandle));
Assert.Equal(1, RuntimeHelpers.SizeOf(typeof(byte).TypeHandle));
Assert.Equal(2, RuntimeHelpers.SizeOf(typeof(short).TypeHandle));
Assert.Equal(2, RuntimeHelpers.SizeOf(typeof(ushort).TypeHandle));
Assert.Equal(4, RuntimeHelpers.SizeOf(typeof(int).TypeHandle));
Assert.Equal(4, RuntimeHelpers.SizeOf(typeof(uint).TypeHandle));
Assert.Equal(8, RuntimeHelpers.SizeOf(typeof(long).TypeHandle));
Assert.Equal(8, RuntimeHelpers.SizeOf(typeof(ulong).TypeHandle));
Assert.Equal(4, RuntimeHelpers.SizeOf(typeof(float).TypeHandle));
Assert.Equal(8, RuntimeHelpers.SizeOf(typeof(double).TypeHandle));
Assert.Equal(3, RuntimeHelpers.SizeOf(typeof(Byte3).TypeHandle));
Assert.Equal(nint.Size, RuntimeHelpers.SizeOf(typeof(void*).TypeHandle));
Assert.Equal(nint.Size, RuntimeHelpers.SizeOf(typeof(delegate* <void>).TypeHandle));
Assert.Equal(nint.Size, RuntimeHelpers.SizeOf(typeof(int).MakeByRefType().TypeHandle));
Assert.Throws<ArgumentNullException>(() => RuntimeHelpers.SizeOf(default));
Assert.ThrowsAny<ArgumentException>(() => RuntimeHelpers.SizeOf(typeof(List<>).TypeHandle));
Assert.ThrowsAny<ArgumentException>(() => RuntimeHelpers.SizeOf(typeof(Dictionary<,>).MakeGenericType([ typeof(int), typeof(Dictionary<,>).GetGenericArguments()[1] ]).TypeHandle));
Assert.ThrowsAny<ArgumentException>(() => RuntimeHelpers.SizeOf(typeof(void).TypeHandle));
}

// We can't even get a RuntimeTypeHandle for a generic parameter type on NativeAOT,
// so we don't even get to the method we're testing.
// So, let's not even waste time running this test on NativeAOT
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNativeAot))]
public static void SizeOfGenericParameter()
{
Assert.ThrowsAny<ArgumentException>(() => RuntimeHelpers.SizeOf(typeof(List<>).GetGenericArguments()[0].TypeHandle));
}
}

public struct Age
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -211,5 +211,20 @@ private static extern unsafe IntPtr GetSpanDataFrom(

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool SufficientExecutionStack();

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern int SizeOf(QCallTypeHandle handle);

public static int SizeOf(RuntimeTypeHandle type)
{
if (type.Value == IntPtr.Zero)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.type);

Type typeObj = Type.GetTypeFromHandle(type)!;
if (typeObj.ContainsGenericParameters || typeObj.IsGenericParameter || typeObj == typeof(void))
throw new ArgumentException(SR.Arg_TypeNotSupported);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Is this a limitation of mono runtime (which doesn't exist in coreclr)?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

No, this is the same limitation in CoreCLR and NativeAOT (though the implementations are slightly different due to how the different type systems are implemented).

am11 reacted with thumbs up emoji

return SizeOf(new QCallTypeHandle(ref type));
}
}
}
1 change: 1 addition & 0 deletionssrc/mono/mono/metadata/icall-def.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -439,6 +439,7 @@ HANDLES(RUNH_7, "InternalGetHashCode", ves_icall_System_Runtime_CompilerServices
HANDLES(RUNH_3a, "PrepareMethod", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_PrepareMethod, void, 3, (MonoMethod_ptr, gpointer, int))
HANDLES(RUNH_4, "RunClassConstructor", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor, void, 1, (MonoType_ptr))
HANDLES(RUNH_5, "RunModuleConstructor", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor, void, 1, (MonoImage_ptr))
HANDLES(RUNH_9, "SizeOf", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SizeOf, gint32, 1, (MonoQCallTypeHandle))
NOHANDLES(ICALL(RUNH_5h, "SufficientExecutionStack", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack))

ICALL_TYPE(GCH, "System.Runtime.InteropServices.GCHandle", GCH_1)
Expand Down
7 changes: 7 additions & 0 deletionssrc/mono/mono/metadata/icall.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1210,6 +1210,13 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_PrepareMethod (MonoMeth
// FIXME: Implement
}

gint32
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SizeOf (MonoQCallTypeHandle type, MonoError* error)
{
int align;
return mono_type_size (type.type, &align);
}

MonoObjectHandle
ves_icall_System_Object_MemberwiseClone (MonoObjectHandle this_obj, MonoError *error)
{
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp