Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 4 additions & 16 deletions ext/json/vendor/fast_float_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,10 @@ static inline double ffp_bits2double(uint64_t bits) {
static inline unsigned int
ffc_nlz_int64(uint64_t x)
{
#if defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT64)
#if defined(HAVE_BUILTIN___BUILTIN_CLZLL) && !(defined(__sun) && defined(__sparc))
return (unsigned int)__builtin_clzll((unsigned long long)x);

#elif defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT64)
return (unsigned int)__lzcnt64(x);

#elif defined(__x86_64__) && defined(__LZCNT__) && defined(HAVE__LZCNT_U64)
Expand All @@ -730,21 +733,6 @@ ffc_nlz_int64(uint64_t x)
unsigned long r;
return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64;

#elif __has_builtin(__builtin_clzl) && __has_builtin(__builtin_clzll) && !(defined(__sun) && defined(__sparc))
if (x == 0) {
return 64;
}
else if (sizeof(long) * CHAR_BIT == 64) {
return (unsigned int)__builtin_clzl((unsigned long)x);
}
else if (sizeof(long long) * CHAR_BIT == 64) {
return (unsigned int)__builtin_clzll((unsigned long long)x);
}
else {
/* :FIXME: Is there a way to make this branch a compile-time error? */
__builtin_unreachable();
}

#else
uint64_t y;
unsigned int n = 64;
Expand Down
26 changes: 9 additions & 17 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ typedef struct gc_function_map {
const char *(*active_gc_name)(void);
// Miscellaneous
struct rb_gc_object_metadata_entry *(*object_metadata)(void *objspace_ptr, VALUE obj);
bool (*pointer_to_heap_p)(void *objspace_ptr, const void *ptr);
bool (*live_object_p)(void *objspace_ptr, const void *ptr);
bool (*garbage_object_p)(void *objspace_ptr, VALUE obj);
void (*set_event_hook)(void *objspace_ptr, const rb_event_flag_t event);
void (*copy_attributes)(void *objspace_ptr, VALUE dest, VALUE obj);
Expand Down Expand Up @@ -850,7 +850,7 @@ ruby_modular_gc_init(void)
load_modular_gc_func(active_gc_name);
// Miscellaneous
load_modular_gc_func(object_metadata);
load_modular_gc_func(pointer_to_heap_p);
load_modular_gc_func(live_object_p);
load_modular_gc_func(garbage_object_p);
load_modular_gc_func(set_event_hook);
load_modular_gc_func(copy_attributes);
Expand Down Expand Up @@ -938,7 +938,7 @@ ruby_modular_gc_init(void)
# define rb_gc_impl_active_gc_name rb_gc_functions.active_gc_name
// Miscellaneous
# define rb_gc_impl_object_metadata rb_gc_functions.object_metadata
# define rb_gc_impl_pointer_to_heap_p rb_gc_functions.pointer_to_heap_p
# define rb_gc_impl_live_object_p rb_gc_functions.live_object_p
# define rb_gc_impl_garbage_object_p rb_gc_functions.garbage_object_p
# define rb_gc_impl_set_event_hook rb_gc_functions.set_event_hook
# define rb_gc_impl_copy_attributes rb_gc_functions.copy_attributes
Expand Down Expand Up @@ -2038,12 +2038,6 @@ rb_objspace_garbage_object_p(VALUE obj)
return !SPECIAL_CONST_P(obj) && rb_gc_impl_garbage_object_p(rb_gc_get_objspace(), obj);
}

bool
rb_gc_pointer_to_heap_p(VALUE obj)
{
return rb_gc_impl_pointer_to_heap_p(rb_gc_get_objspace(), (void *)obj);
}

#define OBJ_ID_INCREMENT (RUBY_IMMEDIATE_MASK + 1)
#define LAST_OBJECT_ID() (object_id_counter * OBJ_ID_INCREMENT)
static VALUE id2ref_value = 0;
Expand Down Expand Up @@ -2892,7 +2886,7 @@ ruby_stack_check(void)
(func)(objspace, (obj_or_ptr)); \
} \
else if (check_obj ? \
rb_gc_impl_pointer_to_heap_p(objspace, (const void *)obj) && \
rb_gc_impl_live_object_p(objspace, (const void *)obj) && \
!rb_gc_impl_garbage_object_p(objspace, obj) : \
true) { \
GC_ASSERT(!rb_gc_impl_during_gc_p(objspace)); \
Expand Down Expand Up @@ -3139,8 +3133,6 @@ gc_location_internal(void *objspace, VALUE value)
return value;
}

GC_ASSERT(rb_gc_impl_pointer_to_heap_p(objspace, (void *)value));

return rb_gc_impl_location(objspace, value);
}

Expand Down Expand Up @@ -3593,7 +3585,7 @@ rb_gc_mark_children(void *objspace, VALUE 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",
BUILTIN_TYPE(obj), (void *)obj,
rb_gc_impl_pointer_to_heap_p(objspace, (void *)obj) ? "corrupted object" : "non object");
rb_gc_impl_live_object_p(objspace, (void *)obj) ? "corrupted object" : "non object");
}
}

Expand Down Expand Up @@ -3722,11 +3714,11 @@ rb_gc_ractor_cache_free(void *cache)
void
rb_gc_register_mark_object(VALUE obj)
{
/* rb_gc_impl_pointer_to_heap_p() walks objspace->heap_pages.sorted, which
/* rb_gc_impl_live_object_p() walks objspace->heap_pages.sorted, which
* another ractor may mutate while allocating heap pages under the VM lock,
* so the lookup must be done under the VM lock as well. */
RB_VM_LOCKING() {
if (rb_gc_impl_pointer_to_heap_p(rb_gc_get_objspace(), (void *)obj)) {
if (rb_gc_impl_live_object_p(rb_gc_get_objspace(), (void *)obj)) {
rb_vm_register_global_object(obj);
}
}
Expand Down Expand Up @@ -4958,7 +4950,7 @@ rb_raw_obj_info_common(char *const buff, const size_t buff_size, const VALUE obj
else {
// const int age = RVALUE_AGE_GET(obj);

if (rb_gc_impl_pointer_to_heap_p(rb_gc_get_objspace(), (void *)obj)) {
if (rb_gc_impl_live_object_p(rb_gc_get_objspace(), (void *)obj)) {
APPEND_F("%p %s/", (void *)obj, obj_type_name(obj));
// TODO: fixme
// APPEND_F("%p [%d%s%s%s%s%s%s] %s ",
Expand Down Expand Up @@ -5238,7 +5230,7 @@ rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj)
if (SPECIAL_CONST_P(obj)) {
raw_obj_info(buff, buff_size, obj);
}
else if (!rb_gc_impl_pointer_to_heap_p(objspace, (const void *)obj)) {
else if (!rb_gc_impl_live_object_p(objspace, (const void *)obj)) {
snprintf(buff, buff_size, "out-of-heap:%p", (void *)obj);
}
#if 0 // maybe no need to check it?
Expand Down
63 changes: 48 additions & 15 deletions gc/default/default.c
Original file line number Diff line number Diff line change
Expand Up @@ -1750,21 +1750,16 @@ rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE ptr)
{
rb_objspace_t *objspace = objspace_ptr;

bool dead = false;

/* Asking whether a freed (T_NONE), moved (T_MOVED), or finalized (T_ZOMBIE)
* object is garbage gives an unreliable answer: the slot may since have been
* reused for an unrelated object. A reference to one of these is stale and a
* bug in the caller. */
asan_unpoisoning_object(ptr) {
switch (BUILTIN_TYPE(ptr)) {
case T_NONE:
case T_MOVED:
case T_ZOMBIE:
dead = true;
break;
default:
break;
}
GC_ASSERT(BUILTIN_TYPE(ptr) != T_NONE);
GC_ASSERT(BUILTIN_TYPE(ptr) != T_MOVED);
GC_ASSERT(BUILTIN_TYPE(ptr) != T_ZOMBIE);
}

if (dead) return true;
return is_lazy_sweeping(objspace) && GET_HEAP_PAGE(ptr)->flags.before_sweep &&
!RVALUE_MARKED(objspace, ptr);
}
Expand Down Expand Up @@ -2802,9 +2797,29 @@ is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr)
}

bool
rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr)
rb_gc_impl_live_object_p(void *objspace_ptr, const void *ptr)
{
return is_pointer_to_heap(objspace_ptr, ptr);
rb_objspace_t *objspace = objspace_ptr;

/* Whether ptr refers to a live object. is_pointer_to_heap is the
* address-only check; T_NONE, T_MOVED, and T_ZOMBIE slots are valid heap
* addresses but not live objects. */
if (!is_pointer_to_heap(objspace, ptr)) return false;

VALUE obj = (VALUE)ptr;
bool live = false;
asan_unpoisoning_object(obj) {
switch (BUILTIN_TYPE(obj)) {
case T_NONE:
case T_MOVED:
case T_ZOMBIE:
break;
default:
live = true;
break;
}
}
return live;
}

#define ZOMBIE_OBJ_KEPT_FLAGS (FL_FINALIZE)
Expand Down Expand Up @@ -4369,6 +4384,8 @@ rb_gc_impl_location(void *objspace_ptr, VALUE value)
{
VALUE destination;

GC_ASSERT(is_pointer_to_heap(objspace_ptr, (void *)value));

asan_unpoisoning_object(value) {
if (BUILTIN_TYPE(value) == T_MOVED) {
destination = (VALUE)RMOVED(value)->destination;
Expand Down Expand Up @@ -5347,6 +5364,22 @@ check_children_i(const VALUE child, void *ptr)
}
}

/* Whether a heap slot currently holds a live object. Returns false for empty
* (T_NONE), moved (T_MOVED), and zombie (T_ZOMBIE) slots, and for garbage
* objects about to be swept. */
static bool
gc_slot_live_object_p(rb_objspace_t *objspace, VALUE obj)
{
switch (BUILTIN_TYPE(obj)) {
case T_NONE:
case T_MOVED:
case T_ZOMBIE:
return false;
default:
return !rb_gc_impl_garbage_object_p(objspace, obj);
}
}

static int
verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
struct verify_internal_consistency_struct *data)
Expand All @@ -5356,7 +5389,7 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,

for (obj = (VALUE)page_start; obj != (VALUE)page_end; obj += stride) {
asan_unpoisoning_object(obj) {
if (!rb_gc_impl_garbage_object_p(objspace, obj)) {
if (gc_slot_live_object_p(objspace, obj)) {
/* count objects */
data->live_object_count++;
data->parent = obj;
Expand Down
2 changes: 1 addition & 1 deletion gc/gc_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ GC_IMPL_FN VALUE rb_gc_impl_stat_heap(void *objspace_ptr, VALUE heap_name, VALUE
GC_IMPL_FN const char *rb_gc_impl_active_gc_name(void);
// Miscellaneous
GC_IMPL_FN struct rb_gc_object_metadata_entry *rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj);
GC_IMPL_FN bool rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr);
GC_IMPL_FN bool rb_gc_impl_live_object_p(void *objspace_ptr, const void *ptr);
GC_IMPL_FN bool rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE obj);
GC_IMPL_FN void rb_gc_impl_set_event_hook(void *objspace_ptr, const rb_event_flag_t event);
GC_IMPL_FN void rb_gc_impl_copy_attributes(void *objspace_ptr, VALUE dest, VALUE obj);
Expand Down
8 changes: 4 additions & 4 deletions gc/mmtk/mmtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,7 @@ rb_gc_impl_mark_and_pin(void *objspace_ptr, VALUE obj)
void
rb_gc_impl_mark_maybe(void *objspace_ptr, VALUE obj)
{
if (rb_gc_impl_pointer_to_heap_p(objspace_ptr, (const void *)obj)) {
if (rb_gc_impl_live_object_p(objspace_ptr, (const void *)obj)) {
rb_gc_impl_mark_and_pin(objspace_ptr, obj);
}
}
Expand Down Expand Up @@ -1080,12 +1080,12 @@ rb_gc_impl_writebarrier(void *objspace_ptr, VALUE a, VALUE b)
if (SPECIAL_CONST_P(b)) return;

#ifdef MMTK_DEBUG
if (!rb_gc_impl_pointer_to_heap_p(objspace_ptr, (void *)a)) {
if (!rb_gc_impl_live_object_p(objspace_ptr, (void *)a)) {
char buff[256];
rb_bug("a: %s is not an object", rb_raw_obj_info(buff, 256, a));
}

if (!rb_gc_impl_pointer_to_heap_p(objspace_ptr, (void *)b)) {
if (!rb_gc_impl_live_object_p(objspace_ptr, (void *)b)) {
char buff[256];
rb_bug("b: %s is not an object", rb_raw_obj_info(buff, 256, b));
}
Expand Down Expand Up @@ -1624,7 +1624,7 @@ rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj)
}

bool
rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr)
rb_gc_impl_live_object_p(void *objspace_ptr, const void *ptr)
{
if (ptr == NULL) return false;
if ((uintptr_t)ptr % sizeof(void*) != 0) return false;
Expand Down
4 changes: 2 additions & 2 deletions gc/wbcheck/wbcheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,7 @@ rb_gc_impl_mark_maybe(void *objspace_ptr, VALUE obj)
{
rb_wbcheck_objspace_t *objspace = objspace_ptr;

if (!rb_gc_impl_pointer_to_heap_p(objspace_ptr, (void *)obj)) return;
if (!rb_gc_impl_live_object_p(objspace_ptr, (void *)obj)) return;

switch (objspace->phase) {
case WBCHECK_PHASE_SNAPSHOT:
Expand Down Expand Up @@ -1901,7 +1901,7 @@ rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj)
}

bool
rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr)
rb_gc_impl_live_object_p(void *objspace_ptr, const void *ptr)
{
GC_ASSERT(wbcheck_global_objspace);

Expand Down
33 changes: 9 additions & 24 deletions imemo.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,15 @@ rb_imemo_tmpbuf_new(void)

rb_gc_register_pinning_obj((VALUE)obj);

obj->marked = false;
obj->ptr = NULL;
obj->size = 0;

return (VALUE)obj;
}

void *
rb_alloc_tmp_buffer(volatile VALUE *store, long len)
rb_alloc_tmp_buffer(volatile VALUE *store, long len, bool marked)
{
if (len < 0) {
rb_raise(rb_eArgError, "negative buffer size (or size too big)");
Expand All @@ -75,18 +76,13 @@ rb_alloc_tmp_buffer(volatile VALUE *store, long len)
rb_imemo_tmpbuf_t *tmpbuf = (rb_imemo_tmpbuf_t *)rb_imemo_tmpbuf_new();
*store = (VALUE)tmpbuf;
void *ptr = ruby_xmalloc(len);
tmpbuf->marked = marked;
tmpbuf->ptr = ptr;
tmpbuf->size = len;

return ptr;
}

void *
rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t size, size_t cnt)
{
return rb_alloc_tmp_buffer(store, (long)size);
}

void
rb_free_tmp_buffer(volatile VALUE *store)
{
Expand Down Expand Up @@ -336,12 +332,6 @@ rb_imemo_memsize(VALUE obj)
* mark
* ========================================================================= */

static bool
moved_or_living_object_strictly_p(VALUE obj)
{
return !SPECIAL_CONST_P(obj) && (!rb_objspace_garbage_object_p(obj) || BUILTIN_TYPE(obj) == T_MOVED);
}

static void
mark_and_move_method_entry(rb_method_entry_t *ment, bool reference_updating)
{
Expand Down Expand Up @@ -424,17 +414,12 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
*/
}
else if (reference_updating) {
if (moved_or_living_object_strictly_p((VALUE)cc->cme_)) {
*((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
*((struct rb_callable_method_entry_struct **)&cc->cme_) =
(struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cc->cme_);
*((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
*((struct rb_callable_method_entry_struct **)&cc->cme_) =
(struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cc->cme_);

RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
}
else {
vm_cc_invalidate(cc);
}
RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
}
else {
RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
Expand Down Expand Up @@ -556,7 +541,7 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
case imemo_tmpbuf: {
const rb_imemo_tmpbuf_t *m = (const rb_imemo_tmpbuf_t *)obj;

if (!reference_updating) {
if (m->marked && !reference_updating) {
rb_gc_mark_locations(m->ptr, m->ptr + (m->size / sizeof(VALUE)));
}

Expand Down
Loading