Last active
January 3, 2016 16:38
-
-
Save urasandesu/8490273 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ... | |
| 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