Managed CodeGen

This blog is to introduce some new features about Managed CodeGen in Whidbey. We provided a new way of doing LightWeight CodeGen, added support for emitting Generics in Reflection.Emit and there is some new exciting token handle stories in Reflection going on.

Sample Code to invoke managed code inside profiling API

ProfilerCallback.cpp


// This is the function that will invoke the managed code through COM interop on another thread

// this function creates the CCW object

// [in] this pointer
DWORD WINAPI CreateManagedStub(LPVOID lpParam)
{
    _ManagedStub * pIManagedStub = NULL;
    HRESULT hr = CoCreateInstance(CLSID_ManagedStub, NULL, CLSCTX_INPROC_SERVER, IID__ManagedStub, (void **)&pIManagedStub); 
    if (FAILED(hr))
    {
        printf("Fail to CoCreateInstance on ManagedStub class 0x%x\n", hr);
        return 1;
    }
    if (pIManagedStub == NULL)
    {
        printf("pIManagedStub is null 0x%x\n", hr);
        return 1;
    }

    // we have the managed instance now.
    ((CProfilerCallback*)lpParam)->m_pIManagedStub = pIManagedStub;
    return 0;
}

// this function is the actual caller to the managed world. 
// this function can be used to get a managed dynamic method token back
// [in] this pointer; method token; assembly name
// [out] delegate type name
DWORD WINAPI ManagedPreStub(LPVOID lpParam)
{
    PMYDATA pData = (PMYDATA)lpParam;
    LPWSTR delegateName = NULL;
    if (pData->thisObj->m_pIManagedStub == NULL)
    {
        printf("pData->thisObj->m_pIManagedStub is null");
        return 1;
    }
    HRESULT hr = pData->thisObj->m_pIManagedStub->PreStub(pData->assemblyName, pData->methodTk, &delegateName);
    if (FAILED(hr))
    {
        printf("Fail to Call PreStub 0x%x\n", hr);
    }
    wcscpy_s(pData->delegateName, (wchar_t*)delegateName);
    return 0;
   
}

......

// Profiler callback function

HRESULT CProfilerCallback::JITCompilationStarted(UINT functionId,
                                                BOOL fIsSafeToBlock)
{
    HANDLE hThread = NULL;
    DWORD dwThreadId;
    /////////////////////////////////////////////////////////
    // We dont want to continue on JITCompilationStarted if the thread is for the "managed code" we are to call from this callback.

    // We store these thread ids in our skip thread hashtable

    // 1. if the JITCompilationStarted is on one of the skipping thread, avoid following steps.
    DWORD currentThreadId = GetCurrentThreadId();
    if (m_SkipJCHashTable->PLookup(currentThreadId))
        return S_OK;

    // create the ManagedStub object
    if (m_pIManagedStub==NULL) // if it is already created, no need to create twice
    {
        hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateManagedStub, this, 0, &dwThreadId);

       // add the thread Id to skip pool so that JITCompilationStarted will do nothing on that thread. 

       m_SkipJCHashTable->SetAt(dwThreadId, 0);  
        if (hThread != NULL)
        {
            WaitForSingleObject(hThread, INFINITE);
            CloseHandle(hThread);
        }
        m_SkipJCHashTable->RemoveKey(dwThreadId);  
    }

....

    ///////////////////////////////////////////////////////
    // try to define a managed dynamic method and get the dynamic method method token
    // prepare the parameters to be passed in
    PMYDATA pData = (PMYDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA));

    if( pData == NULL )
            goto exit;

    pData->assemblyName = wszAssemblyName;
    pData->methodTk = tkMethod;
    pData->thisObj = this;

    ProfilerPrintf("Working on asm %ws func %ws.", wszAssemblyName, wszFunctionName);
  
    hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ManagedPreStub, pData, 0, &dwThreadId);
    m_SkipJCHashTable->SetAt(dwThreadId, 0);  
    if (hThread != NULL)
    {
        WaitForSingleObject(hThread, INFINITE);
        CloseHandle(hThread);
    }
    m_SkipJCHashTable->RemoveKey(dwThreadId);

    // we free up the memory here instead of in the thread because we want some return value back.
    wchar_t wszDelegateName[512];

    if (pData->delegateName == NULL)
        return S_OK;
    // copy the return value out
    wcsncpy_s(wszDelegateName, _countof(pData->delegateName), pData->delegateName, _countof(pData->delegateName));

    HeapFree(GetProcessHeap(), 0, pData);

...

We have these definitions in ProfilerCallback.h:

private:

    CMap<DWORD, DWORD, int, int> * m_SkipJCHashTable;

      ...

    Enjoy!

 

Published Friday, December 09, 2005 8:01 PM by yirutang

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

No Comments

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required
Submit

© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker