5#include "internal/imemo.h"
6#include "internal/object.h"
7#include "internal/st.h"
8#include "vm_callinfo.h"
10size_t rb_iseq_memsize(
const rb_iseq_t *iseq);
11void rb_iseq_mark_and_move(rb_iseq_t *iseq,
bool reference_updating);
12void rb_iseq_free(
const rb_iseq_t *iseq);
15rb_imemo_name(
enum imemo_type
type)
19#define IMEMO_NAME(x) case imemo_##x: return #x;
20 IMEMO_NAME(callcache);
22 IMEMO_NAME(constcache);
30 IMEMO_NAME(throw_data);
32 IMEMO_NAME(cvar_entry);
36 rb_bug(
"unreachable");
44rb_imemo_new(
enum imemo_type
type,
VALUE v0,
size_t size,
bool is_shareable)
47 NEWOBJ_OF(obj,
void, v0, flags, size, 0);
53rb_imemo_tmpbuf_new(
void)
56 NEWOBJ_OF(obj, rb_imemo_tmpbuf_t, 0, flags,
sizeof(rb_imemo_tmpbuf_t), NULL);
65rb_alloc_tmp_buffer_with_count(
volatile VALUE *store,
size_t size,
size_t cnt)
69 rb_imemo_tmpbuf_t *tmpbuf = (rb_imemo_tmpbuf_t *)rb_imemo_tmpbuf_new();
70 *store = (
VALUE)tmpbuf;
71 void *ptr = ruby_xmalloc(size);
79rb_alloc_tmp_buffer(
volatile VALUE *store,
long len)
83 if (
len < 0 || (cnt = (
long)roomof(
len,
sizeof(
VALUE))) < 0) {
84 rb_raise(rb_eArgError,
"negative buffer size (or size too big)");
87 return rb_alloc_tmp_buffer_with_count(store,
len, cnt);
91rb_free_tmp_buffer(
volatile VALUE *store)
93 rb_imemo_tmpbuf_t *s = (rb_imemo_tmpbuf_t*)ATOMIC_VALUE_EXCHANGE(*store, 0);
95 void *ptr = ATOMIC_PTR_EXCHANGE(s->ptr, 0);
102imemo_fields_new(
VALUE owner,
size_t capa,
bool shareable)
105 if (rb_gc_size_allocatable_p(embedded_size)) {
106 VALUE fields = rb_imemo_new(imemo_fields, owner, embedded_size, shareable);
111 VALUE fields = rb_imemo_new(imemo_fields, owner,
sizeof(
struct rb_fields), shareable);
119rb_imemo_fields_new(
VALUE owner,
size_t capa,
bool shareable)
121 return imemo_fields_new(owner,
capa, shareable);
125imemo_fields_new_complex(
VALUE owner,
size_t capa,
bool shareable)
127 VALUE fields = rb_imemo_new(imemo_fields, owner,
sizeof(
struct rb_fields), shareable);
128 IMEMO_OBJ_FIELDS(fields)->as.complex.table = st_init_numtable_with_size(
capa);
134rb_imemo_fields_new_complex(
VALUE owner,
size_t capa,
bool shareable)
136 return imemo_fields_new_complex(owner,
capa, shareable);
140imemo_fields_trigger_wb_i(st_data_t key, st_data_t value, st_data_t arg)
148imemo_fields_complex_wb_i(st_data_t key, st_data_t value, st_data_t arg)
155rb_imemo_fields_new_complex_tbl(
VALUE owner, st_table *tbl,
bool shareable)
157 VALUE fields = rb_imemo_new(imemo_fields, owner,
sizeof(
struct rb_fields), shareable);
158 IMEMO_OBJ_FIELDS(fields)->as.complex.table = tbl;
160 st_foreach(tbl, imemo_fields_trigger_wb_i, (st_data_t)fields);
165rb_imemo_fields_clone(
VALUE fields_obj)
167 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
170 if (rb_shape_too_complex_p(shape_id)) {
171 st_table *src_table = rb_imemo_fields_complex_tbl(fields_obj);
173 st_table *dest_table =
xcalloc(1,
sizeof(st_table));
174 clone = rb_imemo_fields_new_complex_tbl(rb_imemo_fields_owner(fields_obj), dest_table,
false );
176 st_replace(dest_table, src_table);
177 RBASIC_SET_SHAPE_ID(clone, shape_id);
179 st_foreach(dest_table, imemo_fields_complex_wb_i, (st_data_t)clone);
182 clone = imemo_fields_new(rb_imemo_fields_owner(fields_obj), RSHAPE_CAPACITY(shape_id),
false );
183 RBASIC_SET_SHAPE_ID(clone, shape_id);
184 VALUE *fields = rb_imemo_fields_ptr(clone);
185 attr_index_t fields_count = RSHAPE_LEN(shape_id);
186 MEMCPY(fields, rb_imemo_fields_ptr(fields_obj),
VALUE, fields_count);
187 for (attr_index_t i = 0; i < fields_count; i++) {
196rb_imemo_fields_clear(
VALUE fields_obj)
200 if (rb_shape_obj_too_complex_p(fields_obj)) {
201 RBASIC_SET_SHAPE_ID(fields_obj, ROOT_TOO_COMPLEX_SHAPE_ID);
204 RBASIC_SET_SHAPE_ID(fields_obj, ROOT_SHAPE_ID);
207 RBASIC_CLEAR_CLASS(fields_obj);
215rb_imemo_memsize(
VALUE obj)
218 switch (imemo_type(obj)) {
219 case imemo_callcache:
223 case imemo_constcache:
234 size += rb_iseq_memsize((rb_iseq_t *)obj);
240 size +=
sizeof(((rb_method_entry_t *)obj)->def);
245 case imemo_throw_data:
248 size += ((rb_imemo_tmpbuf_t *)obj)->cnt *
sizeof(
VALUE);
251 case imemo_cvar_entry:
255 if (rb_shape_obj_too_complex_p(obj)) {
256 size += st_memsize(IMEMO_OBJ_FIELDS(obj)->as.complex.table);
259 size += RSHAPE_CAPACITY(RBASIC_SHAPE_ID(obj)) *
sizeof(
VALUE);
264 rb_bug(
"unreachable");
275moved_or_living_object_strictly_p(
VALUE obj)
281mark_and_move_method_entry(rb_method_entry_t *ment,
bool reference_updating)
283 rb_method_definition_t *def = ment->def;
285 rb_gc_mark_and_move(&ment->owner);
286 rb_gc_mark_and_move(&ment->defined_class);
290 case VM_METHOD_TYPE_ISEQ:
292 rb_gc_mark_and_move_ptr(&def->body.iseq.
iseqptr);
294 rb_gc_mark_and_move_ptr(&def->body.iseq.
cref);
296 if (!reference_updating) {
297 if (def->iseq_overload && ment->defined_class) {
300 rb_gc_mark((
VALUE)ment);
304 case VM_METHOD_TYPE_ATTRSET:
305 case VM_METHOD_TYPE_IVAR:
306 rb_gc_mark_and_move(&def->body.attr.location);
308 case VM_METHOD_TYPE_BMETHOD:
309 if (!rb_gc_checking_shareable()) {
310 rb_gc_mark_and_move(&def->body.bmethod.proc);
313 case VM_METHOD_TYPE_ALIAS:
314 rb_gc_mark_and_move_ptr(&def->body.alias.original_me);
316 case VM_METHOD_TYPE_REFINED:
317 rb_gc_mark_and_move_ptr(&def->body.refined.orig_me);
319 case VM_METHOD_TYPE_CFUNC:
320 case VM_METHOD_TYPE_ZSUPER:
321 case VM_METHOD_TYPE_MISSING:
322 case VM_METHOD_TYPE_OPTIMIZED:
323 case VM_METHOD_TYPE_UNDEF:
324 case VM_METHOD_TYPE_NOTIMPLEMENTED:
331rb_imemo_mark_and_move(
VALUE obj,
bool reference_updating)
333 switch (imemo_type(obj)) {
334 case imemo_callcache: {
356 if (UNDEF_P(cc->klass)) {
361 else if (reference_updating) {
362 if (moved_or_living_object_strictly_p((
VALUE)cc->cme_)) {
363 *((
VALUE *)&cc->klass) = rb_gc_location(cc->klass);
371 vm_cc_invalidate(cc);
378 rb_gc_mark_weak((
VALUE *)&cc->klass);
379 if ((vm_cc_super_p(cc) || vm_cc_refinement_p(cc))) {
380 rb_gc_mark_movable((
VALUE)cc->cme_);
388 case imemo_constcache: {
391 if ((ice->flags & IMEMO_CONST_CACHE_SHAREABLE) ||
392 !rb_gc_checking_shareable()) {
393 rb_gc_mark_and_move(&ice->value);
399 rb_cref_t *cref = (rb_cref_t *)obj;
401 if (!rb_gc_checking_shareable()) {
403 rb_gc_mark_and_move(&cref->klass_or_self);
406 rb_gc_mark_and_move_ptr(&cref->next);
409 if (!rb_gc_checking_shareable()) {
410 rb_gc_mark_and_move(&cref->refinements);
418 if (LIKELY(env->ep)) {
420 RUBY_ASSERT(rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]) == rb_gc_location(obj));
421 RUBY_ASSERT(reference_updating || VM_ENV_ESCAPED_P(env->ep));
423 for (
unsigned int i = 0; i < env->env_size; i++) {
424 rb_gc_mark_and_move((
VALUE *)&env->env[i]);
427 rb_gc_mark_and_move_ptr(&env->iseq);
429 if (VM_ENV_LOCAL_P(env->ep) && VM_ENV_BOXED_P(env->ep)) {
430 const rb_box_t *box = VM_ENV_BOX(env->ep);
431 if (BOX_USER_P(box)) {
432 rb_gc_mark_and_move((
VALUE *)&box->box_object);
436 if (reference_updating) {
437 ((
VALUE *)env->ep)[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]);
440 if (!VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_WB_REQUIRED)) {
441 VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
443 rb_gc_mark_movable( (
VALUE)rb_vm_env_prev_env(env));
452 if (!reference_updating) {
453 rb_gc_mark_maybe((
VALUE)ifunc->data);
459 rb_iseq_mark_and_move((rb_iseq_t *)obj, reference_updating);
462 struct MEMO *memo = (
struct MEMO *)obj;
464 rb_gc_mark_and_move((
VALUE *)&memo->v1);
465 rb_gc_mark_and_move((
VALUE *)&memo->v2);
466 if (!reference_updating) {
467 rb_gc_mark_maybe(memo->u3.value);
473 mark_and_move_method_entry((rb_method_entry_t *)obj, reference_updating);
479 rb_gc_mark_and_move((
VALUE *)&svar->lastline);
480 rb_gc_mark_and_move((
VALUE *)&svar->backref);
481 rb_gc_mark_and_move((
VALUE *)&svar->others);
485 case imemo_throw_data: {
488 rb_gc_mark_and_move((
VALUE *)&throw_data->throw_obj);
493 const rb_imemo_tmpbuf_t *m = (
const rb_imemo_tmpbuf_t *)obj;
495 if (!reference_updating) {
496 rb_gc_mark_locations(m->ptr, m->ptr + m->cnt);
501 case imemo_cvar_entry: {
503 rb_gc_mark_and_move(&ent->class_value);
504 rb_gc_mark_and_move((
VALUE *)&ent->cref);
510 if (!rb_gc_checking_shareable()) {
514 if (rb_shape_obj_too_complex_p(obj)) {
515 st_table *tbl = rb_imemo_fields_complex_tbl(obj);
516 if (reference_updating) {
517 rb_gc_ref_update_table_values_only(tbl);
520 rb_mark_tbl_no_pin(tbl);
524 VALUE *fields = rb_imemo_fields_ptr(obj);
525 attr_index_t
len = RSHAPE_LEN(RBASIC_SHAPE_ID(obj));
526 for (attr_index_t i = 0; i <
len; i++) {
527 rb_gc_mark_and_move(&fields[i]);
534 rb_bug(
"unreachable");
542static enum rb_id_table_iterator_result
543free_const_entry_i(
VALUE value,
void *data)
545 rb_const_entry_t *ce = (rb_const_entry_t *)value;
547 return ID_TABLE_CONTINUE;
553 rb_id_table_foreach_values(tbl, free_const_entry_i, 0);
554 rb_id_table_free(tbl);
558imemo_fields_free(
struct rb_fields *fields)
561 if (rb_shape_obj_too_complex_p((
VALUE)fields)) {
562 st_free_table(fields->as.complex.table);
565 xfree(fields->as.external.ptr);
571rb_imemo_free(
VALUE obj)
573 switch (imemo_type(obj)) {
574 case imemo_callcache:
575 RB_DEBUG_COUNTER_INC(obj_imemo_callcache);
578 case imemo_callinfo:{
583 if (ci->kwarg->references == 0)
xfree((
void *)ci->kwarg);
585 RB_DEBUG_COUNTER_INC(obj_imemo_callinfo);
589 case imemo_constcache:
590 RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
594 RB_DEBUG_COUNTER_INC(obj_imemo_cref);
602 RB_DEBUG_COUNTER_INC(obj_imemo_env);
607 RB_DEBUG_COUNTER_INC(obj_imemo_ifunc);
610 rb_iseq_free((rb_iseq_t *)obj);
611 RB_DEBUG_COUNTER_INC(obj_imemo_iseq);
615 RB_DEBUG_COUNTER_INC(obj_imemo_memo);
619 rb_free_method_entry((rb_method_entry_t *)obj);
620 RB_DEBUG_COUNTER_INC(obj_imemo_ment);
624 RB_DEBUG_COUNTER_INC(obj_imemo_svar);
627 case imemo_throw_data:
628 RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
632 xfree(((rb_imemo_tmpbuf_t *)obj)->ptr);
633 RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
636 case imemo_cvar_entry:
637 RB_DEBUG_COUNTER_INC(obj_imemo_cvar_entry);
641 imemo_fields_free(IMEMO_OBJ_FIELDS(obj));
642 RB_DEBUG_COUNTER_INC(obj_imemo_fields);
645 rb_bug(
"unreachable");
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define xfree
Old name of ruby_xfree.
#define Qundef
Old name of RUBY_Qundef.
#define T_IMEMO
Old name of RUBY_T_IMEMO.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define FL_SHAREABLE
Old name of RUBY_FL_SHAREABLE.
#define T_ICLASS
Old name of RUBY_T_ICLASS.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
#define FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
#define T_CLASS
Old name of RUBY_T_CLASS.
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
#define T_MOVED
Old name of RUBY_T_MOVED.
#define xcalloc
Old name of ruby_xcalloc.
#define FL_USHIFT
Old name of RUBY_FL_USHIFT.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
int capa
Designed capacity of the buffer.
int len
Length of the buffer.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
VALUE type(ANYARGS)
ANYARGS-ed function type.
int st_foreach(st_table *q, int_type *w, st_data_t e)
Iteration over the given table.
#define RBASIC(obj)
Convenient casting macro.
rb_cref_t * cref
class reference, should be marked
const rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
IFUNC (Internal FUNCtion).
const VALUE cref_or_me
class reference or rb_method_entry_t
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.