Skip to content

Commit 24f260b

Browse files
committed
Enable copying GC for MMTk
1 parent ac5f13d commit 24f260b

File tree

4 files changed

+70
-7
lines changed

4 files changed

+70
-7
lines changed

gc.c

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,11 +1346,24 @@ static inline void gc_prof_sweep_timer_stop(rb_objspace_t *);
13461346
static inline void gc_prof_set_malloc_info(rb_objspace_t *);
13471347
static inline void gc_prof_set_heap_info(rb_objspace_t *);
13481348

1349+
1350+
#if USE_MMTK
1351+
static inline VALUE rb_mmtk_maybe_forward(VALUE object);
1352+
1353+
#define TYPED_UPDATE_IF_MOVED(_objspace, _type, _thing) do { \
1354+
if (rb_mmtk_enabled_p()) { \
1355+
*(_type *)&(_thing) = (_type)rb_mmtk_maybe_forward((VALUE)(_thing)); \
1356+
} else if (gc_object_moved_p((_objspace), (VALUE)(_thing))) { \
1357+
*(_type *)&(_thing) = (_type)RMOVED(_thing)->destination; \
1358+
} \
1359+
} while (0)
1360+
#else
13491361
#define TYPED_UPDATE_IF_MOVED(_objspace, _type, _thing) do { \
13501362
if (gc_object_moved_p((_objspace), (VALUE)(_thing))) { \
13511363
*(_type *)&(_thing) = (_type)RMOVED(_thing)->destination; \
13521364
} \
13531365
} while (0)
1366+
#endif
13541367

13551368
#define UPDATE_IF_MOVED(_objspace, _thing) TYPED_UPDATE_IF_MOVED(_objspace, VALUE, _thing)
13561369

@@ -3607,15 +3620,40 @@ cc_table_mark_i(ID id, VALUE ccs_ptr, void *data_ptr)
36073620
VM_ASSERT(id == ccs->cme->called_id);
36083621

36093622
if (METHOD_ENTRY_INVALIDATED(ccs->cme)) {
3623+
#if USE_MMTK
3624+
if (!rb_mmtk_enabled_p()) {
3625+
// NOTE:
3626+
// Vanilla Ruby assumes no objects are moved during marking phase,
3627+
// and attempts to clean-up invalidated method entries during marking.
3628+
// This doesn't work with MMTk.
3629+
// With an evacuating GC algorithm (such as Immix),
3630+
// children of `ccs` may have been moved during tracing.
3631+
// But the code in `rb_vm_ccs_free` reads many VALUE fields without calling `gc_location`
3632+
// which obviously isn't needed for the non-moving marking phase.
3633+
// We temporarily disable this call for now.
3634+
// FIXME: Clean up method entries properly using the weak reference processing mechanism.
3635+
#endif
36103636
rb_vm_ccs_free(ccs);
3637+
#if USE_MMTK
3638+
}
3639+
#endif
36113640
return ID_TABLE_DELETE;
36123641
}
36133642
else {
36143643
gc_mark(data->objspace, (VALUE)ccs->cme);
36153644

36163645
for (int i=0; i<ccs->len; i++) {
3646+
#if USE_MMTK
3647+
if (!rb_mmtk_enabled_p()) {
3648+
// Type info are stored on the heap, too.
3649+
// With evacuating GC, they may have been moved, too.
3650+
// It is not safe to inspect reference fields during tracing.
3651+
#endif
36173652
VM_ASSERT(data->klass == ccs->entries[i].cc->klass);
36183653
VM_ASSERT(vm_cc_check_cme(ccs->entries[i].cc, ccs->cme));
3654+
#if USE_MMTK
3655+
}
3656+
#endif
36193657

36203658
gc_mark(data->objspace, (VALUE)ccs->entries[i].ci);
36213659
gc_mark(data->objspace, (VALUE)ccs->entries[i].cc);
@@ -11046,10 +11084,6 @@ check_id_table_move(VALUE value, void *data)
1104611084
return ID_TABLE_CONTINUE;
1104711085
}
1104811086

11049-
#if USE_MMTK
11050-
static inline VALUE rb_mmtk_maybe_forward(VALUE object);
11051-
#endif
11052-
1105311087
/* Returns the new location of an object, if it moved. Otherwise returns
1105411088
* the existing location. */
1105511089
VALUE
@@ -15855,9 +15889,7 @@ rb_mmtk_scan_object_ruby_style(MMTk_ObjectReference object)
1585515889

1585615890
rb_objspace_t *objspace = &rb_objspace;
1585715891
gc_mark_children(objspace, obj);
15858-
15859-
// TODO: Enable the following line later.
15860-
//gc_update_object_references(objspace, obj);
15892+
gc_update_object_references(objspace, obj);
1586115893
}
1586215894

1586315895
// This is used to determine the pinning fields of potential pinning parents (PPPs).
@@ -16173,6 +16205,7 @@ rb_mmtk_update_global_weak_tables(void)
1617316205
MMTk_RubyUpcalls ruby_upcalls = {
1617416206
rb_mmtk_init_gc_worker_thread,
1617516207
rb_mmtk_get_gc_thread_tls,
16208+
rb_mmtk_is_mutator,
1617616209
rb_mmtk_stop_the_world,
1617716210
rb_mmtk_resume_mutators,
1617816211
rb_mmtk_block_for_gc,

iseq.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,24 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
312312

313313
const struct rb_callcache *cc = cds[i].cc;
314314
if (cc) {
315+
#if USE_MMTK
316+
// vm_empty_cc is an off-heap object, but has the layout of a heap object.
317+
// In vanilla Ruby, rb_gc_location looks at the header to see if it is T_MOVED.
318+
// Since vm_empty_cc is not T_MOVED, it treats it like an un-moved object.
319+
// But MMTk will think it is not a heap object and will crash.
320+
// We simply skip it if cc is vm_empty_cc.
321+
if (!rb_mmtk_enabled_p() || cc != rb_vm_empty_cc()) {
322+
#endif
323+
#if USE_MMTK
324+
if (rb_mmtk_enabled_p() || reference_updating) {
325+
// Note: With an evacuating collector (such as Immix),
326+
// the object (for example, the `cc` below) is moved whenever we trace it,
327+
// and there is not any distinct "mark phase" where objects do not move.
328+
// So because we look at the contents of `cc` below,
329+
// we must always prepare for the possibility that `cc` may be moved.
330+
#else
315331
if (reference_updating) {
332+
#endif
316333
cc = (const struct rb_callcache *)rb_gc_location((VALUE)cc);
317334
}
318335

@@ -331,6 +348,9 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
331348
cds[i].cc = rb_vm_empty_cc();
332349
}
333350
}
351+
#if USE_MMTK
352+
}
353+
#endif
334354
}
335355
}
336356
}

mmtk.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ typedef struct MMTk_GCThreadTLS {
5757
typedef struct MMTk_RubyUpcalls {
5858
void (*init_gc_worker_thread)(struct MMTk_GCThreadTLS *gc_worker_tls);
5959
struct MMTk_GCThreadTLS *(*get_gc_thread_tls)(void);
60+
bool (*is_mutator)(void);
6061
void (*stop_the_world)(MMTk_VMWorkerThread tls);
6162
void (*resume_mutators)(MMTk_VMWorkerThread tls);
6263
void (*block_for_gc)(MMTk_VMMutatorThread tls);

vm.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3132,6 +3132,11 @@ rb_execution_context_update(rb_execution_context_t *ec)
31323132

31333133
while (cfp != limit_cfp) {
31343134
const VALUE *ep = cfp->ep;
3135+
3136+
#if USE_MMTK
3137+
if (!rb_mmtk_enabled_p() || VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
3138+
#endif
3139+
31353140
cfp->self = rb_gc_location(cfp->self);
31363141
cfp->iseq = (rb_iseq_t *)rb_gc_location((VALUE)cfp->iseq);
31373142
cfp->block_code = (void *)rb_gc_location((VALUE)cfp->block_code);
@@ -3148,6 +3153,10 @@ rb_execution_context_update(rb_execution_context_t *ec)
31483153
}
31493154
}
31503155

3156+
#if USE_MMTK
3157+
}
3158+
#endif
3159+
31513160
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
31523161
}
31533162
}

0 commit comments

Comments
 (0)