rb-sys icon indicating copy to clipboard operation
rb-sys copied to clipboard

Implemented GC methods for `StableApiDefinition` for TruffleRuby support.

Open goyox86 opened this issue 1 year ago • 3 comments

Solves https://github.com/oxidize-rb/rb-sys/issues/447

Implemented:

  • StableApiDefinition::gc_adjust_memory_usage.
  • StableApiDefinition::gc_writebarrier.
  • StableApiDefinition::gc_writebarrier_unprotect.

Note:

I have to tweak the testing macros so it would allow multiple arguments for the data_builder, in the meanwhile I just expanded the macro and tweaked it manually.

goyox86 avatar Feb 06 '25 17:02 goyox86

Looking at Truffle's failure I think they don't have a C API stub for impl_gc_writebarrier, impl_gc_writebarrier_unprotect.

goyox86 avatar Feb 06 '25 17:02 goyox86

Sorry for the late reply, @nirvdrum pinged me today about this.

rb_gc_adjust_memory_usage() is defined on TruffleRuby so that one is fine.

For rb_gc_writebarrier() and rb_gc_writebarrier_unprotect() they are documented in https://github.com/ruby/ruby/blob/17f6a689629ec3507a79fc156833f329dc641bed/include/ruby/internal/gc.h#L660-L675 Copying it here for convenience:

/**
 * This  is  the  implementation  of  #RB_OBJ_WRITE().   People  don't  use  it
 * directly.
 *
 * @param[in]   old    An object that points to `young`.
 * @param[out]  young  An object that is referenced from `old`.
 */
void rb_gc_writebarrier(VALUE old, VALUE young);

/**
 * This is the  implementation of #RB_OBJ_WB_UNPROTECT().  People  don't use it
 * directly.
 *
 * @param[out] obj  An object that does not participate in WB.
 */
void rb_gc_writebarrier_unprotect(VALUE obj);

So those should not be called directly according to those docs, and instead RB_OBJ_WRITE/RB_OBJ_WB_UNPROTECT should be used. RB_OBJ_WRITE is supported on TruffleRuby. Can rb-sys use/expose that instead? If not, see https://github.com/oracle/truffleruby/blob/b3a2cec22635f55b74f350bc59a9fbcca0e4ac3e/lib/cext/include/ruby/internal/gc.h#L791-L805 i.e. TruffleRuby has an empty rb_obj_written() and so rb_gc_writebarrier() if it existed would be empty too.

RB_OBJ_WB_UNPROTECT is not yet supported on TruffleRuby, I believe because so far we have not found any extension using that (do you know any extension actually using it?). FWIW the docs of it:

/**
 * Asserts that the passed object is  not fenced by write barriers.  Objects of
 * such  property do  not contribute  to  generational GCs.   They are  scanned
 * always.
 *
 * @param[out]  x  An object that would not be protected by the barrier.
 */
#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__)

In general TruffleRuby currently never moves any native memory, and does not use a generational GC for it, so currently has no write barriers for writes in C extensions.

To be future-proof though it would be best to test if these functions exist (e.g. have_func('rb_gc_writebarrier') in extconf.rb). And if they don't then assuming they are empty are OK for write-barrier-related functions.

eregon avatar Mar 07 '25 19:03 eregon

Also don't hesitate to ping me and/or @andrykonchin on TruffleRuby-related issues in rb-sys. We are happy rb-sys has truffleruby in CI now and want to help to keep it there.

eregon avatar Mar 10 '25 12:03 eregon