Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Can I Call FastEqualsCheck()?

Tags:

c#

.net

This is mostly academic - but I was looking at the implementation of Equals() for ValueTypes. The source code is here: http://referencesource.microsoft.com/#mscorlib/system/valuetype.cs#38

The code that caught my eye was this:

    // if there are no GC references in this object we can avoid reflection 
    // and do a fast memcmp
    if (CanCompareBits(this))
        return FastEqualsCheck(thisObj, obj);

FastEqualsCheck() is declared as follows:

[System.Security.SecuritySafeCritical]  
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool FastEqualsCheck(Object a, Object b);

My understanding is that the '[MethodImplAttribute(MethodImplOptions.InternalCall)]' indicates that this is implemented in the CLR (source not available), but I thought I would be able to call it directly from my code. When I try, I get a SecurityException

ECall methods must be packaged into a system module.

Can I make these calls myself (or are they meant for internal consumption only)? If I can call them directly, what is the appropriate way of doing so?

like image 356
Rob P. Avatar asked May 20 '14 14:05

Rob P.


1 Answers

You cannot call these methods yourself. They are internal and can only be called by methods that are in the same assembly. This is exactly what the exception tells you.

As suggested in the comments, you can look through the SSCLI code for the actual implementation.

This blog post tells you exactly where to find it:

http://blogs.msdn.com/b/xiangfan/archive/2008/09/01/magic-behind-valuetype-equals.aspx

And the download link to the SSCLI source code:

http://www.microsoft.com/en-us/download/details.aspx?id=4917

The actual implementation is as following:

FCIMPL2(FC_BOOL_RET, ValueTypeHelper::FastEqualsCheck, Object* obj1,
    Object* obj2)
{
    WRAPPER_CONTRACT;
    STATIC_CONTRACT_SO_TOLERANT;

    _ASSERTE(obj1 != NULL);
    _ASSERTE(obj2 != NULL);
    _ASSERTE(!obj1->GetMethodTable()->ContainsPointers());
    _ASSERTE(obj1->GetSize() == obj2->GetSize());

    TypeHandle pTh = obj1->GetTypeHandle();

    FC_RETURN_BOOL(memcmp(obj1->GetData(),obj2->GetData(),pTh.GetSize()) == 0);
}

As you can see, they simply perform a memcmp. So, what you could do is create a function like this in a unmanged DLL and call that, which is essentially the same.

like image 94
Swen Kooij Avatar answered Sep 19 '22 01:09

Swen Kooij