Skip to content

Commit

Permalink
More analyzer annotations
Browse files Browse the repository at this point in the history
This gets us far enough to pass all the .c files without warning.
The .cpp files are another issue (partly because C++ is more complicated,
partly because they play a bit fast and lose with GC rooting).
However, once this is merged, we should be able to set up CI for
the .c files at least.
  • Loading branch information
Keno committed Aug 22, 2018
1 parent f2f1f43 commit 351bcd5
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 54 deletions.
4 changes: 3 additions & 1 deletion src/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,13 +547,15 @@ JL_DLLEXPORT int jl_array_isassigned(jl_array_t *a, size_t i)
return 1;
}

JL_DLLEXPORT void jl_arrayset(jl_array_t *a, jl_value_t *rhs, size_t i)
JL_DLLEXPORT void jl_arrayset(jl_array_t *a JL_ROOTING_ARGUMENT, jl_value_t *rhs JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED, size_t i)
{
assert(i < jl_array_len(a));
jl_value_t *eltype = jl_tparam0(jl_typeof(a));
if (eltype != (jl_value_t*)jl_any_type) {
JL_GC_PUSH1(&rhs);
if (!jl_isa(rhs, eltype))
jl_type_error("arrayset", eltype, rhs);
JL_GC_POP();
}
if (!a->flags.ptrarray) {
if (jl_is_uniontype(eltype)) {
Expand Down
4 changes: 3 additions & 1 deletion src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -3116,8 +3116,10 @@ static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array)
jl_gc_enable_finalizers(ptls, 1); // make sure we don't run any Julia code concurrently before this point
if (tracee_list) {
jl_methtable_t *mt;
while ((mt = (jl_methtable_t*)arraylist_pop(tracee_list)) != NULL)
while ((mt = (jl_methtable_t*)arraylist_pop(tracee_list)) != NULL) {
JL_GC_PROMISE_ROOTED(mt);
jl_typemap_visitor(mt->defs, trace_method, NULL);
}
arraylist_free(tracee_list);
free(tracee_list);
}
Expand Down
64 changes: 39 additions & 25 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ static int8_t jl_cachearg_offset(jl_methtable_t *mt)
/// ----- Insertion logic for special entries ----- ///

// get or create the MethodInstance for a specialization
JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, jl_value_t *type, jl_svec_t *sparams, size_t world)
JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m JL_PROPAGATES_ROOT, jl_value_t *type, jl_svec_t *sparams, size_t world)
{
assert(world >= m->min_world && "typemap lookup is corrupted");
JL_LOCK(&m->writelock);
Expand Down Expand Up @@ -240,7 +240,7 @@ void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr
// returns the inferred source, and may cache the result in li
// if successful, also updates the li argument to describe the validity of this src
// if inference doesn't occur (or can't finish), returns NULL instead
jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int force)
jl_code_info_t *jl_type_infer(jl_method_instance_t **pli JL_ROOTS_TEMPORARILY, size_t world, int force)
{
JL_TIMING(INFERENCE);
if (jl_typeinf_func == NULL)
Expand Down Expand Up @@ -1395,22 +1395,25 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int
{
struct invalidate_conflicting_env *closure = container_of(closure0, struct invalidate_conflicting_env, match);
if (oldentry->max_world > closure->max_world) {
struct set_world def;
def.replaced = oldentry->func.linfo;
def.world = closure->max_world;
jl_method_t *m = def.replaced->def.method;

// truncate the max-valid in the invoke cache
if (m->invokes != NULL)
jl_typemap_visitor(m->invokes, set_max_world2, (void*)&def);
// invalidate mt cache entries
jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)m->sig);
assert(jl_is_datatype(gf) && gf->name->mt && "method signature invalid?");
jl_typemap_visitor(gf->name->mt->cache, set_max_world2, (void*)&def);
jl_method_instance_t *replaced_linfo = oldentry->func.linfo;
{
struct set_world def;
def.replaced = oldentry->func.linfo;
def.world = closure->max_world;
jl_method_t *m = def.replaced->def.method;

// truncate the max-valid in the invoke cache
if (m->invokes != NULL)
jl_typemap_visitor(m->invokes, set_max_world2, (void*)&def);
// invalidate mt cache entries
jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)m->sig);
assert(jl_is_datatype(gf) && gf->name->mt && "method signature invalid?");
jl_typemap_visitor(gf->name->mt->cache, set_max_world2, (void*)&def);
}

// invalidate backedges
JL_LOCK_NOGC(&def.replaced->def.method->writelock);
jl_array_t *backedges = def.replaced->backedges;
JL_LOCK_NOGC(&replaced_linfo->def.method->writelock);
jl_array_t *backedges = replaced_linfo->backedges;
if (backedges) {
size_t i, l = jl_array_len(backedges);
jl_method_instance_t **replaced = (jl_method_instance_t**)jl_array_ptr_data(backedges);
Expand All @@ -1419,8 +1422,8 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int
}
}
closure->invalidated = 1;
def.replaced->backedges = NULL;
JL_UNLOCK_NOGC(&def.replaced->def.method->writelock);
replaced_linfo->backedges = NULL;
JL_UNLOCK_NOGC(&replaced_linfo->def.method->writelock);
}
return 1;
}
Expand Down Expand Up @@ -1494,11 +1497,20 @@ static int typemap_search(jl_typemap_entry_t *entry, void *closure)
return 1;
}

static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_method_t *method) JL_NOTSAFEPOINT;

#ifndef __clang_analyzer__
static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_method_t *method) JL_NOTSAFEPOINT {
jl_value_t *closure = (jl_value_t*)(method);
if (jl_typemap_visitor(mt->defs, typemap_search, &closure))
jl_error("method not in method table");
return (jl_typemap_entry_t *)closure;
}
#endif

JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *method)
{
jl_typemap_entry_t *methodentry = (jl_typemap_entry_t*)(method);
if (jl_typemap_visitor(mt->defs, typemap_search, &methodentry))
jl_error("method not in method table");
jl_typemap_entry_t *methodentry = do_typemap_search(mt, method);
JL_LOCK(&mt->writelock);
// Narrow the world age on the method to make it uncallable
methodentry->max_world = jl_world_counter++;
Expand Down Expand Up @@ -1539,7 +1551,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
else {
oldvalue = check_ambiguous_matches(mt->defs, newentry, check_ambiguous_visitor);
if (mt->backedges) {
jl_value_t **backedges = (jl_value_t**)jl_array_data(mt->backedges);
jl_value_t **backedges = jl_array_ptr_data(mt->backedges);
size_t i, na = jl_array_len(mt->backedges);
size_t ins = 0;
for (i = 1; i < na; i += 2) {
Expand Down Expand Up @@ -1862,7 +1874,7 @@ JL_DLLEXPORT int32_t jl_invoke_api(jl_method_instance_t *mi)
}

// compile-time method lookup
jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world, int mt_cache)
jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES_ROOT, size_t world, int mt_cache)
{
JL_TIMING(METHOD_LOOKUP_COMPILE);
if (jl_has_free_typevars((jl_value_t*)types))
Expand Down Expand Up @@ -1921,7 +1933,6 @@ JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types)
{
size_t world = jl_world_counter;
jl_method_instance_t *li = jl_get_specialization1(types, world, 1);
JL_GC_PROMISE_ROOTED(li); // Rooted via types since mt_cache==1
if (li == NULL)
return 0;
if (jl_generating_output()) {
Expand Down Expand Up @@ -1949,6 +1960,7 @@ JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types)
// additional useful methods that should be compiled
//ALT: if (jl_is_datatype(types) && ((jl_datatype_t*)types)->isdispatchtuple && !jl_egal(li->specTypes, types))
//ALT: if (jl_subtype(types, li->specTypes))
JL_GC_PROMISE_ROOTED(li);
if (!jl_subtype(li->specTypes, (jl_value_t*)types)) {
jl_svec_t *tpenv2 = jl_emptysvec;
jl_value_t *types2 = NULL;
Expand Down Expand Up @@ -2039,7 +2051,7 @@ static void show_call(jl_value_t *F, jl_value_t **args, uint32_t nargs)
}
#endif

static jl_value_t *verify_type(jl_value_t *v)
static jl_value_t *verify_type(jl_value_t *v) JL_NOTSAFEPOINT
{
assert(jl_typeof(jl_typeof(v)));
return v;
Expand Down Expand Up @@ -2180,6 +2192,7 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
jl_method_instance_t *mfunc = jl_lookup_generic_(args, nargs,
jl_int32hash_fast(jl_return_address()),
jl_get_ptls_states()->world_age);
JL_GC_PROMISE_ROOTED(mfunc);
jl_value_t *res = mfunc->invoke(mfunc, args, nargs);
return verify_type(res);
}
Expand Down Expand Up @@ -2251,6 +2264,7 @@ jl_value_t *jl_gf_invoke(jl_value_t *types0, jl_value_t **args, size_t nargs)
JL_UNLOCK(&method->writelock);
}
JL_GC_POP();
JL_GC_PROMISE_ROOTED(mfunc);
return mfunc->invoke(mfunc, args, nargs);
}

Expand Down
2 changes: 2 additions & 0 deletions src/jlapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ JL_DLLEXPORT jl_value_t *(jl_typeof)(jl_value_t *v)
return jl_typeof(v);
}

#ifndef __clang_analyzer__
JL_DLLEXPORT int8_t (jl_gc_unsafe_enter)(void)
{
jl_ptls_t ptls = jl_get_ptls_states();
Expand All @@ -409,6 +410,7 @@ JL_DLLEXPORT void (jl_gc_safe_leave)(int8_t state)
jl_ptls_t ptls = jl_get_ptls_states();
jl_gc_safe_leave(ptls, state);
}
#endif

JL_DLLEXPORT void (jl_gc_safepoint)(void)
{
Expand Down
13 changes: 8 additions & 5 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,12 @@ JL_EXTENSION struct _jl_taggedvalue_t {
};

#ifdef __clang_analyzer__
JL_DLLEXPORT jl_taggedvalue_t *jl_astaggedvalue(jl_value_t *v JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
jl_value_t *jl_valueof(jl_taggedvalue_t *tv JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
JL_DLLEXPORT jl_value_t *jl_typeof(jl_value_t *v JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
JL_DLLEXPORT jl_taggedvalue_t *_jl_astaggedvalue(jl_value_t *v JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
#define jl_astaggedvalue(v) _jl_astaggedvalue((jl_value_t*)v)
jl_value_t *_jl_valueof(jl_taggedvalue_t *tv JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
#define jl_valueof(v) _jl_valueof((jl_taggedvalue_t*)v)
JL_DLLEXPORT jl_value_t *_jl_typeof(jl_value_t *v JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
#define jl_typeof(v) _jl_typeof((jl_value_t*)v)
#else
#define jl_astaggedvalue(v) \
((jl_taggedvalue_t*)((char*)(v) - sizeof(jl_taggedvalue_t)))
Expand Down Expand Up @@ -1103,7 +1106,7 @@ STATIC_INLINE int jl_is_concrete_type(jl_value_t *v) JL_NOTSAFEPOINT
return jl_is_datatype(v) && ((jl_datatype_t*)v)->isconcretetype;
}

STATIC_INLINE jl_value_t *jl_typemap_entry_sig(jl_typemap_t *tmap) JL_NOTSAFEPOINT
STATIC_INLINE jl_value_t *jl_typemap_entry_sig(jl_typemap_t *tmap JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
{
assert(jl_typeof(tmap) == (jl_value_t*)jl_typemap_entry_type);
return (jl_value_t*)((jl_typemap_entry_t*)tmap)->sig;
Expand Down Expand Up @@ -1306,7 +1309,7 @@ JL_DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a);
JL_DLLEXPORT jl_array_t *jl_alloc_vec_any(size_t n);
JL_DLLEXPORT jl_value_t *jl_arrayref(jl_array_t *a, size_t i); // 0-indexed
JL_DLLEXPORT jl_value_t *jl_ptrarrayref(jl_array_t *a JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT; // 0-indexed
JL_DLLEXPORT void jl_arrayset(jl_array_t *a JL_ROOTING_ARGUMENT, jl_value_t *v JL_ROOTED_ARGUMENT, size_t i) JL_NOTSAFEPOINT; // 0-indexed
JL_DLLEXPORT void jl_arrayset(jl_array_t *a JL_ROOTING_ARGUMENT, jl_value_t *v JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED, size_t i); // 0-indexed
JL_DLLEXPORT void jl_arrayunset(jl_array_t *a, size_t i); // 0-indexed
JL_DLLEXPORT int jl_array_isassigned(jl_array_t *a, size_t i); // 0-indexed
JL_DLLEXPORT void jl_array_grow_end(jl_array_t *a, size_t inc);
Expand Down
4 changes: 2 additions & 2 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ jl_value_t *jl_interpret_toplevel_thunk(jl_module_t *m, jl_code_info_t *src);
jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,
jl_code_info_t *src,
jl_svec_t *sparam_vals);
int jl_is_toplevel_only_expr(jl_value_t *e);
int jl_is_toplevel_only_expr(jl_value_t *e) JL_NOTSAFEPOINT;
jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr, jl_module_t *inmodule);
void jl_linenumber_to_lineinfo(jl_code_info_t *ci, jl_module_t *mod, jl_sym_t *name);

Expand Down Expand Up @@ -568,7 +568,7 @@ static inline void jl_set_gc_and_wait(void)
JL_DLLEXPORT jl_value_t *jl_dump_fptr_asm(uint64_t fptr, int raw_mc, const char* asm_variant);

void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len);
int32_t jl_get_llvm_gv(jl_value_t *p);
int32_t jl_get_llvm_gv(jl_value_t *p) JL_NOTSAFEPOINT;
int32_t jl_assign_functionID(const char *fname);
// the first argument to jl_idtable_rehash is used to return a value
// make sure it is rooted if it is used after the function returns
Expand Down
21 changes: 11 additions & 10 deletions src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ typedef enum {
#define write_uint8(s, n) ios_putc((n), (s))
#define read_uint8(s) ((uint8_t)ios_getc((s)))

static void write_uint32(ios_t *s, uint32_t i)
static void write_uint32(ios_t *s, uint32_t i) JL_NOTSAFEPOINT
{
ios_write(s, (char*)&i, 4);
}

static uint32_t read_uint32(ios_t *s)
static uint32_t read_uint32(ios_t *s) JL_NOTSAFEPOINT
{
uint32_t x = 0;
ios_read(s, (char*)&x, 4);
Expand Down Expand Up @@ -305,7 +305,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v)
}
}

static void ios_ensureroom(ios_t *s, size_t newsize)
static void ios_ensureroom(ios_t *s, size_t newsize) JL_NOTSAFEPOINT
{
size_t prevsize = s->size;
if (prevsize < newsize) {
Expand All @@ -315,7 +315,7 @@ static void ios_ensureroom(ios_t *s, size_t newsize)
}
}

static void record_gvar(jl_serializer_state *s, int gid, uintptr_t reloc_id)
static void record_gvar(jl_serializer_state *s, int gid, uintptr_t reloc_id) JL_NOTSAFEPOINT
{
if (gid == 0)
return;
Expand All @@ -326,7 +326,7 @@ static void record_gvar(jl_serializer_state *s, int gid, uintptr_t reloc_id)
}


static void write_padding(ios_t *s, size_t nb)
static void write_padding(ios_t *s, size_t nb) JL_NOTSAFEPOINT
{
static const char zeros[16] = {0};
while (nb > 16) {
Expand All @@ -338,15 +338,15 @@ static void write_padding(ios_t *s, size_t nb)
}


static void write_pointer(ios_t *s)
static void write_pointer(ios_t *s) JL_NOTSAFEPOINT
{
assert((ios_pos(s) & (sizeof(void*) - 1)) == 0 && "stream misaligned for writing a word-sized value");
write_padding(s, sizeof(void*));
}


#define backref_id(s, v) _backref_id(s, (jl_value_t*)(v))
static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v)
static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v) JL_NOTSAFEPOINT
{
assert(v != NULL && "cannot get backref to NULL object");
void *idx = HT_NOTFOUND;
Expand Down Expand Up @@ -374,7 +374,7 @@ static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v)
}


static void write_pointerfield(jl_serializer_state *s, jl_value_t *fld)
static void write_pointerfield(jl_serializer_state *s, jl_value_t *fld) JL_NOTSAFEPOINT
{
if (fld != NULL) {
arraylist_push(&s->relocs_list, (void*)(uintptr_t)ios_pos(s->s));
Expand All @@ -383,7 +383,7 @@ static void write_pointerfield(jl_serializer_state *s, jl_value_t *fld)
write_pointer(s->s);
}

static void write_gctaggedfield(jl_serializer_state *s, uintptr_t ref)
static void write_gctaggedfield(jl_serializer_state *s, uintptr_t ref) JL_NOTSAFEPOINT
{
arraylist_push(&s->gctags_list, (void*)(uintptr_t)ios_pos(s->s));
arraylist_push(&s->gctags_list, (void*)ref);
Expand Down Expand Up @@ -473,7 +473,7 @@ static void jl_write_module(jl_serializer_state *s, uintptr_t item, jl_module_t
write_pointer(s->s);
tot += sizeof(void*);
}
newm = (jl_module_t*)&s->s->buf[reloc_offset];
// newm = (jl_module_t*)&s->s->buf[reloc_offset];
}
}
}
Expand Down Expand Up @@ -1487,6 +1487,7 @@ static void jl_restore_system_image_from_stream(ios_t *f)
deser_tag.items[0] = (void*)const_data.buf;
jl_read_relocations(&s, GC_OLD_MARKED); // gctags
size_t sizeof_tags = ios_pos(&relocs);
(void)sizeof_tags;
jl_read_relocations(&s, 0); // general relocs
ios_close(&relocs);
ios_close(&const_data);
Expand Down
4 changes: 2 additions & 2 deletions src/support/analyzer_annotations.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
#ifdef __cplusplus
extern "C" {
#endif
void JL_GC_PROMISE_ROOTED(void *v);
void jl_may_leak(uintptr_t);
void JL_GC_PROMISE_ROOTED(void *v) JL_NOTSAFEPOINT;
void jl_may_leak(uintptr_t) JL_NOTSAFEPOINT;
#ifdef __cplusplus
}
#endif
Expand Down
6 changes: 3 additions & 3 deletions src/support/ios.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ extern void (*ios_set_io_wait_func)(int);
JL_DLLEXPORT size_t ios_read(ios_t *s, char *dest, size_t n);
JL_DLLEXPORT size_t ios_readall(ios_t *s, char *dest, size_t n);
JL_DLLEXPORT size_t ios_write(ios_t *s, const char *data, size_t n) JL_NOTSAFEPOINT;
JL_DLLEXPORT int64_t ios_seek(ios_t *s, int64_t pos); // absolute seek
JL_DLLEXPORT int64_t ios_seek(ios_t *s, int64_t pos) JL_NOTSAFEPOINT; // absolute seek
JL_DLLEXPORT int64_t ios_seek_end(ios_t *s);
JL_DLLEXPORT int64_t ios_skip(ios_t *s, int64_t offs); // relative seek
JL_DLLEXPORT int64_t ios_pos(ios_t *s); // get current position
JL_DLLEXPORT int64_t ios_pos(ios_t *s) JL_NOTSAFEPOINT; // get current position
JL_DLLEXPORT int ios_trunc(ios_t *s, size_t size) JL_NOTSAFEPOINT;
JL_DLLEXPORT int ios_eof(ios_t *s);
JL_DLLEXPORT int ios_eof_blocking(ios_t *s);
Expand All @@ -102,7 +102,7 @@ JL_DLLEXPORT size_t ios_readprep(ios_t *from, size_t n);

/* stream creation */
JL_DLLEXPORT
ios_t *ios_file(ios_t *s, const char *fname, int rd, int wr, int create, int trunc);
ios_t *ios_file(ios_t *s, const char *fname, int rd, int wr, int create, int trunc) JL_NOTSAFEPOINT;
JL_DLLEXPORT ios_t *ios_mkstemp(ios_t *f, char *fname);
JL_DLLEXPORT ios_t *ios_mem(ios_t *s, size_t initsize) JL_NOTSAFEPOINT;
ios_t *ios_str(ios_t *s, char *str);
Expand Down
Loading

0 comments on commit 351bcd5

Please sign in to comment.