Skip to content

Implement compaction and embedded structs#201

Merged
kou merged 1 commit intoruby:masterfrom
byroot:embedded
Mar 31, 2026
Merged

Implement compaction and embedded structs#201
kou merged 1 commit intoruby:masterfrom
byroot:embedded

Conversation

@byroot
Copy link
Copy Markdown
Member

@byroot byroot commented Mar 30, 2026

GC compaction was introduced in Ruby 2.7.

Embedded Structs was introduced in Ruby 3.3. When enabled, the struct strscanner is stored directly inside the object slot, meaning reading the struct member doesn't require loading another memory region.

GC compaction was introduced in Ruby 2.7.

Embedded Structs was introduced in Ruby 3.3.
When enabled, the `struct strscanner` is stored
direclty inside the object slot, meaning reading
the struct member doesn't require loading another
memory region.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the strscan C extension to better support Ruby’s moving GC (compaction, introduced in Ruby 2.7) and to take advantage of Ruby 3.3’s embedded typed data for StringScanner’s internal struct strscanner.

Changes:

  • Add GC compaction support via movable marking and a dcompact callback that relocates internal VALUE references.
  • Enable embedded typed data for struct strscanner (when supported) and adjust free/memsize behavior accordingly.
  • Extend extconf.rb feature detection for rb_gc_location and RUBY_TYPED_EMBEDDABLE.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
ext/strscan/strscan.c Adds movable marking + compaction relocation, enables embeddable typed data flag, and adjusts free/memsize.
ext/strscan/extconf.rb Detects rb_gc_location and RUBY_TYPED_EMBEDDABLE support at build time.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +187 to +193
#else
# ifdef HAVE_CONST_RUBY_TYPED_EMBEDDABLE
# define RUBY_TYPED_EMBEDDABLE RUBY_TYPED_EMBEDDABLE
# define HAVE_RUBY_TYPED_EMBEDDABLE 1
# else
# define RUBY_TYPED_EMBEDDABLE 0
# endif
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HAVE_CONST_RUBY_TYPED_EMBEDDABLE branch defines RUBY_TYPED_EMBEDDABLE as itself (#define RUBY_TYPED_EMBEDDABLE RUBY_TYPED_EMBEDDABLE), which is effectively a no-op and can be confusing (and may trigger self-referential macro warnings on some toolchains). Since have_const("RUBY_TYPED_EMBEDDABLE") already tells you whether the identifier exists, consider simplifying this detection to only define HAVE_RUBY_TYPED_EMBEDDABLE (and otherwise #define RUBY_TYPED_EMBEDDABLE 0) without redefining the constant name.

Suggested change
#else
# ifdef HAVE_CONST_RUBY_TYPED_EMBEDDABLE
# define RUBY_TYPED_EMBEDDABLE RUBY_TYPED_EMBEDDABLE
# define HAVE_RUBY_TYPED_EMBEDDABLE 1
# else
# define RUBY_TYPED_EMBEDDABLE 0
# endif
#elif defined(HAVE_CONST_RUBY_TYPED_EMBEDDABLE)
# define HAVE_RUBY_TYPED_EMBEDDABLE 1
#else
# define RUBY_TYPED_EMBEDDABLE 0

Copilot uses AI. Check for mistakes.
Comment on lines +196 to 214
#ifdef HAVE_RB_GC_LOCATION
static void
strscan_compact(void *ptr)
{
struct strscanner *p = ptr;
p->str = rb_gc_location(p->str);
p->regex = rb_gc_location(p->regex);
}
#else
#define rb_gc_mark_movable rb_gc_mark
#endif

static void
strscan_mark(void *ptr)
{
struct strscanner *p = ptr;
rb_gc_mark(p->str);
rb_gc_mark(p->regex);
rb_gc_mark_movable(p->str);
rb_gc_mark_movable(p->regex);
}
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new dcompact callback and rb_gc_mark_movable usage changes object marking semantics under compaction. Please add a regression test that exercises StringScanner across GC.compact (e.g., create a scanner, perform a scan to set internal state, call GC.compact, then assert subsequent scans and match data still behave correctly) so failures in dcompact/movable marking are caught in CI.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

@kou kou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@kou kou merged commit a018cbe into ruby:master Mar 31, 2026
47 checks passed
matzbot pushed a commit to ruby/ruby that referenced this pull request Mar 31, 2026
(ruby/strscan#201)

GC compaction was introduced in Ruby 2.7.

Embedded Structs was introduced in Ruby 3.3. When enabled, the `struct
strscanner` is stored directly inside the object slot, meaning reading
the struct member doesn't require loading another memory region.

ruby/strscan@a018cbe40e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants