InsnLocator built its instruction-verify pattern with an atomic group
(?>(?:...)*). Atomic groups are python 3.11+ syntax, but pyproject and
the published wheel both declare requires-python >=3.10. On 3.10
re.compile raises re.error("unknown extension ?>") while the class
attribute is being built, so every findrefs search and getclass
decompile fails before touching the DEX.
The atomic group is a real optimisation - it stops the greedy star from
backtracking over instruction ranges that fail to verify, which is the
common case on a real DEX - so it is kept where the interpreter
understands it and only the 3.10 fallback drops it. Measured on the
supplied reference DEX, replacing it unconditionally costs about 5% on
the gated field_ref_scan metric, so this is not a plain deletion.
Refs #20
- code_item_scan: match the opcode and the referenced idx high byte in one C-level
regex pass, so Python only inspects surviving candidates; bytes.translate + bigint
prefilter for dense opcode classes.
- apk_handler: on-demand partial Deflate inflation for getclass, precise-class
pre-flight, one-shot inflation, fork-based process pool.
- decompiler: startup stubs only for modules that are not already imported.
CI comparison (paired, --samples 31 vs dev-0.1.0): unit/code_scan -84.8%,
unit/field_ref_scan -70.2%, unit/method_ref_scan -68.3%,
cli_findrefs -44.8%, cli_getclass -6.7%.
All gated metrics pass.
misalignment.
The fix makes the class's own declared fields occupy the leading slots of the new field table, ordered by original field_idx ascending, so that four orderings agree: bytecode field operands, the new field table, the class_data declaration order, and the static_values array. The rule is defined once in IndexHandler.preregister_own_fields() and mirrored by DexIndexMapper; DexBuilder then simply trusts the table order instead of re-sorting.