You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
sizeof pre-header and slot count, catch-landing coverage census, and a unicodedata allocation leak (#1195)
* sizeof: count a type's slots as its variable tail
`object.__sizeof__` is `tp_basicsize + Py_SIZE(self) * tp_itemsize`, and the
`nitems` chain answered 0 for a type object, so every class reported its
basicsize alone. A type's variable tail is its `__slots__` member table, so
`Py_SIZE` is the slot count.
The pre-header half of this change is dropped: `#1174` added
`cpython_object_is_gc`, which ports `_PyObject_IS_GC` including the
`type_is_gc` refinement that answers with `Py_TPFLAGS_HEAPTYPE`, and so
already charges a statically declared type no collector header.
Assisted-by: Claude
* jit: verify catch-landing coverage end to end under PYRE_CATCH_LIVE_CENSUS
`catch_target_extra_ref_colors` exists so that every `catch_exception`
finds its landing Ref colors in the marker its owning Python PC resumes
at. The existing census counts the anchorless population; nothing
checked the property itself once the markers were final.
Add a pass that does, gated by the same knob: for each site, resolve the
owner PC, read the finished marker, and report any landing color missing
from it. Unreachable PCs are skipped -- their markers are cleared
wholesale, so an empty set there is correct.
Measured over 34 code objects of exception-shaped sources: 193 sites,
193 distinct owner PCs, 0 uncovered sites and 0 uncovered colors. The
per-PC anchor table in `derive_after_call_indices_from_sparse` keeps one
entry, which would drop a sibling site's colors, but no Python PC owns
more than one site -- `catch_exception` is emitted once per canraise
block exit and the extra catch links of a multi-exit block lower through
`make_exception_link`, which emits none. Recorded on that function.
Extract `catch_landing_ref_colors` so the new pass and the existing one
read a landing the same way.
Assisted-by: Claude
* Make implementation comments self-contained
* unicodedata: allocate the per-call result strings through the managed path
`category`, `bidirectional`, `east_asian_width`, `decomposition`, `name`
and `lookup` build a fresh string on every call and returned it through
`w_str_new`, whose value buffer comes from `malloc_raw` -- a buffer the
collector can never reclaim. Scanning a text one character at a time
accumulated one such buffer per call. `w_str_new_managed` allocates a GC
storage box when the interpreter collector and the value tid are both
live, and falls back to immortal otherwise.
The remaining `w_str_new` calls in the module stay: `unidata_version`
and its siblings are module constants built once per process, and the
others are in tests.
Assisted-by: Claude
* Remove stale and redundant implementation comments
* wasm: pin the recursive-CA counters to the recorded baseline and drop the module fallback
`recursive_call_assembler_does_not_refill_zeroed_nursery_frames` asserted
`compiles == 4` and `BRIDGE_OK == 3`. The committed
`pyre/bench/fib_recursive.wasm.jitstats` records `loops_compiled=1` and
`bridges_compiled=8` for the same bench, and `compiles` is the host's
module-compile tally over both, so it is 9; `BRIDGE_OK` and
`bridges_compiled` count the same event, since `diag_bump(5)` and
`self.stats.bridges_compiled += 1` both sit on the `Ok` side of
`compile_bridge`, so it is 8. `fannkuch_blackhole_helpers_do_not_reflect_through_the_host`
already follows that relation: its `compiles == 28` is `6 + 22` from
`fannkuch.wasm.jitstats`.
All six runtime tests picked `pyre_wasm.wasm` when
`pyre_wasm.wasm-host.wasm` was absent. `pyre-wasm` builds both its `web` and
`wasm-host` features to that one filename, so the fallback can load a `web`
module while the assertions pin wasm-host counters. They now read the
snapshot path only, through one helper.
Assisted-by: Claude
* cpython_tests: carry each failing case's exception line in the digest
`failure_digest` listed unittest's `FAIL:`/`ERROR:` headers, which name the
case but not the cause. A case that fails only on the CI host cannot be
re-run locally to find out, so the header alone left the run diagnosable
only by another CI cycle. Each header now carries the line its traceback
ended on, and the FAIL detail cap rises from 300 to 900 to fit four of them.
Assisted-by: Claude
* parity: cover a module name carrying a lone surrogate
`#1182` made `Module.w_name` a `PyObjectRef`, so a unit test round-tripping
the name through the pyre-object accessors now only restates what the type
already guarantees. The path that can still regress is the interpreter's:
`module.__init__` projecting the argument through `w_str_get_value` panics on
a lone surrogate, which is what the import machinery hands it whenever a
filename was decoded with surrogateescape.
Cover it where it lives, as a parity fixture over construction, `__init__`
re-seeding, `repr` and dict-key lookup. Verified against CPython and pypy3.
Assisted-by: Claude
* cpython_tests: report the last link of a chained traceback
`traceback_verdict` returned the first unindented line after the header, so a
test whose failure chained through `raise ... from` reported the inner cause
rather than the exception it actually failed with.
Taking the block's last unindented line instead would break the other shape:
an assertion failure prints its diff below the `AssertionError`, unindented.
Arm the search on each `Traceback` banner and let the next unindented line
answer for that link, so a chain's later links overwrite the earlier ones
while a diff below the answer is ignored.
Assisted-by: Claude
0 commit comments