diff --git a/debug.c b/debug.c index a54be27152..7c32f6dac0 100644 --- a/debug.c +++ b/debug.c @@ -19,6 +19,15 @@ #include "symbol.h" #include "id.h" +/* This is the only place struct RIMemo is actually used */ +struct RIMemo { + VALUE flags; + VALUE v0; + VALUE v1; + VALUE v2; + VALUE v3; +}; + /* for gdb */ const union { enum ruby_special_consts special_consts; diff --git a/internal.h b/internal.h index 337aee814d..fa6f78b52f 100644 --- a/internal.h +++ b/internal.h @@ -30,6 +30,8 @@ #include "internal/sanitizers.h" #define numberof(array) ((int)(sizeof(array) / sizeof((array)[0]))) +#define roomof(x, y) (((x) + (y) - 1) / (y)) +#define type_roomof(x, y) roomof(sizeof(x), sizeof(y)) /* Prevent compiler from reordering access */ #define ACCESS_ONCE(type,x) (*((volatile type *)&(x))) diff --git a/internal/imemo.h b/internal/imemo.h index 682582a40e..d90b76366c 100644 --- a/internal/imemo.h +++ b/internal/imemo.h @@ -9,18 +9,26 @@ * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ +#include "ruby/config.h" +#include /* for size_t */ +#include "internal/array.h" /* for rb_ary_tmp_new_fill */ +#include "internal/gc.h" /* for RB_OBJ_WRITE */ +#include "internal/stdbool.h" /* for bool */ +#include "ruby/ruby.h" /* for rb_block_call_func_t */ #ifndef IMEMO_DEBUG -#define IMEMO_DEBUG 0 +# define IMEMO_DEBUG 0 #endif -struct RIMemo { - VALUE flags; - VALUE v0; - VALUE v1; - VALUE v2; - VALUE v3; -}; +#define IMEMO_MASK 0x0f + +/* FL_USER0 to FL_USER3 is for type */ +#define IMEMO_FL_USHIFT (FL_USHIFT + 4) +#define IMEMO_FL_USER0 FL_USER4 +#define IMEMO_FL_USER1 FL_USER5 +#define IMEMO_FL_USER2 FL_USER6 +#define IMEMO_FL_USER3 FL_USER7 +#define IMEMO_FL_USER4 FL_USER8 enum imemo_type { imemo_env = 0, @@ -35,7 +43,111 @@ enum imemo_type { imemo_ast = 9, imemo_parser_strterm = 10 }; -#define IMEMO_MASK 0x0f + +/* CREF (Class REFerence) is defined in method.h */ + +/*! SVAR (Special VARiable) */ +struct vm_svar { + VALUE flags; + const VALUE cref_or_me; /*!< class reference or rb_method_entry_t */ + const VALUE lastline; + const VALUE backref; + const VALUE others; +}; + +/*! 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; +}; + +#define THROW_DATA_CONSUMED IMEMO_FL_USER0 + +/* IFUNC (Internal FUNCtion) */ + +struct vm_ifunc_argc { +#if SIZEOF_INT * 2 > SIZEOF_VALUE + signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2; + signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2; +#else + int min, max; +#endif +}; + +/*! IFUNC (Internal FUNCtion) */ +struct vm_ifunc { + VALUE flags; + VALUE reserved; + rb_block_call_func_t func; + const void *data; + struct vm_ifunc_argc argc; +}; + +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 */ +}; + +/*! 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; +}; + +/* ment is in method.h */ + +#define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err) +#define MEMO_CAST(m) (R_CAST(MEMO)(m)) +#define MEMO_NEW(a, b, c) ((struct MEMO *)rb_imemo_new(imemo_memo, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0)) +#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value)) +#define NEW_MEMO_FOR(type, value) \ + ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value)) +#define NEW_PARTIAL_MEMO_FOR(type, value, member) \ + ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), \ + rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \ + MEMO_FOR(type, value)) + +typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t; +VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0); +rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt); +struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc); +void rb_strterm_mark(VALUE obj); +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); + +RUBY_SYMBOL_EXPORT_BEGIN +#if IMEMO_DEBUG +VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line); +#define rb_imemo_new(type, v1, v2, v3, v0) rb_imemo_new_debug(type, v1, v2, v3, v0, __FILE__, __LINE__) +#else +VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0); +#endif +RUBY_SYMBOL_EXPORT_END static inline enum imemo_type imemo_type(VALUE imemo) @@ -58,82 +170,30 @@ imemo_type_p(VALUE imemo, enum imemo_type imemo_type) } } -VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0); +static inline bool +imemo_throw_data_p(VALUE imemo) +{ + return RB_TYPE_P(imemo, T_IMEMO); +} -/* FL_USER0 to FL_USER3 is for type */ -#define IMEMO_FL_USHIFT (FL_USHIFT + 4) -#define IMEMO_FL_USER0 FL_USER4 -#define IMEMO_FL_USER1 FL_USER5 -#define IMEMO_FL_USER2 FL_USER6 -#define IMEMO_FL_USER3 FL_USER7 -#define IMEMO_FL_USER4 FL_USER8 - -/* CREF (Class REFerence) is defined in method.h */ - -/*! SVAR (Special VARiable) */ -struct vm_svar { - VALUE flags; - const VALUE cref_or_me; /*!< class reference or rb_method_entry_t */ - const VALUE lastline; - const VALUE backref; - const VALUE others; -}; - - -#define THROW_DATA_CONSUMED IMEMO_FL_USER0 - -/*! 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; -}; - -#define THROW_DATA_P(err) RB_TYPE_P((VALUE)(err), T_IMEMO) - -/* IFUNC (Internal FUNCtion) */ - -struct vm_ifunc_argc { -#if SIZEOF_INT * 2 > SIZEOF_VALUE - signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2; - signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2; -#else - int min, max; -#endif -}; - -/*! IFUNC (Internal FUNCtion) */ -struct vm_ifunc { - VALUE flags; - VALUE reserved; - rb_block_call_func_t func; - const void *data; - struct vm_ifunc_argc argc; -}; - -#define IFUNC_NEW(a, b, c) ((struct vm_ifunc *)rb_imemo_new(imemo_ifunc, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0)) -struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc); static inline struct vm_ifunc * rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data) { return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS); } -typedef 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 */ -} rb_imemo_tmpbuf_t; +static inline VALUE +rb_imemo_tmpbuf_auto_free_pointer(void) +{ + return rb_imemo_new(imemo_tmpbuf, 0, 0, 0, 0); +} -#define rb_imemo_tmpbuf_auto_free_pointer() rb_imemo_new(imemo_tmpbuf, 0, 0, 0, 0) -rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt); - -#define RB_IMEMO_TMPBUF_PTR(v) \ - ((void *)(((const struct rb_imemo_tmpbuf_struct *)(v))->ptr)) +static inline void * +RB_IMEMO_TMPBUF_PTR(VALUE v) +{ + const struct rb_imemo_tmpbuf_struct *p = (const void *)v; + return p->ptr; +} static inline void * rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr) @@ -162,51 +222,16 @@ rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str) return imemo; } -void rb_strterm_mark(VALUE obj); +static inline void +MEMO_V1_SET(struct MEMO *m, VALUE v) +{ + RB_OBJ_WRITE(m, &m->v1, v); +} -/*! 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 MEMO_V1_SET(m, v) RB_OBJ_WRITE((m), &(m)->v1, (v)) -#define MEMO_V2_SET(m, v) RB_OBJ_WRITE((m), &(m)->v2, (v)) - -#define MEMO_CAST(m) ((struct MEMO *)m) - -#define MEMO_NEW(a, b, c) ((struct MEMO *)rb_imemo_new(imemo_memo, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0)) - -#define roomof(x, y) (((x) + (y) - 1) / (y)) -#define type_roomof(x, y) roomof(sizeof(x), sizeof(y)) -#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value)) -#define NEW_MEMO_FOR(type, value) \ - ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value)) -#define NEW_PARTIAL_MEMO_FOR(type, value, member) \ - ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), \ - rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \ - MEMO_FOR(type, value)) - -/* ment is in method.h */ - -RUBY_SYMBOL_EXPORT_BEGIN -#if IMEMO_DEBUG -VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line); -#define rb_imemo_new(type, v1, v2, v3, v0) rb_imemo_new_debug(type, v1, v2, v3, v0, __FILE__, __LINE__) -#else -VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0); -#endif -RUBY_SYMBOL_EXPORT_END +static inline void +MEMO_V2_SET(struct MEMO *m, VALUE v) +{ + RB_OBJ_WRITE(m, &m->v2, v); +} #endif /* INTERNAL_IMEMO_H */ diff --git a/proc.c b/proc.c index 01890b11bb..e7178bebf5 100644 --- a/proc.c +++ b/proc.c @@ -721,7 +721,8 @@ rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int m } arity.argc.min = min_argc; arity.argc.max = max_argc; - return IFUNC_NEW(func, data, arity.packed); + VALUE ret = rb_imemo_new(imemo_ifunc, (VALUE)func, (VALUE)data, arity.packed, 0); + return (struct vm_ifunc *)ret; } MJIT_FUNC_EXPORTED VALUE