mirror of
https://github.com/NohamR/Reclass.git
synced 2026-05-10 19:59:21 +00:00
Merge pull request #3 from H4vC/main
perf: removed redundant cache invalidations and preindexed lookups for pdbs
This commit is contained in:
@@ -105,6 +105,13 @@ static inline uint64_t resolveAddr(const ComposeState& state,
|
||||
return state.absOffsets[nodeIdx];
|
||||
}
|
||||
|
||||
|
||||
static const QVector<int>& childIndices(const ComposeState& state, uint64_t parentId) {
|
||||
static const QVector<int> kEmpty;
|
||||
auto it = state.childMap.constFind(parentId);
|
||||
return it == state.childMap.constEnd() ? kEmpty : it.value();
|
||||
}
|
||||
|
||||
void composeLeaf(ComposeState& state, const NodeTree& tree,
|
||||
const Provider& prov, int nodeIdx,
|
||||
int depth, uint64_t absAddr, uint64_t scopeId) {
|
||||
@@ -327,10 +334,7 @@ void composeParent(ComposeState& state, const NodeTree& tree,
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<int> children = state.childMap.value(node.id);
|
||||
std::sort(children.begin(), children.end(), [&](int a, int b) {
|
||||
return tree.nodes[a].offset < tree.nodes[b].offset;
|
||||
});
|
||||
const QVector<int>& children = childIndices(state, node.id);
|
||||
|
||||
int childDepth = depth + 1;
|
||||
|
||||
@@ -399,10 +403,7 @@ void composeParent(ComposeState& state, const NodeTree& tree,
|
||||
if (node.kind == NodeKind::Struct && children.isEmpty() && node.refId != 0) {
|
||||
int refIdx = tree.indexOfId(node.refId);
|
||||
if (refIdx >= 0) {
|
||||
QVector<int> refChildren = state.childMap.value(node.refId);
|
||||
std::sort(refChildren.begin(), refChildren.end(), [&](int a, int b) {
|
||||
return tree.nodes[a].offset < tree.nodes[b].offset;
|
||||
});
|
||||
const QVector<int>& refChildren = childIndices(state, node.refId);
|
||||
// Use the referenced struct's scope widths (children come from there)
|
||||
uint64_t refScopeId = node.refId;
|
||||
for (int childIdx : refChildren) {
|
||||
@@ -493,7 +494,7 @@ void composeNode(ComposeState& state, const NodeTree& tree,
|
||||
QString ptrTypeOverride = fmt::pointerTypeName(node.kind, ptrTargetName);
|
||||
|
||||
// Check if this pointer has materialized children (from materializeRefChildren)
|
||||
QVector<int> ptrChildren = state.childMap.value(node.id);
|
||||
const QVector<int>& ptrChildren = childIndices(state, node.id);
|
||||
bool hasMaterialized = !ptrChildren.isEmpty();
|
||||
|
||||
// Force collapsed if this refId is already being virtually expanded
|
||||
@@ -559,9 +560,6 @@ void composeNode(ComposeState& state, const NodeTree& tree,
|
||||
// Render materialized children at the pointer target address.
|
||||
// These are real tree nodes with independent state — use rootId
|
||||
// so resolveAddr computes offsets relative to the pointer target.
|
||||
std::sort(ptrChildren.begin(), ptrChildren.end(), [&](int a, int b) {
|
||||
return tree.nodes[a].offset < tree.nodes[b].offset;
|
||||
});
|
||||
for (int childIdx : ptrChildren) {
|
||||
composeNode(state, tree, childProv, childIdx, depth + 1,
|
||||
pBase, node.id, false, node.id);
|
||||
@@ -630,6 +628,13 @@ ComposeResult compose(const NodeTree& tree, const Provider& prov, uint64_t viewR
|
||||
for (int i = 0; i < tree.nodes.size(); i++)
|
||||
state.childMap[tree.nodes[i].parentId].append(i);
|
||||
|
||||
for (auto it = state.childMap.begin(); it != state.childMap.end(); ++it) {
|
||||
QVector<int>& children = it.value();
|
||||
std::sort(children.begin(), children.end(), [&](int a, int b) {
|
||||
return tree.nodes[a].offset < tree.nodes[b].offset;
|
||||
});
|
||||
}
|
||||
|
||||
// Precompute absolute offsets (baseAddress + structure-relative offset)
|
||||
state.absOffsets.resize(tree.nodes.size());
|
||||
for (int i = 0; i < tree.nodes.size(); i++)
|
||||
@@ -754,10 +759,7 @@ ComposeResult compose(const NodeTree& tree, const Provider& prov, uint64_t viewR
|
||||
state.emitLine(cmdRowText, lm);
|
||||
}
|
||||
|
||||
QVector<int> roots = state.childMap.value(0);
|
||||
std::sort(roots.begin(), roots.end(), [&](int a, int b) {
|
||||
return tree.nodes[a].offset < tree.nodes[b].offset;
|
||||
});
|
||||
const QVector<int>& roots = childIndices(state, 0);
|
||||
|
||||
for (int idx : roots) {
|
||||
// If viewRootId is set, skip roots that don't match
|
||||
|
||||
@@ -232,11 +232,16 @@ struct PdbCtx {
|
||||
NodeTree tree;
|
||||
const TypeTable* tt = nullptr;
|
||||
QHash<uint32_t, uint64_t> typeCache; // typeIndex → nodeId
|
||||
QHash<QString, uint32_t> structDefByName; // struct/class definition name → typeIndex
|
||||
QHash<QString, uint32_t> unionDefByName; // union definition name → typeIndex
|
||||
bool udtDefIndexBuilt = false;
|
||||
|
||||
uint64_t importUDT(uint32_t typeIndex);
|
||||
uint64_t importEnum(uint32_t typeIndex);
|
||||
void importFieldList(uint32_t fieldListIndex, uint64_t parentId);
|
||||
void importMemberType(uint32_t typeIndex, int offset, const QString& name, uint64_t parentId);
|
||||
void buildUdtDefinitionIndex();
|
||||
uint32_t findUdtDefinitionIndex(TRK kind, const char* typeName);
|
||||
|
||||
// Resolve LF_MODIFIER chain to underlying type index
|
||||
uint32_t unwrapModifier(uint32_t typeIndex) const {
|
||||
@@ -249,6 +254,56 @@ struct PdbCtx {
|
||||
}
|
||||
};
|
||||
|
||||
void PdbCtx::buildUdtDefinitionIndex() {
|
||||
if (udtDefIndexBuilt || !tt) return;
|
||||
udtDefIndexBuilt = true;
|
||||
|
||||
for (uint32_t ti = tt->firstIndex(); ti < tt->lastIndex(); ti++) {
|
||||
const auto* rec = tt->get(ti);
|
||||
if (!rec) continue;
|
||||
|
||||
bool isUnion = false;
|
||||
bool isFwd = false;
|
||||
const char* candidateName = nullptr;
|
||||
|
||||
if (rec->header.kind == TRK::LF_UNION) {
|
||||
isUnion = true;
|
||||
isFwd = rec->data.LF_UNION.property.fwdref;
|
||||
candidateName = leafName(rec->data.LF_UNION.data, unionLeafKind(rec->data.LF_UNION.data));
|
||||
} else if (rec->header.kind == TRK::LF_STRUCTURE || rec->header.kind == TRK::LF_CLASS) {
|
||||
isFwd = rec->data.LF_CLASS.property.fwdref;
|
||||
candidateName = leafName(rec->data.LF_CLASS.data, rec->data.LF_CLASS.lfEasy.kind);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isFwd || !candidateName || candidateName[0] == '\0') continue;
|
||||
|
||||
QString qname = QString::fromUtf8(candidateName);
|
||||
QHash<QString, uint32_t>& lookup = isUnion ? unionDefByName : structDefByName;
|
||||
if (!lookup.contains(qname)) lookup.insert(qname, ti);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t PdbCtx::findUdtDefinitionIndex(TRK kind, const char* typeName) {
|
||||
if (!typeName || typeName[0] == '\0') return 0;
|
||||
|
||||
buildUdtDefinitionIndex();
|
||||
|
||||
const QString qname = QString::fromUtf8(typeName);
|
||||
if (kind == TRK::LF_UNION) {
|
||||
auto it = unionDefByName.constFind(qname);
|
||||
return (it != unionDefByName.cend()) ? it.value() : 0;
|
||||
}
|
||||
|
||||
if (kind == TRK::LF_STRUCTURE || kind == TRK::LF_CLASS) {
|
||||
auto it = structDefByName.constFind(qname);
|
||||
return (it != structDefByName.cend()) ? it.value() : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t PdbCtx::importUDT(uint32_t typeIndex) {
|
||||
if (typeIndex < tt->firstIndex()) return 0;
|
||||
|
||||
@@ -576,7 +631,6 @@ void PdbCtx::importMemberType(uint32_t typeIndex, int offset, const QString& nam
|
||||
isFwd = pointeeRec->data.LF_CLASS.property.fwdref;
|
||||
|
||||
if (isFwd) {
|
||||
// Need to find the non-fwdref definition by name
|
||||
const char* typeName = nullptr;
|
||||
if (pointeeRec->header.kind == TRK::LF_UNION)
|
||||
typeName = leafName(pointeeRec->data.LF_UNION.data, unionLeafKind(pointeeRec->data.LF_UNION.data));
|
||||
@@ -584,28 +638,8 @@ void PdbCtx::importMemberType(uint32_t typeIndex, int offset, const QString& nam
|
||||
typeName = leafName(pointeeRec->data.LF_CLASS.data,
|
||||
pointeeRec->data.LF_CLASS.lfEasy.kind);
|
||||
|
||||
if (typeName) {
|
||||
// Linear scan for the definition (cached after first import)
|
||||
for (uint32_t ti = tt->firstIndex(); ti < tt->lastIndex(); ti++) {
|
||||
const auto* candidate = tt->get(ti);
|
||||
if (!candidate) continue;
|
||||
if (candidate->header.kind != pointeeRec->header.kind) continue;
|
||||
bool candidateFwd;
|
||||
const char* candidateName;
|
||||
if (candidate->header.kind == TRK::LF_UNION) {
|
||||
candidateFwd = candidate->data.LF_UNION.property.fwdref;
|
||||
candidateName = leafName(candidate->data.LF_UNION.data, unionLeafKind(candidate->data.LF_UNION.data));
|
||||
} else {
|
||||
candidateFwd = candidate->data.LF_CLASS.property.fwdref;
|
||||
candidateName = leafName(candidate->data.LF_CLASS.data,
|
||||
candidate->data.LF_CLASS.lfEasy.kind);
|
||||
}
|
||||
if (!candidateFwd && candidateName && strcmp(candidateName, typeName) == 0) {
|
||||
defIndex = ti;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t resolved = findUdtDefinitionIndex(pointeeRec->header.kind, typeName);
|
||||
if (resolved != 0) defIndex = resolved;
|
||||
}
|
||||
n.refId = importUDT(defIndex);
|
||||
} else if (pointeeRec->header.kind == TRK::LF_PROCEDURE ||
|
||||
@@ -638,27 +672,8 @@ void PdbCtx::importMemberType(uint32_t typeIndex, int offset, const QString& nam
|
||||
else
|
||||
typeName = leafName(rec->data.LF_CLASS.data, rec->data.LF_CLASS.lfEasy.kind);
|
||||
|
||||
if (typeName) {
|
||||
for (uint32_t ti = tt->firstIndex(); ti < tt->lastIndex(); ti++) {
|
||||
const auto* candidate = tt->get(ti);
|
||||
if (!candidate) continue;
|
||||
if (candidate->header.kind != rec->header.kind) continue;
|
||||
bool candidateFwd;
|
||||
const char* candidateName;
|
||||
if (candidate->header.kind == TRK::LF_UNION) {
|
||||
candidateFwd = candidate->data.LF_UNION.property.fwdref;
|
||||
candidateName = leafName(candidate->data.LF_UNION.data, unionLeafKind(candidate->data.LF_UNION.data));
|
||||
} else {
|
||||
candidateFwd = candidate->data.LF_CLASS.property.fwdref;
|
||||
candidateName = leafName(candidate->data.LF_CLASS.data,
|
||||
candidate->data.LF_CLASS.lfEasy.kind);
|
||||
}
|
||||
if (!candidateFwd && candidateName && strcmp(candidateName, typeName) == 0) {
|
||||
defIndex = ti;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t resolved = findUdtDefinitionIndex(rec->header.kind, typeName);
|
||||
if (resolved != 0) defIndex = resolved;
|
||||
}
|
||||
|
||||
uint64_t refId = importUDT(defIndex);
|
||||
|
||||
@@ -371,7 +371,6 @@ NodeTree importReclassXml(const QString& filePath, QString* errorMsg) {
|
||||
auto it = classIds.find(ref.className);
|
||||
if (it != classIds.end()) {
|
||||
tree.nodes[nodeIdx].refId = it.value();
|
||||
tree.invalidateIdCache();
|
||||
resolved++;
|
||||
} else {
|
||||
qDebug() << "[ImportXML] Unresolved ref:" << ref.className << "for node" << ref.nodeId;
|
||||
|
||||
@@ -1296,7 +1296,6 @@ NodeTree importFromSource(const QString& sourceCode, QString* errorMsg) {
|
||||
auto it = classIds.find(ref.className);
|
||||
if (it != classIds.end()) {
|
||||
tree.nodes[nodeIdx].refId = it.value();
|
||||
tree.invalidateIdCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user