summaryrefslogtreecommitdiff
path: root/internal/imemo.h
diff options
context:
space:
mode:
Diffstat (limited to 'internal/imemo.h')
-rw-r--r--internal/imemo.h141
1 files changed, 80 insertions, 61 deletions
diff --git a/internal/imemo.h b/internal/imemo.h
index 8d1e42353d..e8a5f0fc8e 100644
--- a/internal/imemo.h
+++ b/internal/imemo.h
@@ -37,10 +37,13 @@ enum imemo_type {
imemo_ment = 6,
imemo_iseq = 7,
imemo_tmpbuf = 8,
+ imemo_cvar_entry = 9,
imemo_callinfo = 10,
imemo_callcache = 11,
imemo_constcache = 12,
- imemo_fields = 13,
+ imemo_fields = 13,
+ imemo_subclasses = 14,
+ imemo_cdhash = 15,
};
/* CREF (Class REFerence) is defined in method.h */
@@ -57,7 +60,6 @@ struct vm_svar {
/*! THROW_DATA */
struct vm_throw_data {
VALUE flags;
- VALUE reserved;
const VALUE throw_obj;
const struct rb_control_frame_struct *catch_frame;
int throw_state;
@@ -93,30 +95,36 @@ struct vm_ifunc {
struct rb_imemo_tmpbuf_struct {
VALUE flags;
- VALUE reserved;
VALUE *ptr; /* malloc'ed buffer */
- struct rb_imemo_tmpbuf_struct *next; /* next imemo */
- size_t cnt; /* buffer size in VALUE */
+ size_t size; /* buffer size in bytes */
};
+struct rb_imemo_cdhash {
+ VALUE flags;
+ st_table tbl;
+};
+
+/* Set on imemo_memo when u3 holds a VALUE that GC must mark.
+ * When unset, u3 is a non-VALUE (cnt/state). */
+#define MEMO_U3_IS_VALUE IMEMO_FL_USER0
+
/*! MEMO
*
* @see imemo_type
* */
struct MEMO {
VALUE flags;
- VALUE reserved;
const VALUE v1;
const VALUE v2;
union {
long cnt;
long state;
const VALUE value;
- void (*func)(void);
} u3;
};
-#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T)))
+#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), false))
+#define SHAREABLE_IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), true))
/* ment is in method.h */
@@ -133,16 +141,16 @@ struct MEMO {
#ifndef RUBY_RUBYPARSER_H
typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
#endif
-rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
+VALUE rb_imemo_new(enum imemo_type type, VALUE v0, size_t size, bool is_shareable);
+VALUE rb_imemo_tmpbuf_new(void);
+struct MEMO *rb_imemo_memo_new(VALUE a, VALUE b, long c);
+struct MEMO *rb_imemo_memo_new_value(VALUE a, VALUE b, VALUE c);
struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
static inline enum imemo_type imemo_type(VALUE imemo);
static inline int imemo_type_p(VALUE imemo, enum imemo_type imemo_type);
static inline bool imemo_throw_data_p(VALUE imemo);
static inline struct vm_ifunc *rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data);
-static inline VALUE rb_imemo_tmpbuf_auto_free_pointer(void);
static inline void *RB_IMEMO_TMPBUF_PTR(VALUE v);
-static inline void *rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr);
-static inline VALUE rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str);
static inline void MEMO_V1_SET(struct MEMO *m, VALUE v);
static inline void MEMO_V2_SET(struct MEMO *m, VALUE v);
@@ -151,21 +159,9 @@ void rb_imemo_mark_and_move(VALUE obj, bool reference_updating);
void rb_imemo_free(VALUE obj);
RUBY_SYMBOL_EXPORT_BEGIN
-VALUE rb_imemo_new(enum imemo_type type, VALUE v0, size_t size);
const char *rb_imemo_name(enum imemo_type type);
RUBY_SYMBOL_EXPORT_END
-static inline struct MEMO *
-MEMO_NEW(VALUE a, VALUE b, VALUE c)
-{
- struct MEMO *memo = IMEMO_NEW(struct MEMO, imemo_memo, 0);
- *((VALUE *)&memo->v1) = a;
- *((VALUE *)&memo->v2) = b;
- *((VALUE *)&memo->u3.value) = c;
-
- return memo;
-}
-
static inline enum imemo_type
imemo_type(VALUE imemo)
{
@@ -201,12 +197,6 @@ rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data)
return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS);
}
-static inline VALUE
-rb_imemo_tmpbuf_auto_free_pointer(void)
-{
- return rb_imemo_new(imemo_tmpbuf, 0, sizeof(rb_imemo_tmpbuf_t));
-}
-
static inline void *
RB_IMEMO_TMPBUF_PTR(VALUE v)
{
@@ -214,30 +204,16 @@ RB_IMEMO_TMPBUF_PTR(VALUE v)
return p->ptr;
}
-static inline void *
-rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr)
-{
- return ((rb_imemo_tmpbuf_t *)v)->ptr = ptr;
-}
-
static inline VALUE
-rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str)
+rb_imemo_tmpbuf_new_from_an_RString(VALUE str)
{
- const void *src;
VALUE imemo;
- rb_imemo_tmpbuf_t *tmpbuf;
- void *dst;
size_t len;
StringValue(str);
- /* create tmpbuf to keep the pointer before xmalloc */
- imemo = rb_imemo_tmpbuf_auto_free_pointer();
- tmpbuf = (rb_imemo_tmpbuf_t *)imemo;
len = RSTRING_LEN(str);
- src = RSTRING_PTR(str);
- dst = ruby_xmalloc(len);
- memcpy(dst, src, len);
- tmpbuf->ptr = dst;
+ rb_alloc_tmp_buffer(&imemo, len);
+ memcpy(RB_IMEMO_TMPBUF_PTR(imemo), RSTRING_PTR(str), len);
return imemo;
}
@@ -253,6 +229,15 @@ MEMO_V2_SET(struct MEMO *m, VALUE v)
RB_OBJ_WRITE(m, &m->v2, v);
}
+VALUE rb_imemo_cdhash_new(size_t size, const struct st_hash_type *type);
+
+static inline st_table *
+rb_imemo_cdhash_tbl(VALUE obj)
+{
+ RUBY_ASSERT(IMEMO_TYPE_P(obj, imemo_cdhash));
+ return &((struct rb_imemo_cdhash *)obj)->tbl;
+}
+
struct rb_fields {
struct RBasic basic;
union {
@@ -270,48 +255,82 @@ struct rb_fields {
} as;
};
-#define OBJ_FIELD_EXTERNAL IMEMO_FL_USER0
+// IMEMO/fields and T_OBJECT have exactly the same layout.
+// This is useful for JIT and common codepaths.
+#define OBJ_FIELD_HEAP ROBJECT_HEAP
+STATIC_ASSERT(imemo_fields_flags, OBJ_FIELD_HEAP == IMEMO_FL_USER0);
+STATIC_ASSERT(imemo_fields_embed_offset, offsetof(struct RObject, as.ary) == offsetof(struct rb_fields, as.embed.fields));
+STATIC_ASSERT(imemo_fields_external_offset, offsetof(struct RObject, as.heap.fields) == offsetof(struct rb_fields, as.external.ptr));
+STATIC_ASSERT(imemo_fields_complex_offset, offsetof(struct RObject, as.heap.fields) == offsetof(struct rb_fields, as.complex.table));
+
#define IMEMO_OBJ_FIELDS(fields) ((struct rb_fields *)fields)
-VALUE rb_imemo_fields_new(VALUE owner, size_t capa);
-VALUE rb_imemo_fields_new_complex(VALUE owner, size_t capa);
-VALUE rb_imemo_fields_new_complex_tbl(VALUE owner, st_table *tbl);
+#define IMEMO_SUBCLASSES_HEAP IMEMO_FL_USER0
+
+struct rb_subclasses {
+ VALUE flags;
+ uint32_t count;
+ uint32_t capacity;
+ union {
+ VALUE *external;
+ VALUE embed[1];
+ } as;
+};
+
+static inline VALUE *
+rb_imemo_subclasses_entries(VALUE v)
+{
+ struct rb_subclasses *s = (struct rb_subclasses *)v;
+ return FL_TEST_RAW(v, IMEMO_SUBCLASSES_HEAP) ? s->as.external : s->as.embed;
+}
+
+VALUE rb_imemo_fields_new(VALUE owner, /* shape_id_t */ uint32_t shape_id, bool shareable);
+VALUE rb_imemo_subclasses_new(uint32_t capacity);
+VALUE rb_imemo_fields_new_complex(VALUE owner, /* shape_id_t */ uint32_t shape_id, size_t capa, bool shareable);
+VALUE rb_imemo_fields_new_complex_tbl(VALUE owner, /* shape_id_t */ uint32_t shape_id, st_table *tbl, bool shareable);
VALUE rb_imemo_fields_clone(VALUE fields_obj);
void rb_imemo_fields_clear(VALUE fields_obj);
static inline VALUE
rb_imemo_fields_owner(VALUE fields_obj)
{
+ RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
+
return CLASS_OF(fields_obj);
}
static inline VALUE *
-rb_imemo_fields_ptr(VALUE obj_fields)
+rb_imemo_fields_ptr(VALUE fields_obj)
{
- if (!obj_fields) {
+ if (!fields_obj) {
return NULL;
}
- RUBY_ASSERT(IMEMO_TYPE_P(obj_fields, imemo_fields));
+ RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields) || RB_TYPE_P(fields_obj, T_OBJECT));
- if (RB_UNLIKELY(FL_TEST_RAW(obj_fields, OBJ_FIELD_EXTERNAL))) {
- return IMEMO_OBJ_FIELDS(obj_fields)->as.external.ptr;
+ if (UNLIKELY(FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP))) {
+ return IMEMO_OBJ_FIELDS(fields_obj)->as.external.ptr;
}
else {
- return IMEMO_OBJ_FIELDS(obj_fields)->as.embed.fields;
+ return IMEMO_OBJ_FIELDS(fields_obj)->as.embed.fields;
}
}
static inline st_table *
-rb_imemo_fields_complex_tbl(VALUE obj_fields)
+rb_imemo_fields_complex_tbl(VALUE fields_obj)
{
- if (!obj_fields) {
+ if (!fields_obj) {
return NULL;
}
- RUBY_ASSERT(IMEMO_TYPE_P(obj_fields, imemo_fields));
+ RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields) || RB_TYPE_P(fields_obj, T_OBJECT));
+ RUBY_ASSERT(FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP));
+
+ // Some codepaths unconditionally access the fields_ptr, and assume it can be used as st_table if the
+ // shape is complex.
+ RUBY_ASSERT((st_table *)rb_imemo_fields_ptr(fields_obj) == IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table);
- return IMEMO_OBJ_FIELDS(obj_fields)->as.complex.table;
+ return IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table;
}
#endif /* INTERNAL_IMEMO_H */