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);
15rb_imemo_callinfo_mid(
VALUE obj)
28 if (cc->klass ==
Qundef)
return false;
30 data->klass = cc->klass;
31 data->called_id = vm_cc_cme(cc)->called_id;
36rb_imemo_name(
enum imemo_type
type)
40#define IMEMO_NAME(x) case imemo_##x: return #x;
41 IMEMO_NAME(callcache);
43 IMEMO_NAME(constcache);
51 IMEMO_NAME(throw_data);
53 IMEMO_NAME(cvar_entry);
55 IMEMO_NAME(subclasses);
59 rb_bug(
"unreachable");
67rb_imemo_new(
enum imemo_type
type,
VALUE v0,
size_t size,
bool is_shareable)
70 return rb_newobj_of(v0, flags, size);
74rb_imemo_tmpbuf_new(
void)
79 rb_gc_register_pinning_obj((
VALUE)obj);
89rb_alloc_tmp_buffer(
volatile VALUE *store,
long len,
bool marked)
92 rb_raise(rb_eArgError,
"negative buffer size (or size too big)");
98 *store = (
VALUE)tmpbuf;
99 void *ptr = ruby_xmalloc(
len);
100 tmpbuf->marked = marked;
108rb_free_tmp_buffer(
volatile VALUE *store)
113 void *ptr = ATOMIC_PTR_EXCHANGE(s->ptr, 0);
116 ruby_xfree_sized(ptr, size);
123 struct MEMO *memo = IMEMO_NEW(
struct MEMO, imemo_memo, 0);
125 *((
VALUE *)&memo->v1) = a;
126 *((
VALUE *)&memo->v2) = b;
135 struct MEMO *memo = IMEMO_NEW(
struct MEMO, imemo_memo, 0);
137 *((
VALUE *)&memo->v1) = a;
138 *((
VALUE *)&memo->v2) = b;
139 *((
VALUE *)&memo->u3.value) = c;
140 memo->flags |= MEMO_U3_IS_VALUE;
149 memo->tbl.num_entries = 0;
150 st_init_existing_table_with_size(&memo->tbl,
type, size);
155imemo_fields_new(
VALUE owner, shape_id_t shape_id,
size_t size,
bool is_shareable)
164 shape_id = rb_shape_transition_robject(shape_id);
165 return rb_newobj(GET_EC(), owner, flags, shape_id,
true, size);
169rb_imemo_fields_new(
VALUE owner, shape_id_t shape_id,
bool shareable)
171 size_t capa = RSHAPE(shape_id)->capacity;
174 VALUE fields = imemo_fields_new(owner, shape_id, embedded_size, shareable);
176 RUBY_ASSERT(rb_shape_embedded_capacity(RBASIC_SHAPE_ID(fields)) >=
capa);
182rb_imemo_fields_new_complex_empty(
VALUE owner)
184 return imemo_fields_new(owner, ROOT_SHAPE_ID,
sizeof(
struct rb_fields),
false);
188rb_imemo_fields_new_complex(
VALUE owner, shape_id_t shape_id,
size_t capa,
bool shareable)
191 st_init_existing_numtable_with_size(&tbl,
capa);
192 VALUE fields = imemo_fields_new(owner, shape_id,
sizeof(
struct rb_fields), shareable);
193 MEMCPY(&IMEMO_OBJ_FIELDS(fields)->as.complex.table, &tbl,
st_table, 1);
198imemo_fields_complex_wb_i(st_data_t key, st_data_t value, st_data_t arg)
205rb_imemo_fields_clone(
VALUE fields_obj)
207 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
208 VALUE owner = rb_imemo_fields_owner(fields_obj);
211 if (rb_shape_complex_p(shape_id)) {
212 st_table *src_table = rb_imemo_fields_complex_tbl(fields_obj);
216 clone = imemo_fields_new(owner, ROOT_SHAPE_ID,
sizeof(
struct rb_fields),
false );
217 st_table *dest_table = rb_imemo_fields_complex_tbl(clone);
219 dest_table->entries = NULL;
221 st_replace(dest_table, src_table);
222 st_foreach(dest_table, imemo_fields_complex_wb_i, (st_data_t)clone);
223 RBASIC_SET_FULL_SHAPE_ID(clone, shape_id);
226 clone = rb_imemo_fields_new(owner, shape_id,
false );
227 VALUE *fields = rb_imemo_fields_ptr(clone);
228 attr_index_t fields_count = RSHAPE_LEN(shape_id);
229 MEMCPY(fields, rb_imemo_fields_ptr(fields_obj),
VALUE, fields_count);
230 for (attr_index_t i = 0; i < fields_count; i++) {
239rb_imemo_fields_clear(
VALUE fields_obj)
242 RBASIC_CLEAR_CLASS(fields_obj);
246rb_imemo_subclasses_new(uint32_t capacity)
251 if (rb_gc_size_allocatable_p(embed_size)) {
252 subs = (
struct rb_subclasses *)rb_imemo_new(imemo_subclasses, 0, embed_size,
true);
254 subs->capacity = capacity;
255 memset(subs->as.embed, 0, capacity *
sizeof(
VALUE));
256 rb_gc_declare_weak_references((
VALUE)subs);
260 subs->as.external = NULL;
264 rb_gc_declare_weak_references((
VALUE)subs);
266 subs->capacity = capacity;
276rb_imemo_memsize(
VALUE obj)
279 switch (imemo_type(obj)) {
280 case imemo_callcache:
284 case imemo_constcache:
295 size += rb_iseq_memsize((
rb_iseq_t *)obj);
306 case imemo_throw_data:
312 case imemo_cvar_entry:
315 if (rb_obj_shape_complex_p(obj)) {
316 size += st_memsize(rb_imemo_fields_complex_tbl(obj)) -
sizeof(
st_table);
320 case imemo_subclasses: {
323 size += subs->capacity *
sizeof(
VALUE);
329 size += st_memsize(rb_imemo_cdhash_tbl(obj)) -
sizeof(
st_table);
333 rb_bug(
"unreachable");
348 rb_gc_mark_and_move(&ment->owner);
349 rb_gc_mark_and_move(&ment->defined_class);
352 rb_gc_mark_and_move(&def->original_module);
355 case VM_METHOD_TYPE_ISEQ:
357 rb_gc_mark_and_move_ptr(&def->body.iseq.
iseqptr);
359 rb_gc_mark_and_move_ptr(&def->body.iseq.
cref);
361 if (!reference_updating) {
362 if (def->iseq_overload && ment->defined_class) {
365 rb_gc_mark((
VALUE)ment);
369 case VM_METHOD_TYPE_ATTRSET:
370 case VM_METHOD_TYPE_IVAR:
371 rb_gc_mark_and_move(&def->body.attr.location);
373 case VM_METHOD_TYPE_BMETHOD:
374 rb_gc_mark_and_move(&def->body.bmethod.proc);
376 case VM_METHOD_TYPE_ALIAS:
377 rb_gc_mark_and_move_ptr(&def->body.alias.original_me);
379 case VM_METHOD_TYPE_REFINED:
380 rb_gc_mark_and_move_ptr(&def->body.refined.orig_me);
382 case VM_METHOD_TYPE_CFUNC:
383 case VM_METHOD_TYPE_ZSUPER:
384 case VM_METHOD_TYPE_MISSING:
385 case VM_METHOD_TYPE_OPTIMIZED:
386 case VM_METHOD_TYPE_UNDEF:
387 case VM_METHOD_TYPE_NOTIMPLEMENTED:
394rb_imemo_mark_and_move(
VALUE obj,
bool reference_updating)
396 switch (imemo_type(obj)) {
397 case imemo_callcache: {
419 if (UNDEF_P(cc->klass)) {
424 else if (reference_updating) {
425 *((
VALUE *)&cc->klass) = rb_gc_location(cc->klass);
436 if ((vm_cc_super_p(cc) || vm_cc_refinement_p(cc))) {
437 rb_gc_mark_movable((
VALUE)cc->cme_);
445 case imemo_constcache: {
448 rb_gc_mark_and_move(&ice->value);
455 if (!rb_gc_checking_shareable()) {
457 rb_gc_mark_and_move(&cref->klass_or_self);
460 rb_gc_mark_and_move_ptr(&cref->next);
463 if (!rb_gc_checking_shareable()) {
464 rb_gc_mark_and_move(&cref->refinements);
472 if (LIKELY(env->ep)) {
474 RUBY_ASSERT(rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]) == rb_gc_location(obj));
475 RUBY_ASSERT(reference_updating || VM_ENV_ESCAPED_P(env->ep));
477 for (
unsigned int i = 0; i < env->env_size; i++) {
478 rb_gc_mark_and_move((
VALUE *)&env->env[i]);
481 rb_gc_mark_and_move_ptr(&env->iseq);
483 if (VM_ENV_LOCAL_P(env->ep) && VM_ENV_BOXED_P(env->ep)) {
484 const rb_box_t *box = VM_ENV_BOX(env->ep);
485 if (BOX_USER_P(box)) {
486 rb_gc_mark_and_move((
VALUE *)&box->box_object);
490 if (reference_updating) {
491 ((
VALUE *)env->ep)[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]);
494 if (!VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_WB_REQUIRED)) {
495 VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
497 rb_gc_mark_movable( (
VALUE)rb_vm_env_prev_env(env));
506 if (!reference_updating) {
507 rb_gc_mark_maybe((
VALUE)ifunc->data);
513 rb_iseq_mark_and_move((
rb_iseq_t *)obj, reference_updating);
516 struct MEMO *memo = (
struct MEMO *)obj;
518 rb_gc_mark_and_move((
VALUE *)&memo->v1);
519 rb_gc_mark_and_move((
VALUE *)&memo->v2);
521 rb_gc_mark_and_move((
VALUE *)&memo->u3.value);
533 rb_gc_mark_and_move((
VALUE *)&svar->lastline);
534 rb_gc_mark_and_move((
VALUE *)&svar->backref);
535 rb_gc_mark_and_move((
VALUE *)&svar->others);
539 case imemo_throw_data: {
542 rb_gc_mark_and_move((
VALUE *)&throw_data->throw_obj);
549 if (m->marked && !reference_updating) {
550 rb_gc_mark_locations(m->ptr, m->ptr + (m->size /
sizeof(
VALUE)));
555 case imemo_cvar_entry: {
557 rb_gc_mark_and_move(&ent->class_value);
558 rb_gc_mark_and_move((
VALUE *)&ent->cref);
561 case imemo_subclasses: {
562 if (reference_updating) {
564 VALUE *entries = rb_imemo_subclasses_entries(obj);
565 for (uint32_t i = 0; i < subs->count; i++) {
567 entries[i] = rb_gc_location(entries[i]);
579 if (rb_obj_shape_complex_p(obj)) {
580 st_table *tbl = rb_imemo_fields_complex_tbl(obj);
581 if (reference_updating) {
582 rb_gc_ref_update_table_values_only(tbl);
585 rb_mark_tbl_no_pin(tbl);
589 VALUE *fields = rb_imemo_fields_ptr(obj);
590 attr_index_t
len = RSHAPE_LEN(RBASIC_SHAPE_ID(obj));
591 for (attr_index_t i = 0; i <
len; i++) {
592 rb_gc_mark_and_move(&fields[i]);
598 st_table *tbl = rb_imemo_cdhash_tbl(obj);
599 if (reference_updating) {
600 rb_gc_update_set_refs(tbl);
603 rb_gc_mark_set_no_pin(tbl);
608 rb_bug(
"unreachable");
616static enum rb_id_table_iterator_result
617free_const_entry_i(
VALUE value,
void *data)
621 return ID_TABLE_CONTINUE;
627 rb_id_table_foreach_values(tbl, free_const_entry_i, 0);
628 rb_id_table_free(tbl);
632imemo_fields_free(
struct rb_fields *fields)
634 if (rb_obj_shape_complex_p((
VALUE)fields)) {
635 st_free_embedded_table(&fields->as.complex.table);
640rb_imemo_free(
VALUE obj)
642 switch (imemo_type(obj)) {
643 case imemo_callcache:
644 RB_DEBUG_COUNTER_INC(obj_imemo_callcache);
647 case imemo_callinfo:{
651 RB_DEBUG_COUNTER_INC(obj_imemo_callinfo);
655 case imemo_constcache:
656 RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
660 RB_DEBUG_COUNTER_INC(obj_imemo_cref);
667 SIZED_FREE_N(env->env, env->env_size);
668 RB_DEBUG_COUNTER_INC(obj_imemo_env);
673 RB_DEBUG_COUNTER_INC(obj_imemo_ifunc);
677 RB_DEBUG_COUNTER_INC(obj_imemo_iseq);
681 RB_DEBUG_COUNTER_INC(obj_imemo_memo);
686 RB_DEBUG_COUNTER_INC(obj_imemo_ment);
690 RB_DEBUG_COUNTER_INC(obj_imemo_svar);
693 case imemo_throw_data:
694 RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
699 RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
702 case imemo_cvar_entry:
703 RB_DEBUG_COUNTER_INC(obj_imemo_cvar_entry);
707 imemo_fields_free(IMEMO_OBJ_FIELDS(obj));
708 RB_DEBUG_COUNTER_INC(obj_imemo_fields);
711 case imemo_subclasses: {
714 SIZED_FREE_N(subs->as.external, subs->capacity);
716 RB_DEBUG_COUNTER_INC(obj_imemo_subclasses);
720 st_free_embedded_table(rb_imemo_cdhash_tbl(obj));
721 RB_DEBUG_COUNTER_INC(obj_imemo_cdhash);
725 rb_bug(
"unreachable");
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define Qundef
Old name of RUBY_Qundef.
#define T_IMEMO
Old name of RUBY_T_IMEMO.
#define FL_SHAREABLE
Old name of RUBY_FL_SHAREABLE.
#define ZALLOC_N
Old name of RB_ZALLOC_N.
#define T_ICLASS
Old name of RUBY_T_ICLASS.
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
#define T_CLASS
Old name of RUBY_T_CLASS.
#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.
#define RBASIC(obj)
Convenient casting macro.
Internal header for Ruby Box.
Internal header for Class.
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 ID
Type that represents a Ruby identifier such as a variable name.
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.