mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Refactor common heap iteration code
We have code common to all heap iteration paths in this file. Refactor such that we keep ASAN checks and flags checks in one place
This commit is contained in:
parent
b9488accf9
commit
0b0e2d88ce
Notes:
git
2020-09-29 00:21:00 +09:00
1 changed files with 96 additions and 127 deletions
|
@ -52,29 +52,44 @@ struct total_data {
|
||||||
VALUE klass;
|
VALUE klass;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static void
|
||||||
total_i(void *vstart, void *vend, size_t stride, void *ptr)
|
total_i(VALUE v, void *ptr)
|
||||||
{
|
{
|
||||||
VALUE v;
|
|
||||||
struct total_data *data = (struct total_data *)ptr;
|
struct total_data *data = (struct total_data *)ptr;
|
||||||
|
|
||||||
for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
|
|
||||||
void *poisoned = asan_poisoned_object_p(v);
|
|
||||||
asan_unpoison_object(v, false);
|
|
||||||
|
|
||||||
if (RBASIC(v)->flags) {
|
|
||||||
switch (BUILTIN_TYPE(v)) {
|
switch (BUILTIN_TYPE(v)) {
|
||||||
case T_NONE:
|
case T_NONE:
|
||||||
case T_IMEMO:
|
case T_IMEMO:
|
||||||
case T_ICLASS:
|
case T_ICLASS:
|
||||||
case T_NODE:
|
case T_NODE:
|
||||||
case T_ZOMBIE:
|
case T_ZOMBIE:
|
||||||
continue;
|
return;
|
||||||
default:
|
default:
|
||||||
if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
|
if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
|
||||||
data->total += rb_obj_memsize_of(v);
|
data->total += rb_obj_memsize_of(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*each_obj_with_flags)(VALUE, void*);
|
||||||
|
|
||||||
|
struct obj_itr {
|
||||||
|
each_obj_with_flags cb;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
heap_iter(void *vstart, void *vend, size_t stride, void *ptr)
|
||||||
|
{
|
||||||
|
struct obj_itr * ctx = (struct obj_itr *)ptr;
|
||||||
|
VALUE v;
|
||||||
|
|
||||||
|
for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
|
||||||
|
void *poisoned = asan_poisoned_object_p(v);
|
||||||
|
asan_unpoison_object(v, false);
|
||||||
|
|
||||||
|
if (RBASIC(v)->flags) {
|
||||||
|
(*ctx->cb)(v, ctx->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poisoned) {
|
if (poisoned) {
|
||||||
|
@ -85,6 +100,15 @@ total_i(void *vstart, void *vend, size_t stride, void *ptr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
each_object_with_flags(each_obj_with_flags cb, void *ctx)
|
||||||
|
{
|
||||||
|
struct obj_itr data;
|
||||||
|
data.cb = cb;
|
||||||
|
data.data = ctx;
|
||||||
|
rb_objspace_each_objects(heap_iter, &data);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* ObjectSpace.memsize_of_all([klass]) -> Integer
|
* ObjectSpace.memsize_of_all([klass]) -> Integer
|
||||||
|
@ -122,7 +146,7 @@ memsize_of_all_m(int argc, VALUE *argv, VALUE self)
|
||||||
rb_scan_args(argc, argv, "01", &data.klass);
|
rb_scan_args(argc, argv, "01", &data.klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_objspace_each_objects(total_i, &data);
|
each_object_with_flags(total_i, &data);
|
||||||
return SIZET2NUM(data.total);
|
return SIZET2NUM(data.total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,25 +180,11 @@ setup_hash(int argc, VALUE *argv)
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
cos_i(void *vstart, void *vend, size_t stride, void *data)
|
cos_i(VALUE v, void *data)
|
||||||
{
|
{
|
||||||
size_t *counts = (size_t *)data;
|
size_t *counts = (size_t *)data;
|
||||||
VALUE v = (VALUE)vstart;
|
|
||||||
|
|
||||||
for (;v != (VALUE)vend; v += stride) {
|
|
||||||
void *ptr = asan_poisoned_object_p(v);
|
|
||||||
asan_unpoison_object(v, false);
|
|
||||||
|
|
||||||
if (RBASIC(v)->flags) {
|
|
||||||
counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v);
|
counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v);
|
||||||
}
|
|
||||||
|
|
||||||
if (ptr) {
|
|
||||||
asan_poison_object(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -251,7 +261,7 @@ count_objects_size(int argc, VALUE *argv, VALUE os)
|
||||||
counts[i] = 0;
|
counts[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_objspace_each_objects(cos_i, &counts[0]);
|
each_object_with_flags(cos_i, &counts[0]);
|
||||||
|
|
||||||
for (i = 0; i <= T_MASK; i++) {
|
for (i = 0; i <= T_MASK; i++) {
|
||||||
if (counts[i]) {
|
if (counts[i]) {
|
||||||
|
@ -269,17 +279,12 @@ struct dynamic_symbol_counts {
|
||||||
size_t immortal;
|
size_t immortal;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static void
|
||||||
cs_i(void *vstart, void *vend, size_t stride, void *n)
|
cs_i(VALUE v, void *n)
|
||||||
{
|
{
|
||||||
struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n;
|
struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n;
|
||||||
VALUE v = (VALUE)vstart;
|
|
||||||
|
|
||||||
for (; v != (VALUE)vend; v += stride) {
|
if (BUILTIN_TYPE(v) == T_SYMBOL) {
|
||||||
void *ptr = asan_poisoned_object_p(v);
|
|
||||||
asan_unpoison_object(v, false);
|
|
||||||
|
|
||||||
if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_SYMBOL) {
|
|
||||||
ID id = RSYMBOL(v)->id;
|
ID id = RSYMBOL(v)->id;
|
||||||
if ((id & ~ID_SCOPE_MASK) == 0) {
|
if ((id & ~ID_SCOPE_MASK) == 0) {
|
||||||
counts->mortal++;
|
counts->mortal++;
|
||||||
|
@ -288,13 +293,6 @@ cs_i(void *vstart, void *vend, size_t stride, void *n)
|
||||||
counts->immortal++;
|
counts->immortal++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr) {
|
|
||||||
asan_poison_object(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t rb_sym_immortal_count(void);
|
size_t rb_sym_immortal_count(void);
|
||||||
|
@ -332,7 +330,7 @@ count_symbols(int argc, VALUE *argv, VALUE os)
|
||||||
VALUE hash = setup_hash(argc, argv);
|
VALUE hash = setup_hash(argc, argv);
|
||||||
|
|
||||||
size_t immortal_symbols = rb_sym_immortal_count();
|
size_t immortal_symbols = rb_sym_immortal_count();
|
||||||
rb_objspace_each_objects(cs_i, &dynamic_counts);
|
each_object_with_flags(cs_i, &dynamic_counts);
|
||||||
|
|
||||||
rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.mortal));
|
rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.mortal));
|
||||||
rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal));
|
rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal));
|
||||||
|
@ -342,20 +340,15 @@ count_symbols(int argc, VALUE *argv, VALUE os)
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
cn_i(void *vstart, void *vend, size_t stride, void *n)
|
cn_i(VALUE v, void *n)
|
||||||
{
|
{
|
||||||
size_t *nodes = (size_t *)n;
|
size_t *nodes = (size_t *)n;
|
||||||
VALUE v = (VALUE)vstart;
|
|
||||||
|
|
||||||
for (; v != (VALUE)vend; v += stride) {
|
if (BUILTIN_TYPE(v) == T_NODE) {
|
||||||
if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_NODE) {
|
|
||||||
size_t s = nd_type((NODE *)v);
|
size_t s = nd_type((NODE *)v);
|
||||||
nodes[s]++;
|
nodes[s]++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -392,7 +385,7 @@ count_nodes(int argc, VALUE *argv, VALUE os)
|
||||||
nodes[i] = 0;
|
nodes[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_objspace_each_objects(cn_i, &nodes[0]);
|
each_object_with_flags(cn_i, &nodes[0]);
|
||||||
|
|
||||||
for (i=0; i<NODE_LAST; i++) {
|
for (i=0; i<NODE_LAST; i++) {
|
||||||
if (nodes[i] != 0) {
|
if (nodes[i] != 0) {
|
||||||
|
@ -515,17 +508,12 @@ count_nodes(int argc, VALUE *argv, VALUE os)
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
cto_i(void *vstart, void *vend, size_t stride, void *data)
|
cto_i(VALUE v, void *data)
|
||||||
{
|
{
|
||||||
VALUE hash = (VALUE)data;
|
VALUE hash = (VALUE)data;
|
||||||
VALUE v = (VALUE)vstart;
|
|
||||||
|
|
||||||
for (; v != (VALUE)vend; v += stride) {
|
if (BUILTIN_TYPE(v) == T_DATA) {
|
||||||
void *ptr = asan_poisoned_object_p(v);
|
|
||||||
asan_unpoison_object(v, false);
|
|
||||||
|
|
||||||
if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_DATA) {
|
|
||||||
VALUE counter;
|
VALUE counter;
|
||||||
VALUE key = RBASIC(v)->klass;
|
VALUE key = RBASIC(v)->klass;
|
||||||
|
|
||||||
|
@ -545,13 +533,6 @@ cto_i(void *vstart, void *vend, size_t stride, void *data)
|
||||||
|
|
||||||
rb_hash_aset(hash, key, counter);
|
rb_hash_aset(hash, key, counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr) {
|
|
||||||
asan_poison_object(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -590,23 +571,18 @@ static VALUE
|
||||||
count_tdata_objects(int argc, VALUE *argv, VALUE self)
|
count_tdata_objects(int argc, VALUE *argv, VALUE self)
|
||||||
{
|
{
|
||||||
VALUE hash = setup_hash(argc, argv);
|
VALUE hash = setup_hash(argc, argv);
|
||||||
rb_objspace_each_objects(cto_i, (void *)hash);
|
each_object_with_flags(cto_i, (void *)hash);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ID imemo_type_ids[IMEMO_MASK+1];
|
static ID imemo_type_ids[IMEMO_MASK+1];
|
||||||
|
|
||||||
static int
|
static void
|
||||||
count_imemo_objects_i(void *vstart, void *vend, size_t stride, void *data)
|
count_imemo_objects_i(VALUE v, void *data)
|
||||||
{
|
{
|
||||||
VALUE hash = (VALUE)data;
|
VALUE hash = (VALUE)data;
|
||||||
VALUE v = (VALUE)vstart;
|
|
||||||
|
|
||||||
for (; v != (VALUE)vend; v += stride) {
|
if (BUILTIN_TYPE(v) == T_IMEMO) {
|
||||||
void *ptr = asan_poisoned_object_p(v);
|
|
||||||
asan_unpoison_object(v, false);
|
|
||||||
|
|
||||||
if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_IMEMO) {
|
|
||||||
VALUE counter;
|
VALUE counter;
|
||||||
VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]);
|
VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]);
|
||||||
|
|
||||||
|
@ -621,13 +597,6 @@ count_imemo_objects_i(void *vstart, void *vend, size_t stride, void *data)
|
||||||
|
|
||||||
rb_hash_aset(hash, key, counter);
|
rb_hash_aset(hash, key, counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr) {
|
|
||||||
asan_poison_object(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -679,7 +648,7 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self)
|
||||||
imemo_type_ids[12] = rb_intern("imemo_callcache");
|
imemo_type_ids[12] = rb_intern("imemo_callcache");
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_objspace_each_objects(count_imemo_objects_i, (void *)hash);
|
each_object_with_flags(count_imemo_objects_i, (void *)hash);
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue