Skip to content

Commit b3a00bf

Browse files
committed
Implement object IDs
1 parent 00c32e2 commit b3a00bf

File tree

1 file changed

+108
-7
lines changed

1 file changed

+108
-7
lines changed

gc/mmtk.c

Lines changed: 108 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,18 @@
22

33
#include <stdbool.h>
44

5+
#include "ruby/assert.h"
6+
57
#include "gc/gc.h"
68
#include "gc/gc_impl.h"
79
#include "gc/mmtk.h"
810

11+
struct objspace {
12+
st_table *id_to_obj_tbl;
13+
st_table *obj_to_id_tbl;
14+
unsigned long long next_object_id;
15+
};
16+
917
bool
1018
rb_mmtk_is_mutator(void)
1119
{
@@ -66,14 +74,24 @@ rb_gc_impl_objspace_alloc(void)
6674
MMTk_Builder *builder = mmtk_builder_default();
6775
mmtk_init_binding(builder, NULL, &ruby_upcalls);
6876

69-
return NULL;
77+
return calloc(1, sizeof(struct objspace));
7078
}
7179

72-
static st_table *obj_id_to_obj_table_alloc(void);
80+
static void objspace_obj_id_init(struct objspace *objspace);
7381

74-
void rb_gc_impl_objspace_init(void *objspace_ptr) { }
82+
void
83+
rb_gc_impl_objspace_init(void *objspace_ptr)
84+
{
85+
struct objspace *objspace = objspace_ptr;
7586

76-
void rb_gc_impl_objspace_free(void *objspace_ptr) { }
87+
objspace_obj_id_init(objspace);
88+
}
89+
90+
void
91+
rb_gc_impl_objspace_free(void *objspace_ptr)
92+
{
93+
free(objspace_ptr);
94+
}
7795

7896
void *
7997
rb_gc_impl_ractor_cache_alloc(void *objspace_ptr)
@@ -345,8 +363,85 @@ rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr)
345363
}
346364

347365
// Object ID
348-
VALUE rb_gc_impl_object_id(void *objspace_ptr, VALUE obj) { }
349-
VALUE rb_gc_impl_object_id_to_ref(void *objspace_ptr, VALUE object_id) { }
366+
static int
367+
object_id_cmp(st_data_t x, st_data_t y)
368+
{
369+
if (RB_TYPE_P(x, T_BIGNUM)) {
370+
return !rb_big_eql(x, y);
371+
}
372+
else {
373+
return x != y;
374+
}
375+
}
376+
377+
static st_index_t
378+
object_id_hash(st_data_t n)
379+
{
380+
return FIX2LONG(rb_hash((VALUE)n));
381+
}
382+
383+
#define OBJ_ID_INCREMENT (RUBY_IMMEDIATE_MASK + 1)
384+
#define OBJ_ID_INITIAL (OBJ_ID_INCREMENT)
385+
386+
static const struct st_hash_type object_id_hash_type = {
387+
object_id_cmp,
388+
object_id_hash,
389+
};
390+
391+
static void
392+
objspace_obj_id_init(struct objspace *objspace)
393+
{
394+
objspace->id_to_obj_tbl = st_init_table(&object_id_hash_type);
395+
objspace->obj_to_id_tbl = st_init_numtable();
396+
objspace->next_object_id = OBJ_ID_INITIAL;
397+
}
398+
399+
VALUE
400+
rb_gc_impl_object_id(void *objspace_ptr, VALUE obj)
401+
{
402+
struct objspace *objspace = objspace_ptr;
403+
404+
unsigned int lev = rb_gc_vm_lock();
405+
406+
VALUE id;
407+
if (st_lookup(objspace->obj_to_id_tbl, (st_data_t)obj, &id)) {
408+
RUBY_ASSERT(FL_TEST(obj, FL_SEEN_OBJ_ID));
409+
}
410+
else {
411+
RUBY_ASSERT(!FL_TEST(obj, FL_SEEN_OBJ_ID));
412+
413+
id = ULL2NUM(objspace->next_object_id);
414+
objspace->next_object_id += OBJ_ID_INCREMENT;
415+
416+
st_insert(objspace->obj_to_id_tbl, (st_data_t)obj, (st_data_t)id);
417+
st_insert(objspace->id_to_obj_tbl, (st_data_t)id, (st_data_t)obj);
418+
FL_SET(obj, FL_SEEN_OBJ_ID);
419+
}
420+
421+
rb_gc_vm_unlock(lev);
422+
423+
return id;
424+
}
425+
426+
VALUE
427+
rb_gc_impl_object_id_to_ref(void *objspace_ptr, VALUE object_id)
428+
{
429+
struct objspace *objspace = objspace_ptr;
430+
431+
VALUE obj;
432+
if (st_lookup(objspace->id_to_obj_tbl, object_id, &obj) &&
433+
!rb_gc_impl_garbage_object_p(objspace, obj)) {
434+
return obj;
435+
}
436+
437+
if (rb_funcall(object_id, rb_intern(">="), 1, ULL2NUM(objspace->next_object_id))) {
438+
rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not id value", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10)));
439+
}
440+
else {
441+
rb_raise(rb_eRangeError, "%+"PRIsVALUE" is recycled object", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10)));
442+
}
443+
}
444+
350445
// Statistics
351446
VALUE rb_gc_impl_set_measure_total_time(void *objspace_ptr, VALUE flag) { }
352447
VALUE rb_gc_impl_get_measure_total_time(void *objspace_ptr) { }
@@ -358,6 +453,12 @@ size_t rb_gc_impl_stat_heap(void *objspace_ptr, VALUE heap_name, VALUE hash_or_s
358453
// Miscellaneous
359454
size_t rb_gc_impl_obj_flags(void *objspace_ptr, VALUE obj, ID* flags, size_t max) { }
360455
bool rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr) { }
361-
bool rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE obj) { }
456+
457+
bool
458+
rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE obj)
459+
{
460+
return false;
461+
}
462+
362463
void rb_gc_impl_set_event_hook(void *objspace_ptr, const rb_event_flag_t event) { }
363464
void rb_gc_impl_copy_attributes(void *objspace_ptr, VALUE dest, VALUE obj) { }

0 commit comments

Comments
 (0)