Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Commit

Permalink
Remove ICastable (#8103)
Browse files Browse the repository at this point in the history
Closes #8101
  • Loading branch information
kant2002 authored Apr 21, 2020
1 parent 4f16563 commit 5383d46
Show file tree
Hide file tree
Showing 35 changed files with 27 additions and 1,362 deletions.
25 changes: 3 additions & 22 deletions src/Common/src/Internal/Runtime/EEType.Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ internal enum EETypeFlags : ushort
/// </summary>
HasPointersFlag = 0x0020,

/// <summary>
/// Type implements ICastable to allow dynamic resolution of interface casts.
/// </summary>
ICastableFlag = 0x0040,
// Unused = 0x0040,

/// <summary>
/// This type is generic and one or more of its type parameters is co- or contra-variant. This
Expand Down Expand Up @@ -112,10 +109,7 @@ internal enum EETypeRareFlags : int
/// </summary>
RequiresAlign8Flag = 0x00000001,

/// <summary>
/// Type implements ICastable to allow dynamic resolution of interface casts.
/// </summary>
UNUSED1 = 0x00000002,
// UNUSED1 = 0x00000002,

// UNUSED = 0x00000004,

Expand All @@ -128,10 +122,7 @@ internal enum EETypeRareFlags : int
/// </summary>
HasCctorFlag = 0x0000020,

/// <summary>
/// Old unused flag
/// </summary>
UNUSED2 = 0x00000040,
// UNUSED2 = 0x00000040,

/// <summary>
/// This EEType was constructed from a universal canonical template, and has
Expand Down Expand Up @@ -244,11 +235,6 @@ internal enum EETypeOptionalFieldTag : byte
/// </summary>
RareFlags,

/// <summary>
/// VTable slot of <see cref="ICastable.IsInstanceOfInterface"/> for direct invocation without interface dispatch overhead
/// </summary>
ICastableIsInstSlot,

/// <summary>
/// Index of the dispatch map pointer in the DispathMap table
/// </summary>
Expand All @@ -259,11 +245,6 @@ internal enum EETypeOptionalFieldTag : byte
/// </summary>
ValueTypeFieldPadding,

/// <summary>
/// VTable slot of <see cref="ICastable.GetImplType"/> for direct invocation without interface dispatch overhead
/// </summary>
ICastableGetImplTypeSlot,

/// <summary>
/// Offset in Nullable&lt;T&gt; of the value field
/// </summary>
Expand Down
72 changes: 0 additions & 72 deletions src/Common/src/Internal/Runtime/EEType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -649,78 +649,6 @@ internal bool RequiresAlign8
}
}

internal bool IsICastable
{
get
{
return ((_usFlags & (ushort)EETypeFlags.ICastableFlag) != 0);
}
}

/// <summary>
/// Gets the pointer to the method that implements ICastable.IsInstanceOfInterface.
/// </summary>
internal IntPtr ICastableIsInstanceOfInterfaceMethod
{
get
{
Debug.Assert(IsICastable);

byte* optionalFields = OptionalFieldsPtr;
if(optionalFields != null)
{
const ushort NoSlot = 0xFFFF;
ushort uiSlot = (ushort)OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ICastableIsInstSlot, NoSlot);
if (uiSlot != NoSlot)
{
if (uiSlot < NumVtableSlots)
return GetVTableStartAddress()[uiSlot];
else
return GetSealedVirtualSlot((ushort)(uiSlot - NumVtableSlots));
}
}

EEType* baseType = BaseType;
if (baseType != null)
return baseType->ICastableIsInstanceOfInterfaceMethod;

Debug.Assert(false);
return IntPtr.Zero;
}
}

/// <summary>
/// Gets the pointer to the method that implements ICastable.GetImplType.
/// </summary>
internal IntPtr ICastableGetImplTypeMethod
{
get
{
Debug.Assert(IsICastable);

byte* optionalFields = OptionalFieldsPtr;
if(optionalFields != null)
{
const ushort NoSlot = 0xFFFF;
ushort uiSlot = (ushort)OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ICastableGetImplTypeSlot, NoSlot);
if (uiSlot != NoSlot)
{
if (uiSlot < NumVtableSlots)
return GetVTableStartAddress()[uiSlot];
else
return GetSealedVirtualSlot((ushort)(uiSlot - NumVtableSlots));
}
}

EEType* baseType = BaseType;
if (baseType != null)
return baseType->ICastableGetImplTypeMethod;

Debug.Assert(false);
return IntPtr.Zero;
}
}

internal bool IsValueType
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,21 +276,6 @@ private void AddVirtualMethodUseDependencies(DependencyList dependencyList, Node
{
foreach (var implementedInterface in _type.RuntimeInterfaces)
{
// If the type implements ICastable, the methods are implicitly necessary
if (implementedInterface == factory.ICastableInterface)
{
MethodDesc isInstDecl = implementedInterface.GetKnownMethod("IsInstanceOfInterface", null);
MethodDesc getImplTypeDecl = implementedInterface.GetKnownMethod("GetImplType", null);

MethodDesc isInstMethodImpl = _type.ResolveInterfaceMethodTarget(isInstDecl);
MethodDesc getImplTypeMethodImpl = _type.ResolveInterfaceMethodTarget(getImplTypeDecl);

if (isInstMethodImpl != null)
dependencyList.Add(factory.VirtualMethodUse(isInstMethodImpl), "ICastable IsInst");
if (getImplTypeMethodImpl != null)
dependencyList.Add(factory.VirtualMethodUse(getImplTypeMethodImpl), "ICastable GetImplType");
}

// If any of the implemented interfaces have variance, calls against compatible interface methods
// could result in interface methods of this type being used (e.g. IEnumberable<object>.GetEnumerator()
// can dispatch to an implementation of IEnumerable<string>.GetEnumerator()).
Expand Down Expand Up @@ -561,19 +546,7 @@ private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData)
// to have the variant flag set (even if all the arguments are non-variant).
// This supports e.g. casting uint[] to ICollection<int>
flags |= (UInt16)EETypeFlags.GenericVarianceFlag;
}

if (!(this is CanonicalDefinitionEETypeNode))
{
foreach (DefType itf in _type.RuntimeInterfaces)
{
if (itf == factory.ICastableInterface)
{
flags |= (UInt16)EETypeFlags.ICastableFlag;
break;
}
}
}
}

ISymbolNode relatedTypeNode = GetRelatedTypeNode(factory);

Expand Down Expand Up @@ -917,8 +890,6 @@ protected internal virtual void ComputeOptionalEETypeFields(NodeFactory factory,

ComputeRareFlags(factory, relocsOnly);
ComputeNullableValueOffset();
if (!relocsOnly)
ComputeICastableVirtualMethodSlots(factory);
ComputeValueTypeFieldPadding();
}

Expand Down Expand Up @@ -992,38 +963,6 @@ void ComputeNullableValueOffset()
}
}

/// <summary>
/// ICastable is a special interface whose two methods are not invoked using regular interface dispatch.
/// Instead, their VTable slots are recorded on the EEType of an object implementing ICastable and are
/// called directly.
/// </summary>
protected virtual void ComputeICastableVirtualMethodSlots(NodeFactory factory)
{
if (_type.IsInterface || !EmitVirtualSlotsAndInterfaces)
return;

foreach (DefType itf in _type.RuntimeInterfaces)
{
if (itf == factory.ICastableInterface)
{
MethodDesc isInstDecl = itf.GetKnownMethod("IsInstanceOfInterface", null);
MethodDesc getImplTypeDecl = itf.GetKnownMethod("GetImplType", null);

MethodDesc isInstMethodImpl = _type.ResolveInterfaceMethodTarget(isInstDecl);
MethodDesc getImplTypeMethodImpl = _type.ResolveInterfaceMethodTarget(getImplTypeDecl);

int isInstMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, isInstMethodImpl, _type);
int getImplTypeMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, getImplTypeMethodImpl, _type);

// Slots are usually -1, since these methods are usually in the sealed vtable of the base type.
if (isInstMethodSlot != -1)
_optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.ICastableIsInstSlot, (uint)isInstMethodSlot);
if (getImplTypeMethodSlot != -1)
_optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.ICastableGetImplTypeSlot, (uint)getImplTypeMethodSlot);
}
}
}

protected virtual void ComputeValueTypeFieldPadding()
{
// All objects that can have appreciable which can be derived from size compute ValueTypeFieldPadding.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -892,20 +892,6 @@ public TypeDesc ArrayOfTEnumeratorType
}
}

private TypeDesc _systemICastableType;

public TypeDesc ICastableInterface
{
get
{
if (_systemICastableType == null)
{
_systemICastableType = _context.SystemModule.GetKnownType("System.Runtime.CompilerServices", "ICastable");
}
return _systemICastableType;
}
}

private NodeCache<MethodDesc, VirtualMethodUseNode> _virtMethods;

public DependencyNodeCore<NodeFactory> VirtualMethodUse(MethodDesc decl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public bool GeneratesMetadata(MetadataType typeDef)

public bool IsBlocked(MetadataType typeDef)
{
if (typeDef.Name == "ICastable")
if (typeDef.Name == "IBlockedInterface")
return true;

if (typeDef.HasCustomAttribute("System.Runtime.CompilerServices", "__BlockReflectionAttribute"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class Array<T> : Array, System.Collections.Generic.IList<T> { }

public class Exception { }

public class __ComObject : Private.CompilerServices.ICastable { }
public class BlockedObject : Private.CompilerServices.IBlockedInterface { }

public delegate void Action();

Expand Down Expand Up @@ -97,7 +97,7 @@ public interface IEnumerable<T>

namespace System.Private.CompilerServices
{
internal interface ICastable { }
internal interface IBlockedInterface { }
}

namespace System.Runtime.InteropServices
Expand Down
16 changes: 8 additions & 8 deletions src/ILCompiler.MetadataTransform/tests/SimpleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ public void TestAllTypes()
[Fact]
public void TestBlockedInterface()
{
// __ComObject implements ICastable, which is a metadata blocked type and should not show
// up in the __ComObject interface list.
// BlockedObject implements IBlockedInterface, which is a metadata blocked type and should not show
// up in the BlockedObject interface list.

var policy = new SingleFileMetadataPolicy();
var transformResult = MetadataTransform.Run(policy, new[] { _systemModule });

Cts.MetadataType icastable = _systemModule.GetType("System.Private.CompilerServices", "ICastable");
Cts.MetadataType comObject = _systemModule.GetType("System", "__ComObject");
Cts.MetadataType iblockedinterface = _systemModule.GetType("System.Private.CompilerServices", "IBlockedInterface");
Cts.MetadataType comObject = _systemModule.GetType("System", "BlockedObject");
Assert.Equal(1, comObject.ExplicitlyImplementedInterfaces.Length);
Assert.Equal(icastable, comObject.ExplicitlyImplementedInterfaces[0]);
Assert.Equal(iblockedinterface, comObject.ExplicitlyImplementedInterfaces[0]);

Assert.Null(transformResult.GetTransformedTypeDefinition(icastable));
Assert.Null(transformResult.GetTransformedTypeReference(icastable));
Assert.Null(transformResult.GetTransformedTypeDefinition(iblockedinterface));
Assert.Null(transformResult.GetTransformedTypeReference(iblockedinterface));

TypeDefinition comObjectRecord = transformResult.GetTransformedTypeDefinition(comObject);
Assert.NotNull(comObjectRecord);
Expand Down Expand Up @@ -282,4 +282,4 @@ public void TestFunctionPointerSignatures()
Assert.Equal(objectType, theFieldPointerSignature.Signature.Parameters[0]);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public bool GeneratesMetadata(MetadataType typeDef)

public bool IsBlocked(MetadataType typeDef)
{
if (typeDef.Name == "ICastable")
if (typeDef.Name == "IBlockedInterface")
return true;

if (typeDef.HasCustomAttribute("System.Runtime.CompilerServices", "__BlockReflectionAttribute"))
Expand Down
31 changes: 0 additions & 31 deletions src/Native/Runtime/CachedInterfaceDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,35 +541,4 @@ COOP_PINVOKE_HELPER(void, RhpGetDispatchCellInfo, (InterfaceDispatchCell * pCell
*pDispatchCellInfo = pCell->GetDispatchCellInfo();
}

EXTERN_C DECLSPEC_THREAD void* t_TLS_DispatchCell = nullptr;

COOP_PINVOKE_HELPER(void, RhpSetTLSDispatchCell, (void *dispatchCell))
{
t_TLS_DispatchCell = dispatchCell;
}

extern "C" void RhpTailCallTLSDispatchCell();
COOP_PINVOKE_HELPER(void*, RhpGetTailCallTLSDispatchCell, ())
{
return (void *)(&RhpTailCallTLSDispatchCell);
}

extern "C" void RhpCastableObjectDispatchHelper();
COOP_PINVOKE_HELPER(void*, RhpGetCastableObjectDispatchHelper, ())
{
return (void *)(&RhpCastableObjectDispatchHelper);
}

extern "C" void RhpCastableObjectDispatchHelper_TailCalled();
COOP_PINVOKE_HELPER(void*, RhpGetCastableObjectDispatchHelper_TailCalled, ())
{
return (void *)(&RhpCastableObjectDispatchHelper_TailCalled);
}

extern "C" void RhpCastableObjectDispatch_CommonStub();
COOP_PINVOKE_HELPER(void*, RhpGetCastableObjectDispatch_CommonStub, ())
{
return (void *)(&RhpCastableObjectDispatch_CommonStub);
}

#endif // FEATURE_CACHED_INTERFACE_DISPATCH
20 changes: 0 additions & 20 deletions src/Native/Runtime/amd64/StubDispatch.S
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,6 @@
// trick to avoid PLT relocation at runtime which corrupts registers
#define REL_C_FUNC(name) C_FUNC(name)@gotpcrel

LEAF_ENTRY RhpCastableObjectDispatch_CommonStub, _TEXT
// UNIXTODO: Implement this function
int 3
LEAF_END RhpCastableObjectDispatch_CommonStub, _TEXT

LEAF_ENTRY RhpTailCallTLSDispatchCell, _TEXT
// UNIXTODO: Implement this function
int 3
LEAF_END RhpTailCallTLSDispatchCell, _TEXT

LEAF_ENTRY RhpCastableObjectDispatchHelper_TailCalled, _TEXT
// UNIXTODO: Implement this function
int 3
LEAF_END RhpCastableObjectDispatchHelper_TailCalled, _TEXT

LEAF_ENTRY RhpCastableObjectDispatchHelper, _TEXT
// UNIXTODO: Implement this function
int 3
LEAF_END RhpCastableObjectDispatchHelper, _TEXT


// Macro that generates a stub consuming a cache with the given number of entries.
.macro DEFINE_INTERFACE_DISPATCH_STUB entries
Expand Down
Loading

0 comments on commit 5383d46

Please sign in to comment.