Repository navigation
A constructor whose first field needs no barrier takes the barrier after each later store - #8474
Conversation
…ter each later store matz#8397 made the write-barrier pass rewrite a parenthesised statement, `((o)->f = v);` or a comma sequence of stores into one object as a Struct's or Data's `super(...)` writes its members, so that each store's barrier follows its value. It recognised the statement only from its first store. When that store needs no barrier, an Integer, Float or bool member or a nil, the pass steps over it, and the later reference store did not read as the start of a parenthesised statement: it took the expression wrapper, SP_WBO, which runs the barrier before the value is built. `super(a.size, a.chars)` in a Struct's initialize emitted `(self->iv_n = ..., SP_WBO(self)->iv_c = sp_str_chars(lv_a), 0);`. Built with gcc, the barrier ran first on the still young holder, the collection in the value's allocation promoted the holder, and the young value landed in it unrecorded: with SPINEL_GC_STRESS=2 the mark reached the freed value ("the mark reached a freed slot"), and with SPINEL_GC_STRESS=1 and SPINEL_GC_VERIFY=1 the collector reached a corrupt object; without the verifier, the test's constructors read back wrong members at SPINEL_GC_STRESS=1. Apple clang builds the value first and did not fail. wb_paren_stmt_bol finds the statement's start back over balanced groups, stepping over string and character literals whole (a bracket or a quote inside one is no group), and wb_paren_stmt_start accepts the stores before the current one when they write the same object and each ends at a top-level comma, so the whole sequence is rewritten from its first store. A barrier now follows only the stores the pass would barrier on their own (wb_seg_needs_barrier: a reference field given a value that can be young), where it followed every store. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Gate: green tree e21022a7189b master b8db3ca (darwin-arm64 clang-21.0.0) tests 6918/0
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk | ⚪ Minimal · up to
|
Probed at master
de67c22cf, macOS, Apple clang 21, and Linux, gcc on arm64.This follows up #8397 ("A store written as a parenthesised statement takes its write barrier after the value") and CodeRabbit's review thread on #8398 about reference stores after a skipped first store.
["x", "3", "9", "9"]/"y3"SPINEL_GC_STRESS=1SPINEL_GC_STRESS=1 SPINEL_GC_VERIFY=1SPINEL_GC_STRESS=2old=1The same at
-O0and-O1, with and without--share-strings. Apple clang builds the value before the barrier and does not fail.super(...)in aninitializeof its own writes the members as one parenthesised comma sequence:(self->iv_n = sp_str_length_m(lv_a), SP_WBO(self)->iv_c = sp_str_chars(lv_a), 0);.gc_wb_insert_segrecognised such a statement (wb_paren_stmt_start) only at its first store. A store that needs no barrier (an Integer, Float or bool member, a nil) is stepped over, and the later reference store, with text before it in the statement, took the expression wrapperSP_WBO, which C may run before the value is built.SPINEL_GC_STRESS=2on Linux.The sequence is found from the statement's start.
wb_paren_stmt_bolwalks back from the store over balanced groups (a statement expression in an earlier value among them) to the;,{,}or line end at the store's depth. It steps over a string or character literal whole, back to its opening quote (one with an even number of backslashes before it), so a bracket or a quote inside a literal, assuper("#{a})".size, ...)emits, is no group.wb_paren_stmt_startthen accepts, after the opening parentheses, the stores before the current one when each writes the same object and ends at a top-level comma (wb_stores_one_object), and the whole statement is rewritten from its first store, as #8397 rewrites one that starts with a reference store.A barrier follows each store that needs one.
wb_put_stores_barrieredput a barrier after every store of the sequence; it now asks each store what the pass asks of a store on its own (wb_seg_needs_barrier: a reference field of the holder's class, given a value that can be young), so an Integer member or a nil store takes none.Generated C. Of the 527 programs in
test/that callsuper(,Struct.neworinstance_variable_set, these change, the same in both builds, and only in asuper(...)member sequence:data_new_positional_keyword_init,data_super_kwarg,struct_bare_super_initialize,struct_custom_initialize_super,struct_initialize_forwarding_superandstruct_super_member_nil_defaulttake the rewritten sequence, with a barrier after each reference store, where a later reference store hadSP_WBO;string_handle_initialize's sequence, already rewritten, drops the barrier that followed its Integer member. optcarrot's generated C is unchanged in both builds.The corpus runs come from the local
make gatebelow (this branch merged with masterb8db3cafd, macOS arm64, clang 21); the corpus-wide C diff was not run.Tests.
test/gc_barrier_paren_store.rbgains constructors whose first member is an Integer, a Float, a bool or an Integer computed in a statement expression, followed by a String built by a method that allocates objects, an object or an Array, and three whose earlier value's C holds a string literal with a bracket, a quote and an escaped quote, or a trailing backslash, built 60 times beside a churning loop. Built with gcc it failed on master atSPINEL_GC_STRESS1 (wrong members; withSPINEL_GC_VERIFY=1the verifier abort) and 2, at-O0and-O1, in both builds. With this change it passes there and under Apple clang, atSPINEL_GC_STRESS0, 1 and 2, with and withoutSPINEL_GC_VERIFY=1. The other changed programs pass in both builds at-O0and-O1,SPINEL_GC_STRESS0, 1 and 2 withSPINEL_GC_VERIFY=1.make reject-test,make infer-test,make gc-stress-test,make share-strings-testandtools/refusals.shpass. In that gatemake testpasses (6918 pass, 0 fail, 0 error) and the corpus with sharing on has 6917 pass, 1 known failure (already listed intest/share/known-failures.txt) and 0 new failures.make gate(on this branch merged with current master)Local
make gateon this branch merged with masterb8db3cafd(macOS arm64, clang 21); the head commit carries its Gate trailer..expectedfiles that match CRuby 4.0 run with--enable-frozen-string-literal# spinel: int64🤖 Generated with Claude Code
Summary by CodeRabbit