Skip to content

Commit 88a7b78

Browse files
authored
Merge pull request mruby#6560 from mruby/set-gc-marking-v2
2 parents 4e08fae + a6a0346 commit 88a7b78

7 files changed

Lines changed: 92 additions & 19 deletions

File tree

include/mruby/internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ mrb_value mrb_as_rational(mrb_state *mrb, mrb_value x);
133133
void mrb_rational_copy(mrb_state *mrb, mrb_value x, mrb_value y);
134134
int mrb_rational_mark(mrb_state *mrb, struct RBasic *rat);
135135
#endif
136+
#ifdef MRB_USE_SET
137+
size_t mrb_gc_mark_set(mrb_state *mrb, struct RBasic *set);
138+
void mrb_gc_free_set(mrb_state *mrb, struct RBasic *set);
139+
size_t mrb_set_memsize(mrb_value);
140+
#endif
136141

137142
#ifdef MRUBY_PROC_H
138143
struct RProc *mrb_closure_new(mrb_state*, const mrb_irep*);

include/mruby/value.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
163163
f(MRB_TT_COMPLEX, struct RComplex, "Complex") \
164164
f(MRB_TT_RATIONAL, struct RRational, "Rational") \
165165
f(MRB_TT_BIGINT, struct RBigint, "Integer") \
166-
f(MRB_TT_BACKTRACE, struct RBacktrace, "backtrace")
166+
f(MRB_TT_BACKTRACE, struct RBacktrace, "backtrace") \
167+
f(MRB_TT_SET, struct RSet, "Set")
167168

168169
enum mrb_vtype {
169170
#define MRB_VTYPE_DEFINE(tt, type, name) tt,

mrbgems/mruby-bin-mrbc/tools/mrbc/stub.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,16 @@ int mrb_rational_mark(mrb_state *mrb, struct RBasic *x)
8181
return 2;
8282
}
8383
#endif
84+
85+
#ifdef MRB_USE_SET
86+
size_t mrb_gc_mark_set(mrb_state *mrb, struct RBasic *obj)
87+
{
88+
/* stub for mrbc */
89+
return 0;
90+
}
91+
92+
void mrb_gc_free_set(mrb_state *mrb, struct RBasic *obj)
93+
{
94+
/* stub for mrbc */
95+
}
96+
#endif

mrbgems/mruby-os-memsize/src/memsize.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj)
156156
size += mrb_objspace_page_slot_size();
157157
#endif
158158
break;
159+
#if defined(MRB_USE_SET)
160+
case MRB_TT_SET:
161+
size += mrb_set_memsize(obj);
162+
break;
163+
#endif
159164
case MRB_TT_BIGINT:
160165
#if defined(MRB_USE_BIGINT)
161166
size += mrb_bint_memsize(obj);

mrbgems/mruby-set/mrbgem.rake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
MRuby::Gem::Specification.new('mruby-set') do |spec|
22
spec.license = 'MIT'
33
spec.authors = 'yui-knk'
4+
spec.build.defines << "MRB_USE_SET"
45

56
spec.add_dependency "mruby-hash-ext", :core => "mruby-hash-ext"
67
spec.add_dependency "mruby-enumerator", :core => "mruby-enumerator"

mrbgems/mruby-set/src/set.c

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
KHASH_DECLARE(set, mrb_value, char, FALSE)
2020
KHASH_DEFINE(set, mrb_value, char, FALSE, mrb_obj_hash_code, mrb_eql)
2121

22+
struct RSet {
23+
MRB_OBJECT_HEADER;
24+
khash_t(set) *kh;
25+
};
26+
2227
static void
2328
set_copy_elements(mrb_state *mrb, khash_t(set) *target_kh, khash_t(set) *source_kh)
2429
{
@@ -31,31 +36,60 @@ set_copy_elements(mrb_state *mrb, khash_t(set) *target_kh, khash_t(set) *source_
3136
}
3237
}
3338

34-
#define SET_KHASH_IV MRB_SYM(khash)
35-
39+
#define mrb_set_ptr(o) ((struct RSet*)mrb_obj_ptr(o))
3640
static void
37-
set_free(mrb_state *mrb, void *ptr)
41+
set_set_khash(mrb_state *mrb, mrb_value self, khash_t(set) *kh)
3842
{
39-
khash_t(set) *kh = (khash_t(set)*)ptr;
40-
if (kh) {
41-
kh_destroy(set, mrb, kh);
42-
}
43+
mrb_check_type(mrb, self, MRB_TT_SET);
44+
struct RSet *set = mrb_set_ptr(self);
45+
set->kh = kh;
4346
}
4447

45-
static const struct mrb_data_type set_data_type = {
46-
"Set", set_free
47-
};
48+
static khash_t(set) *
49+
set_get_khash(mrb_state *mrb, mrb_value self)
50+
{
51+
mrb_check_type(mrb, self, MRB_TT_SET);
52+
return mrb_set_ptr(self)->kh;
53+
}
4854

49-
static void
50-
set_set_khash(mrb_state *mrb, mrb_value self, khash_t(set) *kh)
55+
/* Mark function for Set instances */
56+
size_t
57+
mrb_gc_mark_set(mrb_state *mrb, struct RBasic *obj)
5158
{
52-
mrb_data_init(self, kh, &set_data_type);
59+
struct RSet *s = (struct RSet*)obj;
60+
khash_t(set) *kh = s->kh;
61+
if (!kh) return 0;
62+
63+
KHASH_FOREACH(mrb, kh, k) {
64+
if (kh_exist(kh, k)) {
65+
mrb_gc_mark_value(mrb, kh_key(kh, k));
66+
}
67+
}
68+
return kh_size(kh);
5369
}
5470

55-
static khash_t(set) *
56-
set_get_khash(mrb_state *mrb, mrb_value self)
71+
void
72+
mrb_gc_free_set(mrb_state *mrb, struct RBasic *obj)
73+
{
74+
struct RSet *s = (struct RSet*)obj;
75+
if (s->kh) {
76+
khash_t(set) *kh = s->kh;
77+
if (kh) {
78+
kh_destroy(set, mrb, kh);
79+
}
80+
}
81+
}
82+
83+
size_t
84+
mrb_set_memsize(mrb_value set)
5785
{
58-
return (khash_t(set)*)mrb_data_get_ptr(mrb, self, &set_data_type);
86+
87+
size_t size = mrb_objspace_page_slot_size();
88+
struct RSet *s = mrb_set_ptr(set);
89+
if (s->kh) {
90+
size += kh_size(s->kh) * sizeof(mrb_value);
91+
}
92+
return size;
5993
}
6094

6195
/* Helper function to check if a value is a Set and return a boolean result */
@@ -93,7 +127,10 @@ set_init_copy(mrb_state *mrb, mrb_value self)
93127
mrb_value orig = mrb_get_arg1(mrb);
94128
khash_t(set) *kh;
95129

96-
if (mrb_type(orig) != MRB_TT_CDATA || (DATA_TYPE(self) && DATA_TYPE(self) != DATA_TYPE(orig))) {
130+
if (mrb_type(orig) != MRB_TT_SET) {
131+
mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take a Set object");
132+
}
133+
if (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig)) {
97134
mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
98135
}
99136

@@ -1356,7 +1393,7 @@ mrb_mruby_set_gem_init(mrb_state *mrb)
13561393
struct RClass *set;
13571394

13581395
set = mrb_define_class(mrb, "Set", mrb->object_class);
1359-
MRB_SET_INSTANCE_TT(set, MRB_TT_CDATA); /* Set instances will hold a C pointer (khash) */
1396+
MRB_SET_INSTANCE_TT(set, MRB_TT_SET);
13601397

13611398
mrb_include_module(mrb, set, mrb_module_get(mrb, "Enumerable"));
13621399

src/gc.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,11 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
729729
children += mrb_rational_mark(mrb, obj);
730730
break;
731731
#endif
732+
#ifdef MRB_USE_SET
733+
case MRB_TT_SET:
734+
children += mrb_gc_mark_set(mrb, obj);
735+
break;
736+
#endif
732737

733738
default:
734739
break;
@@ -841,6 +846,12 @@ obj_free(mrb_state *mrb, struct RBasic *obj, mrb_bool end)
841846
mrb_gc_free_range(mrb, ((struct RRange*)obj));
842847
break;
843848

849+
#ifdef MRB_USE_SET
850+
case MRB_TT_SET:
851+
mrb_gc_free_set(mrb, obj);
852+
break;
853+
#endif
854+
844855
case MRB_TT_CDATA:
845856
{
846857
struct RData *d = (struct RData*)obj;

0 commit comments

Comments
 (0)