Skip to content

Commit b56237c

Browse files
committed
Add pointer indirection for write barrier calls
This commit sets a function pointer on object space and switches the write barrier function during incremental marking. This means we can eliminate a branch call at the price of indirection.
1 parent 25049e9 commit b56237c

File tree

1 file changed

+35
-14
lines changed

1 file changed

+35
-14
lines changed

gc.c

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,8 @@ enum gc_mode {
497497
gc_mode_sweeping
498498
};
499499

500+
typedef void (*gc_writebarrier)(VALUE a, VALUE b, struct rb_objspace *objspace);
501+
500502
typedef struct rb_objspace {
501503
struct {
502504
size_t limit;
@@ -637,6 +639,8 @@ typedef struct rb_objspace {
637639
#if GC_DEBUG_STRESS_TO_CLASS
638640
VALUE stress_to_class;
639641
#endif
642+
643+
gc_writebarrier wb;
640644
} rb_objspace_t;
641645

642646

@@ -813,6 +817,8 @@ int ruby_gc_debug_indent = 0;
813817
VALUE rb_mGC;
814818
int ruby_disable_gc = 0;
815819

820+
static void
821+
gc_set_incremental_marking(rb_objspace_t *objspace, int incremental);
816822
void rb_iseq_mark(const rb_iseq_t *iseq);
817823
void rb_iseq_free(const rb_iseq_t *iseq);
818824

@@ -1309,6 +1315,7 @@ rb_objspace_alloc(void)
13091315
#else
13101316
rb_objspace_t *objspace = &rb_objspace;
13111317
#endif
1318+
gc_set_incremental_marking(objspace, is_incremental_marking(objspace));
13121319
malloc_limit = gc_params.malloc_limit_min;
13131320

13141321
return objspace;
@@ -5404,7 +5411,7 @@ gc_marks_finish(rb_objspace_t *objspace)
54045411
}
54055412
#endif
54065413

5407-
objspace->flags.during_incremental_marking = FALSE;
5414+
gc_set_incremental_marking(objspace, FALSE);
54085415
/* check children of all marked wb-unprotected objects */
54095416
gc_marks_wb_unprotected_objects(objspace);
54105417
}
@@ -5883,6 +5890,30 @@ gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace)
58835890
}
58845891
}
58855892
}
5893+
5894+
static void
5895+
gc_non_incremental_wb(VALUE a, VALUE b, rb_objspace_t *objspace)
5896+
{
5897+
if (!RVALUE_OLD_P(a) || RVALUE_OLD_P(b)) {
5898+
return;
5899+
}
5900+
else {
5901+
gc_writebarrier_generational(a, b, objspace);
5902+
}
5903+
}
5904+
5905+
static void
5906+
gc_set_incremental_marking(rb_objspace_t *objspace, int incremental)
5907+
{
5908+
if(incremental) {
5909+
objspace->wb = gc_writebarrier_incremental;
5910+
} else {
5911+
objspace->wb = gc_non_incremental_wb;
5912+
}
5913+
5914+
objspace->flags.during_incremental_marking = incremental;
5915+
}
5916+
58865917
#else
58875918
#define gc_writebarrier_incremental(a, b, objspace)
58885919
#endif
@@ -5895,17 +5926,7 @@ rb_gc_writebarrier(VALUE a, VALUE b)
58955926
if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(a)) rb_bug("rb_gc_writebarrier: a is special const");
58965927
if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(b)) rb_bug("rb_gc_writebarrier: b is special const");
58975928

5898-
if (!is_incremental_marking(objspace)) {
5899-
if (!RVALUE_OLD_P(a) || RVALUE_OLD_P(b)) {
5900-
return;
5901-
}
5902-
else {
5903-
gc_writebarrier_generational(a, b, objspace);
5904-
}
5905-
}
5906-
else { /* slow path */
5907-
gc_writebarrier_incremental(a, b, objspace);
5908-
}
5929+
(*objspace->wb)(a, b, objspace);
59095930
}
59105931

59115932
void
@@ -6356,10 +6377,10 @@ gc_start(rb_objspace_t *objspace, const int full_mark, const int immediate_mark,
63566377

63576378
#if GC_ENABLE_INCREMENTAL_MARK
63586379
if (!GC_ENABLE_INCREMENTAL_MARK || objspace->flags.dont_incremental || immediate_mark) {
6359-
objspace->flags.during_incremental_marking = FALSE;
6380+
gc_set_incremental_marking(objspace, FALSE);
63606381
}
63616382
else {
6362-
objspace->flags.during_incremental_marking = do_full_mark;
6383+
gc_set_incremental_marking(objspace, do_full_mark);
63636384
}
63646385
#endif
63656386

0 commit comments

Comments
 (0)