在JIT期间更新方法属性?

时间:2016-05-16 21:53:16

标签: c++ .net jit cil

我正在寻找更新现有方法属性的方法,而无需创建新的方法定义。

以下是我到目前为止的代码:

HRESULT STDMETHODCALLTYPE Weaver::JITCompilationStarted( 
        FunctionID functionId, BOOL fIsSafeToBlock) 
{
    HRESULT status = S_OK;
    MethodInfo methodInfo = GetMethodInfo(functionId);
    if (!IsMdVirtual(methodInfo.Attributes) && !IsMdStatic(methodInfo.Attributes)
        && !IsMdPrivate(methodInfo.Attributes) && !IsMdSpecialName(methodInfo.Attributes))
    {
        CComPtr<IMetaDataEmit> metaDataEmit;
        status = m_profilerInfo3->GetModuleMetaData(methodInfo.Module,
            ofRead | ofWrite, IID_IMetaDataEmit, (IUnknown**)&metaDataEmit);

        // TODO: get module metadata and update method attributes to:  methodInfo.Attributes | mdVirtual
        status = metaDataEmit->ApplyEditAndContinue(metaDataEmit /*?*/);
    }

    return status;
}

如您所见,我缺少检索函数元数据和在线修改的方法。关于此方法的MSDN帮助很薄,找不到ApplyEditAndContinue的使用示例。

1 个答案:

答案 0 :(得分:0)

在评论中采纳Brian的回答:

  

JITCompilationStarted改变属性为时已晚,在调用方法或JIT之前可以很好地检查属性。元数据只能从ModuleLoadFinished回调中修改。

它转换为(严重缩减)的代码:

HRESULT Weaver::ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus)
{
    HRESULT status = S_OK;
    // Filter module

    // Enum & filter types in module
        // Enum & filter methods in type
            DWORD attributes, implFlags; ULONG codeRva;
            status = pMetaImport->GetMethodProps(tkMethod, NULL, NULL, NULL, NULL, &attributes, NULL, NULL, &codeRva, &implFlags);
            status = pMetaEmit->SetMethodProps(tkMethod, attributes | mdVirtual, codeRva, implFlags);

    return status;
}

这将允许在.NET Eg中模拟非虚拟成员:

public class Foo {
    public string Hello() => "test";
}

// ...
var fake = A.Fake<Foo>();
A.CallTo(() => fake.Hello()).Returns("faked");
Assert.Equals("faked", fake.Hello());