codegen: inline 1-byte tag fast path at decode call sites Hoists wire.decode_tag's 1-byte fast path into every generated M.X_decode while-loop, falling back to the helper for multi-byte tags (field ids > 15). The 1-byte case covers every protobuf field with id 1..15 and is the dominant decode dispatch in real payloads. Header now localizes string.byte, bit.band, and bit.rshift so the inlined ops compile to straight local calls. Bench (Person full decode, msgs/s, median-of-3 vs proper post-h8v 3-run baseline): 10B +14.7%, 100B +8.9%, 1KB +7.5%, 10KB +7.0%, 100KB +8.5%. Full encode is flat to small (-0.1% to -2.6%) at large sizes, plausibly from header-upvalue layout. JIT trace gate: 37/37, all bridges still 0. Tests: 745/745. Also documented in bench/PERF_LOG.md, including the methodology note that h8v's earlier numbers used single-run baselines and are therefore ~3-5% optimistic; medians-of-3 are the standard now. beads-tarantool-protobuf-4kj
bench: record gcy (inline nested-message decode) post-mortem Implemented and benchmarked the inline-nested-decode plan from tarantool-protobuf-gcy. Test suite and JIT gate both pass, but median-of-3 bench shows 3-8% regressions on Person 1KB/10KB/100KB encode AND decode. Profile's "100% interpreter bail at Address_decode call" turned out to be a vl trace-attribution artifact; LuaJIT was already handling the call well. Lesson recorded in bench/PERF_LOG.md so the next person who reads the profile entry knows the obvious-looking inline transformation does not deliver here. Code change reverted; only the writeup lands. beads-tarantool-protobuf-gcy
codegen: inline 1-byte varint length prefix at every LEN emit site Eliminates the wire.encode_varint(#body) call + dispatch for every length-delimited field in mode=full codegen. Profile flagged the out[n] = wire.encode_varint(#_b) line as ~33% of hello.Person 1KB encode time, with another ~17% in encode_varint dispatch — together ~50% of encode time. Lifting the 1-byte fast path (the dominant case for proto strings and small message bodies) to the call site removes the function frame entirely for lengths < 128. Applied at every LEN emit site: singular/repeated message body, singular/repeated string|bytes, packed scalar bundle, packed enum bundle, map entry. Map value pieces (emitMapPiece message branch) left as-is — they sit inside a single slot assignment that would require a deeper restructure, and maps are not on the current hot benchmark. Results (hello.Person full encode, msgs/s): 10B +6.9%, 100B +7.9%, 1KB +25.7%, 10KB +48.1%, 100KB +31.9%. Decode flat (unchanged path). Runtime mode flat (descriptor dispatch still calls encode_varint). JIT trace gate: 37/37. Test suite: 745/745. Bench history saved to bench/PERF_LOG.md with full numbers and the workflow this iteration follows. beads-tarantool-protobuf-h8v