summaryrefslogtreecommitdiff
path: root/gc/gc.h
diff options
context:
space:
mode:
Diffstat (limited to 'gc/gc.h')
-rw-r--r--gc/gc.h151
1 files changed, 107 insertions, 44 deletions
diff --git a/gc/gc.h b/gc/gc.h
index c2e985252f..d147a3122a 100644
--- a/gc/gc.h
+++ b/gc/gc.h
@@ -10,16 +10,38 @@
* first introduced for [Feature #20470].
*/
#include "ruby/ruby.h"
+#include "ruby/assert.h"
-#if USE_MODULAR_GC
#include "ruby/thread_native.h"
+#ifndef VM_CHECK_MODE
+# define VM_CHECK_MODE RUBY_DEBUG
+#endif
+
+// From ractor_core.h
+#ifndef RACTOR_CHECK_MODE
+# define RACTOR_CHECK_MODE (VM_CHECK_MODE || RUBY_DEBUG) && (SIZEOF_UINT64_T == SIZEOF_VALUE)
+#endif
+
+#if RACTOR_CHECK_MODE
+void rb_ractor_setup_belonging(VALUE obj);
+
+struct rb_gc_obj_suffix {
+ uint32_t _ractor_belonging_id;
+};
+
+# define RB_GC_OBJ_HAS_SUFFIX 1
+# define RB_GC_OBJ_SUFFIX_SIZE (sizeof(struct rb_gc_obj_suffix))
+#else
+# define RB_GC_OBJ_HAS_SUFFIX 0
+# define RB_GC_OBJ_SUFFIX_SIZE 0
+#endif
+
struct rb_gc_vm_context {
rb_nativethread_lock_t lock;
struct rb_execution_context_struct *ec;
};
-#endif
typedef int (*vm_table_foreach_callback_func)(VALUE value, void *data);
typedef int (*vm_table_update_callback_func)(VALUE *value, void *data);
@@ -28,57 +50,88 @@ enum rb_gc_vm_weak_tables {
RB_GC_VM_CI_TABLE,
RB_GC_VM_OVERLOADED_CME_TABLE,
RB_GC_VM_GLOBAL_SYMBOLS_TABLE,
- RB_GC_VM_GENERIC_IV_TABLE,
+ RB_GC_VM_ID2REF_TABLE,
+ RB_GC_VM_GENERIC_FIELDS_TABLE,
RB_GC_VM_FROZEN_STRINGS_TABLE,
RB_GC_VM_WEAK_TABLE_COUNT
};
+#define RB_GC_VM_LOCK() rb_gc_vm_lock(__FILE__, __LINE__)
+#define RB_GC_VM_UNLOCK(lev) rb_gc_vm_unlock(lev, __FILE__, __LINE__)
+#define RB_GC_CR_LOCK() rb_gc_cr_lock(__FILE__, __LINE__)
+#define RB_GC_CR_UNLOCK(lev) rb_gc_cr_unlock(lev, __FILE__, __LINE__)
+#define RB_GC_VM_LOCK_NO_BARRIER() rb_gc_vm_lock_no_barrier(__FILE__, __LINE__)
+#define RB_GC_VM_UNLOCK_NO_BARRIER(lev) rb_gc_vm_unlock_no_barrier(lev, __FILE__, __LINE__)
+
+#if USE_MODULAR_GC
+# define MODULAR_GC_FN
+#else
+// This takes advantage of internal linkage winning when appearing first.
+// See C99 6.2.2p4.
+# define MODULAR_GC_FN static
+#endif
+
+#if USE_MODULAR_GC
RUBY_SYMBOL_EXPORT_BEGIN
-unsigned int rb_gc_vm_lock(void);
-void rb_gc_vm_unlock(unsigned int lev);
-unsigned int rb_gc_cr_lock(void);
-void rb_gc_cr_unlock(unsigned int lev);
-unsigned int rb_gc_vm_lock_no_barrier(void);
-void rb_gc_vm_unlock_no_barrier(unsigned int lev);
-void rb_gc_vm_barrier(void);
-size_t rb_gc_obj_optimal_size(VALUE obj);
-void rb_gc_mark_children(void *objspace, VALUE obj);
-void rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback, vm_table_update_callback_func update_callback, void *data, bool weak_only, enum rb_gc_vm_weak_tables table);
-void rb_gc_update_object_references(void *objspace, VALUE obj);
-void rb_gc_update_vm_references(void *objspace);
-void rb_gc_event_hook(VALUE obj, rb_event_flag_t event);
-void *rb_gc_get_objspace(void);
+#endif
+
+// These functions cannot be defined as static because they are used by other
+// files in Ruby.
size_t rb_size_mul_or_raise(size_t x, size_t y, VALUE exc);
-void rb_gc_run_obj_finalizer(VALUE objid, long count, VALUE (*callback)(long i, void *data), void *data);
-void rb_gc_set_pending_interrupt(void);
-void rb_gc_unset_pending_interrupt(void);
-void rb_gc_obj_free_vm_weak_references(VALUE obj);
-bool rb_gc_obj_free(void *objspace, VALUE obj);
-void rb_gc_save_machine_context(void);
-void rb_gc_mark_roots(void *objspace, const char **categoryp);
-void rb_gc_ractor_newobj_cache_foreach(void (*func)(void *cache, void *data), void *data);
-bool rb_gc_multi_ractor_p(void);
-void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data);
void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data);
-void rb_obj_info_dump(VALUE obj);
+const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj);
const char *rb_obj_info(VALUE obj);
-bool rb_gc_shutdown_call_finalizer_p(VALUE obj);
-uint32_t rb_gc_get_shape(VALUE obj);
-void rb_gc_set_shape(VALUE obj, uint32_t shape_id);
-uint32_t rb_gc_rebuild_shape(VALUE obj, size_t heap_id);
size_t rb_obj_memsize_of(VALUE obj);
-void rb_gc_prepare_heap_process_object(VALUE obj);
bool ruby_free_at_exit_p(void);
-bool rb_memerror_reentered(void);
+void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data);
+void rb_gc_verify_shareable(VALUE);
+
+MODULAR_GC_FN unsigned int rb_gc_vm_lock(const char *file, int line);
+MODULAR_GC_FN void rb_gc_vm_unlock(unsigned int lev, const char *file, int line);
+MODULAR_GC_FN unsigned int rb_gc_cr_lock(const char *file, int line);
+MODULAR_GC_FN void rb_gc_cr_unlock(unsigned int lev, const char *file, int line);
+MODULAR_GC_FN unsigned int rb_gc_vm_lock_no_barrier(const char *file, int line);
+MODULAR_GC_FN void rb_gc_vm_unlock_no_barrier(unsigned int lev, const char *file, int line);
+MODULAR_GC_FN void rb_gc_vm_barrier(void);
+MODULAR_GC_FN size_t rb_gc_obj_optimal_size(VALUE obj);
+MODULAR_GC_FN void rb_gc_mark_children(void *objspace, VALUE obj);
+MODULAR_GC_FN void rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback, vm_table_update_callback_func update_callback, void *data, bool weak_only, enum rb_gc_vm_weak_tables table);
+MODULAR_GC_FN void rb_gc_update_object_references(void *objspace, VALUE obj);
+MODULAR_GC_FN void rb_gc_update_vm_references(void *objspace);
+MODULAR_GC_FN void rb_gc_event_hook(VALUE obj, rb_event_flag_t event);
+MODULAR_GC_FN void *rb_gc_get_objspace(void);
+MODULAR_GC_FN void rb_gc_run_obj_finalizer(VALUE objid, long count, VALUE (*callback)(long i, void *data), void *data);
+MODULAR_GC_FN void rb_gc_set_pending_interrupt(void);
+MODULAR_GC_FN void rb_gc_unset_pending_interrupt(void);
+MODULAR_GC_FN void rb_gc_obj_free_vm_weak_references(VALUE obj);
+MODULAR_GC_FN bool rb_gc_obj_free(void *objspace, VALUE obj);
+MODULAR_GC_FN void rb_gc_save_machine_context(void);
+MODULAR_GC_FN void rb_gc_mark_roots(void *objspace, const char **categoryp);
+MODULAR_GC_FN void rb_gc_ractor_newobj_cache_foreach(void (*func)(void *cache, void *data), void *data);
+MODULAR_GC_FN bool rb_gc_multi_ractor_p(void);
+MODULAR_GC_FN bool rb_gc_shutdown_call_finalizer_p(VALUE obj);
+MODULAR_GC_FN void rb_gc_obj_changed_pool(VALUE obj, size_t heap_id);
+MODULAR_GC_FN void rb_gc_prepare_heap_process_object(VALUE obj);
+MODULAR_GC_FN bool rb_memerror_reentered(void);
+MODULAR_GC_FN bool rb_obj_id_p(VALUE);
+MODULAR_GC_FN void rb_gc_before_updating_jit_code(void);
+MODULAR_GC_FN void rb_gc_after_updating_jit_code(void);
+MODULAR_GC_FN bool rb_gc_obj_shareable_p(VALUE);
+MODULAR_GC_FN void rb_gc_rp(VALUE);
+MODULAR_GC_FN void rb_gc_handle_weak_references(VALUE obj);
+MODULAR_GC_FN bool rb_gc_obj_needs_cleanup_p(VALUE obj);
#if USE_MODULAR_GC
-bool rb_gc_event_hook_required_p(rb_event_flag_t event);
-void *rb_gc_get_ractor_newobj_cache(void);
-void rb_gc_initialize_vm_context(struct rb_gc_vm_context *context);
-void rb_gc_worker_thread_set_vm_context(struct rb_gc_vm_context *context);
-void rb_gc_worker_thread_unset_vm_context(struct rb_gc_vm_context *context);
+MODULAR_GC_FN bool rb_gc_event_hook_required_p(rb_event_flag_t event);
+MODULAR_GC_FN void *rb_gc_get_ractor_newobj_cache(void);
+MODULAR_GC_FN void rb_gc_initialize_vm_context(struct rb_gc_vm_context *context);
+MODULAR_GC_FN void rb_gc_move_obj_during_marking(VALUE from, VALUE to);
+MODULAR_GC_FN void rb_gc_print_backtrace();
#endif
+
+#if USE_MODULAR_GC
RUBY_SYMBOL_EXPORT_END
+#endif
void rb_ractor_finish_marking(void);
@@ -103,7 +156,7 @@ RBIMPL_WARNING_IGNORED(-Wunused-function)
#endif
#ifndef GC_ASSERT
-# define GC_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(RGENGC_CHECK_MODE > 0, expr, #expr)
+# define GC_ASSERT(expr, ...) RUBY_ASSERT_MESG_WHEN(RGENGC_CHECK_MODE > 0, expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
#endif
static int
@@ -142,6 +195,14 @@ gc_mark_tbl_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
}
static int
+gc_mark_set_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
+{
+ rb_gc_mark_movable((VALUE)key);
+
+ return ST_CONTINUE;
+}
+
+static int
hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
{
if (rb_gc_location((VALUE)key) != (VALUE)key) {
@@ -158,12 +219,14 @@ hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
static int
hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
{
- if (rb_gc_location((VALUE)*key) != (VALUE)*key) {
- *key = rb_gc_location((VALUE)*key);
+ VALUE new_key = rb_gc_location((VALUE)*key);
+ if (new_key != (VALUE)*key) {
+ *key = new_key;
}
- if (rb_gc_location((VALUE)*value) != (VALUE)*value) {
- *value = rb_gc_location((VALUE)*value);
+ VALUE new_value = rb_gc_location((VALUE)*value);
+ if (new_value != (VALUE)*value) {
+ *value = new_value;
}
return ST_CONTINUE;