Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/ILToNative/src/Compiler/AsmWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ void OutputVirtualSlots(TypeDesc implType, TypeDesc declType)
{
MethodDesc declMethod = reg.VirtualSlots[i];

MethodDesc implMethod = ResolveVirtualMethod(implType, declMethod);
MethodDesc implMethod = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(declMethod, implType.GetClosestDefType());

Out.Write(".quad ");
Out.WriteLine(NameMangler.GetMangledMethodName(implMethod));
Expand Down
18 changes: 1 addition & 17 deletions src/ILToNative/src/Compiler/Compilation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ void ExpandVirtualMethods()
{
MethodDesc declMethod = declReg.VirtualSlots[i];

AddMethod(ResolveVirtualMethod(reg.Type, declMethod));
AddMethod(VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(declMethod, reg.Type.GetClosestDefType()));
}
}

Expand Down Expand Up @@ -357,22 +357,6 @@ public void AddField(FieldDesc field)
}
}

internal MethodDesc ResolveVirtualMethod(TypeDesc implType, MethodDesc declMethod)
{
// TODO: Proper virtual method resolution
string name = declMethod.Name;
MethodSignature sig = declMethod.Signature;

MethodDesc implMethod;
TypeDesc t = implType;
for (;;)
{
implMethod = t.GetMethod(name, sig);
if (implMethod != null)
return implMethod;
t = t.BaseType;
}
}

struct ReadyToRunHelperKey : IEquatable<ReadyToRunHelperKey>
{
Expand Down
3 changes: 1 addition & 2 deletions src/ILToNative/src/CppCodeGen/CppWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -729,8 +729,7 @@ void AppendVirtualSlots(StringBuilder sb, TypeDesc implType, TypeDesc declType)
for (int i = 0; i < reg.VirtualSlots.Count; i++)
{
MethodDesc declMethod = reg.VirtualSlots[i];

MethodDesc implMethod = _compilation.ResolveVirtualMethod(implType, declMethod);
MethodDesc implMethod = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(declMethod, implType.GetClosestDefType());

sb.Append("(void*)&");
sb.Append(GetCppTypeName(implMethod.OwningType));
Expand Down
6 changes: 6 additions & 0 deletions src/ILToNative/src/ILToNative.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@
<Compile Include="..\..\TypeSystem\src\Common\TypeDesc.cs">
<Link>TypeSystem\TypeDesc.cs</Link>
</Compile>
<Compile Include="..\..\TypeSystem\src\Common\TypeDesc.MethodImpls.cs">
<Link>TypeSystem\TypeDesc.MethodImpls.cs</Link>
</Compile>
<Compile Include="..\..\TypeSystem\src\Common\VirtualFunctionResolution.cs">
<Link>TypeSystem\VirtualFunctionResolution.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\TypeSystem\src\Ecma\EcmaField.cs">
Expand Down
9 changes: 4 additions & 5 deletions src/NuGet.config
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- NOTE: Leave this file here and keep it in sync with list in dir.props. -->
<!-- The command-line doesn't need it, but the IDE does. -->
<config>
<add key="repositoryPath" value="..\packages" />
</config>
<packageSources>
<clear/>
<add key="myget.org dotnet-core" value="https://www.myget.org/F/dotnet-core/" />
<add key="myget.org dotnet-coreclr" value="https://www.myget.org/F/dotnet-coreclr/" />
<add key="myget.org dotnet-corefxtestdata" value="https://www.myget.org/F/dotnet-corefxtestdata/" />
<add key="myget.org dotnet-buildtools" value="https://www.myget.org/F/dotnet-buildtools/" />
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
</packageSources>
<config>
<add key="repositoryPath" value="..\packages" />
</config>
</configuration>
85 changes: 85 additions & 0 deletions src/TypeSystem/src/Common/TypeDesc.MethodImpls.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should decide on a convention here. FieldLayout related extensions to types all live in FieldLayout.cs. Can we put this in VirtualFunctionResolution.cs? Or should we align FieldLayout with this convention and put those things in TypeDesc.FieldLayout.cs?

My vote is to do nothing for this review, and fix up FieldLayout to align with the new convention introduced here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, I was having that thought too, and concluded that what I wanted in this case was to separate the Type system core functionality from the algorithm, as we may wish to implement load based virtual resolution someday, and it would be better to have the concepts separated to begin with. We can put adjusting the FieldLayout handling into future work.


namespace Internal.TypeSystem
{
public struct MethodImplRecord
{
public MethodDesc Decl;
public MethodDesc Body;
}

// MethodImpl api surface for types.
public partial class MetadataType
{
/// <summary>
/// Compute an array of all MethodImpls that pertain to overriding virtual (non-interface methods) on this type.
/// May be expensive.
/// </summary>
protected abstract MethodImplRecord[] ComputeVirtualMethodImplsForType();

private MethodImplRecord[] _allVirtualMethodImplsForType;
/// <summary>
/// Get an array of all MethodImpls that pertain to overriding virtual (non-interface methods) on this type.
/// Expected to cache results so this api can be used repeatedly.
/// </summary>
public MethodImplRecord[] VirtualMethodImplsForType
{
get
{
if (_allVirtualMethodImplsForType == null)
{
_allVirtualMethodImplsForType = ComputeVirtualMethodImplsForType();
}

return _allVirtualMethodImplsForType;
}
}

/// <summary>
/// Get an array of MethodImpls where the Decl method matches by name with the specified name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public abstract MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string name);
}

// Implementation of MethodImpl api surface implemented without metadata access.
public partial class InstantiatedType
{
/// <summary>
/// Instantiate a MethodImplRecord from uninstantiated form to instantiated form
/// </summary>
/// <param name="uninstMethodImpls"></param>
/// <returns></returns>
private MethodImplRecord[] InstantiateMethodImpls(MethodImplRecord[] uninstMethodImpls)
{
if (uninstMethodImpls.Length == 0)
return uninstMethodImpls;

MethodImplRecord[] instMethodImpls = new MethodImplRecord[uninstMethodImpls.Length];

for (int i = 0; i < uninstMethodImpls.Length; i++)
{
instMethodImpls[i].Decl = _typeDef.Context.GetMethodForInstantiatedType(uninstMethodImpls[i].Decl, this);
instMethodImpls[i].Body = _typeDef.Context.GetMethodForInstantiatedType(uninstMethodImpls[i].Body, this);
}

return instMethodImpls;
}

protected override MethodImplRecord[] ComputeVirtualMethodImplsForType()
{
MethodImplRecord[] uninstMethodImpls = _typeDef.VirtualMethodImplsForType;
return InstantiateMethodImpls(uninstMethodImpls);
}

public override MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string name)
{
MethodImplRecord[] uninstMethodImpls = _typeDef.FindMethodsImplWithMatchingDeclName(name);
return InstantiateMethodImpls(uninstMethodImpls);
}
}
}
54 changes: 54 additions & 0 deletions src/TypeSystem/src/Common/TypeSystemHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Diagnostics;

namespace Internal.TypeSystem
{
static public class TypeSystemHelpers
Expand Down Expand Up @@ -29,5 +31,57 @@ static public TypeDesc MakePointerType(this TypeDesc type)
{
return type.Context.GetPointerType(type);
}

static public MetadataType GetClosestDefType(this TypeDesc type)
{
if (type is MetadataType)
return (MetadataType)type;
else
return type.BaseType;
}


static private MethodDesc FindMethodOnExactTypeWithMatchingTypicalMethod(this TypeDesc type, MethodDesc method)
{
// Assert that either type is instantiated and its type definition is the type that defines the typical
// method definition of method, or that the owning type of the method typical definition is exactly type
Debug.Assert((type is InstantiatedType) ?
((InstantiatedType)type).GetTypeDefinition() == method.GetTypicalMethodDefinition().OwningType :
type == method.GetTypicalMethodDefinition().OwningType);

MethodDesc methodTypicalDefinition = method.GetTypicalMethodDefinition();

foreach (MethodDesc methodToExamine in type.GetMethods())
{
if (methodToExamine.GetTypicalMethodDefinition() == methodTypicalDefinition)
return methodToExamine;
}

Debug.Assert(false, "Behavior of typical type not as expected.");
return null;
}

static public MethodDesc FindMethodOnTypeWithMatchingTypicalMethod(this TypeDesc typeExamine, MethodDesc method)
{
TypeDesc typicalTypeInHierarchyOfTargetMethod = method.GetTypicalMethodDefinition().OwningType;
TypeDesc typeInHierarchyOfTypeExamine = typeExamine;
do
{
TypeDesc typicalTypeInHierarchyOfTypeExamine = typeInHierarchyOfTypeExamine;
if (typicalTypeInHierarchyOfTypeExamine is InstantiatedType)
{
typicalTypeInHierarchyOfTypeExamine = typicalTypeInHierarchyOfTypeExamine.GetTypeDefinition();
}
if (typicalTypeInHierarchyOfTypeExamine == typicalTypeInHierarchyOfTargetMethod)
{
// set targetMethod to method on
return typeInHierarchyOfTypeExamine.FindMethodOnTypeWithMatchingTypicalMethod(method);
}
typeInHierarchyOfTypeExamine = typeInHierarchyOfTypeExamine.BaseType;
} while (typeInHierarchyOfTypeExamine != null);

Debug.Assert(false, "method has no related type in the type hierarchy of type");
return null;
}
}
}
Loading