Skip to content

Instantly share code, notes, and snippets.

@urasandesu
Last active January 3, 2016 16:38
Show Gist options
  • Select an option

  • Save urasandesu/8490273 to your computer and use it in GitHub Desktop.

Select an option

Save urasandesu/8490273 to your computer and use it in GitHub Desktop.
...
STDMETHODIMP CWeaverImpl::JITCompilationStartedCore(
/* [in] */ FunctionID functionId,
/* [in] */ BOOL fIsSafeToBlock)
{
using boost::lexical_cast;
using boost::filesystem::path;
using std::vector;
using Urasandesu::CppAnonym::Utilities::AnyPtr;
D_WCOUT2(L"JITCompilationStartedCore(FunctionID: 0x%|1$08X|, BOOL: 0x%|2$08X|)", functionId, fIsSafeToBlock);
auto *pProcProf = m_pProfInfo->GetCurrentProcessProfiler();
auto pFuncProf = pProcProf->AttachToFunction(functionId);
auto pModProf = pFuncProf->AttachToModule();
if (!pModProf.IsPersisted())
return S_OK;
D_WCOUT(L" This method is candidate for the module that can detour.");
auto pAsmProf = pModProf->AttachToAssembly();
auto pDomainProf = pAsmProf->AttachToAppDomain();
auto *pDisp = pDomainProf->GetMetadataDispenser();
auto asmId = lexical_cast<wstring>(pAsmProf->GetID());
auto pData = pDomainProf->GetData(asmId);
_ASSERTE(pData);
auto &prigData = *pData.Get<PrigData *>();
_ASSERTE(!prigData.m_modPrigPath.empty());
if (!prigData.m_indirectablesInit && pDisp->IsCOMMetaDataDispenserPrepared())
{
auto prigFrmwrkPath = canonical(path(L"Urasandesu.Prig.Framework.dll"));
auto const *pPrigFrmwrk = pDisp->GetAssemblyFrom(prigFrmwrkPath);
auto const *pPrigFrmwrkDll = pPrigFrmwrk->GetMainModule();
auto const *pIndAttrType = pPrigFrmwrkDll->GetType(L"Urasandesu.Prig.Framework.IndirectableAttribute");
auto const *pPrigAsm = pDisp->GetAssemblyFrom(prigData.m_modPrigPath);
auto indAttrs = pPrigAsm->GetCustomAttributes(pIndAttrType, false);
BOOST_FOREACH (auto const *pIndAttr, indAttrs)
prigData.m_indirectables[GetIndirectableToken(pIndAttr)] = pIndAttr;
#ifdef OUTPUT_DEBUG
BOOST_FOREACH (auto const &pair, prigData.m_indirectables)
D_WCOUT1(L" Indirectable Token: 0x%|1$08X|", pair.first);
#endif
prigData.m_indirectablesInit = true;
}
typedef decltype(prigData.m_indirectables) Indirectables;
typedef Indirectables::iterator Iterator;
auto const *pMethodGen = pFuncProf->GetMethodGenerator();
auto mdt = pMethodGen->GetToken();
D_WCOUT1(L" Token: 0x%|1$08X|)", mdt);
auto result = Iterator();
if ((result = prigData.m_indirectables.find(mdt)) == prigData.m_indirectables.end())
return S_OK;
D_WCOUT(L" This method is marked by IndirectableAttribute.");
pFuncProf.Persist();
auto pNewBodyProf = pFuncProf->NewFunctionBody();
auto *pNewBodyGen = pNewBodyProf->GetMethodBodyGenerator();
auto const *pBody = pMethodGen->GetMethodBody();
BOOST_FOREACH (auto const *pLocal, pBody->GetLocals())
pNewBodyGen->DefineLocal(pLocal->GetLocalType());
{
// TODO: この辺実装中。。。・・・新スタブを使った Emit 処理・・・
auto prigFrmwrkPath = canonical(path(L"Urasandesu.Prig.Framework.dll"));
auto const *pPrigFrmwrk = pDisp->GetAssemblyFrom(prigFrmwrkPath);
auto const *pPrigFrmwrkDll = pPrigFrmwrk->GetMainModule();
auto const *pRetType = pMethodGen->GetReturnType();
auto const *pIndInfo = pPrigFrmwrkDll->GetType(L"Urasandesu.Prig.Framework.IndirectionInfo");
auto const *pIndHolder1 = pPrigFrmwrkDll->GetType(L"Urasandesu.Prig.Framework.IndirectionHolder`1");
auto const *pIndDelegate = pPrigFrmwrkDll->GetType(L"Urasandesu.Prig.Framework.IndirectionFunc`1"); // TODO: 引数の数によって生成する delegate を切り替える必要あり!
auto const *pLooseCrossDomainAccessor = pPrigFrmwrkDll->GetType(L"Urasandesu.Prig.Framework.LooseCrossDomainAccessor");
auto const *pIndDelegateInst = static_cast<IType *>(nullptr);
{
auto genericArgs = vector<IType const *>();
genericArgs.push_back(pRetType);
pIndDelegateInst = pIndDelegate->MakeGenericType(genericArgs);
}
auto const *pIndHolder1IndDelegateInst = static_cast<IType *>(nullptr);
{
auto genericArgs = vector<IType const *>();
genericArgs.push_back(pIndDelegateInst);
pIndHolder1IndDelegateInst = pIndHolder1->MakeGenericType(genericArgs);
}
auto const *pIndInfo_set_AssemblyName = pIndInfo->GetMethod(L"set_AssemblyName");
auto const *pIndInfo_set_TypeFullName = pIndInfo->GetMethod(L"set_TypeFullName");
auto const *pIndInfo_set_MethodName = pIndInfo->GetMethod(L"set_MethodName");
auto const *pIndDelegateInst_Invoke = pIndDelegateInst->GetMethod(L"Invoke");
auto const *pLooseCrossDomainAccessor_TryGet = pLooseCrossDomainAccessor->GetMethod(L"TryGet");
auto const *pIndHolder1IndDelegateInst_TryGet = pIndHolder1IndDelegateInst->GetMethod(L"TryGet");
auto const *pLooseCrossDomainAccessor_TryGetIndHolderIndDelegateInst = static_cast<IMethod *>(nullptr);
{
auto genericArgs = vector<IType const *>();
genericArgs.push_back(pIndHolder1IndDelegateInst);
pLooseCrossDomainAccessor_TryGetIndHolderIndDelegateInst = pLooseCrossDomainAccessor_TryGet->MakeGenericMethod(genericArgs);
}
auto *pLocal0 = pNewBodyGen->DefineLocal(pRetType);
auto *pLocal1_holder = pNewBodyGen->DefineLocal(pIndHolder1IndDelegateInst);
auto *pLocal2_info = pNewBodyGen->DefineLocal(pIndInfo);
auto *pLocal3_ind = pNewBodyGen->DefineLocal(pIndDelegateInst);
auto label0 = pNewBodyGen->DefineLabel();
pNewBodyGen->Emit(OpCodes::Ldnull);
pNewBodyGen->Emit(OpCodes::Stloc_S, pLocal1_holder);
pNewBodyGen->Emit(OpCodes::Ldloca_S, pLocal1_holder);
pNewBodyGen->Emit(OpCodes::Call, pLooseCrossDomainAccessor_TryGetIndHolderIndDelegateInst);
pNewBodyGen->Emit(OpCodes::Brfalse_S, label0);
pNewBodyGen->Emit(OpCodes::Ldloca_S, pLocal2_info);
pNewBodyGen->Emit(OpCodes::Initobj, pIndInfo);
pNewBodyGen->Emit(OpCodes::Ldloca_S, pLocal2_info);
pNewBodyGen->Emit(OpCodes::Ldstr, pMethodGen->GetAssembly()->GetFullName());
pNewBodyGen->Emit(OpCodes::Call, pIndInfo_set_AssemblyName);
pNewBodyGen->Emit(OpCodes::Ldloca_S, pLocal2_info);
pNewBodyGen->Emit(OpCodes::Ldstr, pMethodGen->GetDeclaringType()->GetFullName()); // TODO: パターン拡充必要。Module に直接生えてるメソッドの場合ぬるぽ。
pNewBodyGen->Emit(OpCodes::Call, pIndInfo_set_TypeFullName);
pNewBodyGen->Emit(OpCodes::Ldloca_S, pLocal2_info);
pNewBodyGen->Emit(OpCodes::Ldstr, pMethodGen->GetName()); // TODO: オーバーロードがあった場合の処理が必要!
pNewBodyGen->Emit(OpCodes::Call, pIndInfo_set_MethodName);
pNewBodyGen->Emit(OpCodes::Ldnull);
pNewBodyGen->Emit(OpCodes::Stloc_S, pLocal3_ind);
pNewBodyGen->Emit(OpCodes::Ldloc_S, pLocal1_holder);
pNewBodyGen->Emit(OpCodes::Ldloc_S, pLocal2_info);
pNewBodyGen->Emit(OpCodes::Ldloca_S, pLocal3_ind);
pNewBodyGen->Emit(OpCodes::Callvirt, pIndHolder1IndDelegateInst_TryGet);
pNewBodyGen->Emit(OpCodes::Brfalse_S, label0);
pNewBodyGen->Emit(OpCodes::Ldloc_S, pLocal3_ind);
// TODO: 引数があるのであれば、ここで評価スタックに積む!
pNewBodyGen->Emit(OpCodes::Callvirt, pIndDelegateInst_Invoke);
pNewBodyGen->Emit(OpCodes::Ret);
pNewBodyGen->MarkLabel(label0);
}
auto indInstsSize = pNewBodyGen->GetInstructions().size();
BOOST_FOREACH (auto const *pInst, pBody->GetInstructions())
pNewBodyGen->Emit(pInst);
BOOST_FOREACH (auto const *pExClause, pBody->GetExceptionClauses())
pNewBodyGen->DefineExceptionClause(pExClause, indInstsSize); // TODO: こんな感じだと超スッキリする!
pFuncProf->SetFunctionBody(pNewBodyProf);
pProcProf->DetachFromFunction(functionId);
return S_OK;
}
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment