Skip to content

Commit

Permalink
Static Analyzer Part 2 - Add all the annotations
Browse files Browse the repository at this point in the history
Also changes the gc_cache to use gc_mark_data_t in its definition
(rather than char * and casting back and forth). I don't remember
what the exact problem was, but not doing this
confuses the static analyzer.
  • Loading branch information
Keno committed Jan 27, 2018
1 parent 7d3991f commit ea88dff
Show file tree
Hide file tree
Showing 7 changed files with 364 additions and 292 deletions.
20 changes: 10 additions & 10 deletions src/gc-debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
return;
}
void **top = sp.pc + pc_offset;
char *data_top = sp.data;
jl_gc_mark_data_t *data_top = sp.data;
sp.data = ptls->gc_cache.data_stack;
sp.pc = ptls->gc_cache.pc_stack;
int isroot = 1;
Expand All @@ -1264,7 +1264,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
isroot = 0;
if (pc == gc_mark_label_addrs[GC_MARK_L_marked_obj]) {
gc_mark_marked_obj_t *data = gc_repush_markdata(&sp, gc_mark_marked_obj_t);
if ((char*)data > data_top) {
if ((jl_gc_mark_data_t *)data > data_top) {
jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n");
break;
}
Expand All @@ -1275,7 +1275,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
}
else if (pc == gc_mark_label_addrs[GC_MARK_L_scan_only]) {
gc_mark_marked_obj_t *data = gc_repush_markdata(&sp, gc_mark_marked_obj_t);
if ((char*)data > data_top) {
if ((jl_gc_mark_data_t *)data > data_top) {
jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n");
break;
}
Expand All @@ -1286,7 +1286,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
}
else if (pc == gc_mark_label_addrs[GC_MARK_L_finlist]) {
gc_mark_finlist_t *data = gc_repush_markdata(&sp, gc_mark_finlist_t);
if ((char*)data > data_top) {
if ((jl_gc_mark_data_t *)data > data_top) {
jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n");
break;
}
Expand All @@ -1296,7 +1296,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
}
else if (pc == gc_mark_label_addrs[GC_MARK_L_objarray]) {
gc_mark_objarray_t *data = gc_repush_markdata(&sp, gc_mark_objarray_t);
if ((char*)data > data_top) {
if ((jl_gc_mark_data_t *)data > data_top) {
jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n");
break;
}
Expand All @@ -1307,7 +1307,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
}
else if (pc == gc_mark_label_addrs[GC_MARK_L_obj8]) {
gc_mark_obj8_t *data = gc_repush_markdata(&sp, gc_mark_obj8_t);
if ((char*)data > data_top) {
if ((jl_gc_mark_data_t *)data > data_top) {
jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n");
break;
}
Expand All @@ -1320,7 +1320,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
}
else if (pc == gc_mark_label_addrs[GC_MARK_L_obj16]) {
gc_mark_obj16_t *data = gc_repush_markdata(&sp, gc_mark_obj16_t);
if ((char*)data > data_top) {
if ((jl_gc_mark_data_t *)data > data_top) {
jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n");
break;
}
Expand All @@ -1333,7 +1333,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
}
else if (pc == gc_mark_label_addrs[GC_MARK_L_obj32]) {
gc_mark_obj32_t *data = gc_repush_markdata(&sp, gc_mark_obj32_t);
if ((char*)data > data_top) {
if ((jl_gc_mark_data_t *)data > data_top) {
jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n");
break;
}
Expand All @@ -1346,7 +1346,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
}
else if (pc == gc_mark_label_addrs[GC_MARK_L_stack]) {
gc_mark_stackframe_t *data = gc_repush_markdata(&sp, gc_mark_stackframe_t);
if ((char*)data > data_top) {
if ((jl_gc_mark_data_t *)data > data_top) {
jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n");
break;
}
Expand All @@ -1358,7 +1358,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset
else if (pc == gc_mark_label_addrs[GC_MARK_L_module_binding]) {
// module_binding
gc_mark_binding_t *data = gc_repush_markdata(&sp, gc_mark_binding_t);
if ((char*)data > data_top) {
if ((jl_gc_mark_data_t *)data > data_top) {
jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n");
break;
}
Expand Down
18 changes: 9 additions & 9 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1386,12 +1386,12 @@ void *gc_mark_label_addrs[_GC_MARK_L_MAX];
// Double the mark stack (both pc and data) with the lock held.
static void NOINLINE gc_mark_stack_resize(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp)
{
char *old_data = gc_cache->data_stack;
jl_gc_mark_data_t *old_data = gc_cache->data_stack;
void **pc_stack = sp->pc_start;
size_t stack_size = (char*)sp->pc_end - (char*)pc_stack;
JL_LOCK_NOGC(&gc_cache->stack_lock);
gc_cache->data_stack = (char*)realloc(old_data, stack_size * 2 * sizeof(gc_mark_data_t));
sp->data += gc_cache->data_stack - old_data;
gc_cache->data_stack = (jl_gc_mark_data_t *)realloc(old_data, stack_size * 2 * sizeof(jl_gc_mark_data_t));
sp->data = (jl_gc_mark_data_t *)(((char*)sp->data) + (((char*)gc_cache->data_stack) - ((char*)old_data)));

sp->pc_start = gc_cache->pc_stack = (void**)realloc(pc_stack, stack_size * 2 * sizeof(void*));
gc_cache->pc_stack_end = sp->pc_end = sp->pc_start + stack_size * 2;
Expand All @@ -1408,13 +1408,13 @@ static void NOINLINE gc_mark_stack_resize(jl_gc_mark_cache_t *gc_cache, gc_mark_
STATIC_INLINE void gc_mark_stack_push(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp,
void *pc, void *data, size_t data_size, int inc)
{
assert(data_size <= sizeof(gc_mark_data_t));
assert(data_size <= sizeof(jl_gc_mark_data_t));
if (__unlikely(sp->pc == sp->pc_end))
gc_mark_stack_resize(gc_cache, sp);
*sp->pc = pc;
memcpy(sp->data, data, data_size);
if (inc) {
sp->data += data_size;
sp->data = (jl_gc_mark_data_t *)(((char*)sp->data) + data_size);
sp->pc++;
}
}
Expand Down Expand Up @@ -1969,7 +1969,7 @@ module_binding: {
objary = (gc_mark_objarray_t*)sp.data;
goto objarray_loaded;
}
sp.data += sizeof(data);
sp.data = (jl_gc_mark_data_t *)(((char*)sp.data) + sizeof(data));
sp.pc++;
}
else {
Expand Down Expand Up @@ -2111,7 +2111,7 @@ mark: {
gc_mark_binding_t markdata = {m, table + 1, table + bsize, nptr, bits};
gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(module_binding),
&markdata, sizeof(markdata), 0);
sp.data += sizeof(markdata);
sp.data = (jl_gc_mark_data_t *)(((char*)sp.data) + sizeof(markdata));
goto module_binding;
}
else if (vt == jl_task_type) {
Expand Down Expand Up @@ -2231,7 +2231,7 @@ mark: {
gc_mark_obj32_t markdata = {new_obj, desc + first, desc + nfields, nptr};
gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(obj32),
&markdata, sizeof(markdata), 0);
sp.data += sizeof(markdata);
sp.data = (jl_gc_mark_data_t *)(((char*)sp.data) + sizeof(markdata));
goto obj32;
}
}
Expand Down Expand Up @@ -2712,7 +2712,7 @@ void jl_init_thread_heap(jl_ptls_t ptls)
size_t init_size = 1024;
gc_cache->pc_stack = (void**)malloc(init_size * sizeof(void*));
gc_cache->pc_stack_end = gc_cache->pc_stack + init_size;
gc_cache->data_stack = (char*)malloc(init_size * sizeof(gc_mark_data_t));
gc_cache->data_stack = (jl_gc_mark_data_t *)malloc(init_size * sizeof(jl_gc_mark_data_t));
}

// System-wide initializations
Expand Down
79 changes: 40 additions & 39 deletions src/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#endif
#include <inttypes.h>
#include "julia.h"
#include "julia_threads.h"
#include "julia_internal.h"
#include "threading.h"
#ifndef _OS_WINDOWS_
Expand Down Expand Up @@ -76,7 +77,7 @@ typedef struct {

typedef struct {
void **pc; // Current stack address for the pc (up growing)
char *data; // Current stack address for the data (up growing)
jl_gc_mark_data_t *data; // Current stack address for the data (up growing)
void **pc_start; // Cached value of `gc_cache->pc_stack`
void **pc_end; // Cached value of `gc_cache->pc_stack_end`
} gc_mark_sp_t;
Expand All @@ -94,29 +95,6 @@ enum {
_GC_MARK_L_MAX
};

// Pop a data struct from the mark data stack (i.e. decrease the stack pointer)
// This should be used after dispatch and therefore the pc stack pointer is already popped from
// the stack.
STATIC_INLINE void *gc_pop_markdata_(gc_mark_sp_t *sp, size_t size)
{
char *data = sp->data - size;
sp->data = data;
return data;
}
#define gc_pop_markdata(sp, type) ((type*)gc_pop_markdata_(sp, sizeof(type)))

// Re-push a frame to the mark stack (both data and pc)
// The data and pc are expected to be on the stack (or updated in place) already.
// Mainly useful to pause the current scanning in order to scan an new object.
STATIC_INLINE void *gc_repush_markdata_(gc_mark_sp_t *sp, size_t size)
{
char *data = sp->data;
sp->pc++;
sp->data = data + size;
return data;
}
#define gc_repush_markdata(sp, type) ((type*)gc_repush_markdata_(sp, sizeof(type)))

/**
* The `nptr` member of marking data records the number of pointers slots referenced by
* an object to be used in the full collection heuristics as well as whether the object
Expand Down Expand Up @@ -198,7 +176,7 @@ typedef struct {
// We'll use this size to determine the size of the data stack corresponding to a
// PC stack size. Since the data objects are not all of the same size, we'll waste
// some memory on the data stack this way but that size is unlikely going to be significant.
typedef union {
union _jl_gc_mark_data {
gc_mark_marked_obj_t marked;
gc_mark_objarray_t objarray;
gc_mark_obj8_t obj8;
Expand All @@ -207,7 +185,30 @@ typedef union {
gc_mark_stackframe_t stackframe;
gc_mark_binding_t binding;
gc_mark_finlist_t finlist;
} gc_mark_data_t;
};

// Pop a data struct from the mark data stack (i.e. decrease the stack pointer)
// This should be used after dispatch and therefore the pc stack pointer is already popped from
// the stack.
STATIC_INLINE void *gc_pop_markdata_(gc_mark_sp_t *sp, size_t size)
{
jl_gc_mark_data_t *data = (jl_gc_mark_data_t *)(((char*)sp->data) - size);
sp->data = data;
return data;
}
#define gc_pop_markdata(sp, type) ((type*)gc_pop_markdata_(sp, sizeof(type)))

// Re-push a frame to the mark stack (both data and pc)
// The data and pc are expected to be on the stack (or updated in place) already.
// Mainly useful to pause the current scanning in order to scan an new object.
STATIC_INLINE void *gc_repush_markdata_(gc_mark_sp_t *sp, size_t size)
{
jl_gc_mark_data_t *data = sp->data;
sp->pc++;
sp->data = (jl_gc_mark_data_t *)(((char*)sp->data) + size);
return data;
}
#define gc_repush_markdata(sp, type) ((type*)gc_repush_markdata_(sp, sizeof(type)))

// layout for big (>2k) objects

Expand Down Expand Up @@ -519,18 +520,18 @@ void gc_final_pause_end(int64_t t0, int64_t tend);
#endif

#ifdef GC_TIME
void gc_time_pool_start(void);
void gc_time_count_page(int freedall, int pg_skpd);
void gc_time_pool_end(int sweep_full);
void gc_time_sysimg_end(uint64_t t0);
void gc_time_pool_start(void) JL_NOTSAFEPOINT;
void gc_time_count_page(int freedall, int pg_skpd) JL_NOTSAFEPOINT;
void gc_time_pool_end(int sweep_full) JL_NOTSAFEPOINT;
void gc_time_sysimg_end(uint64_t t0) JL_NOTSAFEPOINT;

void gc_time_big_start(void);
void gc_time_count_big(int old_bits, int bits);
void gc_time_big_end(void);
void gc_time_big_start(void) JL_NOTSAFEPOINT;
void gc_time_count_big(int old_bits, int bits) JL_NOTSAFEPOINT;
void gc_time_big_end(void) JL_NOTSAFEPOINT;

void gc_time_mallocd_array_start(void);
void gc_time_count_mallocd_array(int bits);
void gc_time_mallocd_array_end(void);
void gc_time_mallocd_array_start(void) JL_NOTSAFEPOINT;
void gc_time_count_mallocd_array(int bits) JL_NOTSAFEPOINT;
void gc_time_mallocd_array_end(void) JL_NOTSAFEPOINT;

void gc_time_mark_pause(int64_t t0, int64_t scanned_bytes,
int64_t perm_scanned_bytes);
Expand All @@ -539,22 +540,22 @@ void gc_time_sweep_pause(uint64_t gc_end_t, int64_t actual_allocd,
int sweep_full);
#else
#define gc_time_pool_start()
STATIC_INLINE void gc_time_count_page(int freedall, int pg_skpd)
STATIC_INLINE void gc_time_count_page(int freedall, int pg_skpd) JL_NOTSAFEPOINT
{
(void)freedall;
(void)pg_skpd;
}
#define gc_time_pool_end(sweep_full) (void)(sweep_full)
#define gc_time_sysimg_end(t0) (void)(t0)
#define gc_time_big_start()
STATIC_INLINE void gc_time_count_big(int old_bits, int bits)
STATIC_INLINE void gc_time_count_big(int old_bits, int bits) JL_NOTSAFEPOINT
{
(void)old_bits;
(void)bits;
}
#define gc_time_big_end()
#define gc_time_mallocd_array_start()
STATIC_INLINE void gc_time_count_mallocd_array(int bits)
STATIC_INLINE void gc_time_count_mallocd_array(int bits) JL_NOTSAFEPOINT
{
(void)bits;
}
Expand Down
Loading

0 comments on commit ea88dff

Please sign in to comment.