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
{{ message }}
Repository navigation
The #7850 probe family has moved to the property-get IC-miss tail: get_field_by_name_tail probes 4 registries before reading the GcHeader it then switches on (1.8% of pipeline_big) #7867
object::field_get_set::get_field_by_name_tail — the by-name property-get IC-miss tail —
runs four address-keyed side-registry probes before it reads the GcHeader, and then reads that header anyway and switches on it for the rest of the function:
:246 buffer::is_registered_buffer(obj)
:403 typedarray::lookup_typed_array_kind(obj)
:467 set::is_registered_set(obj)
:517 symbol::is_registered_symbol(obj) <-- process-global Mutex + SipHash
:543 let gc_type = (*gc_header).obj_type; <-- and from here it is all obj_type
:709 if gc_type == GC_TYPE_ERROR ...
:892 if gc_type == GC_TYPE_ARRAY ...
:1006 if gc_type == GC_TYPE_STRING ...
:1086 if gc_type == GC_TYPE_MAP || gc_type == GC_TYPE_SET <-- done the right way
:1099 if gc_type == GC_TYPE_OBJECT && regex::is_regex_pointer(obj)
The same file already contains both idioms: the Map/Set arm at :1086 is header-directed,
while the Set probe at :467 and the Symbol probe at :517 are not. is_registered_set
ends in obj_type == GC_TYPE_SET (set.rs:262) and alloc_symbol uses gc_malloc(_, GC_TYPE_STRING), so the header can rule both out for free — the same
argument as #7474 / #7765 / #7850.
Measurement — this is where the #7850 family actually lives now
Every single is_registered_symbol_slow sample in the profile comes from that chain. Zero come from native_call_method::gc_pointer_and_type_from_value, which is where #7850 measured 6.5% before #7852 landed — that PR removed pipeline's
generic-specialization miss, and the dynamic-dispatch load the probe was riding
disappeared with it (pipeline 0.483 s → 0.274 s on the quiet mini). The family did not
go away; it moved from the method-dispatch path to the property-get miss path.
Caveat, stated because this family has produced vacuous numbers before: the profile above
was taken on a contended dev machine, so it is attribution, not a timing claim. The
absolute cost must be re-measured on the quiet mini before anyone sizes a fix from it,
and the cost is workload-dependent by construction — it scales with IC misses, not
with property reads.
Why this is more delicate than #7850 and needs its own PR
get_field_by_name_tail is ~1500 lines on the hottest path in the runtime, and the
ordering is load-bearing in places: small Buffer allocations carry noGcHeader,
so the buffer and typed-array probes at :246/:403 cannot be moved behind a header
read; and is_registered_set documents (set.rs) that probing addr - 8 for an
arbitrary above-band candidate segfaults on Linux where freed pages get unmapped. A fix
should therefore gate only the Set (:467) and Symbol (:517) probes on the header the
function already reads at :543, leaving the headerless kinds where they are.
For the Symbol probe specifically, #7850 added symbol::may_be_symbol_header(ptr) — a
single 4-byte SYMBOL_MAGIC load that is exact in the false direction and covers both gc_malloc'd and Box-leaked symbols. That is the piece this site needs, and it already
exists.
Found while fixing #7850. Sibling: #7865 (js_dyn_index_get / js_dyn_index_set).
Activity