Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize GetType with known type #87579

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b753523
Optimize GetType with known type
MichalPetryka Jun 14, 2023
5862a59
Keep side effects
MichalPetryka Jun 14, 2023
41f70ed
Update importercalls.cpp
MichalPetryka Jun 14, 2023
7448b59
Update importercalls.cpp
MichalPetryka Jun 15, 2023
929d18f
Update importercalls.cpp
MichalPetryka Jun 15, 2023
779a799
Update importercalls.cpp
MichalPetryka Jun 15, 2023
4de198e
Update importercalls.cpp
MichalPetryka Jun 15, 2023
7f44e8f
Check if box is at fault here
MichalPetryka Jun 16, 2023
127bd47
Update importer.cpp
MichalPetryka Jun 16, 2023
0e62429
Sprinkle some asserts
MichalPetryka Jun 21, 2023
cde9a24
Fix building
MichalPetryka Jun 21, 2023
dcf25a8
Update importercalls.cpp
MichalPetryka Jun 23, 2023
6abbd7b
Update importercalls.cpp
MichalPetryka Jun 23, 2023
4b35aa9
Format code
MichalPetryka Jun 23, 2023
eb56645
Merge
MichalPetryka Jun 23, 2023
6a60fc0
Try fixing the r2r test
MichalPetryka Jun 23, 2023
cbe32bf
Update test.cs
MichalPetryka Jun 24, 2023
a128856
Update main.cs
MichalPetryka Jun 24, 2023
f573051
Update newarray.cs
MichalPetryka Jun 24, 2023
f2dad1d
Update generics.cs
MichalPetryka Jun 24, 2023
a1b6fd7
Update gentree.cpp
MichalPetryka Jun 27, 2023
b61f1e1
Update gentree.cpp
MichalPetryka Jun 27, 2023
be56999
Update lclvars.cpp
MichalPetryka Jun 27, 2023
c95231a
Update lclvars.cpp
MichalPetryka Jun 27, 2023
0885714
Merge branch 'dotnet:main' into gettype-exacttype
MichalPetryka Jun 28, 2023
e1514e4
Merge
MichalPetryka Jul 10, 2023
ff1adcd
Revert separated changes
MichalPetryka Jul 10, 2023
cf9e771
Cleanup
MichalPetryka Jul 10, 2023
32c2b3a
Fix the helper
MichalPetryka Jul 11, 2023
75163fd
Update src/coreclr/jit/importer.cpp
MichalPetryka Jul 11, 2023
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
3 changes: 3 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4068,6 +4068,9 @@ class Compiler
GenTree** clone,
unsigned curLevel,
Statement** pAfterStmt DEBUGARG(const char* reason));

CORINFO_CLASS_HANDLE impImportHandleFromStack(bool allowShared);

GenTree* impStoreStruct(GenTree* store,
unsigned curLevel,
Statement** pAfterStmt = nullptr,
Expand Down
39 changes: 39 additions & 0 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,45 @@ GenTree* Compiler::impCloneExpr(GenTree* tree,
return gtNewLclvNode(temp, type);
}

//------------------------------------------------------------------------
// impImportHandleFromStack: Imports the tree on the top of the stack
// and extracts the handle from it
//
// Arguments:
// allowShared - whether shared types are considered as valid handles
//
// Return Value:
// The extracted handle, or NO_CLASS_HANDLE if no handle could be extracted
//
CORINFO_CLASS_HANDLE Compiler::impImportHandleFromStack(bool allowShared)
{
GenTree* tree = impStackTop().val;
bool isExact = false;
bool notNull = false;
CORINFO_CLASS_HANDLE typeHnd = gtGetClassHandle(tree, &isExact, &notNull);
if ((typeHnd != NO_CLASS_HANDLE) && isExact)
{
assert((info.compCompHnd->getClassAttribs(typeHnd) & CORINFO_FLG_GENERIC_TYPE_VARIABLE) == 0);
if (!allowShared && ((info.compCompHnd->getClassAttribs(typeHnd) & CORINFO_FLG_SHAREDINST) != 0))
{
return NO_CLASS_HANDLE;
}

JITDUMP("Retuning a constant handle from imported tree\n");
impPopStack();
if (!notNull && fgAddrCouldBeNull(tree))
{
impAppendTree(gtNewNullCheck(tree, compCurBB), CHECK_SPILL_ALL, impCurStmtDI);
}
else if ((tree->gtFlags & GTF_SIDE_EFFECT) != 0)
{
impAppendTree(gtUnusedValNode(tree), CHECK_SPILL_ALL, impCurStmtDI);
}
return typeHnd;
}
return NO_CLASS_HANDLE;
}

//------------------------------------------------------------------------
// impCreateDIWithCurrentStackInfo: Create a DebugInfo instance with the
// specified IL offset and 'is call' bit, using the current stack to determine
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3561,6 +3561,18 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
}
}

// Load handle directly for known types
if (retNode == nullptr)
{
CORINFO_CLASS_HANDLE typeHnd = impImportHandleFromStack(false);
if (typeHnd != NO_CLASS_HANDLE)
{
JITDUMP("Optimizing object.GetType() with known type to typeof\n");
GenTree* handle = gtNewIconEmbClsHndNode(typeHnd);
retNode = gtNewHelperCallNode(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, TYP_REF, handle);
}
}

#ifdef DEBUG
if (retNode != nullptr)
{
Expand Down
10 changes: 7 additions & 3 deletions src/tests/readytorun/tests/generics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3073,13 +3073,17 @@ public static class Assert
{
public static bool HasAssertFired;

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void AreEqual(Object actual, Object expected)
{
if (!(actual == null && expected == null) && !actual.Equals(expected))
if (ReferenceEquals(expected, actual))
return;

if (ReferenceEquals(expected, null) || !expected.Equals(actual))
{
Console.WriteLine("Not equal!");
Console.WriteLine("actual = " + actual.ToString());
Console.WriteLine("expected = " + expected.ToString());
Console.WriteLine("expected = " + expected?.ToString());
Console.WriteLine("actual = " + actual?.ToString());
HasAssertFired = true;
}
}
Expand Down
28 changes: 15 additions & 13 deletions src/tests/readytorun/tests/main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,9 @@ static void TestChangingHFAStruct()
[MethodImplAttribute(MethodImplOptions.NoInlining)]
static void TestGetType()
{
new MyClass().GetType().ToString();
NoInline(new MyClass()).GetType().ToString();
[MethodImplAttribute(MethodImplOptions.NoInlining)]
static object NoInline(object o) => o;
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
Expand Down Expand Up @@ -393,17 +395,17 @@ static void GenericLdtokenFieldsTest()
string expectedDllField4 = "System.Collections.Generic.KeyValuePair`2[???,System.Int32] MyGeneric`2[???,???]::m_Field4".Replace("???", instArg.ToString());
string expectedDllField5 = "System.Int32 MyGeneric`2[???,???]::m_Field5".Replace("???", instArg.ToString());

Assert.AreEqual(expectedField1, FieldFullName(getter.GetGenT_Field1()));
Assert.AreEqual(expectedField2, FieldFullName(getter.GetGenT_Field2()));
Assert.AreEqual(expectedField3, FieldFullName(getter.GetGenT_Field3()));
Assert.AreEqual(expectedField4, FieldFullName(getter.GetGenT_Field4()));
Assert.AreEqual(expectedField5, FieldFullName(getter.GetGenT_Field5()));

Assert.AreEqual(expectedDllField1, FieldFullName(getter.GetGenDllT_Field1()));
Assert.AreEqual(expectedDllField2, FieldFullName(getter.GetGenDllT_Field2()));
Assert.AreEqual(expectedDllField3, FieldFullName(getter.GetGenDllT_Field3()));
Assert.AreEqual(expectedDllField4, FieldFullName(getter.GetGenDllT_Field4()));
Assert.AreEqual(expectedDllField5, FieldFullName(getter.GetGenDllT_Field5()));
Assert.AreEqual(FieldFullName(getter.GetGenT_Field1()), expectedField1);
Assert.AreEqual(FieldFullName(getter.GetGenT_Field2()), expectedField2);
Assert.AreEqual(FieldFullName(getter.GetGenT_Field3()), expectedField3);
Assert.AreEqual(FieldFullName(getter.GetGenT_Field4()), expectedField4);
Assert.AreEqual(FieldFullName(getter.GetGenT_Field5()), expectedField5);

Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field1()), expectedDllField1);
Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field2()), expectedDllField2);
Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field3()), expectedDllField3);
Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field4()), expectedDllField4);
Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field5()), expectedDllField5);
}
}

Expand Down Expand Up @@ -438,7 +440,7 @@ static void TestILBodyChange()
{
int actualMethodCallResult = (int)typeof(ILInliningTest).GetMethod("TestDifferentIntValue").Invoke(null, new object[]{});
Console.WriteLine(actualMethodCallResult);
Assert.AreEqual(ILInliningTest.TestDifferentIntValue(), actualMethodCallResult);
Assert.AreEqual(actualMethodCallResult, ILInliningTest.TestDifferentIntValue());
}

static void RunAllTests()
Expand Down
10 changes: 7 additions & 3 deletions src/tests/readytorun/tests/newarray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,17 @@ public static class Assert
{
public static bool HasAssertFired;

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void AreEqual(Object actual, Object expected)
{
if (!(actual == null && expected == null) && !actual.Equals(expected))
if (ReferenceEquals(expected, actual))
return;

if (ReferenceEquals(expected, null) || !expected.Equals(actual))
{
Console.WriteLine("Not equal!");
Console.WriteLine("actual = " + actual.ToString());
Console.WriteLine("expected = " + expected.ToString());
Console.WriteLine("expected = " + expected?.ToString());
Console.WriteLine("actual = " + actual?.ToString());
HasAssertFired = true;
}
}
Expand Down
42 changes: 23 additions & 19 deletions src/tests/readytorun/tests/test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ public static class Assert
{
public static bool HasAssertFired;

[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void AreEqual(Object actual, Object expected)
{
if (!(actual == null && expected == null) && !actual.Equals(expected))
if (ReferenceEquals(expected, actual))
return;

if (ReferenceEquals(expected, null) || !expected.Equals(actual))
{
Console.WriteLine("Not equal!");
Console.WriteLine("actual = " + actual.ToString());
Console.WriteLine("expected = " + expected.ToString());
Console.WriteLine("expected = " + expected?.ToString());
Console.WriteLine("actual = " + actual?.ToString());
HasAssertFired = true;
}
}
Expand Down Expand Up @@ -623,8 +627,6 @@ static void TestMovedGenericVirtualMethod()
Assert.AreEqual(o.ChangedToVirtual<WeakReference>(), typeof(List<WeakReference>).ToString());
}



[MethodImplAttribute(MethodImplOptions.NoInlining)]
static void TestMovedGenericVirtualMethodOnNullReference()
{
Expand Down Expand Up @@ -729,7 +731,9 @@ static void TestChangingHFAStruct()
[MethodImplAttribute(MethodImplOptions.NoInlining)]
static void TestGetType()
{
new MyClass().GetType().ToString();
NoInline(new MyClass()).GetType().ToString();
[MethodImplAttribute(MethodImplOptions.NoInlining)]
static object NoInline(object o) => o;
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
Expand Down Expand Up @@ -848,17 +852,17 @@ static void TestGenericLdtokenFields()
string expectedDllField4 = "System.Collections.Generic.KeyValuePair`2[???,System.Int32] MyGeneric`2[???,???]::m_Field4".Replace("???", instArg.ToString());
string expectedDllField5 = "System.Int32 MyGeneric`2[???,???]::m_Field5".Replace("???", instArg.ToString());

Assert.AreEqual(expectedField1, FieldFullName(getter.GetGenT_Field1()));
Assert.AreEqual(expectedField2, FieldFullName(getter.GetGenT_Field2()));
Assert.AreEqual(expectedField3, FieldFullName(getter.GetGenT_Field3()));
Assert.AreEqual(expectedField4, FieldFullName(getter.GetGenT_Field4()));
Assert.AreEqual(expectedField5, FieldFullName(getter.GetGenT_Field5()));

Assert.AreEqual(expectedDllField1, FieldFullName(getter.GetGenDllT_Field1()));
Assert.AreEqual(expectedDllField2, FieldFullName(getter.GetGenDllT_Field2()));
Assert.AreEqual(expectedDllField3, FieldFullName(getter.GetGenDllT_Field3()));
Assert.AreEqual(expectedDllField4, FieldFullName(getter.GetGenDllT_Field4()));
Assert.AreEqual(expectedDllField5, FieldFullName(getter.GetGenDllT_Field5()));
Assert.AreEqual(FieldFullName(getter.GetGenT_Field1()), expectedField1);
Assert.AreEqual(FieldFullName(getter.GetGenT_Field2()), expectedField2);
Assert.AreEqual(FieldFullName(getter.GetGenT_Field3()), expectedField3);
Assert.AreEqual(FieldFullName(getter.GetGenT_Field4()), expectedField4);
Assert.AreEqual(FieldFullName(getter.GetGenT_Field5()), expectedField5);

Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field1()), expectedDllField1);
Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field2()), expectedDllField2);
Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field3()), expectedDllField3);
Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field4()), expectedDllField4);
Assert.AreEqual(FieldFullName(getter.GetGenDllT_Field5()), expectedDllField5);
}
}

Expand Down Expand Up @@ -888,7 +892,7 @@ private static void ValidateTestHasCrossModuleImplementation(string testName, Li
found = true;
}
Console.WriteLine($"Found:{found}");
Assert.AreEqual(expectedToBePresent, found);
Assert.AreEqual(found, expectedToBePresent);
}

public static void RunAllTests(Assembly assembly)
Expand Down Expand Up @@ -1012,4 +1016,4 @@ public static void RunAllTests(Assembly assembly)
}

static int s;
}
}