aboutsummaryrefslogtreecommitdiffstats
path: root/.auto/parked/fast_pc_nums.patch
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-07 09:13:33 +0200
committeruser <user@clank>2026-08-07 09:13:33 +0200
commit0fc0b3a9d667f7f464939bce8bfdf4cd9cd889bb (patch)
treef8c30d42e79b683b2f7770f2caeecbedcaab22ae /.auto/parked/fast_pc_nums.patch
parentdecomp_map: memoise obj_id -> ea for the whole function instead of only compa... (diff)
downloadida-tui-0fc0b3a9d667f7f464939bce8bfdf4cd9cd889bb.tar.gz
ida-tui-0fc0b3a9d667f7f464939bce8bfdf4cd9cd889bb.tar.xz
ida-tui-0fc0b3a9d667f7f464939bce8bfdf4cd9cd889bb.zip
Park two proven-but-unresolvable F5-path optimisations, and record how to spot a counter-drift outlier
pc_nums allocated three ctree_item_t SWIG objects per candidate column -- the third instance of the same fault already fixed in decomp_map and found in decompile_function_safe. 1247 -> 614ms warm over 18991 lines of bash, identical literal counts, 0 mismatches over echo's 128 functions. Both it and the fast decompile_function_safe are parked rather than applied: together they are worth ~350ms against a run-to-run spread of ~500ms on this box (means 25045 with, 25140 without over seven runs), so the benchmark cannot resolve them. Neither adds complexity -- both remove allocations -- so they are kept on disk with their measurements for a per-operation-latency goal. Also records the 27283ms outlier: the work counters moved with it, which is how an outlier is told from a regression.
Diffstat (limited to '.auto/parked/fast_pc_nums.patch')
-rw-r--r--.auto/parked/fast_pc_nums.patch52
1 files changed, 52 insertions, 0 deletions
diff --git a/.auto/parked/fast_pc_nums.patch b/.auto/parked/fast_pc_nums.patch
new file mode 100644
index 0000000..f06bfe1
--- /dev/null
+++ b/.auto/parked/fast_pc_nums.patch
@@ -0,0 +1,52 @@
+diff --git a/server/patch_server.py b/server/patch_server.py
+index 6667e12..5e20671 100644
+--- a/server/patch_server.py
++++ b/server/patch_server.py
+@@ -1900,7 +1900,7 @@ def _idatui_lit_extent(plain, x):
+ return (lo, hi)
+
+
+-def _idatui_pc_nums(cf, sl):
++def _idatui_pc_nums(cf, sl, plain=None):
+ """Every number literal on one pseudocode line, as
+ [{x0, x1, ea, opnum, value, nbytes, fmt}].
+
+@@ -1912,16 +1912,26 @@ def _idatui_pc_nums(cf, sl):
+ import ida_lines
+ import idaapi
+
+- plain = ida_lines.tag_remove(sl.line)
++ # ``plain`` is the untagged line; callers that already have it pass it in
++ # rather than making tag_remove run twice over every line of the function.
++ if plain is None:
++ plain = ida_lines.tag_remove(sl.line)
+ out = []
+ x = 0
++ # One ctree_item_t for the whole line, and no head/tail at all. They are
++ # SWIG allocations in the innermost loop of a scan that probes every
++ # literal-looking character -- and 'a' to 'f' are hex digits, so `a1`, `v6`
++ # and `sub_1F4C0` all qualify and most columns of a line get probed. head
++ # and tail were never read. (Same three costs as decomp_map's sweep.)
++ item = ida_hexrays.ctree_item_t()
++ line = sl.line
++ get_line_item = cf.get_line_item
+ while x < len(plain):
+ ch = plain[x]
+ if ch not in _IDATUI_LIT_CHARS and ch != "'":
+ x += 1
+ continue
+- head, item, tail = (ida_hexrays.ctree_item_t() for _ in range(3))
+- if not cf.get_line_item(sl.line, x, True, head, item, tail):
++ if not get_line_item(line, x, True, None, item, None):
+ x += 1
+ continue
+ if item.citype != ida_hexrays.VDI_EXPR:
+@@ -1997,7 +2007,7 @@ def pc_nums(
+ for i in range(len(sv)):
+ plain = ida_lines.tag_remove(sv[i].line)
+ compact = _idatui_compact(plain)
+- for rec in _idatui_pc_nums(cf, sv[i]):
++ for rec in _idatui_pc_nums(cf, sv[i], plain):
+ out.append({
+ "line": i,
+ "x0": _idatui_compact_col(plain, compact, rec["x0"]),