Implemented GC methods for `StableApiDefinition` for TruffleRuby support.
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.
Looking at Truffle's failure I think they don't have a C API stub for impl_gc_writebarrier, impl_gc_writebarrier_unprotect.
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.
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.