diff options
Diffstat (limited to 'internal')
55 files changed, 1386 insertions, 488 deletions
diff --git a/internal/array.h b/internal/array.h index 00e03c116e..39f6fcbea6 100644 --- a/internal/array.h +++ b/internal/array.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_ARRAY_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_ARRAY_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -19,32 +18,29 @@ # define ARRAY_DEBUG (0+RUBY_DEBUG) #endif -#define RARRAY_PTR_IN_USE_FLAG FL_USER14 +#define RARRAY_SHARED_FLAG ELTS_SHARED +#define RARRAY_SHARED_ROOT_FLAG FL_USER12 +#define RARRAY_PTR_IN_USE_FLAG FL_USER14 /* array.c */ +VALUE rb_ary_hash_values(long len, const VALUE *elements); VALUE rb_ary_last(int, const VALUE *, VALUE); void rb_ary_set_len(VALUE, long); void rb_ary_delete_same(VALUE, VALUE); -VALUE rb_ary_tmp_new_fill(long capa); +VALUE rb_ary_hidden_new_fill(long capa); VALUE rb_ary_at(VALUE, VALUE); size_t rb_ary_memsize(VALUE); VALUE rb_to_array_type(VALUE obj); VALUE rb_to_array(VALUE obj); void rb_ary_cancel_sharing(VALUE ary); +size_t rb_ary_size_as_embedded(VALUE ary); +void rb_ary_make_embedded(VALUE ary); +bool rb_ary_embeddable_p(VALUE ary); +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); -RUBY_SYMBOL_EXPORT_BEGIN -/* array.c (export) */ -void rb_ary_detransient(VALUE a); -VALUE *rb_ary_ptr_use_start(VALUE ary); -void rb_ary_ptr_use_end(VALUE ary); -RUBY_SYMBOL_EXPORT_END - -MJIT_SYMBOL_EXPORT_BEGIN VALUE rb_ary_tmp_new_from_values(VALUE, long, const VALUE *); VALUE rb_check_to_array(VALUE ary); VALUE rb_ary_behead(VALUE, long); @@ -52,13 +48,13 @@ VALUE rb_ary_aref1(VALUE ary, VALUE i); struct rb_execution_context_struct; VALUE rb_ec_ary_new_from_values(struct rb_execution_context_struct *ec, long n, const VALUE *elts); -MJIT_SYMBOL_EXPORT_END +// YJIT needs this function to never allocate and never raise 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; @@ -76,20 +72,48 @@ ARY_PTR_USING_P(VALUE ary) return FL_TEST_RAW(ary, RARRAY_PTR_IN_USE_FLAG); } -static inline void -RARY_TRANSIENT_SET(VALUE ary) +RBIMPL_ATTR_MAYBE_UNUSED() +static inline int +ary_should_not_be_shared_and_embedded(VALUE ary) { -#if USE_TRANSIENT_HEAP - FL_SET_RAW(ary, RARRAY_TRANSIENT_FLAG); -#endif + return !FL_ALL_RAW(ary, RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG); } -static inline void -RARY_TRANSIENT_UNSET(VALUE ary) +static inline bool +ARY_SHARED_P(VALUE ary) { -#if USE_TRANSIENT_HEAP - FL_UNSET_RAW(ary, RARRAY_TRANSIENT_FLAG); -#endif + assert(RB_TYPE_P(ary, T_ARRAY)); + assert(ary_should_not_be_shared_and_embedded(ary)); + return FL_TEST_RAW(ary, RARRAY_SHARED_FLAG); +} + +static inline bool +ARY_EMBED_P(VALUE ary) +{ + assert(RB_TYPE_P(ary, T_ARRAY)); + assert(ary_should_not_be_shared_and_embedded(ary)); + return FL_TEST_RAW(ary, RARRAY_EMBED_FLAG); +} + +static inline VALUE +ARY_SHARED_ROOT(VALUE ary) +{ + assert(ARY_SHARED_P(ary)); + return RARRAY(ary)->as.heap.aux.shared_root; +} + +static inline bool +ARY_SHARED_ROOT_P(VALUE ary) +{ + assert(RB_TYPE_P(ary, T_ARRAY)); + return FL_TEST_RAW(ary, RARRAY_SHARED_ROOT_FLAG); +} + +static inline long +ARY_SHARED_ROOT_REFCNT(VALUE ary) +{ + assert(ARY_SHARED_ROOT_P(ary)); + return RARRAY(ary)->as.heap.aux.capa; } #undef rb_ary_new_from_args @@ -112,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 new file mode 100644 index 0000000000..a59403631e --- /dev/null +++ b/internal/basic_operators.h @@ -0,0 +1,63 @@ +#ifndef INTERNAL_BOP_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_BOP_H + +#include "internal.h" +#include "ruby/internal/dllexport.h" + +enum ruby_basic_operators { + BOP_PLUS, + BOP_MINUS, + BOP_MULT, + BOP_DIV, + BOP_MOD, + BOP_EQ, + BOP_EQQ, + BOP_LT, + BOP_LE, + BOP_LTLT, + BOP_AREF, + BOP_ASET, + BOP_LENGTH, + BOP_SIZE, + BOP_EMPTY_P, + BOP_NIL_P, + BOP_SUCC, + BOP_GT, + BOP_GE, + BOP_NOT, + BOP_NEQ, + BOP_MATCH, + BOP_FREEZE, + BOP_UMINUS, + BOP_MAX, + BOP_MIN, + BOP_HASH, + BOP_CALL, + BOP_AND, + BOP_OR, + BOP_CMP, + BOP_DEFAULT, + + BOP_LAST_ +}; + +RUBY_EXTERN short ruby_vm_redefined_flag[BOP_LAST_]; + +/* optimize insn */ +#define INTEGER_REDEFINED_OP_FLAG (1 << 0) +#define FLOAT_REDEFINED_OP_FLAG (1 << 1) +#define STRING_REDEFINED_OP_FLAG (1 << 2) +#define ARRAY_REDEFINED_OP_FLAG (1 << 3) +#define HASH_REDEFINED_OP_FLAG (1 << 4) +/* #define BIGNUM_REDEFINED_OP_FLAG (1 << 5) */ +#define SYMBOL_REDEFINED_OP_FLAG (1 << 6) +#define TIME_REDEFINED_OP_FLAG (1 << 7) +#define REGEXP_REDEFINED_OP_FLAG (1 << 8) +#define NIL_REDEFINED_OP_FLAG (1 << 9) +#define TRUE_REDEFINED_OP_FLAG (1 << 10) +#define FALSE_REDEFINED_OP_FLAG (1 << 11) +#define PROC_REDEFINED_OP_FLAG (1 << 12) + +#define BASIC_OP_UNREDEFINED_P(op, klass) (LIKELY((ruby_vm_redefined_flag[(op)]&(klass)) == 0)) + +#endif diff --git a/internal/bignum.h b/internal/bignum.h index 9b89e61f28..db8d3aee83 100644 --- a/internal/bignum.h +++ b/internal/bignum.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_BIGNUM_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_BIGNUM_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -164,11 +163,9 @@ VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck); VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags); RUBY_SYMBOL_EXPORT_END -MJIT_SYMBOL_EXPORT_BEGIN #if defined(HAVE_INT128_T) VALUE rb_int128t2big(int128_t n); #endif -MJIT_SYMBOL_EXPORT_END /* sign: positive:1, negative:0 */ static inline bool diff --git a/internal/bits.h b/internal/bits.h index 746947bfc2..1fe98fa430 100644 --- a/internal/bits.h +++ b/internal/bits.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_BITS_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_BITS_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -35,8 +34,7 @@ # include <stdlib.h> /* for _byteswap_uint64 */ #endif -#if defined(HAVE_X86INTRIN_H) && ! defined(MJIT_HEADER) -# /* Rule out MJIT_HEADER, which does not interface well with <immintrin.h> */ +#if defined(HAVE_X86INTRIN_H) # include <x86intrin.h> /* for _lzcnt_u64 */ #elif MSC_VERSION_SINCE(1310) # include <intrin.h> /* for the following intrinsics */ @@ -120,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 @@ -236,7 +238,7 @@ nlz_int32(uint32_t x) * safety. */ return (unsigned int)__lzcnt(x); -#elif defined(__x86_64__) && defined(__LZCNT__) && ! defined(MJIT_HEADER) +#elif defined(__x86_64__) && defined(__LZCNT__) return (unsigned int)_lzcnt_u32(x); #elif MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */ @@ -265,7 +267,7 @@ nlz_int64(uint64_t x) #if defined(_MSC_VER) && defined(__AVX2__) return (unsigned int)__lzcnt64(x); -#elif defined(__x86_64__) && defined(__LZCNT__) && ! defined(MJIT_HEADER) +#elif defined(__x86_64__) && defined(__LZCNT__) return (unsigned int)_lzcnt_u64(x); #elif defined(_WIN64) && MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */ @@ -396,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 @@ -426,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 @@ -451,7 +453,7 @@ rb_popcount_intptr(uintptr_t x) static inline int ntz_int32(uint32_t x) { -#if defined(__x86_64__) && defined(__BMI__) && ! defined(MJIT_HEADER) +#if defined(__x86_64__) && defined(__BMI__) return (unsigned)_tzcnt_u32(x); #elif MSC_VERSION_SINCE(1400) @@ -473,7 +475,7 @@ ntz_int32(uint32_t x) static inline int ntz_int64(uint64_t x) { -#if defined(__x86_64__) && defined(__BMI__) && ! defined(MJIT_HEADER) +#if defined(__x86_64__) && defined(__BMI__) return (unsigned)_tzcnt_u64(x); #elif defined(_WIN64) && MSC_VERSION_SINCE(1400) diff --git a/internal/class.h b/internal/class.h index 6c03a31a4e..8a6c956233 100644 --- a/internal/class.h +++ b/internal/class.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_CLASS_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_CLASS_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -9,12 +8,19 @@ * file COPYING are met. Consult the file for details. * @brief Internal header for Class. */ +#include "id.h" #include "id_table.h" /* for struct rb_id_table */ -#include "internal/gc.h" /* for RB_OBJ_WRITE */ #include "internal/serial.h" /* for rb_serial_t */ +#include "internal/static_assert.h" +#include "internal/variable.h" /* for rb_class_ivar_set */ #include "ruby/internal/stdbool.h" /* for bool */ #include "ruby/intern.h" /* for rb_alloc_func_t */ #include "ruby/ruby.h" /* for struct RBasic */ +#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 # undef RCLASS_SUPER @@ -23,103 +29,162 @@ struct rb_subclass_entry { VALUE klass; struct rb_subclass_entry *next; + struct rb_subclass_entry *prev; }; +typedef struct rb_subclass_entry rb_subclass_entry_t; -struct rb_iv_index_tbl_entry { +struct rb_cvar_class_tbl_entry { uint32_t index; - rb_serial_t class_serial; + rb_serial_t global_cvar_state; + const rb_cref_t * cref; VALUE class_value; }; struct rb_classext_struct { - struct st_table *iv_index_tbl; // ID -> struct rb_iv_index_tbl_entry - struct st_table *iv_tbl; -#if SIZEOF_SERIAL_T == SIZEOF_VALUE /* otherwise m_tbl is in struct RClass */ - struct rb_id_table *m_tbl; -#endif + 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; struct rb_subclass_entry *subclasses; - struct rb_subclass_entry **parent_subclasses; + struct rb_subclass_entry *subclass_entry; /** * In the case that this is an `ICLASS`, `module_subclasses` points to the link * in the module's `subclasses` list that indicates that the klass has been * included. Hopefully that makes sense. */ - struct rb_subclass_entry **module_subclasses; -#if SIZEOF_SERIAL_T != SIZEOF_VALUE /* otherwise class_serial is in struct RClass */ - rb_serial_t class_serial; -#endif + struct rb_subclass_entry *module_subclass_entry; const VALUE origin_; const VALUE refined_class; - rb_alloc_func_t allocator; + union { + struct { + rb_alloc_func_t allocator; + } class; + struct { + VALUE attached_object; + } singleton_class; + } as; const VALUE includer; + attr_index_t max_iv_count; + unsigned char variation_count; + bool permanent_classpath : 1; + bool cloned : 1; + VALUE classpath; }; +typedef struct rb_classext_struct rb_classext_t; + +STATIC_ASSERT(shape_max_variations, SHAPE_MAX_VARIATIONS < (1 << (sizeof(((rb_classext_t *)0)->variation_count) * CHAR_BIT))); struct RClass { struct RBasic basic; VALUE super; - struct rb_classext_struct *ptr; -#if SIZEOF_SERIAL_T == SIZEOF_VALUE - /* Class serial is as wide as VALUE. Place it here. */ - rb_serial_t class_serial; -#else - /* Class serial does not fit into struct RClass. Place m_tbl instead. */ struct rb_id_table *m_tbl; -#endif }; -typedef struct rb_subclass_entry rb_subclass_entry_t; -typedef struct rb_classext_struct rb_classext_t; +// 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); + +struct RClass_and_rb_classext_t { + struct RClass rclass; + rb_classext_t classext; +}; -#define RCLASS_EXT(c) (RCLASS(c)->ptr) -#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) +#define RCLASS_EXT(c) (&((struct RClass_and_rb_classext_t*)(c))->classext) #define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) -#if SIZEOF_SERIAL_T == SIZEOF_VALUE -# define RCLASS_M_TBL(c) (RCLASS_EXT(c)->m_tbl) -#else -# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) -#endif +#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) +#define RCLASS_IVPTR(c) (RCLASS_EXT(c)->iv_ptr) #define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl) #define RCLASS_CC_TBL(c) (RCLASS_EXT(c)->cc_tbl) -#define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl) +#define RCLASS_CVC_TBL(c) (RCLASS_EXT(c)->cvc_tbl) #define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_) #define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class) -#if SIZEOF_SERIAL_T == SIZEOF_VALUE -# define RCLASS_SERIAL(c) (RCLASS(c)->class_serial) -#else -# define RCLASS_SERIAL(c) (RCLASS_EXT(c)->class_serial) -#endif #define RCLASS_INCLUDER(c) (RCLASS_EXT(c)->includer) -#define RCLASS_PARENT_SUBCLASSES(c) (RCLASS_EXT(c)->parent_subclasses) -#define RCLASS_MODULE_SUBCLASSES(c) (RCLASS_EXT(c)->module_subclasses) -#define RCLASS_ALLOCATOR(c) (RCLASS_EXT(c)->allocator) +#define RCLASS_SUBCLASS_ENTRY(c) (RCLASS_EXT(c)->subclass_entry) +#define RCLASS_MODULE_SUBCLASS_ENTRY(c) (RCLASS_EXT(c)->module_subclass_entry) #define RCLASS_SUBCLASSES(c) (RCLASS_EXT(c)->subclasses) +#define RCLASS_SUPERCLASS_DEPTH(c) (RCLASS_EXT(c)->superclass_depth) +#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 -#define RICLASS_IS_ORIGIN FL_USER5 -#define RCLASS_CLONED FL_USER6 -#define RICLASS_ORIGIN_SHARED_MTBL FL_USER8 +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); +void rb_class_update_superclasses(VALUE); +size_t rb_class_superclasses_memsize(VALUE); +void rb_class_remove_subclass_head(VALUE); int rb_singleton_class_internal_p(VALUE sklass); VALUE rb_class_boot(VALUE); +VALUE rb_class_s_alloc(VALUE klass); +VALUE rb_module_s_alloc(VALUE klass); +void rb_module_set_initialized(VALUE module); +void rb_module_check_initializable(VALUE module); VALUE rb_make_metaclass(VALUE, VALUE); VALUE rb_include_class_new(VALUE, VALUE); 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); VALUE rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj); +VALUE rb_class_undefined_instance_methods(VALUE mod); VALUE rb_special_singleton_class(VALUE); VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach); VALUE rb_singleton_class_get(VALUE obj); -int rb_class_has_methods(VALUE c); void rb_undef_methods_from(VALUE klass, VALUE super); static inline void RCLASS_SET_ORIGIN(VALUE klass, VALUE origin); @@ -128,10 +193,30 @@ static inline VALUE RCLASS_SUPER(VALUE klass); static inline VALUE RCLASS_SET_SUPER(VALUE klass, VALUE super); static inline void RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass); -MJIT_SYMBOL_EXPORT_BEGIN VALUE rb_class_inherited(VALUE, VALUE); VALUE rb_keyword_error_new(const char *, VALUE); -MJIT_SYMBOL_EXPORT_END + +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 (RCLASS_SINGLETON_P(klass)) { + return 0; + } + return RCLASS_EXT(klass)->as.class.allocator; +} + +static inline void +RCLASS_SET_ALLOCATOR(VALUE klass, rb_alloc_func_t allocator) +{ + assert(!RCLASS_SINGLETON_P(klass)); + RCLASS_EXT(klass)->as.class.allocator = allocator; +} static inline void RCLASS_SET_ORIGIN(VALUE klass, VALUE origin) @@ -172,7 +257,27 @@ RCLASS_SET_SUPER(VALUE klass, VALUE super) rb_class_subclass_add(super, klass); } RB_OBJ_WRITE(klass, &RCLASS(klass)->super, super); + rb_class_update_superclasses(klass); return super; } +static inline void +RCLASS_SET_CLASSPATH(VALUE klass, VALUE classpath, bool permanent) +{ + assert(BUILTIN_TYPE(klass) == T_CLASS || BUILTIN_TYPE(klass) == T_MODULE); + assert(classpath == 0 || BUILTIN_TYPE(classpath) == T_STRING); + + RB_OBJ_WRITE(klass, &(RCLASS_EXT(klass)->classpath), classpath); + RCLASS_EXT(klass)->permanent_classpath = permanent; +} + +static inline VALUE +RCLASS_SET_ATTACHED_OBJECT(VALUE klass, VALUE attached_object) +{ + assert(RCLASS_SINGLETON_P(klass)); + + RB_OBJ_WRITE(klass, &RCLASS_EXT(klass)->as.singleton_class.attached_object, attached_object); + return attached_object; +} + #endif /* INTERNAL_CLASS_H */ diff --git a/internal/cmdlineopt.h b/internal/cmdlineopt.h new file mode 100644 index 0000000000..e79b993345 --- /dev/null +++ b/internal/cmdlineopt.h @@ -0,0 +1,65 @@ +#ifndef INTERNAL_CMDLINEOPT_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_CMDLINEOPT_H + +#include "rjit.h" +#include "yjit.h" + +typedef struct { + unsigned int mask; + unsigned int set; +} ruby_features_t; + +typedef struct ruby_cmdline_options { + const char *script; + VALUE script_name; + VALUE e_script; + struct { + struct { + VALUE name; + int index; + } enc; + } src, ext, intern; + VALUE req_list; + ruby_features_t features; + ruby_features_t warn; + unsigned int dump; + long backtrace_length_limit; +#if USE_RJIT + struct rb_rjit_options rjit; +#endif + + 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; + unsigned int do_print: 1; + unsigned int do_line: 1; + unsigned int do_split: 1; + unsigned int do_search: 1; + unsigned int setids: 2; +#if USE_YJIT + unsigned int yjit: 1; +#endif +} ruby_cmdline_options_t; + +struct ruby_opt_message { + const char *str; + unsigned short namelen, secondlen; +}; + +#define RUBY_OPT_MESSAGE(shortopt, longopt, desc) { \ + shortopt " " longopt " " desc, \ + (unsigned short)sizeof(shortopt), \ + (unsigned short)sizeof(longopt), \ +} + +#define opt_match(s, l, name) \ + ((((l) > rb_strlen_lit(name)) ? (s)[rb_strlen_lit(name)] == '=' : \ + (l) == rb_strlen_lit(name)) && \ + memcmp((s), name, rb_strlen_lit(name)) == 0 && \ + (((s) += rb_strlen_lit(name)), 1)) + +#endif diff --git a/internal/compar.h b/internal/compar.h index 888a3b5e1e..9115e4bd63 100644 --- a/internal/compar.h +++ b/internal/compar.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_COMPAR_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_COMPAR_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -9,38 +8,18 @@ * file COPYING are met. Consult the file for details. * @brief Internal header for Comparable. */ -#include "internal/vm.h" /* for rb_method_basic_definition_p */ +#include "internal/basic_operators.h" #define STRING_P(s) (RB_TYPE_P((s), T_STRING) && CLASS_OF(s) == rb_cString) -enum { - cmp_opt_Integer, - cmp_opt_String, - cmp_opt_Float, - cmp_optimizable_count -}; +#define CMP_OPTIMIZABLE(type) BASIC_OP_UNREDEFINED_P(BOP_CMP, type##_REDEFINED_OP_FLAG) -struct cmp_opt_data { - unsigned int opt_methods; - unsigned int opt_inited; -}; - -#define NEW_CMP_OPT_MEMO(type, value) \ - NEW_PARTIAL_MEMO_FOR(type, value, cmp_opt) -#define CMP_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(cmp_opt_,type)) -#define CMP_OPTIMIZABLE(data, type) \ - (((data).opt_inited & CMP_OPTIMIZABLE_BIT(type)) ? \ - ((data).opt_methods & CMP_OPTIMIZABLE_BIT(type)) : \ - (((data).opt_inited |= CMP_OPTIMIZABLE_BIT(type)), \ - rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \ - ((data).opt_methods |= CMP_OPTIMIZABLE_BIT(type)))) - -#define OPTIMIZED_CMP(a, b, data) \ - ((FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data, Integer)) ? \ +#define OPTIMIZED_CMP(a, b) \ + ((FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) ? \ (((long)a > (long)b) ? 1 : ((long)a < (long)b) ? -1 : 0) : \ - (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data, String)) ? \ + (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) ? \ rb_str_cmp(a, b) : \ - (RB_FLOAT_TYPE_P(a) && RB_FLOAT_TYPE_P(b) && CMP_OPTIMIZABLE(data, Float)) ? \ + (RB_FLOAT_TYPE_P(a) && RB_FLOAT_TYPE_P(b) && CMP_OPTIMIZABLE(FLOAT)) ? \ rb_float_cmp(a, b) : \ rb_cmpint(rb_funcallv(a, id_cmp, 1, &b), a, b)) diff --git a/internal/compile.h b/internal/compile.h index 9842e0f5e0..2ece5396f6 100644 --- a/internal/compile.h +++ b/internal/compile.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_COMPILE_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_COMPILE_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -18,15 +17,18 @@ 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 *); +int rb_insn_len(VALUE insn); const char *rb_insns_name(int i); VALUE rb_insns_name_array(void); +int rb_iseq_cdhash_cmp(VALUE val, VALUE lit); +st_index_t rb_iseq_cdhash_hash(VALUE a); /* iseq.c */ int rb_vm_insn_addr2insn(const void *); +int rb_vm_insn_decode(const VALUE encoded); +extern bool ruby_vm_keep_script_lines; -MJIT_SYMBOL_EXPORT_BEGIN /* iseq.c (export) */ rb_event_flag_t rb_iseq_event_flags(const struct rb_iseq_struct *iseq, size_t pos); -MJIT_SYMBOL_EXPORT_END #endif /* INTERNAL_COMPILE_H */ diff --git a/internal/compilers.h b/internal/compilers.h index 975bf4575d..26c2f05cc0 100644 --- a/internal/compilers.h +++ b/internal/compilers.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_COMPILERS_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_COMPILERS_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/complex.h b/internal/complex.h index 9eae804ddb..42151652b7 100644 --- a/internal/complex.h +++ b/internal/complex.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_COMPLEX_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_COMPLEX_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/cont.h b/internal/cont.h index 9e49dd3c8e..3c2528a02a 100644 --- a/internal/cont.h +++ b/internal/cont.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_CONT_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_CONT_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -10,17 +9,27 @@ * @brief Internal header for Fiber. */ #include "ruby/ruby.h" /* for VALUE */ +#include "iseq.h" struct rb_thread_struct; /* in vm_core.h */ struct rb_fiber_struct; /* in cont.c */ +struct rb_execution_context_struct; /* in vm_core.c */ /* cont.c */ -VALUE rb_obj_is_fiber(VALUE); void rb_fiber_reset_root_local_storage(struct rb_thread_struct *); void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(VALUE), VALUE (*rollback_func)(VALUE)); -void rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber); +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); VALUE rb_fiberptr_self(struct rb_fiber_struct *fiber); unsigned int rb_fiberptr_blocking(struct rb_fiber_struct *fiber); +struct rb_execution_context_struct * rb_fiberptr_get_ec(struct rb_fiber_struct *fiber); #endif /* INTERNAL_CONT_H */ diff --git a/internal/dir.h b/internal/dir.h index ffbdb25208..0a4dc90ece 100644 --- a/internal/dir.h +++ b/internal/dir.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_DIR_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_DIR_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/enc.h b/internal/enc.h index 0afc74db5d..a005dc810d 100644 --- a/internal/enc.h +++ b/internal/enc.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_ENC_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_ENC_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/encoding.h b/internal/encoding.h index c0cf061bd4..fe9ea10ec4 100644 --- a/internal/encoding.h +++ b/internal/encoding.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_ENCODING_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_ENCODING_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -13,9 +12,13 @@ #include "ruby/encoding.h" /* for rb_encoding */ #define rb_enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc)) +#define rb_is_usascii_enc(enc) ((enc) == rb_usascii_encoding()) +#define rb_is_ascii8bit_enc(enc) ((enc) == rb_ascii8bit_encoding()) +#define rb_is_locale_enc(enc) ((enc) == rb_locale_encoding()) /* 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); @@ -25,7 +28,9 @@ int rb_encdb_dummy(const char *name); void rb_encdb_declare(const char *name); void rb_enc_set_base(const char *name, const char *orig); int rb_enc_set_dummy(int index); -void rb_encdb_set_unicode(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/enum.h b/internal/enum.h index 50890f0c9f..282464436f 100644 --- a/internal/enum.h +++ b/internal/enum.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_ENUM_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_ENUM_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/enumerator.h b/internal/enumerator.h index 2e20c37d9e..e11a684c5b 100644 --- a/internal/enumerator.h +++ b/internal/enumerator.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_ENUMERATOR_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_ENUMERATOR_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/error.h b/internal/error.h index 0dd629f052..7e41f134d7 100644 --- a/internal/error.h +++ b/internal/error.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_ERROR_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_ERROR_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -30,26 +29,115 @@ #define rb_raise_static(e, m) \ rb_raise_cstr_i((e), rb_str_new_static((m), rb_strlen_lit(m))) #ifdef RUBY_FUNCTION_NAME_STRING -# define rb_sys_fail_path(path) rb_sys_fail_path_in(RUBY_FUNCTION_NAME_STRING, path) # define rb_syserr_fail_path(err, path) rb_syserr_fail_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path)) # define rb_syserr_new_path(err, path) rb_syserr_new_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path)) #else -# define rb_sys_fail_path(path) rb_sys_fail_str(path) # define rb_syserr_fail_path(err, path) rb_syserr_fail_str((err), (path)) # define rb_syserr_new_path(err, path) rb_syserr_new_str((err), (path)) #endif +#define rb_sys_fail(mesg) \ +do { \ + int errno_to_fail = errno; \ + rb_syserr_fail(errno_to_fail, (mesg)); \ +} while (0) + +#define rb_sys_fail_str(mesg) \ +do { \ + int errno_to_fail = errno; \ + rb_syserr_fail_str(errno_to_fail, (mesg)); \ +} while (0) + +#define rb_sys_fail_path(path) \ +do { \ + int errno_to_fail = errno; \ + rb_syserr_fail_path(errno_to_fail, (path)); \ +} while (0) + +#define rb_sys_fail_sprintf(...) \ +do { \ + int errno_to_fail = errno; \ + rb_syserr_fail_str(errno_to_fail, rb_sprintf("" __VA_ARGS__)); \ +} while (0) + /* error.c */ extern long rb_backtrace_length_limit; extern VALUE rb_eEAGAIN; extern VALUE rb_eEWOULDBLOCK; extern VALUE rb_eEINPROGRESS; +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0) void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args); NORETURN(void rb_async_bug_errno(const char *,int)); const char *rb_builtin_type_name(int t); const char *rb_builtin_class_name(VALUE x); PRINTF_ARGS(void rb_warn_deprecated(const char *fmt, const char *suggest, ...), 1, 3); -PRINTF_ARGS(void rb_warn_deprecated_to_remove(const char *fmt, const char *removal, ...), 1, 3); +PRINTF_ARGS(void rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...), 2, 4); +#if RUBY_DEBUG +# include "ruby/version.h" +# define RUBY_VERSION_SINCE(major, minor) (RUBY_API_VERSION_CODE >= (major * 10000) + (minor) * 100) +# define RUBY_VERSION_BEFORE(major, minor) (RUBY_API_VERSION_CODE < (major * 10000) + (minor) * 100) +# if defined(RBIMPL_WARNING_PRAGMA0) +# define RBIMPL_TODO0(x) RBIMPL_WARNING_PRAGMA0(message(x)) +# elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) +# define RBIMPL_TODO0(x) __pragma(message(x)) +# endif + +# if RBIMPL_HAS_ATTRIBUTE(diagnose_if) || defined(__OPTIMIZE__) + +#define RUBY_VERSION_isdigit(c) ('0'<=(c)&&(c)<='9') +// upto 99 +#define RUBY_VERSION__number_len(v, ofs) \ + (!RUBY_VERSION_isdigit((v)[ofs]) ? \ + 0 : !RUBY_VERSION_isdigit((v)[(ofs) + 1]) ? 1 : 2) +#define RUBY_VERSION__to_number(v, ofs) \ + (!RUBY_VERSION_isdigit((v)[ofs]) ? \ + 0 : !RUBY_VERSION_isdigit((v)[(ofs) + 1]) ? \ + ((v)[ofs]-'0') : \ + (((v)[ofs]-'0')*10+(v)[(ofs)+1]-'0')) + +#define RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v) \ + (RUBY_VERSION__to_number(v, 0) * 10000 + \ + ((v)[RUBY_VERSION__number_len(v, 0)] == '.' ? \ + RUBY_VERSION__to_number(v, RUBY_VERSION__number_len(v, 0)+1) * 100 : 0)) +#define RUBY_VERSION_STRING_SINCE(v) (RUBY_API_VERSION_CODE >= RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v)) +#define RUBY_VERSION_STRING_BEFORE(v) (RUBY_API_VERSION_CODE < RUBY_VERSION_CODE_FROM_MAJOR_MINOR_STRING(v)) + +# if RBIMPL_HAS_ATTRIBUTE(diagnose_if) +RBIMPL_ATTR_FORCEINLINE() +static void +rb_deprecated_method_to_be_removed(const char *removal) + RBIMPL_ATTR_DIAGNOSE_IF(!RUBY_VERSION_isdigit(removal[0]), "malformed version number", "error") + RBIMPL_ATTR_DIAGNOSE_IF(RUBY_VERSION_STRING_SINCE(removal), "deprecated method to be removed", "error") +{ +} +# else +RBIMPL_ATTR_ERROR(("deprecated")) +void rb_deprecated_method_to_be_removed(const char *); +# define rb_deprecated_method_to_be_removed(removal) \ + (sizeof(char[1-2*(!RUBY_VERSION_isdigit(removal[0]) || RUBY_VERSION_STRING_SINCE(removal))])!=1 ? \ + rb_deprecated_method_to_be_removed(removal) : \ + RBIMPL_ASSERT_NOTHING) +# endif +# define rb_warn_deprecated_to_remove_at(removal, ...) \ + (rb_deprecated_method_to_be_removed(#removal), \ + rb_warn_deprecated_to_remove(#removal, __VA_ARGS__)) +# endif +#endif +#ifndef rb_warn_deprecated_to_remove_at +# define rb_warn_deprecated_to_remove_at(removal, ...) \ + rb_warn_deprecated_to_remove(#removal, __VA_ARGS__) +#endif +#ifndef RUBY_VERSION_SINCE +# define RUBY_VERSION_SINCE(major, minor) 0 +#endif +#ifndef RUBY_VERSION_BEFORE +# define RUBY_VERSION_BEFORE(major, minor) 0 +#endif +#ifndef RBIMPL_TODO0 +# define RBIMPL_TODO0(x) +#endif +#define RBIMPL_TODO(message) RBIMPL_TODO0("TODO: " message) +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 6, 0) VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*, va_list); 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); @@ -60,6 +148,7 @@ VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method); VALUE rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv); VALUE rb_key_err_new(VALUE mesg, VALUE recv, VALUE name); PRINTF_ARGS(VALUE rb_warning_string(const char *fmt, ...), 1, 2); +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0) NORETURN(void rb_vraise(VALUE, const char *, va_list)); NORETURN(static inline void rb_raise_cstr(VALUE etype, const char *mesg)); NORETURN(static inline void rb_raise_cstr_i(VALUE etype, VALUE mesg)); @@ -80,6 +169,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 8dae76b6f8..e594d8516d 100644 --- a/internal/eval.h +++ b/internal/eval.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_EVAL_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_EVAL_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -22,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/file.h b/internal/file.h index a93c1392f0..9c192ff4d1 100644 --- a/internal/file.h +++ b/internal/file.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_FILE_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_FILE_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/fixnum.h b/internal/fixnum.h index 7e0e4be84c..8c251adef1 100644 --- a/internal/fixnum.h +++ b/internal/fixnum.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_FIXNUM_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_FIXNUM_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -19,7 +18,7 @@ #if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG # define DLONG LONG_LONG # define DL2NUM(x) LL2NUM(x) -#elif defined(HAVE_INT128_T) +#elif defined(HAVE_INT128_T) && !(defined(__OpenBSD__) && defined(__mips64__)) # define DLONG int128_t # define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x)) VALUE rb_int128t2big(int128_t n); /* in bignum.c */ diff --git a/internal/gc.h b/internal/gc.h index 86a2512c85..ecc3f11b2c 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_GC_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_GC_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -15,38 +14,119 @@ #include "internal/compilers.h" /* for __has_attribute */ #include "ruby/ruby.h" /* for rb_event_flag_t */ +#include "vm_core.h" /* for GET_EC() */ -struct rb_execution_context_struct; /* in vm_core.h */ -struct rb_objspace; /* in vm_core.h */ +#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__) +#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movl\t%%esp, %0" : "=r" (*(p))) +#elif (defined(__powerpc__) || defined(__powerpc64__)) && defined(__GNUC__) && !defined(_AIX) && !defined(__APPLE__) // Not Apple is NEEDED to unbreak ppc64 build on Darwin. Don't ask. +#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mr\t%0, %%r1" : "=r" (*(p))) +#elif (defined(__powerpc__) || defined(__powerpc64__)) && defined(__GNUC__) && defined(_AIX) +#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mr %0,1" : "=r" (*(p))) +#elif defined(__POWERPC__) && defined(__APPLE__) // Darwin ppc and ppc64 +#define SET_MACHINE_STACK_END(p) __asm__ volatile("mr %0, r1" : "=r" (*(p))) +#elif defined(__aarch64__) && defined(__GNUC__) +#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("mov\t%0, sp" : "=r" (*(p))) +#else +NOINLINE(void rb_gc_set_stack_end(VALUE **stack_end_p)); +#define SET_MACHINE_STACK_END(p) rb_gc_set_stack_end(p) +#define USE_CONSERVATIVE_STACK_END +#endif + +/* for GC debug */ + +#ifndef RUBY_MARK_FREE_DEBUG +#define RUBY_MARK_FREE_DEBUG 0 +#endif + +#if RUBY_MARK_FREE_DEBUG +extern int ruby_gc_debug_indent; + +static inline void +rb_gc_debug_indent(void) +{ + ruby_debug_printf("%*s", ruby_gc_debug_indent, ""); +} + +static inline void +rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr) +{ + if (st == 0) { + ruby_gc_debug_indent--; + } + rb_gc_debug_indent(); + ruby_debug_printf("%s: %s %s (%p)\n", mode, st ? "->" : "<-", msg, ptr); + + if (st) { + ruby_gc_debug_indent++; + } + + fflush(stdout); +} + +#define RUBY_MARK_ENTER(msg) rb_gc_debug_body("mark", (msg), 1, ptr) +#define RUBY_MARK_LEAVE(msg) rb_gc_debug_body("mark", (msg), 0, ptr) +#define RUBY_FREE_ENTER(msg) rb_gc_debug_body("free", (msg), 1, ptr) +#define RUBY_FREE_LEAVE(msg) rb_gc_debug_body("free", (msg), 0, ptr) +#define RUBY_GC_INFO rb_gc_debug_indent(), ruby_debug_printf + +#else +#define RUBY_MARK_ENTER(msg) +#define RUBY_MARK_LEAVE(msg) +#define RUBY_FREE_ENTER(msg) +#define RUBY_FREE_LEAVE(msg) +#define RUBY_GC_INFO if(0)printf +#endif -#ifndef USE_RVARGC -#define USE_RVARGC 0 +#define RUBY_FREE_UNLESS_NULL(ptr) if(ptr){ruby_xfree(ptr);(ptr)=NULL;} + +#if STACK_GROW_DIRECTION > 0 +# define STACK_UPPER(x, a, b) (a) +#elif STACK_GROW_DIRECTION < 0 +# define STACK_UPPER(x, a, b) (b) +#else +RUBY_EXTERN int ruby_stack_grow_direction; +int ruby_get_stack_grow_direction(volatile VALUE *addr); +# define stack_growup_p(x) ( \ + (ruby_stack_grow_direction ? \ + ruby_stack_grow_direction : \ + ruby_get_stack_grow_direction(x)) > 0) +# define STACK_UPPER(x, a, b) (stack_growup_p(x) ? (a) : (b)) #endif -#ifdef NEWOBJ_OF -# undef NEWOBJ_OF -# undef RB_NEWOBJ_OF -# undef RB_OBJ_WRITE +/* + STACK_GROW_DIR_DETECTION is used with STACK_DIR_UPPER. + + On most normal systems, stacks grow from high address to lower address. In + this case, STACK_DIR_UPPER(a, b) will return (b), but on exotic systems where + the stack grows UP (from low address to high address), it will return (a). +*/ + +#if STACK_GROW_DIRECTION +#define STACK_GROW_DIR_DETECTION +#define STACK_DIR_UPPER(a,b) STACK_UPPER(0, (a), (b)) +#else +#define STACK_GROW_DIR_DETECTION VALUE stack_grow_dir_detection +#define STACK_DIR_UPPER(a,b) STACK_UPPER(&stack_grow_dir_detection, (a), (b)) #endif +#define IS_STACK_DIR_UPPER() STACK_DIR_UPPER(1,0) -/* optimized version of NEWOBJ() */ -#define RB_NEWOBJ_OF(var, T, c, f) \ - T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \ - rb_wb_protected_newobj_of((c), (f) & ~FL_WB_PROTECTED, 0) : \ - rb_wb_unprotected_newobj_of((c), (f), 0)) +const char *rb_obj_info(VALUE obj); +const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj); -#define RB_EC_NEWOBJ_OF(ec, var, T, c, f) \ - T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \ - rb_ec_wb_protected_newobj_of((ec), (c), (f) & ~FL_WB_PROTECTED, 0) : \ - rb_wb_unprotected_newobj_of((c), (f), 0)) +struct rb_execution_context_struct; /* in vm_core.h */ +struct rb_objspace; /* in vm_core.h */ -#define RB_RVARGC_NEWOBJ_OF(var, T, c, f, s) \ - T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \ - rb_wb_protected_newobj_of((c), (f) & ~FL_WB_PROTECTED, s) : \ - rb_wb_unprotected_newobj_of((c), (f), s)) +#define NEWOBJ_OF(var, T, c, f, s, ec) \ + T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \ + 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) RB_NEWOBJ_OF((var), T, (c), (f)) -#define RVARGC_NEWOBJ_OF(var, T, c, f, s) RB_RVARGC_NEWOBJ_OF((var), T, (c), (f), (s)) #define RB_OBJ_GC_FLAGS_MAX 6 /* used in ext/objspace */ #ifndef USE_UNALIGNED_MEMBER_ACCESS @@ -64,64 +144,130 @@ struct rb_objspace; /* in vm_core.h */ COMPILER_WARNING_POP; \ unaligned_member_access_result; \ }) + +# define UNALIGNED_MEMBER_PTR(ptr, mem) __extension__({ \ + COMPILER_WARNING_PUSH; \ + COMPILER_WARNING_IGNORED(-Waddress-of-packed-member); \ + const volatile void *unaligned_member_ptr_result = &(ptr)->mem; \ + COMPILER_WARNING_POP; \ + (__typeof__((ptr)->mem) *)unaligned_member_ptr_result; \ +}) +#endif + +#ifndef UNALIGNED_MEMBER_PTR +# define UNALIGNED_MEMBER_PTR(ptr, mem) UNALIGNED_MEMBER_ACCESS(&(ptr)->mem) +#endif + +#define RB_OBJ_WRITE_UNALIGNED(old, slot, young) do { \ + VALUE *_slot = UNALIGNED_MEMBER_ACCESS(slot); \ + RB_OBJ_WRITE(old, _slot, young); \ +} while (0) + +// We use SIZE_POOL_COUNT number of shape IDs for transitions out of different size pools +// The next available shape ID will be the SPECIAL_CONST_SHAPE_ID +#ifndef SIZE_POOL_COUNT +# define SIZE_POOL_COUNT 5 #endif -#define UNALIGNED_MEMBER_PTR(ptr, mem) UNALIGNED_MEMBER_ACCESS(&(ptr)->mem) -#define RB_OBJ_WRITE(a, slot, b) \ - rb_obj_write((VALUE)(a), UNALIGNED_MEMBER_ACCESS((VALUE *)(slot)), \ - (VALUE)(b), __FILE__, __LINE__) +/* 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; +} rb_ractor_newobj_size_pool_cache_t; -#define RVARGC_PAYLOAD_INIT(obj, size) (void *)rb_rvargc_payload_init((VALUE)obj, (size_t)size) +typedef struct ractor_newobj_cache { + size_t incremental_mark_step_allocated_slots; + rb_ractor_newobj_size_pool_cache_t size_pool_caches[SIZE_POOL_COUNT]; +} 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); RUBY_ATTR_MALLOC void *rb_xmalloc_mul_add_mul(size_t, size_t, size_t, size_t); 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); +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(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); \ + if (_obj != (VALUE)*(ptr)) *(ptr) = (void *)_obj; \ +} while (0) RUBY_SYMBOL_EXPORT_BEGIN +/* exports for objspace module */ +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); + +void rb_objspace_each_objects( + int (*callback)(void *start, void *end, size_t stride, void *data), + void *data); + +size_t rb_gc_obj_slot_size(VALUE obj); + +VALUE rb_gc_disable_no_rest(void); + + /* gc.c (export) */ const char *rb_objspace_data_type_name(VALUE obj); -VALUE rb_wb_protected_newobj_of(VALUE, VALUE, size_t); +VALUE rb_wb_protected_newobj_of(struct rb_execution_context_struct *, VALUE, VALUE, size_t); VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE, size_t); -VALUE rb_ec_wb_protected_newobj_of(struct rb_execution_context_struct *ec, VALUE klass, VALUE flags, size_t); -VALUE rb_rvargc_payload_init(VALUE obj, size_t size); -void * rb_rvargc_payload_data_ptr(VALUE obj); size_t rb_obj_memsize_of(VALUE); 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); -int rb_slot_size(void); RUBY_SYMBOL_EXPORT_END -MJIT_SYMBOL_EXPORT_BEGIN int rb_ec_stack_check(struct rb_execution_context_struct *ec); void rb_gc_writebarrier_remember(VALUE obj); const char *rb_obj_info(VALUE obj); -MJIT_SYMBOL_EXPORT_END #if defined(HAVE_MALLOC_USABLE_SIZE) || defined(HAVE_MALLOC_SIZE) || defined(_WIN32) @@ -145,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 * @@ -168,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 a4677c581b..fe859cb716 100644 --- a/internal/hash.h +++ b/internal/hash.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_HASH_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_HASH_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -29,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) @@ -41,17 +36,23 @@ enum ruby_rhash_flags { RHASH_LEV_MAX = 127, /* 7 bits */ }; -struct RHash { - struct RBasic basic; - union { - st_table *st; - struct ar_table_struct *ar; /* possibly 0 */ - } as; - const VALUE ifnone; +typedef struct ar_table_pair_struct { + VALUE key; + VALUE val; +} ar_table_pair; + +typedef struct ar_table_struct { union { ar_hint_t ary[RHASH_AR_TABLE_MAX_SIZE]; VALUE word; } ar_hint; + /* 64bit CPU: 8B * 2 * 8 = 128B */ + ar_table_pair pairs[RHASH_AR_TABLE_MAX_SIZE]; +} ar_table; + +struct RHash { + struct RBasic basic; + const VALUE ifnone; }; #define RHASH(obj) ((struct RHash *)(obj)) @@ -74,6 +75,8 @@ VALUE rb_hash_default_value(VALUE hash, VALUE key); VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc); long rb_dbl_long_hash(double d); st_table *rb_init_identtable(void); +st_index_t rb_any_hash(VALUE a); +int rb_any_cmp(VALUE a, VALUE b); VALUE rb_to_hash_type(VALUE obj); VALUE rb_hash_key_str(VALUE); VALUE rb_hash_values(VALUE hash); @@ -83,7 +86,8 @@ VALUE rb_hash_set_pair(VALUE hash, VALUE pair); 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); -extern st_table *rb_hash_st_table(VALUE hash); +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); @@ -95,9 +99,6 @@ static inline struct ar_table_struct *RHASH_AR_TABLE(VALUE h); static inline st_table *RHASH_ST_TABLE(VALUE h); static inline size_t RHASH_ST_SIZE(VALUE h); static inline void RHASH_ST_CLEAR(VALUE h); -static inline bool RHASH_TRANSIENT_P(VALUE h); -static inline void RHASH_SET_TRANSIENT_FLAG(VALUE h); -static inline void RHASH_UNSET_TRANSIENT_FLAG(VALUE h); RUBY_SYMBOL_EXPORT_BEGIN /* hash.c (export) */ @@ -106,7 +107,6 @@ VALUE rb_ident_hash_new(void); int rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg); RUBY_SYMBOL_EXPORT_END -MJIT_SYMBOL_EXPORT_BEGIN VALUE rb_hash_new_with_size(st_index_t size); VALUE rb_hash_resurrect(VALUE hash); int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval); @@ -116,31 +116,8 @@ VALUE rb_hash_compare_by_id_p(VALUE hash); st_table *rb_hash_tbl_raw(VALUE hash, const char *file, int line); #define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h, __FILE__, __LINE__) -MJIT_SYMBOL_EXPORT_END - -#if 0 /* for debug */ - -static inline bool -RHASH_AR_TABLE_P(VALUE h) -{ - extern int rb_hash_ar_table_p(VALUE hash); - return rb_hash_ar_table_p(h) -} - -static inline struct ar_table_struct * -RHASH_AR_TABLE(VALUE h) -{ - extern struct ar_table_struct *rb_hash_ar_table(VALUE hash); - return rb_hash_ar_table(h) -} -static inline st_table * -RHASH_ST_TABLE(VALUE h) -{ - return rb_hash_st_table(h) -} - -#else +VALUE rb_hash_compare_by_id(VALUE hash); static inline bool RHASH_AR_TABLE_P(VALUE h) @@ -148,20 +125,20 @@ 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 RHASH(h)->as.ar; + return (struct ar_table_struct *)((uintptr_t)h + sizeof(struct RHash)); } +RBIMPL_ATTR_RETURNS_NONNULL() static inline st_table * RHASH_ST_TABLE(VALUE h) { - return RHASH(h)->as.st; + return (st_table *)((uintptr_t)h + sizeof(struct RHash)); } -#endif - static inline VALUE RHASH_IFNONE(VALUE h) { @@ -200,8 +177,7 @@ RHASH_ST_SIZE(VALUE h) static inline void RHASH_ST_CLEAR(VALUE h) { - FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG); - RHASH(h)->as.ar = NULL; + memset(RHASH_ST_TABLE(h), 0, sizeof(st_table)); } static inline unsigned @@ -212,30 +188,4 @@ RHASH_AR_TABLE_SIZE_RAW(VALUE h) return (unsigned)ret; } -static inline bool -RHASH_TRANSIENT_P(VALUE h) -{ -#if USE_TRANSIENT_HEAP - return FL_TEST_RAW(h, RHASH_TRANSIENT_FLAG); -#else - return false; -#endif -} - -static inline void -RHASH_SET_TRANSIENT_FLAG(VALUE h) -{ -#if USE_TRANSIENT_HEAP - FL_SET_RAW(h, RHASH_TRANSIENT_FLAG); -#endif -} - -static inline void -RHASH_UNSET_TRANSIENT_FLAG(VALUE h) -{ -#if USE_TRANSIENT_HEAP - FL_UNSET_RAW(h, RHASH_TRANSIENT_FLAG); -#endif -} - #endif /* INTERNAL_HASH_H */ diff --git a/internal/imemo.h b/internal/imemo.h index a9e2136ac4..36c0776987 100644 --- a/internal/imemo.h +++ b/internal/imemo.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_IMEMO_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_IMEMO_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -11,8 +10,7 @@ */ #include "ruby/internal/config.h" #include <stddef.h> /* for size_t */ -#include "internal/array.h" /* for rb_ary_tmp_new_fill */ -#include "internal/gc.h" /* for RB_OBJ_WRITE */ +#include "internal/array.h" /* for rb_ary_hidden_new_fill */ #include "ruby/internal/stdbool.h" /* for bool */ #include "ruby/ruby.h" /* for rb_block_call_func_t */ @@ -41,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, @@ -84,7 +82,7 @@ struct vm_ifunc_argc { /*! IFUNC (Internal FUNCtion) */ struct vm_ifunc { VALUE flags; - VALUE reserved; + VALUE *svar_lep; rb_block_call_func_t func; const void *data; struct vm_ifunc_argc argc; @@ -115,24 +113,25 @@ 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_tmp_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value)) + ((value) = rb_ary_hidden_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)), \ + ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), \ 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; -VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0); +#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); @@ -144,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) { @@ -175,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) @@ -192,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 * @@ -217,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 680c9cc1a5..03de289dd4 100644 --- a/internal/inits.h +++ b/internal/inits.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_INITS_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_INITS_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -20,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 b184cec439..1891248a19 100644 --- a/internal/io.h +++ b/internal/io.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_IO_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_IO_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -10,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); @@ -25,6 +126,10 @@ void rb_io_fptr_finalize_internal(void *ptr); #define rb_io_fptr_finalize rb_io_fptr_finalize_internal VALUE rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt); +VALUE rb_io_prep_stdin(void); +VALUE rb_io_prep_stdout(void); +VALUE rb_io_prep_stderr(void); + RUBY_SYMBOL_EXPORT_BEGIN /* io.c (export) */ void rb_maygvl_fd_fix_cloexec(int fd); diff --git a/internal/load.h b/internal/load.h index 37c1dee351..d4c0bb91ba 100644 --- a/internal/load.h +++ b/internal/load.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_LOAD_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_LOAD_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/loadpath.h b/internal/loadpath.h index f89f6694cd..b3a85e7b41 100644 --- a/internal/loadpath.h +++ b/internal/loadpath.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_LOADPATH_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_LOADPATH_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/math.h b/internal/math.h index cd8d553790..08f852ffc1 100644 --- a/internal/math.h +++ b/internal/math.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_MATH_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_MATH_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/missing.h b/internal/missing.h index 0224075b3d..6ca508c8f9 100644 --- a/internal/missing.h +++ b/internal/missing.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_MISSING_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_MISSING_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -14,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 32d5bd27fa..6406cfc2fa 100644 --- a/internal/numeric.h +++ b/internal/numeric.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_NUMERIC_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_NUMERIC_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -36,9 +35,22 @@ enum ruby_num_rounding_mode { RUBY_NUM_ROUND_DEFAULT = ROUND_DEFAULT, }; +/* same as internal.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)) + +#if SIZEOF_DOUBLE <= SIZEOF_VALUE +typedef double rb_float_value_type; +#else +typedef struct { + VALUE values[roomof(SIZEOF_DOUBLE, SIZEOF_VALUE)]; +} rb_float_value_type; +#endif + struct RFloat { struct RBasic basic; - double float_value; + rb_float_value_type float_value; }; #define RFLOAT(obj) ((struct RFloat *)(obj)) @@ -74,9 +86,11 @@ 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); +VALUE rb_check_integer_type(VALUE); VALUE rb_num_pow(VALUE x, VALUE y); VALUE rb_float_ceil(VALUE num, int ndigits); VALUE rb_float_floor(VALUE x, int ndigits); @@ -96,10 +110,8 @@ static inline bool FLOAT_ZERO_P(VALUE num); RUBY_SYMBOL_EXPORT_BEGIN /* numeric.c (export) */ -VALUE rb_int_positive_pow(long x, unsigned long y); RUBY_SYMBOL_EXPORT_END -MJIT_SYMBOL_EXPORT_BEGIN VALUE rb_flo_div_flo(VALUE x, VALUE y); double ruby_float_mod(double x, double y); VALUE rb_float_equal(VALUE x, VALUE y); @@ -113,7 +125,6 @@ VALUE rb_int_abs(VALUE num); VALUE rb_int_bit_length(VALUE num); VALUE rb_int_uminus(VALUE num); VALUE rb_int_comp(VALUE num); -MJIT_SYMBOL_EXPORT_END static inline bool INT_POSITIVE_P(VALUE num) @@ -148,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; @@ -210,7 +221,15 @@ rb_float_flonum_value(VALUE v) static inline double rb_float_noflonum_value(VALUE v) { +#if SIZEOF_DOUBLE <= SIZEOF_VALUE return RFLOAT(v)->float_value; +#else + union { + rb_float_value_type v; + double d; + } u = {RFLOAT(v)->float_value}; + return u.d; +#endif } static inline double diff --git a/internal/object.h b/internal/object.h index 2af90c1fdc..92ad37fdc8 100644 --- a/internal/object.h +++ b/internal/object.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_OBJECT_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_OBJECT_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -10,31 +9,28 @@ * @brief Internal header for Object. */ #include "ruby/ruby.h" /* for VALUE */ -#include "internal/class.h" /* for RCLASS_IV_INDEX_TBL */ - -#ifdef ROBJECT_IV_INDEX_TBL -# undef ROBJECT_IV_INDEX_TBL -#endif /* 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 rb_bool_expected(VALUE, const char *, int raise); static inline void RBASIC_CLEAR_CLASS(VALUE obj); static inline void RBASIC_SET_CLASS_RAW(VALUE obj, VALUE klass); static inline void RBASIC_SET_CLASS(VALUE obj, VALUE klass); -static inline struct st_table *ROBJECT_IV_INDEX_TBL_inline(VALUE obj); RUBY_SYMBOL_EXPORT_BEGIN /* object.c (export) */ int rb_opts_exception_p(VALUE opts, int default_value); RUBY_SYMBOL_EXPORT_END -MJIT_SYMBOL_EXPORT_BEGIN CONSTFUNC(VALUE rb_obj_equal(VALUE obj1, VALUE obj2)); CONSTFUNC(VALUE rb_obj_not(VALUE obj)); VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); @@ -42,7 +38,7 @@ void rb_obj_copy_ivar(VALUE dest, VALUE obj); VALUE rb_false(VALUE obj); VALUE rb_convert_type_with_id(VALUE v, int t, const char* nam, ID mid); VALUE rb_obj_size(VALUE self, VALUE args, VALUE obj); -MJIT_SYMBOL_EXPORT_END +VALUE rb_get_freeze_opt(int argc, VALUE *argv); static inline void RBASIC_SET_CLASS_RAW(VALUE obj, VALUE klass) @@ -64,20 +60,4 @@ RBASIC_SET_CLASS(VALUE obj, VALUE klass) RBASIC_SET_CLASS_RAW(obj, klass); RB_OBJ_WRITTEN(obj, oldv, klass); } - -RBIMPL_ATTR_PURE() -static inline struct st_table * -ROBJECT_IV_INDEX_TBL_inline(VALUE obj) -{ - if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { - VALUE klass = rb_obj_class(obj); - return RCLASS_IV_INDEX_TBL(klass); - } - else { - const struct RObject *const ptr = ROBJECT(obj); - return ptr->as.heap.iv_index_tbl; - } -} -#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL_inline - #endif /* INTERNAL_OBJECT_H */ diff --git a/internal/parse.h b/internal/parse.h index a37a39f84d..f06020c73f 100644 --- a/internal/parse.h +++ b/internal/parse.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_PARSE_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_PARSE_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -9,15 +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 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_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 VALUE (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/proc.h b/internal/proc.h index 5628a1f1c7..c75f15b283 100644 --- a/internal/proc.h +++ b/internal/proc.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_PROC_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_PROC_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -23,11 +22,9 @@ int rb_block_min_max_arity(int *max); VALUE rb_block_to_s(VALUE self, const struct rb_block *block, const char *additional_info); VALUE rb_callable_receiver(VALUE); -MJIT_SYMBOL_EXPORT_BEGIN VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val); VALUE rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc); VALUE rb_iseq_location(const struct rb_iseq_struct *iseq); VALUE rb_sym_to_proc(VALUE sym); -MJIT_SYMBOL_EXPORT_END #endif /* INTERNAL_PROC_H */ diff --git a/internal/process.h b/internal/process.h index 904c9a5cea..fd4994cb4b 100644 --- a/internal/process.h +++ b/internal/process.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_PROCESS_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_PROCESS_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -21,12 +20,13 @@ #endif #include "ruby/ruby.h" /* for VALUE */ +#include "internal/compilers.h" /* for __has_warning */ #include "internal/imemo.h" /* for RB_IMEMO_TMPBUF_PTR */ -#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */ #define RB_MAX_GROUPS (65536) struct waitpid_state; +struct rb_process_status; struct rb_execarg { union { struct { @@ -57,6 +57,7 @@ struct rb_execarg { unsigned gid_given : 1; unsigned exception : 1; unsigned exception_given : 1; + struct rb_process_status *status; struct waitpid_state *waitpid_state; /* for async process management */ rb_pid_t pgroup_pgid; /* asis(-1), new pgroup(0), specified pgroup (0<V). */ VALUE rlimit_limits; /* Qfalse or [[rtype, softlim, hardlim], ...] */ @@ -74,7 +75,7 @@ struct rb_execarg { }; /* process.c */ -rb_pid_t rb_fork_ruby(int *status); +rb_pid_t rb_call_proc__fork(void); void rb_last_status_clear(void); static inline char **ARGVSTR2ARGV(VALUE argv_str); static inline size_t ARGVSTR2ARGC(VALUE argv_str); @@ -120,17 +121,4 @@ ARGVSTR2ARGC(VALUE argv_str) return i - 1; } -#ifdef HAVE_WORKING_FORK -COMPILER_WARNING_PUSH -#if __has_warning("-Wdeprecated-declarations") || RBIMPL_COMPILER_IS(GCC) -COMPILER_WARNING_IGNORED(-Wdeprecated-declarations) -#endif -static inline rb_pid_t -rb_fork(void) -{ - return fork(); -} -COMPILER_WARNING_POP -#endif - #endif /* INTERNAL_PROCESS_H */ diff --git a/internal/ractor.h b/internal/ractor.h new file mode 100644 index 0000000000..eef5ffdb89 --- /dev/null +++ b/internal/ractor.h @@ -0,0 +1,6 @@ +#ifndef INTERNAL_RACTOR_H /*-*-C-*-vi:se ft=c:*/ +#define INTERNAL_RACTOR_H + +void rb_ractor_ensure_main_ractor(const char *msg); + +#endif /* INTERNAL_RACTOR_H */ diff --git a/internal/random.h b/internal/random.h index a92e65b8ba..127b908e16 100644 --- a/internal/random.h +++ b/internal/random.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_RANDOM_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_RANDOM_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -13,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/range.h b/internal/range.h index 4fe6037c89..2394937bf8 100644 --- a/internal/range.h +++ b/internal/range.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_RANGE_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_RANGE_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -25,13 +24,13 @@ RANGE_BEG(VALUE r) static inline VALUE RANGE_END(VALUE r) { - return RSTRUCT(r)->as.ary[1]; + return RSTRUCT_GET(r, 1); } static inline VALUE RANGE_EXCL(VALUE r) { - return RSTRUCT(r)->as.ary[2]; + return RSTRUCT_GET(r, 2); } VALUE diff --git a/internal/rational.h b/internal/rational.h index 6bbd2a9810..f11fab4583 100644 --- a/internal/rational.h +++ b/internal/rational.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_RATIONAL_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_RATIONAL_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -11,7 +10,6 @@ */ #include "ruby/internal/config.h" /* for HAVE_LIBGMP */ #include "ruby/ruby.h" /* for struct RBasic */ -#include "internal/gc.h" /* for RB_OBJ_WRITE */ #include "internal/numeric.h" /* for INT_POSITIVE_P */ #include "ruby_assert.h" /* for assert */ @@ -39,6 +37,7 @@ VALUE rb_rational_cmp(VALUE self, VALUE other); VALUE rb_rational_pow(VALUE self, VALUE other); VALUE rb_rational_floor(VALUE self, int ndigits); VALUE rb_numeric_quo(VALUE x, VALUE y); +VALUE rb_flo_round_by_rational(int argc, VALUE *argv, VALUE num); VALUE rb_float_numerator(VALUE x); VALUE rb_float_denominator(VALUE x); diff --git a/internal/re.h b/internal/re.h index 28fa3fb51c..3e20114665 100644 --- a/internal/re.h +++ b/internal/re.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_RE_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_RE_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -18,12 +17,12 @@ VALUE rb_reg_check_preprocess(VALUE); long rb_reg_search0(VALUE, VALUE, long, int, int); VALUE rb_reg_match_p(VALUE re, VALUE str, long pos); bool rb_reg_start_with_p(VALUE re, VALUE str); +VALUE rb_reg_hash(VALUE re); +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); -MJIT_SYMBOL_EXPORT_BEGIN VALUE rb_reg_new_ary(VALUE ary, int options); -MJIT_SYMBOL_EXPORT_END +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..98c3461954 --- /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); +VALUE rb_parser_lex_get_str(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 vast); + +#endif /* INTERNAL_RUBY_PARSE_H */ diff --git a/internal/sanitizers.h b/internal/sanitizers.h index b4f5bdeda1..b0eb1fc851 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_SANITIZERS_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_SANITIZERS_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -17,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 @@ -30,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) @@ -61,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)) @@ -90,9 +95,7 @@ # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0 #endif -#ifndef MJIT_HEADER - -/*! +/** * 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 @@ -102,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) @@ -112,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) @@ -124,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) @@ -146,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, @@ -157,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) @@ -173,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) @@ -186,6 +189,109 @@ asan_unpoison_object(VALUE obj, bool newobj_p) asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p); } -#endif /* MJIT_HEADER */ +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/serial.h b/internal/serial.h index 977cb35477..df9e9a44f0 100644 --- a/internal/serial.h +++ b/internal/serial.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_SERIAL_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_SERIAL_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/signal.h b/internal/signal.h index 6b4672f15b..2363bf412c 100644 --- a/internal/signal.h +++ b/internal/signal.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_SIGNAL_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_SIGNAL_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -14,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/static_assert.h b/internal/static_assert.h index 284e410313..70dd0b7a1e 100644 --- a/internal/static_assert.h +++ b/internal/static_assert.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_STATIC_ASSERT_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_STATIC_ASSERT_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/string.h b/internal/string.h index 8907a1a6e6..fb37f73114 100644 --- a/internal/string.h +++ b/internal/string.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_STRING_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_STRING_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -18,6 +17,7 @@ #define STR_NOEMBED FL_USER1 #define STR_SHARED FL_USER2 /* = ELTS_SHARED */ +#define STR_CHILLED FL_USER3 #ifdef rb_fstring_cstr # undef rb_fstring_cstr @@ -38,11 +38,15 @@ VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc); VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts); VALUE rb_enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl); -VALUE rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc); +VALUE rb_str_escape(VALUE str); size_t rb_str_memsize(VALUE); char *rb_str_to_cstr(VALUE str); const char *ruby_escaped_char(int c); 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); @@ -55,13 +59,16 @@ 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); 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); RUBY_SYMBOL_EXPORT_END -MJIT_SYMBOL_EXPORT_BEGIN VALUE rb_fstring_new(const char *ptr, long len); VALUE rb_obj_as_string_result(VALUE str, VALUE obj); VALUE rb_str_opt_plus(VALUE x, VALUE y); @@ -71,8 +78,7 @@ VALUE rb_id_quote_unprintable(ID); VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc); struct rb_execution_context_struct; -VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str); -MJIT_SYMBOL_EXPORT_END +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) @@ -100,7 +106,27 @@ STR_EMBED_P(VALUE str) static inline bool STR_SHARED_P(VALUE str) { - return FL_ALL_RAW(str, STR_NOEMBED | ELTS_SHARED); + return FL_ALL_RAW(str, STR_NOEMBED | STR_SHARED); +} + +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) +{ + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "literal string will be frozen in the future"); + FL_UNSET_RAW(str, STR_CHILLED | FL_FREEZE); +} + +static inline void +STR_CHILL_RAW(VALUE str) +{ + // Chilled strings are always also frozen + FL_SET_RAW(str, STR_CHILLED | RUBY_FL_FREEZE); } static inline bool @@ -115,7 +141,23 @@ 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 rb_str_eql_internal(const VALUE str1, const VALUE str2) { diff --git a/internal/struct.h b/internal/struct.h index 82b2738b69..6da5bad10a 100644 --- a/internal/struct.h +++ b/internal/struct.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_STRUCT_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_STRUCT_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -10,14 +9,12 @@ * @brief Internal header for Struct. */ #include "ruby/internal/stdbool.h" /* for bool */ -#include "internal/gc.h" /* for RB_OBJ_WRITE */ #include "ruby/ruby.h" /* for struct RBasic */ enum { - RSTRUCT_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX, - RSTRUCT_EMBED_LEN_MASK = (RUBY_FL_USER2|RUBY_FL_USER1), + 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 = FL_USER3, }; struct RStruct { @@ -27,7 +24,12 @@ struct RStruct { long len; const VALUE *ptr; } heap; - const VALUE ary[RSTRUCT_EMBED_LEN_MAX]; + /* This is a length 1 array because: + * 1. GCC has a bug that does not optimize C flexible array members + * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452) + * 2. Zero length arrays are not supported by all compilers + */ + const VALUE ary[1]; } as; }; @@ -58,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); @@ -68,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) { @@ -147,7 +120,7 @@ RSTRUCT_GET(VALUE st, long k) static inline const VALUE * rb_struct_const_heap_ptr(VALUE st) { - /* TODO: check embed on debug mode */ + assert(!FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)); return RSTRUCT(st)->as.heap.ptr; } diff --git a/internal/symbol.h b/internal/symbol.h index 691df66228..e7730cb70f 100644 --- a/internal/symbol.h +++ b/internal/symbol.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_SYMBOL_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_SYMBOL_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -29,7 +28,12 @@ int rb_is_local_name(VALUE name); PUREFUNC(int rb_is_const_sym(VALUE sym)); PUREFUNC(int rb_is_attrset_sym(VALUE sym)); ID rb_make_internal_id(void); +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) \ diff --git a/internal/thread.h b/internal/thread.h index 09b8551b5c..47273436e3 100644 --- a/internal/thread.h +++ b/internal/thread.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_THREAD_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_THREAD_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -11,9 +10,17 @@ */ #include "ruby/ruby.h" /* for VALUE */ #include "ruby/intern.h" /* for rb_blocking_function_t */ +#include "ccan/list/list.h" /* for list in rb_io_close_wait_list */ struct rb_thread_struct; /* in vm_core.h */ +#define RB_VM_SAVE_MACHINE_CONTEXT(th) \ + do { \ + FLUSH_REGISTER_WINDOWS; \ + setjmp((th)->ec->machine.regs); \ + SET_MACHINE_STACK_END(&(th)->ec->machine.stack_end); \ + } while (0) + /* thread.c */ #define COVERAGE_INDEX_LINES 0 #define COVERAGE_INDEX_BRANCHES 1 @@ -21,6 +28,11 @@ struct rb_thread_struct; /* in vm_core.h */ #define COVERAGE_TARGET_BRANCHES 2 #define COVERAGE_TARGET_METHODS 4 #define COVERAGE_TARGET_ONESHOT_LINES 8 +#define COVERAGE_TARGET_EVAL 16 + +#define RUBY_FATAL_THREAD_KILLED INT2FIX(0) +#define RUBY_FATAL_THREAD_TERMINATED INT2FIX(1) +#define RUBY_FATAL_FIBER_KILLED RB_INT2FIX(2) VALUE rb_obj_is_mutex(VALUE obj); VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg); @@ -29,6 +41,7 @@ VALUE rb_get_coverages(void); int rb_get_coverage_mode(void); VALUE rb_default_coverage(int); VALUE rb_thread_shield_new(void); +bool rb_thread_shield_owned(VALUE self); VALUE rb_thread_shield_wait(VALUE self); VALUE rb_thread_shield_release(VALUE self); VALUE rb_thread_shield_destroy(VALUE self); @@ -36,19 +49,31 @@ int rb_thread_to_be_killed(VALUE thread); 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); +struct rb_io_close_wait_list { + struct ccan_list_head pending_fd_users; + VALUE closing_thread; + VALUE wakeup_mutex; +}; +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 -MJIT_SYMBOL_EXPORT_BEGIN int rb_threadptr_execute_interrupts(struct rb_thread_struct *th, int blocking_timing); -MJIT_SYMBOL_EXPORT_END +bool rb_thread_mn_schedulable(VALUE thread); #endif /* INTERNAL_THREAD_H */ diff --git a/internal/time.h b/internal/time.h index f9ac084603..a3bf0587ec 100644 --- a/internal/time.h +++ b/internal/time.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_TIME_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_TIME_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or diff --git a/internal/transcode.h b/internal/transcode.h index a60ac06d10..ce4f2341be 100644 --- a/internal/transcode.h +++ b/internal/transcode.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_TRANSCODE_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_TRANSCODE_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -18,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/util.h b/internal/util.h index c28b884d32..6eadbb9f94 100644 --- a/internal/util.h +++ b/internal/util.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_UTIL_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_UTIL_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -23,9 +22,6 @@ char *ruby_hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign RUBY_SYMBOL_EXPORT_BEGIN /* util.c (export) */ -extern const signed char ruby_digit36_to_number_table[]; -extern const char ruby_hexdigits[]; -extern unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow); RUBY_SYMBOL_EXPORT_END #endif /* INTERNAL_UTIL_H */ diff --git a/internal/variable.h b/internal/variable.h index 057beccfcc..b2a30c7c58 100644 --- a/internal/variable.h +++ b/internal/variable.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_VARIABLE_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_VARIABLE_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -14,10 +13,7 @@ #include "constant.h" /* for rb_const_entry_t */ #include "ruby/internal/stdbool.h" /* for bool */ #include "ruby/ruby.h" /* for VALUE */ - -/* global variable */ - -#define ROBJECT_TRANSIENT_FLAG FL_USER13 +#include "shape.h" /* for rb_shape_t */ /* variable.c */ void rb_gc_mark_global_tbl(void); @@ -25,7 +21,6 @@ void rb_gc_update_global_tbl(void); size_t rb_generic_ivar_memsize(VALUE); VALUE rb_search_class_path(VALUE); VALUE rb_attr_delete(VALUE, ID); -VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef); void rb_autoload_str(VALUE mod, ID id, VALUE file); VALUE rb_autoload_at_p(VALUE, ID, int); NORETURN(VALUE rb_mod_const_missing(VALUE,VALUE)); @@ -33,52 +28,45 @@ 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); +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_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); void rb_iv_tbl_copy(VALUE dst, VALUE src); -void rb_deprecate_constant(VALUE mod, const char *name); RUBY_SYMBOL_EXPORT_END -MJIT_SYMBOL_EXPORT_BEGIN +VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef); 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); -void rb_init_iv_list(VALUE obj); -MJIT_SYMBOL_EXPORT_END - -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 -} +void rb_ensure_iv_list_size(VALUE obj, uint32_t len, uint32_t newsize); +attr_index_t rb_obj_ivar_set(VALUE obj, ID id, VALUE val); #endif /* INTERNAL_VARIABLE_H */ diff --git a/internal/vm.h b/internal/vm.h index 689b4fa61f..74635e6ad8 100644 --- a/internal/vm.h +++ b/internal/vm.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_VM_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_VM_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or @@ -41,28 +40,25 @@ enum method_missing_reason { }; /* vm_insnhelper.h */ -rb_serial_t rb_next_class_serial(void); +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)); -void rb_vm_inc_const_missing_count(void); const void **rb_vm_get_insns_address_table(void); VALUE rb_source_location(int *pline); const char *rb_source_location_cstr(int *pline); -MJIT_STATIC void rb_vm_pop_cfunc_frame(void); -int rb_vm_add_root_module(VALUE module); +void rb_vm_pop_cfunc_frame(void); 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); -MJIT_STATIC VALUE ruby_vm_special_exception_copy(VALUE); +VALUE ruby_vm_special_exception_copy(VALUE); PUREFUNC(st_table *rb_vm_fstring_table(void)); -MJIT_SYMBOL_EXPORT_BEGIN -VALUE vm_exec(struct rb_execution_context_struct *, bool); /* used in JIT-ed code */ -MJIT_SYMBOL_EXPORT_END +void rb_lastline_set_up(VALUE val, unsigned int up); /* vm_eval.c */ VALUE rb_current_realfilepath(void); @@ -82,23 +78,31 @@ 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); struct rb_iseq_struct; -MJIT_SYMBOL_EXPORT_BEGIN const struct rb_callcache *rb_vm_search_method_slowpath(const struct rb_callinfo *ci, VALUE klass); -MJIT_SYMBOL_EXPORT_END /* vm_method.c */ struct rb_execution_context_struct; -MJIT_SYMBOL_EXPORT_BEGIN int rb_ec_obj_respond_to(struct rb_execution_context_struct *ec, VALUE obj, ID id, int priv); -MJIT_SYMBOL_EXPORT_END + +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); @@ -106,16 +110,18 @@ 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); +const struct rb_iseq_struct *rb_get_iseq_from_frame_info(VALUE obj); -MJIT_SYMBOL_EXPORT_BEGIN VALUE rb_ec_backtrace_object(const struct rb_execution_context_struct *ec); void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self); -MJIT_SYMBOL_EXPORT_END #define RUBY_DTRACE_CREATE_HOOK(name, arg) \ RUBY_DTRACE_HOOK(name##_CREATE, arg) diff --git a/internal/warnings.h b/internal/warnings.h index e9de46eb38..020212ebd8 100644 --- a/internal/warnings.h +++ b/internal/warnings.h @@ -1,7 +1,6 @@ #ifndef INTERNAL_WARNINGS_H /*-*-C-*-vi:se ft=c:*/ #define INTERNAL_WARNINGS_H /** - * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or |