17

When use ILSpy to check the code of System.String, I found there are some methods marked as MethodImplOptions.InternalCall such as:

[SecurityCritical]
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int nativeCompareOrdinalEx(string strA, int indexA, string strB, int indexB, int count);

I know MethodImplOptions.InternalCall means this method is implemented natively by the common language runtime to optimized code to improve performance.

My question is: Is that anyway can enable us to see the code marked as MethodImplOptions.InternalCall?

2power10
  • 1,259
  • 1
  • 11
  • 33
  • 3
    You will have to look at the underlying C code. This is also handled differently between frameworks, ie normal vs micro. – leppie May 16 '13 at 04:43
  • You can get "Shared Source" from Microsoft for many pieces of the CLR. I haven't checked but I think the `System.String` implementation should be included -- both managed and native parts. See http://referencesource.microsoft.com/ for details – Ben Voigt May 16 '13 at 04:50
  • 1
    @BenVoigt thank you for your info. I get the source from Microsoft, and in the source file of String, it have following comments: `** Purpose: Your favorite String class. Native methods ** are implemented in StringNative.cpp`. However, it seems MS didn't public this file. – 2power10 May 16 '13 at 05:45
  • You can also check the Mono source code, since they have fully implemented `System.String` and it is completely open source. – Ben Voigt May 16 '13 at 05:53

3 Answers3

14

You'll need the source code for the CLR to see the implementation of these methods. That's a bit hard to come by, Microsoft doesn't publish it and it is not covered by the Reference Source.

As long as the method is "old", available since .NET 2.0, then you'll have a shot at it from the SSCLI20 source code. With a non-zero risk that you will be looking at an outdated version of the code of course. But good enough to get an idea what it looks like and often still accurate.

The starting point to start searching for the code is the clr/src/vm/ecall.cpp source code file. It contains the tables that the jitter searches for internal methods. The section that's relevant for nativeCompareOrdinalEx() looks like this:

FCFuncStart(gStringFuncs)
    FCDynamic("FastAllocateString", CORINFO_INTRINSIC_Illegal, ECall::FastAllocateString)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_ArrChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharArrayManaged)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_ArrChar_Int_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharArrayStartLengthManaged)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrManaged)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrChar_Int_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharPtrStartLengthManaged)
    FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_Char_Int_RetVoid, CORINFO_INTRINSIC_Illegal, ECall::CtorCharCountManaged)

    FCFuncElement("nativeCompareOrdinal", COMString::FCCompareOrdinal)     // <=== Here
    FCFuncElement("nativeCompareOrdinalWC", COMString::FCCompareOrdinalWC)
    FCIntrinsic("get_Length", COMString::Length, CORINFO_INTRINSIC_StringLength)
    // etc..
}

Note how the FCFuncElement has the method name as a string and a function pointer to the C++ method that implements the internal call. Grepping the source code tree then takes you to clr/src/vm/comstring.cpp. I won't bore everybody with the C++ code, just have a look for yourself.

/*================================CompareOrdinal===============================*/
FCIMPL3(INT32, COMString::FCCompareOrdinal, StringObject* strA, StringObject* strB, CLR_BOOL bIgnoreCase) {
    // Yadayada
    //...
}

Searching for CaseInsensitiveCompHelper() and FastCompareStringHelperAligned() takes you to the actual implementations of the, respectively, case-insensitive and case-sensitive comparison functions in the same source code file.

The only other thing notable about this is that CLR version 4 made some changes to this mechanism. Adding lots of new internal methods and supporting an entirely different additional interop mechanism through a [DllImport] attribute for a fake DLL named "QCall". There's no good way to see source for these additions that I know of.


UPDATE: source is now available from the CoreCLR project. The table was moved from ecall.cpp to ecalllist.h, the mechanics are still the same. Do keep in mind that this is the .NETCore version of the CLR, the desktop version source is still closed-source. The two version are however likely to have much in common.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
3

Since now CoreCLR is open source, so we could check out the internal code.

You could search COMString::CompareOrdinalEx keyword in stringnative.cpp to see the internal implementation.

2power10
  • 1,259
  • 1
  • 11
  • 33
1

As the help string says, they are "implemented in the CLR itself", so you'll need to consult its C++ sources or disassembly.

Generally, the files that comprise the CLR engine are a few native DLLs in the %WINDIR%\Microsoft.NET\Framework\<.NET engine version> folder, mostly mscor*.dll and clr.dll. The root .NET DLL, mscoree.dll, is in System32 but it seems to only act as a launcher.

Since the InternalCall method implementations are implementation details, there's no guarantee that those methods are implemented in a consistent way, e.g. that there's even some global registry of them.

E.g. disassembling shows that .NET 4 System.String's native methods are implemented in clr.dll and referenced in a directory-like structure while System.Deployment.Application.NativeMethods.IClrRuntimeInfo is backed by the CLRRuntimeInfoImpl COM class in mscoreei.dll, the methods simply being its virtual functions.

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152