ExnTreeInfo build_exn_tree(const FuncEmitter& fe, php::Func& func, FindBlock findBlock) { ExnTreeInfo ret; auto nextExnNode = uint32_t{0}; for (auto& eh : fe.ehtab()) { auto node = folly::make_unique<php::ExnNode>(); node->id = nextExnNode++; node->parent = nullptr; switch (eh.m_type) { case EHEnt::Type::Fault: { auto const fault = findBlock(eh.m_fault); ret.funcletNodes[fault].push_back(borrow(node)); ret.faultFuncletStarts.insert(eh.m_fault); node->info = php::FaultRegion { fault, eh.m_iterId, eh.m_itRef }; } break; case EHEnt::Type::Catch: { auto treg = php::TryRegion {}; for (auto& centry : eh.m_catches) { auto const catchBlk = findBlock(centry.second); treg.catches.emplace_back( fe.ue().lookupLitstr(centry.first), catchBlk ); } node->info = treg; } break; } ret.ehMap[&eh] = borrow(node); if (eh.m_parentIndex != -1) { auto it = ret.ehMap.find(&fe.ehtab()[eh.m_parentIndex]); assert(it != end(ret.ehMap)); node->parent = it->second; it->second->children.emplace_back(std::move(node)); } else { func.exnNodes.emplace_back(std::move(node)); } } ret.faultFuncletStarts.insert(fe.past()); return ret; }
void FuncRepoProxy::GetFuncsStmt ::get(UnitEmitter& ue) { RepoTxn txn(m_repo); if (!prepared()) { std::stringstream ssSelect; ssSelect << "SELECT funcSn,preClassId,name,top,extraData " "FROM " << m_repo.table(m_repoId, "Func") << " WHERE unitSn == @unitSn ORDER BY funcSn ASC;"; txn.prepare(*this, ssSelect.str()); } RepoTxnQuery query(txn, *this); query.bindInt64("@unitSn", ue.sn()); do { query.step(); if (query.row()) { int funcSn; /**/ query.getInt(0, funcSn); Id preClassId; /**/ query.getId(1, preClassId); StringData* name; /**/ query.getStaticString(2, name); bool top; /**/ query.getBool(3, top); BlobDecoder extraBlob = /**/ query.getBlob(4); FuncEmitter* fe; if (preClassId < 0) { fe = ue.newFuncEmitter(name); } else { PreClassEmitter* pce = ue.pce(preClassId); fe = ue.newMethodEmitter(name, pce); bool added UNUSED = pce->addMethod(fe); assert(added); } assert(fe->sn() == funcSn); fe->setTop(top); fe->serdeMetaData(extraBlob); if (!SystemLib::s_inited && !fe->isPseudoMain()) { assert(fe->attrs() & AttrBuiltin); if (preClassId < 0) { assert(fe->attrs() & AttrPersistent); assert(fe->attrs() & AttrUnique); assert(fe->attrs() & AttrSkipFrame); } } fe->setEhTabIsSorted(); fe->finish(fe->past(), true); ue.recordFunction(fe); } } while (!query.done()); txn.commit(); }