diff options
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | class.c | 8 | ||||
-rw-r--r-- | constant.h | 4 | ||||
-rw-r--r-- | ext/json/generator/generator.c | 2 | ||||
-rw-r--r-- | ext/json/parser/parser.c | 2 | ||||
-rw-r--r-- | gc.c | 1279 | ||||
-rw-r--r-- | gc.h | 4 | ||||
-rw-r--r-- | hash.c | 40 | ||||
-rw-r--r-- | id_table.c | 22 | ||||
-rw-r--r-- | id_table.h | 3 | ||||
-rw-r--r-- | include/ruby/intern.h | 6 | ||||
-rw-r--r-- | include/ruby/ruby.h | 12 | ||||
-rw-r--r-- | include/ruby/st.h | 3 | ||||
-rw-r--r-- | internal.h | 42 | ||||
-rw-r--r-- | iseq.c | 100 | ||||
-rw-r--r-- | iseq.h | 2 | ||||
-rw-r--r-- | method.h | 24 | ||||
-rw-r--r-- | st.c | 23 | ||||
-rw-r--r-- | symbol.c | 7 | ||||
-rw-r--r-- | symbol.h | 7 | ||||
-rw-r--r-- | test/ruby/test_gc_compact.rb | 97 | ||||
-rw-r--r-- | thread.c | 6 | ||||
-rw-r--r-- | transient_heap.c | 50 | ||||
-rw-r--r-- | transient_heap.h | 2 | ||||
-rw-r--r-- | variable.c | 32 | ||||
-rw-r--r-- | vm.c | 31 | ||||
-rw-r--r-- | vm_core.h | 8 | ||||
-rw-r--r-- | vm_eval.c | 1 |
28 files changed, 1719 insertions, 107 deletions
@@ -102,6 +102,15 @@ JIT:: * Default value of +--jit-min-calls+ is changed from 5 to 10,000 === Miscellaneous changes * Require compilers to support C99 [Misc #15347] @@ -539,6 +539,7 @@ boot_defclass(const char *name, VALUE super) rb_name_class(obj, id); rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); return obj; } @@ -730,6 +731,9 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super) " (%"PRIsVALUE" is given but was %"PRIsVALUE")", outer, rb_id2str(id), RCLASS_SUPER(klass), super); } return klass; } if (!super) { @@ -740,6 +744,7 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super) rb_set_class_path_string(klass, outer, rb_id2str(id)); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); rb_gc_register_mark_object(klass); return klass; @@ -777,10 +782,13 @@ rb_define_module(const char *name) rb_raise(rb_eTypeError, "%s is not a module (%"PRIsVALUE")", name, rb_obj_class(module)); } return module; } module = rb_define_module_id(id); rb_vm_add_root_module(id, module); rb_const_set(rb_cObject, id, module); return module; @@ -31,8 +31,8 @@ typedef enum { typedef struct rb_const_entry_struct { rb_const_flag_t flag; int line; - const VALUE value; /* should be mark */ - const VALUE file; /* should be mark */ } rb_const_entry_t; VALUE rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj); @@ -1344,6 +1344,8 @@ void Init_generator(void) eGeneratorError = rb_path2class("JSON::GeneratorError"); eNestingError = rb_path2class("JSON::NestingError"); cState = rb_define_class_under(mGenerator, "State", rb_cObject); rb_define_alloc_func(cState, cState_s_allocate); @@ -2091,6 +2091,8 @@ void Init_parser(void) cParser = rb_define_class_under(mExt, "Parser", rb_cObject); eParserError = rb_path2class("JSON::ParserError"); eNestingError = rb_path2class("JSON::NestingError"); rb_define_alloc_func(cParser, cJSON_parser_s_allocate); rb_define_method(cParser, "initialize", cParser_initialize, -1); rb_define_method(cParser, "parse", cParser_parse, 0); @@ -29,6 +29,7 @@ #include "ruby_atomic.h" #include "probes.h" #include "id_table.h" #include <stdio.h> #include <stdarg.h> #include <setjmp.h> @@ -404,6 +405,7 @@ typedef struct RVALUE { VALUE flags; /* always 0 for freed obj */ struct RVALUE *next; } free; struct RBasic basic; struct RObject object; struct RClass klass; @@ -581,6 +583,7 @@ typedef struct rb_objspace { #if USE_RGENGC size_t minor_gc_count; size_t major_gc_count; #if RGENGC_PROFILE > 0 size_t total_generated_normal_object_count; size_t total_generated_shady_object_count; @@ -635,6 +638,12 @@ typedef struct rb_objspace { size_t error_count; #endif } rgengc; #if GC_ENABLE_INCREMENTAL_MARK struct { size_t pooled_slots; @@ -643,6 +652,9 @@ typedef struct rb_objspace { #endif #endif /* USE_RGENGC */ #if GC_DEBUG_STRESS_TO_CLASS VALUE stress_to_class; #endif @@ -682,6 +694,8 @@ struct heap_page { #if USE_RGENGC bits_t wb_unprotected_bits[HEAP_PAGE_BITMAP_LIMIT]; #endif /* the following three bitmaps are cleared at the beginning of full GC */ bits_t mark_bits[HEAP_PAGE_BITMAP_LIMIT]; #if USE_RGENGC @@ -706,6 +720,7 @@ struct heap_page { /* getting bitmap */ #define GET_HEAP_MARK_BITS(x) (&GET_HEAP_PAGE(x)->mark_bits[0]) #if USE_RGENGC #define GET_HEAP_UNCOLLECTIBLE_BITS(x) (&GET_HEAP_PAGE(x)->uncollectible_bits[0]) #define GET_HEAP_WB_UNPROTECTED_BITS(x) (&GET_HEAP_PAGE(x)->wb_unprotected_bits[0]) @@ -826,7 +841,9 @@ VALUE rb_mGC; int ruby_disable_gc = 0; void rb_iseq_mark(const rb_iseq_t *iseq); void rb_iseq_free(const rb_iseq_t *iseq); void rb_gcdebug_print_obj_condition(VALUE obj); @@ -861,8 +878,11 @@ static void gc_sweep_rest(rb_objspace_t *objspace); static void gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *heap); static inline void gc_mark(rb_objspace_t *objspace, VALUE ptr); static void gc_mark_ptr(rb_objspace_t *objspace, VALUE ptr); NO_SANITIZE("memory", static void gc_mark_maybe(rb_objspace_t *objspace, VALUE ptr)); static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr); static int gc_mark_stacked_objects_incremental(rb_objspace_t *, size_t count); @@ -895,6 +915,14 @@ static inline void gc_prof_sweep_timer_stop(rb_objspace_t *); static inline void gc_prof_set_malloc_info(rb_objspace_t *); static inline void gc_prof_set_heap_info(rb_objspace_t *); #define gc_prof_record(objspace) (objspace)->profile.current_record #define gc_prof_enabled(objspace) ((objspace)->profile.run && (objspace)->profile.current_record) @@ -1020,6 +1048,7 @@ tick(void) #define FL_UNSET2(x,f) FL_CHECK2("FL_UNSET2", x, RBASIC(x)->flags &= ~(f)) #define RVALUE_MARK_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), (obj)) #define RVALUE_PAGE_MARKED(page, obj) MARKED_IN_BITMAP((page)->mark_bits, (obj)) #if USE_RGENGC @@ -1114,12 +1143,39 @@ check_rvalue_consistency(const VALUE obj) #endif static inline int RVALUE_MARKED(VALUE obj) { check_rvalue_consistency(obj); return RVALUE_MARK_BITMAP(obj) != 0; } #if USE_RGENGC static inline int RVALUE_WB_UNPROTECTED(VALUE obj) @@ -1363,6 +1419,8 @@ rb_objspace_free(rb_objspace_t *objspace) objspace->eden_heap.total_pages = 0; objspace->eden_heap.total_slots = 0; } free_stack_chunks(&objspace->mark_stack); #if !(defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE) if (objspace == &rb_objspace) return; @@ -2207,6 +2265,19 @@ obj_free(rb_objspace_t *objspace, VALUE obj) FL_UNSET(obj, FL_EXIVAR); } #if USE_RGENGC if (RVALUE_WB_UNPROTECTED(obj)) CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj); @@ -2374,6 +2445,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) break; case T_RATIONAL: case T_COMPLEX: break; case T_ICLASS: /* Basically , T_ICLASS shares table with the module */ @@ -2496,6 +2568,9 @@ Init_heap(void) { rb_objspace_t *objspace = &rb_objspace; gc_stress_set(objspace, ruby_initial_gc_stress); #if RGENGC_ESTIMATE_OLDMALLOC @@ -2639,6 +2714,7 @@ internal_object_p(VALUE obj) UNEXPECTED_NODE(internal_object_p); break; case T_NONE: case T_IMEMO: case T_ICLASS: case T_ZOMBIE: @@ -3214,6 +3290,7 @@ id2ref(VALUE obj, VALUE objid) #endif rb_objspace_t *objspace = &rb_objspace; VALUE ptr; void *p0; ptr = NUM2PTR(objid); @@ -3226,6 +3303,10 @@ id2ref(VALUE obj, VALUE objid) if (FLONUM_P(ptr)) return (VALUE)ptr; ptr = obj_id_to_ref(objid); if ((ptr % sizeof(RVALUE)) == (4 << 2)) { ID symid = ptr / sizeof(RVALUE); if (rb_id2str(symid) == 0) @@ -3245,6 +3326,70 @@ id2ref(VALUE obj, VALUE objid) return (VALUE)ptr; } /* * Document-method: __id__ * Document-method: object_id @@ -3301,20 +3446,8 @@ rb_obj_id(VALUE obj) * 24 if 32-bit, double is 8-byte aligned * 40 if 64-bit */ - if (STATIC_SYM_P(obj)) { - return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG; - } - else if (FLONUM_P(obj)) { -#if SIZEOF_LONG == SIZEOF_VOIDP - return LONG2NUM((SIGNED_VALUE)obj); -#else - return LL2NUM((SIGNED_VALUE)obj); -#endif - } - else if (SPECIAL_CONST_P(obj)) { - return LONG2NUM((SIGNED_VALUE)obj); - } - return nonspecial_obj_id(obj); } #include "regint.h" @@ -3437,6 +3570,7 @@ obj_memsize_of(VALUE obj, int use_all_types) break; case T_ZOMBIE: break; default: @@ -3493,6 +3627,7 @@ type_sym(size_t type) COUNT_TYPE(T_NODE); COUNT_TYPE(T_ICLASS); COUNT_TYPE(T_ZOMBIE); #undef COUNT_TYPE default: return INT2NUM(type); break; } @@ -4204,7 +4339,7 @@ mark_locations_array(rb_objspace_t *objspace, register const VALUE *x, register VALUE v; while (n--) { v = *x; - gc_mark_maybe(objspace, v); x++; } } @@ -4226,12 +4361,12 @@ rb_gc_mark_locations(const VALUE *start, const VALUE *end) } static void -gc_mark_values(rb_objspace_t *objspace, long n, const VALUE *values) { long i; for (i=0; i<n; i++) { - gc_mark(objspace, values[i]); } } @@ -4239,17 +4374,52 @@ void rb_gc_mark_values(long n, const VALUE *values) { rb_objspace_t *objspace = &rb_objspace; - gc_mark_values(objspace, n, values); } static int -mark_entry(st_data_t key, st_data_t value, st_data_t data) { rb_objspace_t *objspace = (rb_objspace_t *)data; gc_mark(objspace, (VALUE)value); return ST_CONTINUE; } static void mark_tbl(rb_objspace_t *objspace, st_table *tbl) { @@ -4283,7 +4453,12 @@ mark_keyvalue(st_data_t key, st_data_t value, st_data_t data) { rb_objspace_t *objspace = (rb_objspace_t *)data; - gc_mark(objspace, (VALUE)key); gc_mark(objspace, (VALUE)value); return ST_CONTINUE; } @@ -4463,8 +4638,14 @@ rb_mark_tbl(st_table *tbl) mark_tbl(&rb_objspace, tbl); } static void -gc_mark_maybe(rb_objspace_t *objspace, VALUE obj) { (void)VALGRIND_MAKE_MEM_DEFINED(&obj, sizeof(obj)); if (is_pointer_to_heap(objspace, (void *)obj)) { @@ -4473,19 +4654,35 @@ gc_mark_maybe(rb_objspace_t *objspace, VALUE obj) unpoison_object(obj, false); type = BUILTIN_TYPE(obj); - if (type != T_ZOMBIE && type != T_NONE) { gc_mark_ptr(objspace, obj); } if (ptr) { poison_object(obj); } } } void rb_gc_mark_maybe(VALUE obj) { - gc_mark_maybe(&rb_objspace, obj); } static inline int @@ -4621,6 +4818,21 @@ gc_mark_ptr(rb_objspace_t *objspace, VALUE obj) } static inline void gc_mark(rb_objspace_t *objspace, VALUE obj) { if (!is_markable_object(objspace, obj)) return; @@ -4628,11 +4840,17 @@ gc_mark(rb_objspace_t *objspace, VALUE obj) } void -rb_gc_mark(VALUE ptr) { gc_mark(&rb_objspace, ptr); } /* CAUTION: THIS FUNCTION ENABLE *ONLY BEFORE* SWEEPING. * This function is only for GC_END_MARK timing. */ @@ -4643,6 +4861,12 @@ rb_objspace_marked_object_p(VALUE obj) return RVALUE_MARKED(obj) ? TRUE : FALSE; } static inline void gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj) { @@ -4664,9 +4888,9 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) { const rb_env_t *env = (const rb_env_t *)obj; GC_ASSERT(VM_ENV_ESCAPED_P(env->ep)); - gc_mark_values(objspace, (long)env->env_size, env->env); VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED); - gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env)); gc_mark(objspace, (VALUE)env->iseq); } return; @@ -4758,7 +4982,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) case T_MODULE: mark_m_tbl(objspace, RCLASS_M_TBL(obj)); if (!RCLASS_EXT(obj)) break; - mark_tbl(objspace, RCLASS_IV_TBL(obj)); mark_const_tbl(objspace, RCLASS_CONST_TBL(obj)); gc_mark(objspace, RCLASS_SUPER((VALUE)obj)); break; @@ -4886,6 +5110,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) #if GC_DEBUG rb_gcdebug_print_obj_condition((VALUE)obj); #endif if (BUILTIN_TYPE(obj) == T_NONE) rb_bug("rb_gc_mark(): %p is T_NONE", (void *)obj); if (BUILTIN_TYPE(obj) == T_ZOMBIE) rb_bug("rb_gc_mark(): %p is T_ZOMBIE", (void *)obj); rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s", @@ -5365,7 +5590,12 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v /* count objects */ data->live_object_count++; - rb_objspace_reachable_objects_from(obj, check_children_i, (void *)data); #if USE_RGENGC /* check health of children */ @@ -6115,6 +6345,7 @@ rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap) list_for_each(&heap->pages, page, page_node) { memset(&page->mark_bits[0], 0, HEAP_PAGE_BITMAP_SIZE); memset(&page->marking_bits[0], 0, HEAP_PAGE_BITMAP_SIZE); memset(&page->uncollectible_bits[0], 0, HEAP_PAGE_BITMAP_SIZE); page->flags.has_uncollectible_shady_objects = FALSE; @@ -6369,7 +6600,7 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max) size_t n = 0; static ID ID_marked; #if USE_RGENGC - static ID ID_wb_protected, ID_old, ID_marking, ID_uncollectible; #endif if (!ID_marked) { @@ -6380,6 +6611,7 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max) I(old); I(marking); I(uncollectible); #endif #undef I } @@ -6391,6 +6623,7 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max) if (MARKED_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj) && n<max) flags[n++] = ID_marking; #endif if (MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj) && n<max) flags[n++] = ID_marked; return n; } @@ -6964,6 +7197,955 @@ gc_start_internal(int argc, VALUE *argv, VALUE self) return Qnil; } VALUE rb_gc_start(void) { @@ -7176,6 +8358,7 @@ enum gc_stat_sym { #if USE_RGENGC gc_stat_sym_minor_gc_count, gc_stat_sym_major_gc_count, gc_stat_sym_remembered_wb_unprotected_objects, gc_stat_sym_remembered_wb_unprotected_objects_limit, gc_stat_sym_old_objects, @@ -7251,6 +8434,7 @@ setup_gc_stat_symbols(void) S(malloc_increase_bytes_limit); #if USE_RGENGC S(minor_gc_count); S(major_gc_count); S(remembered_wb_unprotected_objects); S(remembered_wb_unprotected_objects_limit); @@ -7423,6 +8607,7 @@ gc_stat_internal(VALUE hash_or_sym) SET(malloc_increase_bytes_limit, malloc_limit); #if USE_RGENGC SET(minor_gc_count, objspace->profile.minor_gc_count); SET(major_gc_count, objspace->profile.major_gc_count); SET(remembered_wb_unprotected_objects, objspace->rgengc.uncollectible_wb_unprotected_objects); SET(remembered_wb_unprotected_objects_limit, objspace->rgengc.uncollectible_wb_unprotected_objects_limit); @@ -8628,10 +9813,25 @@ wmap_mark_map(st_data_t key, st_data_t val, st_data_t arg) } #endif static void wmap_mark(void *ptr) { struct weakmap *w = ptr; #if WMAP_DELETE_DEAD_OBJECT_IN_MARK if (w->obj2wmap) st_foreach(w->obj2wmap, wmap_mark_map, (st_data_t)&rb_objspace); #endif @@ -9631,6 +10831,7 @@ type_name(int type, VALUE obj) TYPE_NAME(T_UNDEF); TYPE_NAME(T_IMEMO); TYPE_NAME(T_ICLASS); TYPE_NAME(T_ZOMBIE); case T_DATA: if (obj && rb_objspace_data_type_name(obj)) { @@ -9679,7 +10880,7 @@ method_type_name(rb_method_type_t type) static void rb_raw_iseq_info(char *buff, const int buff_size, const rb_iseq_t *iseq) { - if (iseq->body && iseq->body->location.label) { VALUE path = rb_iseq_path(iseq); VALUE n = iseq->body->location.first_lineno; snprintf(buff, buff_size, "%s %s@%s:%d", buff, @@ -9710,10 +10911,11 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags); if (is_pointer_to_heap(&rb_objspace, (void *)obj)) { - snprintf(buff, buff_size, "%p [%d%s%s%s%s] %s", (void *)obj, age, C(RVALUE_UNCOLLECTIBLE_BITMAP(obj), "L"), C(RVALUE_MARK_BITMAP(obj), "M"), C(RVALUE_MARKING_BITMAP(obj), "R"), C(RVALUE_WB_UNPROTECTED_BITMAP(obj), "U"), obj_type_name(obj)); @@ -9738,10 +10940,12 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) snprintf(buff, buff_size, "%s (temporary internal)", buff); } else { VALUE class_path = rb_class_path_cached(RBASIC(obj)->klass); if (!NIL_P(class_path)) { snprintf(buff, buff_size, "%s (%s)", buff, RSTRING_PTR(class_path)); } } #if GC_DEBUG @@ -9777,6 +10981,10 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) snprintf(buff, buff_size, "%s %s", buff, RSTRING_PTR(obj)); break; } case T_HASH: { snprintf(buff, buff_size, "%s [%c%c] %d", buff, RHASH_AR_TABLE_P(obj) ? 'A' : 'S', @@ -9938,6 +11146,12 @@ rb_gcdebug_print_obj_condition(VALUE obj) fprintf(stderr, "created at: %s:%d\n", RANY(obj)->file, RANY(obj)->line); if (is_pointer_to_heap(objspace, (void *)obj)) { fprintf(stderr, "pointer to heap?: true\n"); } @@ -9947,6 +11161,7 @@ rb_gcdebug_print_obj_condition(VALUE obj) } fprintf(stderr, "marked? : %s\n", MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj) ? "true" : "false"); #if USE_RGENGC fprintf(stderr, "age? : %d\n", RVALUE_AGE(obj)); fprintf(stderr, "old? : %s\n", RVALUE_OLD_P(obj) ? "true" : "false"); @@ -10105,6 +11320,7 @@ Init_GC(void) rb_define_singleton_method(rb_mGC, "count", gc_count, 0); rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); rb_define_singleton_method(rb_mGC, "latest_gc_info", gc_latest_gc_info, -1); rb_define_method(rb_mGC, "garbage_collect", gc_start_internal, -1); gc_constants = rb_hash_new(); @@ -10165,6 +11381,7 @@ Init_GC(void) /* internal methods */ rb_define_singleton_method(rb_mGC, "verify_internal_consistency", gc_verify_internal_consistency, 0); rb_define_singleton_method(rb_mGC, "verify_transient_heap_internal_consistency", gc_verify_transient_heap_internal_consistency, 0); #if MALLOC_ALLOCATED_SIZE rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0); @@ -57,6 +57,10 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr) #define RUBY_GC_INFO if(0)printf #endif #define RUBY_MARK_UNLESS_NULL(ptr) do { \ VALUE markobj = (ptr); \ if (RTEST(markobj)) {rb_gc_mark(markobj);} \ @@ -781,7 +781,7 @@ ar_add_direct_with_hash(VALUE hash, st_data_t key, st_data_t val, st_hash_t hash } static int -ar_foreach(VALUE hash, int (*func)(ANYARGS), st_data_t arg) { if (RHASH_AR_TABLE_SIZE(hash) > 0) { unsigned i, bound = RHASH_AR_TABLE_BOUND(hash); @@ -799,6 +799,20 @@ ar_foreach(VALUE hash, int (*func)(ANYARGS), st_data_t arg) case ST_CHECK: case ST_STOP: return 0; case ST_DELETE: ar_clear_entry(RHASH_AR_TABLE_REF(hash, i)); RHASH_AR_TABLE_SIZE_DEC(hash); @@ -810,6 +824,18 @@ ar_foreach(VALUE hash, int (*func)(ANYARGS), st_data_t arg) } static int ar_foreach_check(VALUE hash, int (*func)(ANYARGS), st_data_t arg, st_data_t never) { @@ -845,6 +871,7 @@ ar_foreach_check(VALUE hash, int (*func)(ANYARGS), st_data_t arg, case ST_CONTINUE: break; case ST_STOP: return 0; case ST_DELETE: { if (!ar_empty_entry(cur_entry)) { @@ -1257,6 +1284,17 @@ rb_hash_stlike_foreach(VALUE hash, int (*func)(ANYARGS), st_data_t arg) } } static VALUE hash_foreach_call(VALUE arg) { @@ -267,6 +267,28 @@ rb_id_table_delete(struct rb_id_table *tbl, ID id) } void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data) { int i, capa = tbl->capa; @@ -9,6 +9,7 @@ enum rb_id_table_iterator_result { ID_TABLE_CONTINUE = ST_CONTINUE, ID_TABLE_STOP = ST_STOP, ID_TABLE_DELETE = ST_DELETE, ID_TABLE_ITERATOR_RESULT_END }; @@ -23,9 +24,11 @@ int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val); int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp); int rb_id_table_delete(struct rb_id_table *tbl, ID id); typedef enum rb_id_table_iterator_result rb_id_table_foreach_func_t(ID id, VALUE val, void *data); typedef enum rb_id_table_iterator_result rb_id_table_foreach_values_func_t(VALUE val, void *data); void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data); void rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, void *data); #endif /* RUBY_ID_TABLE_H */ @@ -507,10 +507,15 @@ COLDFUNC NORETURN(void rb_memerror(void)); PUREFUNC(int rb_during_gc(void)); void rb_gc_mark_locations(const VALUE*, const VALUE*); void rb_mark_tbl(struct st_table*); void rb_mark_set(struct st_table*); void rb_mark_hash(struct st_table*); void rb_gc_mark_maybe(VALUE); void rb_gc_mark(VALUE); void rb_gc_force_recycle(VALUE); void rb_gc(void); void rb_gc_copy_finalizer(VALUE,VALUE); @@ -622,6 +627,7 @@ VALUE rb_obj_trust(VALUE); VALUE rb_obj_freeze(VALUE); PUREFUNC(VALUE rb_obj_frozen_p(VALUE)); VALUE rb_obj_id(VALUE); VALUE rb_obj_class(VALUE); PUREFUNC(VALUE rb_class_real(VALUE)); PUREFUNC(VALUE rb_class_inherited_p(VALUE, VALUE)); @@ -512,6 +512,7 @@ enum ruby_value_type { RUBY_T_NODE = 0x1b, RUBY_T_ICLASS = 0x1c, RUBY_T_ZOMBIE = 0x1d, RUBY_T_MASK = 0x1f }; @@ -542,6 +543,7 @@ enum ruby_value_type { #define T_UNDEF RUBY_T_UNDEF #define T_NODE RUBY_T_NODE #define T_ZOMBIE RUBY_T_ZOMBIE #define T_MASK RUBY_T_MASK #define RB_BUILTIN_TYPE(x) (int)(((struct RBasic*)(x))->flags & RUBY_T_MASK) @@ -845,6 +847,7 @@ enum ruby_fl_type { RUBY_FL_FINALIZE = (1<<7), RUBY_FL_TAINT = (1<<8), RUBY_FL_UNTRUSTED = RUBY_FL_TAINT, RUBY_FL_EXIVAR = (1<<10), RUBY_FL_FREEZE = (1<<11), @@ -883,7 +886,7 @@ enum ruby_fl_type { struct RUBY_ALIGNAS(SIZEOF_VALUE) RBasic { VALUE flags; - const VALUE klass; }; VALUE rb_obj_hide(VALUE obj); @@ -1105,7 +1108,7 @@ struct RArray { struct RRegexp { struct RBasic basic; struct re_pattern_buffer *ptr; - const VALUE src; unsigned long usecnt; }; #define RREGEXP_PTR(r) (RREGEXP(r)->ptr) @@ -1144,7 +1147,8 @@ struct rb_data_type_struct { void (*dmark)(void*); void (*dfree)(void*); size_t (*dsize)(const void *); - void *reserved[2]; /* For future extension. This array *must* be filled with ZERO. */ } function; const rb_data_type_t *parent; @@ -1255,6 +1259,7 @@ int rb_big_sign(VALUE); #define RBIGNUM_NEGATIVE_P(b) (RBIGNUM_SIGN(b)==0) #define R_CAST(st) (struct st*) #define RBASIC(obj) (R_CAST(RBasic)(obj)) #define ROBJECT(obj) (R_CAST(RObject)(obj)) #define RCLASS(obj) (R_CAST(RClass)(obj)) @@ -1273,6 +1278,7 @@ int rb_big_sign(VALUE); #define FL_FINALIZE ((VALUE)RUBY_FL_FINALIZE) #define FL_TAINT ((VALUE)RUBY_FL_TAINT) #define FL_UNTRUSTED ((VALUE)RUBY_FL_UNTRUSTED) #define FL_EXIVAR ((VALUE)RUBY_FL_EXIVAR) #define FL_FREEZE ((VALUE)RUBY_FL_FREEZE) @@ -96,7 +96,7 @@ struct st_table { #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) -enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK}; st_table *st_init_table(const struct st_hash_type *); st_table *st_init_table_with_size(const struct st_hash_type *, st_index_t); @@ -118,6 +118,7 @@ typedef int st_update_callback_func(st_data_t *key, st_data_t *value, st_data_t * results of hash() are same and compare() returns 0, otherwise the * behavior is undefined */ int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg); int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); int st_foreach_check(st_table *, int (*)(ANYARGS), st_data_t, st_data_t); st_index_t st_keys(st_table *table, st_data_t *keys, st_index_t size); @@ -731,8 +731,8 @@ struct RBignum { struct RRational { struct RBasic basic; - const VALUE num; - const VALUE den; }; #define RRATIONAL(obj) (R_CAST(RRational)(obj)) @@ -748,8 +748,8 @@ struct RFloat { struct RComplex { struct RBasic basic; - const VALUE real; - const VALUE imag; }; #define RCOMPLEX(obj) (R_CAST(RComplex)(obj)) @@ -816,8 +816,8 @@ struct RHash { st_table *st; struct ar_table_struct *ar; /* possibly 0 */ } as; - const int iter_lev; - const VALUE ifnone; }; #ifdef RHASH_ITER_LEV @@ -830,6 +830,11 @@ struct RHash { # define RHASH_SIZE(h) (RHASH_AR_TABLE_P(h) ? RHASH_AR_TABLE_SIZE_RAW(h) : RHASH_ST_SIZE(h)) #endif /* #ifdef RHASH_ITER_LEV */ /* missing/setproctitle.c */ #ifndef HAVE_SETPROCTITLE extern void ruby_init_setproctitle(int argc, char *argv[]); @@ -947,7 +952,7 @@ struct rb_classext_struct { */ rb_subclass_entry_t **module_subclasses; rb_serial_t class_serial; - const VALUE origin_; VALUE refined_class; rb_alloc_func_t allocator; }; @@ -1065,10 +1070,10 @@ imemo_type_p(VALUE imemo, enum imemo_type imemo_type) /*! SVAR (Special VARiable) */ struct vm_svar { VALUE flags; - const VALUE cref_or_me; /*!< class reference or rb_method_entry_t */ - const VALUE lastline; - const VALUE backref; - const VALUE others; }; @@ -1078,7 +1083,7 @@ struct vm_svar { struct vm_throw_data { VALUE flags; VALUE reserved; - const VALUE throw_obj; const struct rb_control_frame_struct *catch_frame; VALUE throw_state; }; @@ -1101,7 +1106,7 @@ struct vm_ifunc { VALUE flags; VALUE reserved; VALUE (*func)(ANYARGS); - const void *data; struct vm_ifunc_argc argc; }; @@ -1158,12 +1163,12 @@ void rb_strterm_mark(VALUE obj); struct MEMO { VALUE flags; VALUE reserved; - const VALUE v1; - const VALUE v2; union { long cnt; long state; - const VALUE value; VALUE (*func)(ANYARGS); } u3; }; @@ -1566,6 +1571,7 @@ void rb_hash_bulk_insert(long, const VALUE *, VALUE); int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval); int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval); int rb_hash_stlike_foreach(VALUE hash, int (*func)(ANYARGS), st_data_t arg); int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg); /* inits.c */ @@ -2330,6 +2336,7 @@ extern unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, si /* variable.c (export) */ void rb_mark_generic_ivar(VALUE); VALUE rb_const_missing(VALUE klass, VALUE name); int rb_class_ivar_set(VALUE klass, ID vid, VALUE value); st_table *rb_st_copy(VALUE obj, struct st_table *orig_tbl); @@ -2341,9 +2348,10 @@ VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE); size_t rb_obj_memsize_of(VALUE); void rb_gc_verify_internal_consistency(void); -#define RB_OBJ_GC_FLAGS_MAX 5 size_t rb_obj_gc_flags(VALUE, ID[], size_t); void rb_gc_mark_values(long n, const VALUE *values); #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); @@ -137,11 +137,11 @@ rb_vm_insn_null_translator(const void *addr) return (VALUE)addr; } -typedef void iseq_value_itr_t(void *ctx, VALUE obj); typedef VALUE rb_vm_insns_translator_t(const void *addr); static int -iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void *data, rb_vm_insns_translator_t * translator) { VALUE insn = translator((void *)code[pos]); int len = insn_len(insn); @@ -157,7 +157,10 @@ iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void { VALUE op = code[pos + op_no + 1]; if (!SPECIAL_CONST_P(op)) { - func(data, op); } break; } @@ -165,7 +168,10 @@ iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void { union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)code[pos + op_no + 1]; if (is->once.value) { - func(data, is->once.value); } break; } @@ -181,7 +187,7 @@ static void rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) { unsigned int size; - const VALUE *code; size_t n; rb_vm_insns_translator_t * translator; const struct rb_iseq_constant_body *const body = iseq->body; @@ -205,10 +211,65 @@ rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) } } -static void each_insn_value(void *ctx, VALUE obj) { - rb_gc_mark(obj); } void @@ -225,12 +286,12 @@ rb_iseq_mark(const rb_iseq_t *iseq) rb_iseq_each_value(iseq, each_insn_value, NULL); } - rb_gc_mark(body->variable.coverage); - rb_gc_mark(body->variable.pc2branchindex); - rb_gc_mark(body->location.label); - rb_gc_mark(body->location.base_label); - rb_gc_mark(body->location.pathobj); - RUBY_MARK_UNLESS_NULL((VALUE)body->parent_iseq); if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) { const struct rb_iseq_param_keyword *const keyword = body->param.keyword; @@ -253,7 +314,7 @@ rb_iseq_mark(const rb_iseq_t *iseq) const struct iseq_catch_table_entry *entry; entry = &table->entries[i]; if (entry->iseq) { - rb_gc_mark((VALUE)entry->iseq); } } } @@ -264,11 +325,14 @@ rb_iseq_mark(const rb_iseq_t *iseq) } else if (FL_TEST_RAW(iseq, ISEQ_USE_COMPILE_DATA)) { const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq); - VM_ASSERT(compile_data != NULL); - - RUBY_MARK_UNLESS_NULL(compile_data->mark_ary); RUBY_MARK_UNLESS_NULL(compile_data->err_info); - RUBY_MARK_UNLESS_NULL(compile_data->catch_table_ary); } else { /* executable */ @@ -236,7 +236,7 @@ struct iseq_catch_table_entry { * CATCH_TYPE_REDO, CATCH_TYPE_NEXT: * NULL. */ - const rb_iseq_t *iseq; unsigned int start; unsigned int end; @@ -40,9 +40,9 @@ typedef struct rb_scope_visi_struct { /*! CREF (Class REFerence) */ typedef struct rb_cref_struct { VALUE flags; - const VALUE refinements; - const VALUE klass; - struct rb_cref_struct * const next; const rb_scope_visibility_t scope_visi; } rb_cref_t; @@ -50,10 +50,10 @@ typedef struct rb_cref_struct { typedef struct rb_method_entry_struct { VALUE flags; - const VALUE defined_class; struct rb_method_definition_struct * const def; ID called_id; - const VALUE owner; } rb_method_entry_t; typedef struct rb_callable_method_entry_struct { /* same fields with rb_method_entry_t */ @@ -123,8 +123,8 @@ typedef struct rb_iseq_struct rb_iseq_t; #endif typedef struct rb_method_iseq_struct { - const rb_iseq_t * const iseqptr; /*!< iseq pointer, should be separated from iseqval */ - rb_cref_t * const cref; /*!< class reference, should be marked */ } rb_method_iseq_t; /* check rb_add_method_iseq() when modify the fields */ typedef struct rb_method_cfunc_struct { @@ -135,20 +135,20 @@ typedef struct rb_method_cfunc_struct { typedef struct rb_method_attr_struct { ID id; - const VALUE location; /* should be marked */ } rb_method_attr_t; typedef struct rb_method_alias_struct { - const struct rb_method_entry_struct * const original_me; /* original_me->klass is original owner */ } rb_method_alias_t; typedef struct rb_method_refined_struct { - const struct rb_method_entry_struct * const orig_me; - const VALUE owner; } rb_method_refined_t; typedef struct rb_method_bmethod_struct { - const VALUE proc; /* should be marked */ struct rb_hook_list_struct *hooks; } rb_method_bmethod_t; @@ -1548,7 +1548,7 @@ st_update(st_table *tab, st_data_t key, different for ST_CHECK and when the current element is removed during traversing. */ static inline int -st_general_foreach(st_table *tab, int (*func)(ANYARGS), st_data_t arg, int check_p) { st_index_t bin; @@ -1572,6 +1572,15 @@ st_general_foreach(st_table *tab, int (*func)(ANYARGS), st_data_t arg, rebuilds_num = tab->rebuilds_num; hash = curr_entry_ptr->hash; retval = (*func)(key, curr_entry_ptr->record, arg, 0); if (rebuilds_num != tab->rebuilds_num) { retry: entries = tab->entries; @@ -1600,6 +1609,8 @@ st_general_foreach(st_table *tab, int (*func)(ANYARGS), st_data_t arg, curr_entry_ptr = &entries[i]; } switch (retval) { case ST_CONTINUE: break; case ST_CHECK: @@ -1648,9 +1659,15 @@ st_general_foreach(st_table *tab, int (*func)(ANYARGS), st_data_t arg, } int st_foreach(st_table *tab, int (*func)(ANYARGS), st_data_t arg) { - return st_general_foreach(tab, func, arg, FALSE); } /* See comments for function st_delete_safe. */ @@ -1658,7 +1675,7 @@ int st_foreach_check(st_table *tab, int (*func)(ANYARGS), st_data_t arg, st_data_t never ATTRIBUTE_UNUSED) { - return st_general_foreach(tab, func, arg, TRUE); } /* Set up array KEYS by at most SIZE keys of head table TAB entries. @@ -60,12 +60,7 @@ enum id_entry_type { ID_ENTRY_SIZE }; -static struct symbols { - rb_id_serial_t last_id; - st_table *str_sym; - VALUE ids; - VALUE dsymbol_fstr_hash; -} global_symbols = {tNEXT_ID-1}; static const struct st_hash_type symhash = { rb_str_hash_cmp, @@ -54,6 +54,13 @@ id_type(ID id) typedef uint32_t rb_id_serial_t; static inline rb_id_serial_t rb_id_to_serial(ID id) { @@ -0,0 +1,97 @@ @@ -4957,7 +4957,7 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE struct exec_recursive_params p; int outermost; p.list = recursive_list_access(sym); - p.objid = rb_obj_id(obj); p.obj = obj; p.pairid = pairid; p.arg = arg; @@ -5026,7 +5026,7 @@ rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg) VALUE rb_exec_recursive_paired(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg) { - return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 0); } /* @@ -5050,7 +5050,7 @@ rb_exec_recursive_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg) VALUE rb_exec_recursive_paired_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg) { - return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 1); } /* @@ -796,6 +796,56 @@ blocks_clear_marked_index(struct transient_heap_block* block) } } void rb_transient_heap_start_marking(int full_marking) { @@ -30,6 +30,7 @@ void rb_transient_heap_mark(VALUE obj, const void *ptr); void rb_transient_heap_promote(VALUE obj); void rb_transient_heap_start_marking(int full_marking); void rb_transient_heap_finish_marking(void); /* for debug API */ void rb_transient_heap_dump(void); @@ -48,6 +49,7 @@ void rb_struct_transient_heap_evacuate(VALUE st, int promote); #define rb_transient_heap_verify() ((void)0) #define rb_transient_heap_promote(obj) ((void)0) #define rb_transient_heap_start_marking(full_marking) ((void)0) #define rb_transient_heap_finish_marking() ((void)0) #define rb_transient_heap_mark(obj, ptr) ((void)0) @@ -1201,6 +1201,16 @@ rb_mark_generic_ivar(VALUE obj) } void rb_free_generic_ivar(VALUE obj) { st_data_t key = (st_data_t)obj; @@ -1950,7 +1960,7 @@ rb_mod_const_missing(VALUE klass, VALUE name) static void autoload_mark(void *ptr) { - rb_mark_tbl((st_table *)ptr); } static void @@ -1966,9 +1976,15 @@ autoload_memsize(const void *ptr) return st_memsize(tbl); } static const rb_data_type_t autoload_data_type = { "autoload", - {autoload_mark, autoload_free, autoload_memsize,}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; @@ -2015,11 +2031,18 @@ struct autoload_data_i { }; static void autoload_i_mark(void *ptr) { struct autoload_data_i *p = ptr; - rb_gc_mark(p->feature); /* allow GC to free us if no modules refer to this via autoload_const.ad */ if (list_empty(&p->constants)) { @@ -2046,7 +2069,7 @@ autoload_i_memsize(const void *ptr) static const rb_data_type_t autoload_data_i_type = { "autoload_i", - {autoload_i_mark, autoload_i_free, autoload_i_memsize,}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; @@ -2971,6 +2994,7 @@ rb_define_const(VALUE klass, const char *name, VALUE val) if (!rb_is_const_id(id)) { rb_warn("rb_define_const: invalid name `%s' for constant", name); } rb_const_set(klass, id, val); } @@ -2203,6 +2203,15 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, /* vm */ void rb_vm_mark(void *ptr) { RUBY_MARK_ENTER("vm"); @@ -2210,12 +2219,30 @@ rb_vm_mark(void *ptr) if (ptr) { rb_vm_t *vm = ptr; rb_thread_t *th = 0; list_for_each(&vm->living_threads, th, vmlt_node) { rb_gc_mark(th->self); } rb_gc_mark(vm->thgroup_default); rb_gc_mark(vm->mark_object_ary); rb_gc_mark(vm->load_path); rb_gc_mark(vm->load_path_snapshot); RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache); @@ -2225,6 +2252,8 @@ rb_vm_mark(void *ptr) rb_gc_mark(vm->top_self); RUBY_MARK_UNLESS_NULL(vm->coverages); rb_gc_mark(vm->defined_module_hash); if (vm->loading_table) { rb_mark_tbl(vm->loading_table); @@ -2463,7 +2492,7 @@ rb_execution_context_mark(const rb_execution_context_t *ec) rb_control_frame_t *cfp = ec->cfp; rb_control_frame_t *limit_cfp = (void *)(ec->vm_stack + ec->vm_stack_size); - rb_gc_mark_values((long)(sp - p), p); while (cfp != limit_cfp) { const VALUE *ep = cfp->ep; @@ -346,7 +346,7 @@ struct rb_iseq_constant_body { } type; /* instruction sequence type */ unsigned int iseq_size; - const VALUE *iseq_encoded; /* encoded iseq (insn addr and operands) */ /** * parameter information @@ -414,7 +414,7 @@ struct rb_iseq_constant_body { int bits_start; int rest_start; const ID *table; - const VALUE *default_values; } *keyword; } param; @@ -433,7 +433,7 @@ struct rb_iseq_constant_body { const ID *local_table; /* must free */ /* catch table */ - const struct iseq_catch_table *catch_table; /* for child iseq */ const struct rb_iseq_struct *parent_iseq; @@ -1029,7 +1029,7 @@ typedef struct { typedef struct { VALUE flags; /* imemo header */ - const rb_iseq_t *iseq; const VALUE *ep; const VALUE *env; unsigned int env_size; @@ -484,6 +484,7 @@ rb_type_str(enum ruby_value_type type) case type_case(T_NODE); case type_case(T_ICLASS); case type_case(T_ZOMBIE); case T_MASK: break; } #undef type_case |