如何找到extern bool InternalEquals的实现代码

之前看Allen lee的《如何找到public extern bool Equals(String value)的实现代码》,现在sscli2.0中comstring里已经没有Equals了

在微软提供的Rotor源代码中,Object.InternalEquals的代码只有下面两行:

[MethodImplAttribute(MethodImplOptions.InternalCall)]
internalstaticexternbool InternalEquals(Object objA, Object objB);


在哪里可以找到该方法的实现代码呢?
打开Rotor源代码的sscli20/clr/src/vm/ecall.cpp文件,搜索“InternalEquals”关键字,你将找到如下所示的相关的一些宏:

FCFuncStart(gObjectFuncs)
//......省略若干
FCFuncElement("InternalEquals", ObjectNative::Equals)
//......省略若干
FCFuncEnd()


他们的相关定义为:

代码
#define FCFuncFlags(intrinsicID, dynamicID) \
(BYTE
*)( (((BYTE)intrinsicID) <<16) + (((BYTE)dynamicID) <<24) )

#define FCFuncElement(name, impl) FCFuncFlags(CORINFO_INTRINSIC_Illegal, ECall::InvalidDynamicFCallId), \
GetEEFuncEntryPoint(impl), NULL, NULL, (LPVOID)name,

#define FCFuncStart(name) static LPVOID name[] = {

#define FCFuncEnd() FCFuncFlag_EndOfArray + FCFuncFlags(CORINFO_INTRINSIC_Illegal, ECall::InvalidDynamicFCallId) };


其中ObjectNative::Equals是实现的函数,查找FCFuncStart、FCFuncElement、FCFuncEnd宏展开来就是:

代码
static LPVOID gObjectFuncs[] =
{
//......省略若干
FCFuncFlags( CORINFO_INTRINSIC_Illegal,ECall::InvalidDynamicFCallId),
GetEEFuncEntryPoint(ObjectNative::Equals),
NULL,
NULL,
(LPVOID)InternalEquals,
//......省略若干
FCFuncFlag_EndOfArray + FCFuncFlags(CORINFO_INTRINSIC_Illegal,ECall::InvalidDynamicFCallId)
};


其中 FCFuncFlags又是一个宏,完全展开后的原型:

代码
static LPVOID gObjectFuncs[] =
{
//......省略若干
(BYTE*)( (((BYTE)CORINFO_INTRINSIC_Illegal) <<16) + (((BYTE)ECall::InvalidDynamicFCallId) <<24) ),
GetEEFuncEntryPoint(ObjectNative::Equals),
NULL,
NULL,
(LPVOID)InternalEquals,
//......省略若干
FCFuncFlag_EndOfArray + (BYTE*)( (((BYTE)CORINFO_INTRINSIC_Illegal) <<16) + (((BYTE)ECall::InvalidDynamicFCallId) <<24) )
};


一堆宏看得人眼花缭乱,但是不必要理会,我们只要找寻 ObjectNative::Equals,原先String的extern Equals

实现在comstring.cpp里,但是因为版本不同,现在comstring已经没有Equals了,而Object.InternalEquals由ObjectNative来处理

打开Rotor源代码的sscli20/clr/src/vm/comobject.cpp文件,搜索“ObjectNative::Equals”关键字找到了如下代码:

代码
FCIMPL2(FC_BOOL_RET, ObjectNative::Equals, Object *pThisRef, Object *pCompareRef)
{
CONTRACTL
{
THROWS;
DISABLED(GC_NOTRIGGER);
INJECT_FAULT(FCThrow(kOutOfMemoryException););
MODE_COOPERATIVE;
SO_TOLERANT;
}
CONTRACTL_END;

if (pThisRef == pCompareRef)
FC_RETURN_BOOL(TRUE);

// Since we are in FCALL, we must handle NULL specially.
if (pThisRef == NULL || pCompareRef == NULL)
FC_RETURN_BOOL(FALSE);

MethodTable
*pThisMT = pThisRef->GetMethodTable();

// If it's not a value class, don't compare by value
if (!pThisMT->IsValueClass())
FC_RETURN_BOOL(FALSE);

// Make sure they are the same type.
if (pThisMT != pCompareRef->GetMethodTable())
FC_RETURN_BOOL(FALSE);

// Compare the contents (size - vtable - sink block index).
BOOL ret = memcmp(
(
void*) (pThisRef+1),
(
void*) (pCompareRef+1),
pThisRef
->GetMethodTable()->GetBaseSize() -sizeof(Object) -sizeof(int)) ==0;

FC_GC_POLL_RET();

FC_RETURN_BOOL(ret);
}
FCIMPLEND


其中FCIMPL2和FCIMPLEND是一组成对出现的宏:

#define FCIMPL2(rettype, funcname, a1, a2) rettype F_CALL_CONV funcname(int /* EAX */, a2, a1) { FCIMPL_PROLOG(funcname)
#define FCIMPLEND FCIMPL_EPILOG(); }


展开后以上一段代码的开头和结尾成了:

FC_BOOL_RET F_CALL_CONV ObjectNative::Equals(int/* EAX */, Object *pThisRef, Object *pCompareRef)
{
FCIMPL_PROLOG(ObjectNative::Equals)
//......省略若干
FCIMPL_EPILOG();
}


其中夹杂的几个宏我们不必理会,关键的代码是:

BOOL ret = memcmp((void*)(pThisRef+1), (void*)(pCompareRef+1), pThisRef->GetMethodTable()->GetBaseSize() -sizeof(Object) -sizeof(int)) ==0;


这里调用了C标准库的memcmp函数比较两个Object*对象是否相等。

posted @ 2011-01-20 22:43  toda  阅读(1476)  评论(9编辑  收藏  举报