diff options
Diffstat (limited to 'internal')
-rw-r--r-- | internal/array.h | 29 | ||||
-rw-r--r-- | internal/basic_operators.h | 1 | ||||
-rw-r--r-- | internal/bits.h | 20 | ||||
-rw-r--r-- | internal/class.h | 72 | ||||
-rw-r--r-- | internal/cmdlineopt.h | 6 | ||||
-rw-r--r-- | internal/compile.h | 1 | ||||
-rw-r--r-- | internal/cont.h | 3 | ||||
-rw-r--r-- | internal/encoding.h | 4 | ||||
-rw-r--r-- | internal/error.h | 5 | ||||
-rw-r--r-- | internal/eval.h | 1 | ||||
-rw-r--r-- | internal/gc.h | 87 | ||||
-rw-r--r-- | internal/hash.h | 7 | ||||
-rw-r--r-- | internal/imemo.h | 35 | ||||
-rw-r--r-- | internal/inits.h | 3 | ||||
-rw-r--r-- | internal/io.h | 102 | ||||
-rw-r--r-- | internal/missing.h | 1 | ||||
-rw-r--r-- | internal/numeric.h | 3 | ||||
-rw-r--r-- | internal/object.h | 4 | ||||
-rw-r--r-- | internal/parse.h | 106 | ||||
-rw-r--r-- | internal/random.h | 1 | ||||
-rw-r--r-- | internal/re.h | 2 | ||||
-rw-r--r-- | internal/ruby_parser.h | 102 | ||||
-rw-r--r-- | internal/sanitizers.h | 159 | ||||
-rw-r--r-- | internal/signal.h | 5 | ||||
-rw-r--r-- | internal/st.h | 11 | ||||
-rw-r--r-- | internal/string.h | 45 | ||||
-rw-r--r-- | internal/struct.h | 30 | ||||
-rw-r--r-- | internal/symbol.h | 3 | ||||
-rw-r--r-- | internal/thread.h | 5 | ||||
-rw-r--r-- | internal/transcode.h | 3 | ||||
-rw-r--r-- | internal/variable.h | 58 | ||||
-rw-r--r-- | internal/vm.h | 19 |
32 files changed, 732 insertions, 201 deletions
diff --git a/internal/array.h b/internal/array.h index 7e55b66a87..39f6fcbea6 100644 --- a/internal/array.h +++ b/internal/array.h @@ -40,8 +40,6 @@ VALUE rb_ary_diff(VALUE ary1, VALUE ary2); static inline VALUE rb_ary_entry_internal(VALUE ary, long offset); static inline bool ARY_PTR_USING_P(VALUE ary); -static inline void RARY_TRANSIENT_SET(VALUE ary); -static inline void RARY_TRANSIENT_UNSET(VALUE ary); VALUE rb_ary_tmp_new_from_values(VALUE, long, const VALUE *); VALUE rb_check_to_array(VALUE ary); @@ -56,7 +54,7 @@ static inline VALUE rb_ary_entry_internal(VALUE ary, long offset) { long len = RARRAY_LEN(ary); - const VALUE *ptr = RARRAY_CONST_PTR_TRANSIENT(ary); + const VALUE *ptr = RARRAY_CONST_PTR(ary); if (len == 0) return Qnil; if (offset < 0) { offset += len; @@ -118,22 +116,6 @@ ARY_SHARED_ROOT_REFCNT(VALUE ary) return RARRAY(ary)->as.heap.aux.capa; } -static inline void -RARY_TRANSIENT_SET(VALUE ary) -{ -#if USE_TRANSIENT_HEAP - FL_SET_RAW(ary, RARRAY_TRANSIENT_FLAG); -#endif -} - -static inline void -RARY_TRANSIENT_UNSET(VALUE ary) -{ -#if USE_TRANSIENT_HEAP - FL_UNSET_RAW(ary, RARRAY_TRANSIENT_FLAG); -#endif -} - #undef rb_ary_new_from_args #if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments") # /* Skip it; clang -pedantic doesn't like the following */ @@ -154,9 +136,16 @@ RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RARRAY_AREF(VALUE ary, long i) { + VALUE val; RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); - return RARRAY_CONST_PTR_TRANSIENT(ary)[i]; + RBIMPL_WARNING_PUSH(); +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 13 + RBIMPL_WARNING_IGNORED(-Warray-bounds); +#endif + val = RARRAY_CONST_PTR(ary)[i]; + RBIMPL_WARNING_POP(); + return val; } #endif /* INTERNAL_ARRAY_H */ diff --git a/internal/basic_operators.h b/internal/basic_operators.h index a59403631e..4732a65403 100644 --- a/internal/basic_operators.h +++ b/internal/basic_operators.h @@ -37,6 +37,7 @@ enum ruby_basic_operators { BOP_OR, BOP_CMP, BOP_DEFAULT, + BOP_PACK, BOP_LAST_ }; diff --git a/internal/bits.h b/internal/bits.h index 6248e4cfa9..1fe98fa430 100644 --- a/internal/bits.h +++ b/internal/bits.h @@ -118,12 +118,16 @@ MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX) #endif -#ifdef MUL_OVERFLOW_P +#if defined(MUL_OVERFLOW_P) && defined(USE___BUILTIN_MUL_OVERFLOW_LONG_LONG) # define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_P(a, b) +#else +# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX) +#endif + +#ifdef MUL_OVERFLOW_P # define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_P(a, b) # define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_P(a, b) #else -# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX) # define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX) # define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX) #endif @@ -394,9 +398,9 @@ rb_popcount32(uint32_t x) #else x = (x & 0x55555555) + (x >> 1 & 0x55555555); x = (x & 0x33333333) + (x >> 2 & 0x33333333); - x = (x & 0x0f0f0f0f) + (x >> 4 & 0x0f0f0f0f); - x = (x & 0x001f001f) + (x >> 8 & 0x001f001f); - x = (x & 0x0000003f) + (x >>16 & 0x0000003f); + x = (x & 0x07070707) + (x >> 4 & 0x07070707); + x = (x & 0x000f000f) + (x >> 8 & 0x000f000f); + x = (x & 0x0000001f) + (x >>16 & 0x0000001f); return (unsigned int)x; #endif @@ -424,9 +428,9 @@ rb_popcount64(uint64_t x) x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555); x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333); x = (x & 0x0707070707070707) + (x >> 4 & 0x0707070707070707); - x = (x & 0x001f001f001f001f) + (x >> 8 & 0x001f001f001f001f); - x = (x & 0x0000003f0000003f) + (x >>16 & 0x0000003f0000003f); - x = (x & 0x000000000000007f) + (x >>32 & 0x000000000000007f); + x = (x & 0x000f000f000f000f) + (x >> 8 & 0x000f000f000f000f); + x = (x & 0x0000001f0000001f) + (x >>16 & 0x0000001f0000001f); + x = (x & 0x000000000000003f) + (x >>32 & 0x000000000000003f); return (unsigned int)x; #endif diff --git a/internal/class.h b/internal/class.h index d76da84bd1..8a6c956233 100644 --- a/internal/class.h +++ b/internal/class.h @@ -19,6 +19,7 @@ #include "shape.h" #include "ruby_assert.h" #include "vm_core.h" +#include "vm_sync.h" #include "method.h" /* for rb_cref_t */ #ifdef RCLASS_SUPER @@ -43,7 +44,7 @@ struct rb_classext_struct { VALUE *iv_ptr; struct rb_id_table *const_tbl; struct rb_id_table *callable_m_tbl; - struct rb_id_table *cc_tbl; /* ID -> [[ci, cc1], cc2, ...] */ + struct rb_id_table *cc_tbl; /* ID -> [[ci1, cc1], [ci2, cc2] ...] */ struct rb_id_table *cvc_tbl; size_t superclass_depth; VALUE *superclasses; @@ -85,7 +86,12 @@ struct RClass { // Assert that classes can be embedded in size_pools[2] (which has 160B slot size) STATIC_ASSERT(sizeof_rb_classext_t, sizeof(struct RClass) + sizeof(rb_classext_t) <= 4 * RVALUE_SIZE); -#define RCLASS_EXT(c) ((rb_classext_t *)((char *)(c) + sizeof(struct RClass))) +struct RClass_and_rb_classext_t { + struct RClass rclass; + rb_classext_t classext; +}; + +#define RCLASS_EXT(c) (&((struct RClass_and_rb_classext_t*)(c))->classext) #define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) #define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) #define RCLASS_IVPTR(c) (RCLASS_EXT(c)->iv_ptr) @@ -102,10 +108,56 @@ STATIC_ASSERT(sizeof_rb_classext_t, sizeof(struct RClass) + sizeof(rb_classext_t #define RCLASS_SUPERCLASSES(c) (RCLASS_EXT(c)->superclasses) #define RCLASS_ATTACHED_OBJECT(c) (RCLASS_EXT(c)->as.singleton_class.attached_object) +#define RCLASS_IS_ROOT FL_USER0 #define RICLASS_IS_ORIGIN FL_USER0 #define RCLASS_SUPERCLASSES_INCLUDE_SELF FL_USER2 #define RICLASS_ORIGIN_SHARED_MTBL FL_USER3 +static inline st_table * +RCLASS_IV_HASH(VALUE obj) +{ + RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE)); + RUBY_ASSERT(rb_shape_obj_too_complex(obj)); + return (st_table *)RCLASS_IVPTR(obj); +} + +static inline void +RCLASS_SET_IV_HASH(VALUE obj, const st_table *tbl) +{ + RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE)); + RUBY_ASSERT(rb_shape_obj_too_complex(obj)); + RCLASS_IVPTR(obj) = (VALUE *)tbl; +} + +static inline uint32_t +RCLASS_IV_COUNT(VALUE obj) +{ + RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE)); + if (rb_shape_obj_too_complex(obj)) { + uint32_t count; + + // "Too complex" classes could have their IV hash mutated in + // parallel, so lets lock around getting the hash size. + RB_VM_LOCK_ENTER(); + { + count = (uint32_t)rb_st_table_size(RCLASS_IV_HASH(obj)); + } + RB_VM_LOCK_LEAVE(); + + return count; + } + else { + return rb_shape_get_shape_by_id(RCLASS_SHAPE_ID(obj))->next_iv_index; + } +} + +static inline void +RCLASS_SET_M_TBL(VALUE klass, struct rb_id_table *table) +{ + RUBY_ASSERT(!RB_OBJ_PROMOTED(klass)); + RCLASS_M_TBL(klass) = table; +} + /* class.c */ void rb_class_subclass_add(VALUE super, VALUE klass); void rb_class_remove_from_super_subclasses(VALUE); @@ -124,6 +176,7 @@ void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE); void rb_class_detach_subclasses(VALUE); void rb_class_detach_module_subclasses(VALUE); void rb_class_remove_from_module_subclasses(VALUE); +VALUE rb_define_class_id_under_no_pin(VALUE outer, ID id, VALUE super); VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj); VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj); VALUE rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj); @@ -143,11 +196,17 @@ static inline void RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass); VALUE rb_class_inherited(VALUE, VALUE); VALUE rb_keyword_error_new(const char *, VALUE); +static inline bool +RCLASS_SINGLETON_P(VALUE klass) +{ + return RB_TYPE_P(klass, T_CLASS) && FL_TEST_RAW(klass, FL_SINGLETON); +} + static inline rb_alloc_func_t RCLASS_ALLOCATOR(VALUE klass) { - if (FL_TEST_RAW(klass, FL_SINGLETON)) { - return NULL; + if (RCLASS_SINGLETON_P(klass)) { + return 0; } return RCLASS_EXT(klass)->as.class.allocator; } @@ -155,7 +214,7 @@ RCLASS_ALLOCATOR(VALUE klass) static inline void RCLASS_SET_ALLOCATOR(VALUE klass, rb_alloc_func_t allocator) { - assert(!FL_TEST(klass, FL_SINGLETON)); + assert(!RCLASS_SINGLETON_P(klass)); RCLASS_EXT(klass)->as.class.allocator = allocator; } @@ -215,8 +274,7 @@ RCLASS_SET_CLASSPATH(VALUE klass, VALUE classpath, bool permanent) static inline VALUE RCLASS_SET_ATTACHED_OBJECT(VALUE klass, VALUE attached_object) { - assert(BUILTIN_TYPE(klass) == T_CLASS); - assert(FL_TEST_RAW(klass, FL_SINGLETON)); + assert(RCLASS_SINGLETON_P(klass)); RB_OBJ_WRITE(klass, &RCLASS_EXT(klass)->as.singleton_class.attached_object, attached_object); return attached_object; diff --git a/internal/cmdlineopt.h b/internal/cmdlineopt.h index 483a5d4f75..e79b993345 100644 --- a/internal/cmdlineopt.h +++ b/internal/cmdlineopt.h @@ -23,11 +23,15 @@ typedef struct ruby_cmdline_options { ruby_features_t features; ruby_features_t warn; unsigned int dump; + long backtrace_length_limit; #if USE_RJIT struct rb_rjit_options rjit; #endif - int sflag, xflag; + const char *crash_report; + + signed int sflag: 2; + unsigned int xflag: 1; unsigned int warning: 1; unsigned int verbose: 1; unsigned int do_loop: 1; diff --git a/internal/compile.h b/internal/compile.h index eebb7605cd..2ece5396f6 100644 --- a/internal/compile.h +++ b/internal/compile.h @@ -17,7 +17,6 @@ struct rb_iseq_struct; /* in vm_core.h */ /* compile.c */ int rb_dvar_defined(ID, const struct rb_iseq_struct *); int rb_local_defined(ID, const struct rb_iseq_struct *); -bool rb_insns_leaf_p(int i); int rb_insn_len(VALUE insn); const char *rb_insns_name(int i); VALUE rb_insns_name_array(void); diff --git a/internal/cont.h b/internal/cont.h index c3b091668a..3c2528a02a 100644 --- a/internal/cont.h +++ b/internal/cont.h @@ -22,6 +22,9 @@ void rb_jit_cont_init(void); void rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data); void rb_jit_cont_finish(void); +/* vm.c */ +void rb_free_shared_fiber_pool(void); + // Copy locals from the current execution to the specified fiber. VALUE rb_fiber_inherit_storage(struct rb_execution_context_struct *ec, struct rb_fiber_struct *fiber); diff --git a/internal/encoding.h b/internal/encoding.h index a3b81bd388..fe9ea10ec4 100644 --- a/internal/encoding.h +++ b/internal/encoding.h @@ -18,6 +18,7 @@ /* encoding.c */ ID rb_id_encoding(void); +const char * rb_enc_inspect_name(rb_encoding *enc); rb_encoding *rb_enc_get_from_index(int index); rb_encoding *rb_enc_check_str(VALUE str1, VALUE str2); int rb_encdb_replicate(const char *alias, const char *orig); @@ -29,4 +30,7 @@ void rb_enc_set_base(const char *name, const char *orig); int rb_enc_set_dummy(int index); PUREFUNC(int rb_data_is_encoding(VALUE obj)); +/* vm.c */ +void rb_free_global_enc_table(void); + #endif /* INTERNAL_ENCODING_H */ diff --git a/internal/error.h b/internal/error.h index 5fee468929..7a4daca6b3 100644 --- a/internal/error.h +++ b/internal/error.h @@ -142,6 +142,8 @@ VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*, PRINTF_ARGS(void rb_enc_warn(rb_encoding *enc, const char *fmt, ...), 2, 3); PRINTF_ARGS(void rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...), 2, 3); PRINTF_ARGS(void rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...), 3, 4); +PRINTF_ARGS(void rb_enc_compile_warning(rb_encoding *enc, const char *file, int line, const char *fmt, ...), 4, 5); +PRINTF_ARGS(void rb_enc_compile_warn(rb_encoding *enc, const char *file, int line, const char *fmt, ...), 4, 5); rb_warning_category_t rb_warning_category_from_name(VALUE category); bool rb_warning_category_enabled_p(rb_warning_category_t category); VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method); @@ -169,6 +171,9 @@ VALUE rb_syserr_new_path_in(const char *func_name, int n, VALUE path); #endif RUBY_SYMBOL_EXPORT_END +/* vm.c */ +void rb_free_warning(void); + static inline void rb_raise_cstr_i(VALUE etype, VALUE mesg) { diff --git a/internal/eval.h b/internal/eval.h index 73bb656d96..e594d8516d 100644 --- a/internal/eval.h +++ b/internal/eval.h @@ -21,6 +21,7 @@ extern ID ruby_static_id_status; VALUE rb_refinement_module_get_refined_class(VALUE module); void rb_class_modify_check(VALUE); NORETURN(VALUE rb_f_raise(int argc, VALUE *argv)); +VALUE rb_top_main_class(const char *method); /* eval_error.c */ VALUE rb_get_backtrace(VALUE info); diff --git a/internal/gc.h b/internal/gc.h index d19b09f6fc..ecc3f11b2c 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -16,6 +16,10 @@ #include "ruby/ruby.h" /* for rb_event_flag_t */ #include "vm_core.h" /* for GET_EC() */ +#ifndef USE_SHARED_GC +# define USE_SHARED_GC 0 +#endif + #if defined(__x86_64__) && !defined(_ILP32) && defined(__GNUC__) #define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movq\t%%rsp, %0" : "=r" (*(p))) #elif defined(__i386) && defined(__GNUC__) @@ -79,14 +83,6 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr) #define RUBY_GC_INFO if(0)printf #endif -#define RUBY_MARK_MOVABLE_UNLESS_NULL(ptr) do { \ - VALUE markobj = (ptr); \ - if (RTEST(markobj)) {rb_gc_mark_movable(markobj);} \ -} while (0) -#define RUBY_MARK_UNLESS_NULL(ptr) do { \ - VALUE markobj = (ptr); \ - if (RTEST(markobj)) {rb_gc_mark(markobj);} \ -} while (0) #define RUBY_FREE_UNLESS_NULL(ptr) if(ptr){ruby_xfree(ptr);(ptr)=NULL;} #if STACK_GROW_DIRECTION > 0 @@ -123,30 +119,14 @@ int ruby_get_stack_grow_direction(volatile VALUE *addr); const char *rb_obj_info(VALUE obj); const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj); -size_t rb_size_pool_slot_size(unsigned char pool_id); - struct rb_execution_context_struct; /* in vm_core.h */ struct rb_objspace; /* in vm_core.h */ -#ifdef NEWOBJ_OF -# undef NEWOBJ_OF -# undef RB_NEWOBJ_OF -#endif - -#define NEWOBJ_OF_0(var, T, c, f, s, ec) \ - T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \ - rb_wb_protected_newobj_of(GET_EC(), (c), (f) & ~FL_WB_PROTECTED, s) : \ - rb_wb_unprotected_newobj_of((c), (f), s)) -#define NEWOBJ_OF_ec(var, T, c, f, s, ec) \ +#define NEWOBJ_OF(var, T, c, f, s, ec) \ T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \ - rb_wb_protected_newobj_of((ec), (c), (f) & ~FL_WB_PROTECTED, s) : \ + rb_wb_protected_newobj_of((ec ? ec : GET_EC()), (c), (f) & ~FL_WB_PROTECTED, s) : \ rb_wb_unprotected_newobj_of((c), (f), s)) -#define NEWOBJ_OF(var, T, c, f, s, ec) \ - NEWOBJ_OF_HELPER(ec)(var, T, c, f, s, ec) - -#define NEWOBJ_OF_HELPER(ec) NEWOBJ_OF_ ## ec - #define RB_OBJ_GC_FLAGS_MAX 6 /* used in ext/objspace */ #ifndef USE_UNALIGNED_MEMBER_ACCESS @@ -189,6 +169,17 @@ struct rb_objspace; /* in vm_core.h */ # define SIZE_POOL_COUNT 5 #endif +/* Used in places that could malloc during, which can cause the GC to run. We + * need to temporarily disable the GC to allow the malloc to happen. + * Allocating memory during GC is a bad idea, so use this only when absolutely + * necessary. */ +#define DURING_GC_COULD_MALLOC_REGION_START() \ + assert(rb_during_gc()); \ + VALUE _already_disabled = rb_gc_disable_no_rest() + +#define DURING_GC_COULD_MALLOC_REGION_END() \ + if (_already_disabled == Qfalse) rb_gc_enable() + typedef struct ractor_newobj_size_pool_cache { struct RVALUE *freelist; struct heap_page *using_page; @@ -200,21 +191,19 @@ typedef struct ractor_newobj_cache { } rb_ractor_newobj_cache_t; /* gc.c */ -extern VALUE *ruby_initial_gc_stress_ptr; extern int ruby_disable_gc; RUBY_ATTR_MALLOC void *ruby_mimmalloc(size_t size); +RUBY_ATTR_MALLOC void *ruby_mimcalloc(size_t num, size_t size); void ruby_mimfree(void *ptr); +void rb_gc_prepare_heap(void); void rb_objspace_set_event_hook(const rb_event_flag_t event); VALUE rb_objspace_gc_enable(struct rb_objspace *); VALUE rb_objspace_gc_disable(struct rb_objspace *); void ruby_gc_set_params(void); -void rb_copy_wb_protected_attribute(VALUE dest, VALUE obj); -#if __has_attribute(alloc_align) -__attribute__((__alloc_align__(1))) -#endif -RUBY_ATTR_MALLOC void *rb_aligned_malloc(size_t, size_t) RUBY_ATTR_ALLOC_SIZE((2)); +void rb_gc_copy_attributes(VALUE dest, VALUE obj); size_t rb_size_mul_or_raise(size_t, size_t, VALUE); /* used in compile.c */ size_t rb_size_mul_add_or_raise(size_t, size_t, size_t, VALUE); /* used in iseq.h */ +size_t rb_malloc_grow_capa(size_t current_capacity, size_t type_size); RUBY_ATTR_MALLOC void *rb_xmalloc_mul_add(size_t, size_t, size_t); RUBY_ATTR_MALLOC void *rb_xcalloc_mul_add(size_t, size_t, size_t); void *rb_xrealloc_mul_add(const void *, size_t, size_t, size_t); @@ -223,17 +212,22 @@ RUBY_ATTR_MALLOC void *rb_xcalloc_mul_add_mul(size_t, size_t, size_t, size_t); static inline void *ruby_sized_xrealloc_inlined(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2)); static inline void *ruby_sized_xrealloc2_inlined(void *ptr, size_t new_count, size_t elemsiz, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3)); static inline void ruby_sized_xfree_inlined(void *ptr, size_t size); -VALUE rb_class_allocate_instance(VALUE klass); void rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache); -size_t rb_gc_obj_slot_size(VALUE obj); bool rb_gc_size_allocatable_p(size_t size); +size_t *rb_gc_size_pool_sizes(void); +size_t rb_gc_size_pool_id_for_size(size_t size); int rb_objspace_garbage_object_p(VALUE obj); -bool rb_gc_is_ptr_to_obj(void *ptr); -VALUE rb_gc_id2ref_obj_tbl(VALUE objid); -VALUE rb_define_finalizer_no_check(VALUE obj, VALUE block); +bool rb_gc_is_ptr_to_obj(const void *ptr); void rb_gc_mark_and_move(VALUE *ptr); +void rb_gc_mark_weak(VALUE *ptr); +void rb_gc_remove_weak(VALUE parent_obj, VALUE *ptr); + +void rb_gc_ref_update_table_values_only(st_table *tbl); + +void rb_gc_initial_stress_set(VALUE flag); + #define rb_gc_mark_and_move_ptr(ptr) do { \ VALUE _obj = (VALUE)*(ptr); \ rb_gc_mark_and_move(&_obj); \ @@ -242,21 +236,15 @@ void rb_gc_mark_and_move(VALUE *ptr); RUBY_SYMBOL_EXPORT_BEGIN /* exports for objspace module */ -size_t rb_objspace_data_type_memsize(VALUE obj); void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data); void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *data); int rb_objspace_markable_object_p(VALUE obj); int rb_objspace_internal_object_p(VALUE obj); -int rb_objspace_marked_object_p(VALUE obj); void rb_objspace_each_objects( int (*callback)(void *start, void *end, size_t stride, void *data), void *data); -void rb_objspace_each_objects_without_setup( - int (*callback)(void *, void *, size_t, void *), - void *data); - size_t rb_gc_obj_slot_size(VALUE obj); VALUE rb_gc_disable_no_rest(void); @@ -271,6 +259,7 @@ void rb_gc_verify_internal_consistency(void); size_t rb_obj_gc_flags(VALUE, ID[], size_t); void rb_gc_mark_values(long n, const VALUE *values); void rb_gc_mark_vm_stack_values(long n, const VALUE *values); +void rb_gc_update_values(long n, VALUE *values); void *ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2)); void *ruby_sized_xrealloc2(void *ptr, size_t new_count, size_t element_size, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3)); void ruby_sized_xfree(void *x, size_t size); @@ -302,6 +291,12 @@ ruby_sized_xfree_inlined(void *ptr, size_t size) # define SIZED_REALLOC_N(x, y, z, w) REALLOC_N(x, y, z) +static inline void * +ruby_sized_realloc_n(void *ptr, size_t new_count, size_t element_size, size_t old_count) +{ + return ruby_xrealloc2(ptr, new_count, element_size); +} + #else static inline void * @@ -325,6 +320,12 @@ ruby_sized_xfree_inlined(void *ptr, size_t size) # define SIZED_REALLOC_N(v, T, m, n) \ ((v) = (T *)ruby_sized_xrealloc2((void *)(v), (m), sizeof(T), (n))) +static inline void * +ruby_sized_realloc_n(void *ptr, size_t new_count, size_t element_size, size_t old_count) +{ + return ruby_sized_xrealloc2(ptr, new_count, element_size, old_count); +} + #endif /* HAVE_MALLOC_USABLE_SIZE */ #define ruby_sized_xrealloc ruby_sized_xrealloc_inlined diff --git a/internal/hash.h b/internal/hash.h index 3874abeaa5..fe859cb716 100644 --- a/internal/hash.h +++ b/internal/hash.h @@ -28,10 +28,6 @@ enum ruby_rhash_flags { RHASH_AR_TABLE_BOUND_MASK = (FL_USER8|FL_USER9|FL_USER10|FL_USER11), /* FL 8..11 */ RHASH_AR_TABLE_BOUND_SHIFT = (FL_USHIFT+8), -#if USE_TRANSIENT_HEAP - RHASH_TRANSIENT_FLAG = FL_USER12, /* FL 12 */ -#endif - // we can not put it in "enum" because it can exceed "int" range. #define RHASH_LEV_MASK (FL_USER13 | FL_USER14 | FL_USER15 | /* FL 13..19 */ \ FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19) @@ -91,6 +87,7 @@ int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval); int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg); int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func, st_data_t arg); VALUE rb_ident_hash_new_with_size(st_index_t size); +void rb_hash_free(VALUE hash); static inline unsigned RHASH_AR_TABLE_SIZE_RAW(VALUE h); static inline VALUE RHASH_IFNONE(VALUE h); @@ -128,12 +125,14 @@ RHASH_AR_TABLE_P(VALUE h) return ! FL_TEST_RAW(h, RHASH_ST_TABLE_FLAG); } +RBIMPL_ATTR_RETURNS_NONNULL() static inline struct ar_table_struct * RHASH_AR_TABLE(VALUE h) { return (struct ar_table_struct *)((uintptr_t)h + sizeof(struct RHash)); } +RBIMPL_ATTR_RETURNS_NONNULL() static inline st_table * RHASH_ST_TABLE(VALUE h) { diff --git a/internal/imemo.h b/internal/imemo.h index 57a705ce77..36c0776987 100644 --- a/internal/imemo.h +++ b/internal/imemo.h @@ -39,7 +39,7 @@ enum imemo_type { imemo_ment = 6, imemo_iseq = 7, imemo_tmpbuf = 8, - imemo_ast = 9, + imemo_ast = 9, // Obsolete due to the universal parser imemo_parser_strterm = 10, imemo_callinfo = 11, imemo_callcache = 12, @@ -113,11 +113,12 @@ struct MEMO { } u3; }; +#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0))) + /* ment is in method.h */ #define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err) #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 MEMO_FOR(type, value) ((type *)RARRAY_PTR(value)) #define NEW_MEMO_FOR(type, value) \ ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value)) @@ -126,10 +127,11 @@ struct MEMO { rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \ MEMO_FOR(type, value)) +#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); 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); @@ -141,16 +143,33 @@ static inline VALUE rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE static inline void MEMO_V1_SET(struct MEMO *m, VALUE v); static inline void MEMO_V2_SET(struct MEMO *m, VALUE v); +size_t rb_imemo_memsize(VALUE obj); +void rb_cc_table_mark(VALUE klass); +void rb_imemo_mark_and_move(VALUE obj, bool reference_updating); +void rb_cc_table_free(VALUE klass); +void rb_imemo_free(VALUE obj); + 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); +VALUE rb_imemo_new_debug(enum imemo_type type, 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); +VALUE rb_imemo_new(enum imemo_type type, VALUE v0); #endif 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) { @@ -172,7 +191,7 @@ imemo_type_p(VALUE imemo, enum imemo_type imemo_type) } } -#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)v, t) +#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)(v), t) static inline bool imemo_throw_data_p(VALUE imemo) @@ -189,7 +208,7 @@ rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data) static inline VALUE rb_imemo_tmpbuf_auto_free_pointer(void) { - return rb_imemo_new(imemo_tmpbuf, 0, 0, 0, 0); + return rb_imemo_new(imemo_tmpbuf, 0); } static inline void * @@ -214,7 +233,7 @@ rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str) void *dst; size_t len; - SafeStringValue(str); + StringValue(str); /* create tmpbuf to keep the pointer before xmalloc */ imemo = rb_imemo_tmpbuf_auto_free_pointer(); tmpbuf = (rb_imemo_tmpbuf_t *)imemo; diff --git a/internal/inits.h b/internal/inits.h index 03e180f77b..03de289dd4 100644 --- a/internal/inits.h +++ b/internal/inits.h @@ -19,9 +19,6 @@ void Init_ext(void); /* file.c */ void Init_File(void); -/* gc.c */ -void Init_heap(void); - /* localeinit.c */ int Init_enc_set_filesystem_encoding(void); diff --git a/internal/io.h b/internal/io.h index b5f15499d7..1891248a19 100644 --- a/internal/io.h +++ b/internal/io.h @@ -9,8 +9,110 @@ * @brief Internal header for IO. */ #include "ruby/ruby.h" /* for VALUE */ + +#define HAVE_RB_IO_T +struct rb_io; + #include "ruby/io.h" /* for rb_io_t */ +#define IO_WITHOUT_GVL(func, arg) rb_thread_call_without_gvl(func, arg, RUBY_UBF_IO, 0) +#define IO_WITHOUT_GVL_INT(func, arg) (int)(VALUE)IO_WITHOUT_GVL(func, arg) + +/** Ruby's IO, metadata and buffers. */ +struct rb_io { + + /** The IO's Ruby level counterpart. */ + VALUE self; + + /** stdio ptr for read/write, if available. */ + FILE *stdio_file; + + /** file descriptor. */ + int fd; + + /** mode flags: FMODE_XXXs */ + int mode; + + /** child's pid (for pipes) */ + rb_pid_t pid; + + /** number of lines read */ + int lineno; + + /** pathname for file */ + VALUE pathv; + + /** finalize proc */ + void (*finalize)(struct rb_io*,int); + + /** Write buffer. */ + rb_io_buffer_t wbuf; + + /** + * (Byte) read buffer. Note also that there is a field called + * ::rb_io_t::cbuf, which also concerns read IO. + */ + rb_io_buffer_t rbuf; + + /** + * Duplex IO object, if set. + * + * @see rb_io_set_write_io() + */ + VALUE tied_io_for_writing; + + struct rb_io_encoding encs; /**< Decomposed encoding flags. */ + + /** Encoding converter used when reading from this IO. */ + rb_econv_t *readconv; + + /** + * rb_io_ungetc() destination. This buffer is read before checking + * ::rb_io_t::rbuf + */ + rb_io_buffer_t cbuf; + + /** Encoding converter used when writing to this IO. */ + rb_econv_t *writeconv; + + /** + * This is, when set, an instance of ::rb_cString which holds the "common" + * encoding. Write conversion can convert strings twice... In case + * conversion from encoding X to encoding Y does not exist, Ruby finds an + * encoding Z that bridges the two, so that X to Z to Y conversion happens. + */ + VALUE writeconv_asciicompat; + + /** Whether ::rb_io_t::writeconv is already set up. */ + int writeconv_initialized; + + /** + * Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before + * initialising ::rb_io_t::writeconv. + */ + int writeconv_pre_ecflags; + + /** + * Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising + * ::rb_io_t::writeconv. + */ + VALUE writeconv_pre_ecopts; + + /** + * This is a Ruby level mutex. It avoids multiple threads to write to an + * IO at once; helps for instance rb_io_puts() to ensure newlines right + * next to its arguments. + * + * This of course doesn't help inter-process IO interleaves, though. + */ + VALUE write_lock; + + /** + * The timeout associated with this IO when performing blocking operations. + */ + VALUE timeout; +}; + /* io.c */ void ruby_set_inplace_mode(const char *); void rb_stdio_set_default_encoding(void); diff --git a/internal/missing.h b/internal/missing.h index c0992a151a..6ca508c8f9 100644 --- a/internal/missing.h +++ b/internal/missing.h @@ -13,6 +13,7 @@ /* missing/setproctitle.c */ #ifndef HAVE_SETPROCTITLE extern void ruby_init_setproctitle(int argc, char *argv[]); +extern void ruby_free_proctitle(void); #endif #endif /* INTERNAL_MISSING_H */ diff --git a/internal/numeric.h b/internal/numeric.h index f7b8d0ad2d..6406cfc2fa 100644 --- a/internal/numeric.h +++ b/internal/numeric.h @@ -86,6 +86,7 @@ VALUE rb_int_equal(VALUE x, VALUE y); VALUE rb_int_divmod(VALUE x, VALUE y); VALUE rb_int_and(VALUE x, VALUE y); VALUE rb_int_lshift(VALUE x, VALUE y); +VALUE rb_int_rshift(VALUE x, VALUE y); VALUE rb_int_div(VALUE x, VALUE y); int rb_int_positive_p(VALUE num); int rb_int_negative_p(VALUE num); @@ -158,7 +159,7 @@ rb_num_compare_with_zero(VALUE num, ID mid) { VALUE zero = INT2FIX(0); VALUE r = rb_check_funcall(num, mid, 1, &zero); - if (r == Qundef) { + if (RB_UNDEF_P(r)) { rb_cmperr(num, zero); } return r; diff --git a/internal/object.h b/internal/object.h index 58e989562a..92ad37fdc8 100644 --- a/internal/object.h +++ b/internal/object.h @@ -11,10 +11,14 @@ #include "ruby/ruby.h" /* for VALUE */ /* object.c */ +size_t rb_obj_embedded_size(uint32_t numiv); +VALUE rb_class_allocate_instance(VALUE klass); VALUE rb_class_search_ancestor(VALUE klass, VALUE super); NORETURN(void rb_undefined_alloc(VALUE klass)); double rb_num_to_dbl(VALUE val); VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound); +VALUE rb_obj_clone_setup(VALUE obj, VALUE clone, VALUE kwfreeze); +VALUE rb_obj_dup_setup(VALUE obj, VALUE dup); VALUE rb_immutable_obj_clone(int, VALUE *, VALUE); VALUE rb_check_convert_type_with_id(VALUE,int,const char*,ID); int rb_bool_expected(VALUE, const char *, int raise); diff --git a/internal/parse.h b/internal/parse.h index f242c384ad..4a9c4acf8a 100644 --- a/internal/parse.h +++ b/internal/parse.h @@ -8,18 +8,110 @@ * file COPYING are met. Consult the file for details. * @brief Internal header for the parser. */ -#include "ruby/ruby.h" /* for VALUE */ +#include <limits.h> +#include "rubyparser.h" +#include "internal/static_assert.h" + +#ifdef UNIVERSAL_PARSER +#define rb_encoding const void +#endif + struct rb_iseq_struct; /* in vm_core.h */ +/* structs for managing terminator of string literal and heredocment */ +typedef struct rb_strterm_literal_struct { + long nest; + int func; /* STR_FUNC_* (e.g., STR_FUNC_ESCAPE and STR_FUNC_EXPAND) */ + int paren; /* '(' of `%q(...)` */ + int term; /* ')' of `%q(...)` */ +} rb_strterm_literal_t; + +typedef struct rb_strterm_heredoc_struct { + rb_parser_string_t *lastline; /* the string of line that contains `<<"END"` */ + long offset; /* the column of END in `<<"END"` */ + int sourceline; /* lineno of the line that contains `<<"END"` */ + unsigned length; /* the length of END in `<<"END"` */ + uint8_t quote; + uint8_t func; +} rb_strterm_heredoc_t; + +#define HERETERM_LENGTH_MAX UINT_MAX + +typedef struct rb_strterm_struct { + bool heredoc; + union { + rb_strterm_literal_t literal; + rb_strterm_heredoc_t heredoc; + } u; +} rb_strterm_t; + /* parse.y */ -VALUE rb_parser_set_yydebug(VALUE, VALUE); -void *rb_parser_load_file(VALUE parser, VALUE name); -void rb_parser_keep_script_lines(VALUE vparser); -void rb_parser_error_tolerant(VALUE vparser); -void rb_parser_keep_tokens(VALUE vparser); +void rb_ruby_parser_mark(void *ptr); +size_t rb_ruby_parser_memsize(const void *ptr); + +void rb_ruby_parser_set_options(rb_parser_t *p, int print, int loop, int chomp, int split); +rb_parser_t *rb_ruby_parser_set_context(rb_parser_t *p, const struct rb_iseq_struct *base, int main); +void rb_ruby_parser_set_script_lines(rb_parser_t *p); +void rb_ruby_parser_error_tolerant(rb_parser_t *p); +void rb_ruby_parser_keep_tokens(rb_parser_t *p); +typedef rb_parser_string_t*(rb_parser_lex_gets_func)(struct parser_params*, rb_parser_input_data, int); +rb_ast_t *rb_parser_compile(rb_parser_t *p, rb_parser_lex_gets_func *gets, VALUE fname, rb_parser_input_data input, int line); RUBY_SYMBOL_EXPORT_BEGIN -VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int); + +rb_encoding *rb_ruby_parser_encoding(rb_parser_t *p); +int rb_ruby_parser_end_seen_p(rb_parser_t *p); +int rb_ruby_parser_set_yydebug(rb_parser_t *p, int flag); +rb_parser_string_t *rb_str_to_parser_string(rb_parser_t *p, VALUE str); + +int rb_parser_dvar_defined_ref(struct parser_params*, ID, ID**); +ID rb_parser_internal_id(struct parser_params*); +int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int); +int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc); +int rb_parser_local_defined(struct parser_params *p, ID id, const struct rb_iseq_struct *iseq); + RUBY_SYMBOL_EXPORT_END +#ifndef UNIVERSAL_PARSER +rb_parser_t *rb_ruby_parser_allocate(void); +rb_parser_t *rb_ruby_parser_new(void); +#endif + +#ifdef RIPPER +void ripper_parser_mark(void *ptr); +void ripper_parser_free(void *ptr); +size_t ripper_parser_memsize(const void *ptr); +void ripper_error(struct parser_params *p); +VALUE ripper_value(struct parser_params *p); +int rb_ruby_parser_get_yydebug(rb_parser_t *p); +void rb_ruby_parser_set_value(rb_parser_t *p, VALUE value); +int rb_ruby_parser_error_p(rb_parser_t *p); +VALUE rb_ruby_parser_debug_output(rb_parser_t *p); +void rb_ruby_parser_set_debug_output(rb_parser_t *p, VALUE output); +VALUE rb_ruby_parser_parsing_thread(rb_parser_t *p); +void rb_ruby_parser_set_parsing_thread(rb_parser_t *p, VALUE parsing_thread); +void rb_ruby_parser_ripper_initialize(rb_parser_t *p, rb_parser_lex_gets_func *gets, rb_parser_input_data input, VALUE sourcefile_string, const char *sourcefile, int sourceline); +VALUE rb_ruby_parser_result(rb_parser_t *p); +rb_encoding *rb_ruby_parser_enc(rb_parser_t *p); +VALUE rb_ruby_parser_ruby_sourcefile_string(rb_parser_t *p); +int rb_ruby_parser_ruby_sourceline(rb_parser_t *p); +int rb_ruby_parser_lex_state(rb_parser_t *p); +void rb_ruby_ripper_parse0(rb_parser_t *p); +int rb_ruby_ripper_dedent_string(rb_parser_t *p, VALUE string, int width); +int rb_ruby_ripper_initialized_p(rb_parser_t *p); +void rb_ruby_ripper_parser_initialize(rb_parser_t *p); +long rb_ruby_ripper_column(rb_parser_t *p); +long rb_ruby_ripper_token_len(rb_parser_t *p); +rb_parser_string_t *rb_ruby_ripper_lex_lastline(rb_parser_t *p); +VALUE rb_ruby_ripper_lex_state_name(struct parser_params *p, int state); +#ifdef UNIVERSAL_PARSER +rb_parser_t *rb_ripper_parser_params_allocate(const rb_parser_config_t *config); +#endif +struct parser_params *rb_ruby_ripper_parser_allocate(void); +#endif + +#ifdef UNIVERSAL_PARSER +#undef rb_encoding +#endif + #endif /* INTERNAL_PARSE_H */ diff --git a/internal/random.h b/internal/random.h index 231e2d5d7e..127b908e16 100644 --- a/internal/random.h +++ b/internal/random.h @@ -12,5 +12,6 @@ /* random.c */ int ruby_fill_random_bytes(void *, size_t, int); +void rb_free_default_rand_key(void); #endif /* INTERNAL_RANDOM_H */ diff --git a/internal/re.h b/internal/re.h index 7b2505b9a8..3e20114665 100644 --- a/internal/re.h +++ b/internal/re.h @@ -22,7 +22,7 @@ VALUE rb_reg_equal(VALUE re1, VALUE re2); void rb_backref_set_string(VALUE string, long pos, long len); void rb_match_unbusy(VALUE); int rb_match_count(VALUE match); -int rb_match_nth_defined(int nth, VALUE match); VALUE rb_reg_new_ary(VALUE ary, int options); +VALUE rb_reg_last_defined(VALUE match); #endif /* INTERNAL_RE_H */ diff --git a/internal/ruby_parser.h b/internal/ruby_parser.h new file mode 100644 index 0000000000..8e306d18de --- /dev/null +++ b/internal/ruby_parser.h @@ -0,0 +1,102 @@ +#ifndef INTERNAL_RUBY_PARSE_H +#define INTERNAL_RUBY_PARSE_H + +#include "internal.h" +#include "internal/bignum.h" +#include "internal/compilers.h" +#include "internal/complex.h" +#include "internal/parse.h" +#include "internal/rational.h" +#include "rubyparser.h" +#include "vm.h" + +struct lex_pointer_string { + VALUE str; + long ptr; +}; + +RUBY_SYMBOL_EXPORT_BEGIN +#ifdef UNIVERSAL_PARSER +const rb_parser_config_t *rb_ruby_parser_config(void); +rb_parser_t *rb_parser_params_new(void); +#endif +VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int); +VALUE rb_parser_new(void); +VALUE rb_parser_compile_string_path(VALUE vparser, VALUE fname, VALUE src, int line); +VALUE rb_str_new_parser_string(rb_parser_string_t *str); +VALUE rb_str_new_mutable_parser_string(rb_parser_string_t *str); +rb_parser_string_t *rb_parser_lex_get_str(struct parser_params *p, struct lex_pointer_string *ptr_str); + +VALUE rb_node_str_string_val(const NODE *); +VALUE rb_node_sym_string_val(const NODE *); +VALUE rb_node_dstr_string_val(const NODE *); +VALUE rb_node_regx_string_val(const NODE *); +VALUE rb_node_dregx_string_val(const NODE *); +VALUE rb_node_line_lineno_val(const NODE *); +VALUE rb_node_file_path_val(const NODE *); +VALUE rb_node_encoding_val(const NODE *); + +VALUE rb_node_integer_literal_val(const NODE *); +VALUE rb_node_float_literal_val(const NODE *); +VALUE rb_node_rational_literal_val(const NODE *); +VALUE rb_node_imaginary_literal_val(const NODE *); +RUBY_SYMBOL_EXPORT_END + +VALUE rb_parser_end_seen_p(VALUE); +VALUE rb_parser_encoding(VALUE); +VALUE rb_parser_set_yydebug(VALUE, VALUE); +VALUE rb_parser_build_script_lines_from(rb_parser_ary_t *script_lines); +void rb_parser_set_options(VALUE, int, int, int, int); +VALUE rb_parser_load_file(VALUE parser, VALUE name); +void rb_parser_set_script_lines(VALUE vparser); +void rb_parser_error_tolerant(VALUE vparser); +void rb_parser_keep_tokens(VALUE vparser); + +VALUE rb_parser_compile_string(VALUE, const char*, VALUE, int); +VALUE rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE input, int line); +VALUE rb_parser_compile_generic(VALUE vparser, rb_parser_lex_gets_func *lex_gets, VALUE fname, VALUE input, int line); +VALUE rb_parser_compile_array(VALUE vparser, VALUE fname, VALUE array, int start); + +enum lex_state_bits { + EXPR_BEG_bit, /* ignore newline, +/- is a sign. */ + EXPR_END_bit, /* newline significant, +/- is an operator. */ + EXPR_ENDARG_bit, /* ditto, and unbound braces. */ + EXPR_ENDFN_bit, /* ditto, and unbound braces. */ + EXPR_ARG_bit, /* newline significant, +/- is an operator. */ + EXPR_CMDARG_bit, /* newline significant, +/- is an operator. */ + EXPR_MID_bit, /* newline significant, +/- is an operator. */ + EXPR_FNAME_bit, /* ignore newline, no reserved words. */ + EXPR_DOT_bit, /* right after `.', `&.' or `::', no reserved words. */ + EXPR_CLASS_bit, /* immediate after `class', no here document. */ + EXPR_LABEL_bit, /* flag bit, label is allowed. */ + EXPR_LABELED_bit, /* flag bit, just after a label. */ + EXPR_FITEM_bit, /* symbol literal as FNAME. */ + EXPR_MAX_STATE +}; +/* examine combinations */ +enum lex_state_e { +#define DEF_EXPR(n) EXPR_##n = (1 << EXPR_##n##_bit) + DEF_EXPR(BEG), + DEF_EXPR(END), + DEF_EXPR(ENDARG), + DEF_EXPR(ENDFN), + DEF_EXPR(ARG), + DEF_EXPR(CMDARG), + DEF_EXPR(MID), + DEF_EXPR(FNAME), + DEF_EXPR(DOT), + DEF_EXPR(CLASS), + DEF_EXPR(LABEL), + DEF_EXPR(LABELED), + DEF_EXPR(FITEM), + EXPR_VALUE = EXPR_BEG, + EXPR_BEG_ANY = (EXPR_BEG | EXPR_MID | EXPR_CLASS), + EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG), + EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN), + EXPR_NONE = 0 +}; + +VALUE rb_ruby_ast_new(const NODE *const root); +rb_ast_t *rb_ruby_ast_data_get(VALUE ast_value); + +#endif /* INTERNAL_RUBY_PARSE_H */ diff --git a/internal/sanitizers.h b/internal/sanitizers.h index 7b7d166c74..b0eb1fc851 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -16,11 +16,15 @@ #endif #ifdef HAVE_SANITIZER_ASAN_INTERFACE_H -# include <sanitizer/asan_interface.h> +# if __has_feature(address_sanitizer) +# define RUBY_ASAN_ENABLED +# include <sanitizer/asan_interface.h> +# endif #endif #ifdef HAVE_SANITIZER_MSAN_INTERFACE_H # if __has_feature(memory_sanitizer) +# define RUBY_MSAN_ENABLED # include <sanitizer/msan_interface.h> # endif #endif @@ -29,10 +33,10 @@ #include "ruby/ruby.h" /* for VALUE */ #if 0 -#elif __has_feature(memory_sanitizer) && __has_feature(address_sanitizer) +#elif defined(RUBY_ASAN_ENABLED) && defined(RUBY_MSAN_ENABLED) # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ __attribute__((__no_sanitize__("memory, address"), __noinline__)) x -#elif __has_feature(address_sanitizer) +#elif defined(RUBY_ASAN_ENABLED) # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ __attribute__((__no_sanitize__("address"), __noinline__)) x #elif defined(NO_SANITIZE_ADDRESS) @@ -60,13 +64,15 @@ # define NO_SANITIZE(x, y) y #endif -#if !__has_feature(address_sanitizer) +#ifndef RUBY_ASAN_ENABLED # define __asan_poison_memory_region(x, y) # define __asan_unpoison_memory_region(x, y) # define __asan_region_is_poisoned(x, y) 0 +# define __asan_get_current_fake_stack() NULL +# define __asan_addr_is_in_fake_stack(fake_stack, slot, start, end) NULL #endif -#if !__has_feature(memory_sanitizer) +#ifndef RUBY_MSAN_ENABLED # define __msan_allocated_memory(x, y) ((void)(x), (void)(y)) # define __msan_poison(x, y) ((void)(x), (void)(y)) # define __msan_unpoison(x, y) ((void)(x), (void)(y)) @@ -89,7 +95,7 @@ # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0 #endif -/*! +/** * This function asserts that a (continuous) memory region from ptr to size * being "poisoned". Both read / write access to such memory region are * prohibited until properly unpoisoned. The region must be previously @@ -99,8 +105,8 @@ * region to reuse later: poison when you keep it unused, and unpoison when you * reuse. * - * \param[in] ptr pointer to the beginning of the memory region to poison. - * \param[in] size the length of the memory region to poison. + * @param[in] ptr pointer to the beginning of the memory region to poison. + * @param[in] size the length of the memory region to poison. */ static inline void asan_poison_memory_region(const volatile void *ptr, size_t size) @@ -109,10 +115,10 @@ asan_poison_memory_region(const volatile void *ptr, size_t size) __asan_poison_memory_region(ptr, size); } -/*! +/** * This is a variant of asan_poison_memory_region that takes a VALUE. * - * \param[in] obj target object. + * @param[in] obj target object. */ static inline void asan_poison_object(VALUE obj) @@ -121,20 +127,20 @@ asan_poison_object(VALUE obj) asan_poison_memory_region(ptr, SIZEOF_VALUE); } -#if !__has_feature(address_sanitizer) -#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) -#else +#ifdef RUBY_ASAN_ENABLED #define asan_poison_object_if(ptr, obj) do { \ if (ptr) asan_poison_object(obj); \ } while (0) +#else +#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) #endif -/*! +/** * This function predicates if the given object is fully addressable or not. * - * \param[in] obj target object. - * \retval 0 the given object is fully addressable. - * \retval otherwise pointer to first such byte who is poisoned. + * @param[in] obj target object. + * @retval 0 the given object is fully addressable. + * @retval otherwise pointer to first such byte who is poisoned. */ static inline void * asan_poisoned_object_p(VALUE obj) @@ -143,7 +149,7 @@ asan_poisoned_object_p(VALUE obj) return __asan_region_is_poisoned(ptr, SIZEOF_VALUE); } -/*! +/** * This function asserts that a (formally poisoned) memory region from ptr to * size is now addressable. Write access to such memory region gets allowed. * However read access might or might not be possible depending on situations, @@ -154,9 +160,9 @@ asan_poisoned_object_p(VALUE obj) * the other hand, that memory region is fully defined and can be read * immediately. * - * \param[in] ptr pointer to the beginning of the memory region to unpoison. - * \param[in] size the length of the memory region. - * \param[in] malloc_p if the memory region is like a malloc's return value or not. + * @param[in] ptr pointer to the beginning of the memory region to unpoison. + * @param[in] size the length of the memory region. + * @param[in] malloc_p if the memory region is like a malloc's return value or not. */ static inline void asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p) @@ -170,11 +176,11 @@ asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p } } -/*! +/** * This is a variant of asan_unpoison_memory_region that takes a VALUE. * - * \param[in] obj target object. - * \param[in] malloc_p if the memory region is like a malloc's return value or not. + * @param[in] obj target object. + * @param[in] malloc_p if the memory region is like a malloc's return value or not. */ static inline void asan_unpoison_object(VALUE obj, bool newobj_p) @@ -183,4 +189,109 @@ asan_unpoison_object(VALUE obj, bool newobj_p) asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p); } +static inline void * +asan_unpoison_object_temporary(VALUE obj) +{ + void *ptr = asan_poisoned_object_p(obj); + asan_unpoison_object(obj, false); + return ptr; +} + +static inline void * +asan_poison_object_restore(VALUE obj, void *ptr) +{ + if (ptr) { + asan_poison_object(obj); + } + return NULL; +} + + +/** + * Checks if the given pointer is on an ASAN fake stack. If so, it returns the + * address this variable has on the real frame; if not, it returns the origin + * address unmodified. + * + * n.b. - _dereferencing_ the returned address is meaningless and should not + * be done; even though ASAN reserves space for the variable in both the real and + * fake stacks, the _value_ of that variable is only in the fake stack. + * + * n.b. - this only works for addresses passed in from local variables on the same + * thread, because the ASAN fake stacks are threadlocal. + * + * @param[in] slot the address of some local variable + * @retval a pointer to something from that frame on the _real_ machine stack + */ +static inline void * +asan_get_real_stack_addr(void* slot) +{ + VALUE *addr; + addr = __asan_addr_is_in_fake_stack(__asan_get_current_fake_stack(), slot, NULL, NULL); + return addr ? addr : slot; +} + +/** + * Gets the current thread's fake stack handle, which can be passed into get_fake_stack_extents + * + * @retval An opaque value which can be passed to asan_get_fake_stack_extents + */ +static inline void * +asan_get_thread_fake_stack_handle(void) +{ + return __asan_get_current_fake_stack(); +} + +/** + * Checks if the given VALUE _actually_ represents a pointer to an ASAN fake stack. + * + * If the given slot _is_ actually a reference to an ASAN fake stack, and that fake stack + * contains the real values for the passed-in range of machine stack addresses, returns true + * and the range of the fake stack through the outparams. + * + * Otherwise, returns false, and sets the outparams to NULL. + * + * Note that this function expects "start" to be > "end" on downward-growing stack architectures; + * + * @param[in] thread_fake_stack_handle The asan fake stack reference for the thread we're scanning + * @param[in] slot The value on the machine stack we want to inspect + * @param[in] machine_stack_start The extents of the real machine stack on which slot lives + * @param[in] machine_stack_end The extents of the real machine stack on which slot lives + * @param[out] fake_stack_start_out The extents of the fake stack which contains real VALUEs + * @param[out] fake_stack_end_out The extents of the fake stack which contains real VALUEs + * @return Whether slot is a pointer to a fake stack for the given machine stack range +*/ + +static inline bool +asan_get_fake_stack_extents(void *thread_fake_stack_handle, VALUE slot, + void *machine_stack_start, void *machine_stack_end, + void **fake_stack_start_out, void **fake_stack_end_out) +{ + /* the ifdef is needed here to suppress a warning about fake_frame_{start/end} being + uninitialized if __asan_addr_is_in_fake_stack is an empty macro */ +#ifdef RUBY_ASAN_ENABLED + void *fake_frame_start; + void *fake_frame_end; + void *real_stack_frame = __asan_addr_is_in_fake_stack( + thread_fake_stack_handle, (void *)slot, &fake_frame_start, &fake_frame_end + ); + if (real_stack_frame) { + bool in_range; +#if STACK_GROW_DIRECTION < 0 + in_range = machine_stack_start >= real_stack_frame && real_stack_frame >= machine_stack_end; +#else + in_range = machine_stack_start <= real_stack_frame && real_stack_frame <= machine_stack_end; +#endif + if (in_range) { + *fake_stack_start_out = fake_frame_start; + *fake_stack_end_out = fake_frame_end; + return true; + } + } +#endif + *fake_stack_start_out = 0; + *fake_stack_end_out = 0; + return false; +} + + #endif /* INTERNAL_SANITIZERS_H */ diff --git a/internal/signal.h b/internal/signal.h index 86fb54e949..2363bf412c 100644 --- a/internal/signal.h +++ b/internal/signal.h @@ -13,9 +13,12 @@ extern int ruby_enable_coredump; int rb_get_next_signal(void); +#ifdef POSIX_SIGNAL +void (*ruby_posix_signal(int, void (*)(int)))(int); +#endif + RUBY_SYMBOL_EXPORT_BEGIN /* signal.c (export) */ -int rb_grantpt(int fd); RUBY_SYMBOL_EXPORT_END #endif /* INTERNAL_SIGNAL_H */ diff --git a/internal/st.h b/internal/st.h new file mode 100644 index 0000000000..a26b224505 --- /dev/null +++ b/internal/st.h @@ -0,0 +1,11 @@ +#ifndef INTERNAL_ST_H +#define INTERNAL_ST_H + +#include "include/ruby/st.h" + +st_table *rb_st_replace(st_table *new_tab, st_table *old_tab); +#define st_replace rb_st_replace +st_table *rb_st_init_existing_table_with_size(st_table *tab, const struct st_hash_type *type, st_index_t size); +#define st_init_existing_table_with_size rb_st_init_existing_table_with_size + +#endif diff --git a/internal/string.h b/internal/string.h index 5f59d9621b..3533766ffb 100644 --- a/internal/string.h +++ b/internal/string.h @@ -17,6 +17,11 @@ #define STR_NOEMBED FL_USER1 #define STR_SHARED FL_USER2 /* = ELTS_SHARED */ +#define STR_CHILLED FL_USER3 + +enum ruby_rstring_private_flags { + RSTRING_CHILLED = STR_CHILLED, +}; #ifdef rb_fstring_cstr # undef rb_fstring_cstr @@ -45,6 +50,7 @@ void rb_str_make_independent(VALUE str); int rb_enc_str_coderange_scan(VALUE str, rb_encoding *enc); int rb_ascii8bit_appendable_encoding_index(rb_encoding *enc, unsigned int code); VALUE rb_str_include(VALUE str, VALUE arg); +VALUE rb_str_byte_substr(VALUE str, VALUE beg, VALUE len); static inline bool STR_EMBED_P(VALUE str); static inline bool STR_SHARED_P(VALUE str); @@ -57,6 +63,7 @@ static inline VALUE rb_str_eql_internal(const VALUE str1, const VALUE str2); RUBY_SYMBOL_EXPORT_BEGIN /* string.c (export) */ VALUE rb_str_tmp_frozen_acquire(VALUE str); +VALUE rb_str_tmp_frozen_no_embed_acquire(VALUE str); void rb_str_tmp_frozen_release(VALUE str, VALUE tmp); VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc); VALUE rb_str_upto_each(VALUE, VALUE, int, int (*each)(VALUE, VALUE), VALUE); @@ -64,7 +71,6 @@ VALUE rb_str_upto_endless_each(VALUE, int (*each)(VALUE, VALUE), VALUE); void rb_str_make_embedded(VALUE); size_t rb_str_size_as_embedded(VALUE); bool rb_str_reembeddable_p(VALUE); -void rb_str_update_shared_ary(VALUE str, VALUE old_root, VALUE new_root); RUBY_SYMBOL_EXPORT_END VALUE rb_fstring_new(const char *ptr, long len); @@ -74,9 +80,10 @@ VALUE rb_str_concat_literals(size_t num, const VALUE *strary); VALUE rb_str_eql(VALUE str1, VALUE str2); VALUE rb_id_quote_unprintable(ID); VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc); +VALUE rb_enc_literal_str(const char *ptr, long len, rb_encoding *enc); struct rb_execution_context_struct; -VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str); +VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str, bool chilled); #define rb_fstring_lit(str) rb_fstring_new((str), rb_strlen_lit(str)) #define rb_fstring_literal(str) rb_fstring_lit(str) @@ -108,6 +115,25 @@ STR_SHARED_P(VALUE str) } static inline bool +CHILLED_STRING_P(VALUE obj) +{ + return RB_TYPE_P(obj, T_STRING) && FL_TEST_RAW(obj, STR_CHILLED); +} + +static inline void +CHILLED_STRING_MUTATED(VALUE str) +{ + FL_UNSET_RAW(str, STR_CHILLED); + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "literal string will be frozen in the future"); +} + +static inline void +STR_CHILL_RAW(VALUE str) +{ + FL_SET_RAW(str, STR_CHILLED); +} + +static inline bool is_ascii_string(VALUE str) { return rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT; @@ -119,6 +145,21 @@ is_broken_string(VALUE str) return rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN; } +static inline bool +at_char_boundary(const char *s, const char *p, const char *e, rb_encoding *enc) +{ + return rb_enc_left_char_head(s, p, e, enc) == p; +} + +static inline bool +at_char_right_boundary(const char *s, const char *p, const char *e, rb_encoding *enc) +{ + RUBY_ASSERT(s <= p); + RUBY_ASSERT(p <= e); + + return rb_enc_right_char_head(s, p, e, enc) == p; +} + /* expect tail call optimization */ // YJIT needs this function to never allocate and never raise static inline VALUE diff --git a/internal/struct.h b/internal/struct.h index 9b56254541..6da5bad10a 100644 --- a/internal/struct.h +++ b/internal/struct.h @@ -15,7 +15,6 @@ enum { RSTRUCT_EMBED_LEN_MASK = RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3 | RUBY_FL_USER2 | RUBY_FL_USER1, RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1), - RSTRUCT_TRANSIENT_FLAG = RUBY_FL_USER8, }; struct RStruct { @@ -61,9 +60,6 @@ VALUE rb_struct_init_copy(VALUE copy, VALUE s); VALUE rb_struct_lookup(VALUE s, VALUE idx); VALUE rb_struct_s_keyword_init(VALUE klass); static inline const VALUE *rb_struct_const_heap_ptr(VALUE st); -static inline bool RSTRUCT_TRANSIENT_P(VALUE st); -static inline void RSTRUCT_TRANSIENT_SET(VALUE st); -static inline void RSTRUCT_TRANSIENT_UNSET(VALUE st); static inline long RSTRUCT_EMBED_LEN(VALUE st); static inline long RSTRUCT_LEN(VALUE st); static inline int RSTRUCT_LENINT(VALUE st); @@ -71,32 +67,6 @@ static inline const VALUE *RSTRUCT_CONST_PTR(VALUE st); static inline void RSTRUCT_SET(VALUE st, long k, VALUE v); static inline VALUE RSTRUCT_GET(VALUE st, long k); -static inline bool -RSTRUCT_TRANSIENT_P(VALUE st) -{ -#if USE_TRANSIENT_HEAP - return FL_TEST_RAW(st, RSTRUCT_TRANSIENT_FLAG); -#else - return false; -#endif -} - -static inline void -RSTRUCT_TRANSIENT_SET(VALUE st) -{ -#if USE_TRANSIENT_HEAP - FL_SET_RAW(st, RSTRUCT_TRANSIENT_FLAG); -#endif -} - -static inline void -RSTRUCT_TRANSIENT_UNSET(VALUE st) -{ -#if USE_TRANSIENT_HEAP - FL_UNSET_RAW(st, RSTRUCT_TRANSIENT_FLAG); -#endif -} - static inline long RSTRUCT_EMBED_LEN(VALUE st) { diff --git a/internal/symbol.h b/internal/symbol.h index 30c81ea004..e7730cb70f 100644 --- a/internal/symbol.h +++ b/internal/symbol.h @@ -32,6 +32,9 @@ ID rb_make_temporary_id(size_t n); void rb_gc_free_dsymbol(VALUE); int rb_static_id_valid_p(ID id); +/* vm.c */ +void rb_free_static_symid_str(void); + #if __has_builtin(__builtin_constant_p) #define rb_sym_intern_ascii_cstr(ptr) \ (__builtin_constant_p(ptr) ? \ diff --git a/internal/thread.h b/internal/thread.h index c41a16c12d..47273436e3 100644 --- a/internal/thread.h +++ b/internal/thread.h @@ -50,6 +50,7 @@ void rb_mutex_allow_trap(VALUE self, int val); VALUE rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data); VALUE rb_mutex_owned_p(VALUE self); VALUE rb_exec_recursive_outer_mid(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h, ID mid); +void ruby_mn_threads_params(void); int rb_thread_wait_for_single_fd(int fd, int events, struct timeval * timeout); @@ -62,13 +63,17 @@ int rb_notify_fd_close(int fd, struct rb_io_close_wait_list *busy); void rb_notify_fd_close_wait(struct rb_io_close_wait_list *busy); RUBY_SYMBOL_EXPORT_BEGIN + /* Temporary. This API will be removed (renamed). */ VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd); +VALUE rb_thread_io_blocking_call(rb_blocking_function_t *func, void *data1, int fd, int events); /* thread.c (export) */ int ruby_thread_has_gvl_p(void); /* for ext/fiddle/closure.c */ + RUBY_SYMBOL_EXPORT_END int rb_threadptr_execute_interrupts(struct rb_thread_struct *th, int blocking_timing); +bool rb_thread_mn_schedulable(VALUE thread); #endif /* INTERNAL_THREAD_H */ diff --git a/internal/transcode.h b/internal/transcode.h index 9922332ea9..ce4f2341be 100644 --- a/internal/transcode.h +++ b/internal/transcode.h @@ -17,4 +17,7 @@ extern VALUE rb_cEncodingConverter; size_t rb_econv_memsize(rb_econv_t *); +/* vm.c */ +void rb_free_transcoder_table(void); + #endif /* INTERNAL_TRANSCODE_H */ diff --git a/internal/variable.h b/internal/variable.h index 4436cd789c..b2a30c7c58 100644 --- a/internal/variable.h +++ b/internal/variable.h @@ -15,10 +15,6 @@ #include "ruby/ruby.h" /* for VALUE */ #include "shape.h" /* for rb_shape_t */ -/* global variable */ - -#define ROBJECT_TRANSIENT_FLAG FL_USER2 - /* variable.c */ void rb_gc_mark_global_tbl(void); void rb_gc_update_global_tbl(void); @@ -32,17 +28,33 @@ rb_gvar_getter_t *rb_gvar_getter_function_of(ID); rb_gvar_setter_t *rb_gvar_setter_function_of(ID); void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_); void rb_gvar_ractor_local(const char *name); -static inline bool ROBJ_TRANSIENT_P(VALUE obj); -static inline void ROBJ_TRANSIENT_SET(VALUE obj); -static inline void ROBJ_TRANSIENT_UNSET(VALUE obj); + +/** + * Sets the name of a module. + * + * Non-permanently named classes can have a temporary name assigned (or + * cleared). In that case the name will be used for `#inspect` and `#to_s`, and + * nested classes/modules will be named with the temporary name as a prefix. + * + * After the module is assigned to a constant, the temporary name will be + * discarded, and the name will be computed based on the nesting. + * + * @param[in] mod An instance of ::rb_cModule. + * @param[in] name An instance of ::rb_cString. + * @retval mod + */ +VALUE rb_mod_set_temporary_name(VALUE, VALUE); struct gen_ivtbl; int rb_gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl); -int rb_obj_evacuate_ivs_to_hash_table(ID key, VALUE val, st_data_t arg); +void rb_obj_copy_ivs_to_hash_table(VALUE obj, st_table *table); +void rb_obj_convert_to_too_complex(VALUE obj, st_table *table); +void rb_evict_ivars_to_hash(VALUE obj); RUBY_SYMBOL_EXPORT_BEGIN /* variable.c (export) */ -void rb_mark_and_update_generic_ivar(VALUE); +void rb_mark_generic_ivar(VALUE obj); +void rb_ref_update_generic_ivar(VALUE); void rb_mv_generic_ivar(VALUE src, VALUE dst); VALUE rb_const_missing(VALUE klass, VALUE name); int rb_class_ivar_set(VALUE klass, ID vid, VALUE value); @@ -54,35 +66,7 @@ VALUE rb_gvar_get(ID); VALUE rb_gvar_set(ID, VALUE); VALUE rb_gvar_defined(ID); void rb_const_warn_if_deprecated(const rb_const_entry_t *, VALUE, ID); -rb_shape_t * rb_grow_iv_list(VALUE obj); void rb_ensure_iv_list_size(VALUE obj, uint32_t len, uint32_t newsize); -struct gen_ivtbl *rb_ensure_generic_iv_list_size(VALUE obj, rb_shape_t *shape, uint32_t newsize); attr_index_t rb_obj_ivar_set(VALUE obj, ID id, VALUE val); -static inline bool -ROBJ_TRANSIENT_P(VALUE obj) -{ -#if USE_TRANSIENT_HEAP - return FL_TEST_RAW(obj, ROBJECT_TRANSIENT_FLAG); -#else - return false; -#endif -} - -static inline void -ROBJ_TRANSIENT_SET(VALUE obj) -{ -#if USE_TRANSIENT_HEAP - FL_SET_RAW(obj, ROBJECT_TRANSIENT_FLAG); -#endif -} - -static inline void -ROBJ_TRANSIENT_UNSET(VALUE obj) -{ -#if USE_TRANSIENT_HEAP - FL_UNSET_RAW(obj, ROBJECT_TRANSIENT_FLAG); -#endif -} - #endif /* INTERNAL_VARIABLE_H */ diff --git a/internal/vm.h b/internal/vm.h index 7943027946..74635e6ad8 100644 --- a/internal/vm.h +++ b/internal/vm.h @@ -45,19 +45,21 @@ VALUE rb_vm_push_frame_fname(struct rb_execution_context_struct *ec, VALUE fname /* vm.c */ VALUE rb_obj_is_thread(VALUE obj); void rb_vm_mark(void *ptr); +void rb_vm_register_global_object(VALUE obj); void rb_vm_each_stack_value(void *ptr, void (*cb)(VALUE, void*), void *ctx); PUREFUNC(VALUE rb_vm_top_self(void)); const void **rb_vm_get_insns_address_table(void); VALUE rb_source_location(int *pline); const char *rb_source_location_cstr(int *pline); void rb_vm_pop_cfunc_frame(void); -int rb_vm_add_root_module(VALUE module); void rb_vm_check_redefinition_by_prepend(VALUE klass); int rb_vm_check_optimizable_mid(VALUE mid); VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements); VALUE ruby_vm_special_exception_copy(VALUE); PUREFUNC(st_table *rb_vm_fstring_table(void)); +void rb_lastline_set_up(VALUE val, unsigned int up); + /* vm_eval.c */ VALUE rb_current_realfilepath(void); VALUE rb_check_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE); @@ -76,6 +78,16 @@ VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv, VALUE data2); void rb_check_stack_overflow(void); +#if USE_YJIT +/* vm_exec.c */ +extern uint64_t rb_vm_insns_count; +#endif + +extern bool rb_free_at_exit; + +/* miniinit.c and builtin.c */ +void rb_free_loaded_builtin_table(void); + /* vm_insnhelper.c */ VALUE rb_equal_opt(VALUE obj1, VALUE obj2); VALUE rb_eql_opt(VALUE obj1, VALUE obj2); @@ -90,7 +102,7 @@ int rb_ec_obj_respond_to(struct rb_execution_context_struct *ec, VALUE obj, ID i void rb_clear_constant_cache(void); /* vm_dump.c */ -void rb_print_backtrace(void); +void rb_print_backtrace(FILE *); /* vm_backtrace.c */ VALUE rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval); @@ -98,10 +110,11 @@ VALUE rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval) VALUE rb_vm_backtrace(int argc, const VALUE * argv, struct rb_execution_context_struct * ec); VALUE rb_vm_backtrace_locations(int argc, const VALUE * argv, struct rb_execution_context_struct * ec); VALUE rb_make_backtrace(void); -void rb_backtrace_print_as_bugreport(void); +void rb_backtrace_print_as_bugreport(FILE*); int rb_backtrace_p(VALUE obj); VALUE rb_backtrace_to_str_ary(VALUE obj); VALUE rb_backtrace_to_location_ary(VALUE obj); +VALUE rb_location_ary_to_backtrace(VALUE ary); void rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output); int rb_frame_info_p(VALUE obj); int rb_get_node_id_from_frame_info(VALUE obj); |