Skip to content

Commit

Permalink
Add GC static analysis annotations for builtins.c
Browse files Browse the repository at this point in the history
  • Loading branch information
Keno committed Aug 18, 2018
1 parent e99204b commit 7136049
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 32 deletions.
4 changes: 3 additions & 1 deletion doc/src/devdocs/gc-sa.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ jl_ast_context_t *jl_ast_ctx(fl_context_t *fl) JL_GLOBALLY_ROOTED;
This annotations is essentially equivalent to JL_GLOBALLY_ROOTED, except that
is should only be used if those values are globally rooted by virtue of being
a leaftype. The rooting of leaftypes is a bit complicated, and we can generally
a leaftype. The rooting of leaftypes is a bit complicated. They are generally
rooted through `cache` field of the corresponding `TypeName`, which itself is
rooted by the containing module (so they're rooted as long as the containing module is ok) and we can generally
assume that leaftypes are rooted where they are used, but we may refine this
property in the future, so the separate annotation helps split out the reason
for being globally rooted.
Expand Down
30 changes: 15 additions & 15 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extern "C" {

// egal and object_id ---------------------------------------------------------

static int bits_equal(void *a, void *b, int sz)
static int bits_equal(void *a, void *b, int sz) JL_NOTSAFEPOINT
{
switch (sz) {
case 1: return *(int8_t*)a == *(int8_t*)b;
Expand Down Expand Up @@ -63,7 +63,7 @@ static int bits_equal(void *a, void *b, int sz)
// The solution is to keep the code in jl_egal simple and split out the
// (more) complex cases into their own functions which are marked with
// NOINLINE.
static int NOINLINE compare_svec(jl_svec_t *a, jl_svec_t *b)
static int NOINLINE compare_svec(jl_svec_t *a, jl_svec_t *b) JL_NOTSAFEPOINT
{
size_t l = jl_svec_len(a);
if (l != jl_svec_len(b))
Expand All @@ -76,7 +76,7 @@ static int NOINLINE compare_svec(jl_svec_t *a, jl_svec_t *b)
}

// See comment above for an explanation of NOINLINE.
static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *dt)
static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *dt) JL_NOTSAFEPOINT
{
size_t f, nf = jl_datatype_nfields(dt);
for (f = 0; f < nf; f++) {
Expand Down Expand Up @@ -116,7 +116,7 @@ static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *
return 1;
}

static int egal_types(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env)
static int egal_types(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env) JL_NOTSAFEPOINT
{
if (a == b)
return 1;
Expand Down Expand Up @@ -163,7 +163,7 @@ static int egal_types(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env)
return jl_egal(a, b);
}

JL_DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b)
JL_DLLEXPORT int jl_egal(jl_value_t *a JL_MAYBE_UNROOTED, jl_value_t *b JL_MAYBE_UNROOTED) JL_NOTSAFEPOINT
{
// warning: a,b may NOT have been gc-rooted by the caller
if (a == b)
Expand Down Expand Up @@ -199,7 +199,7 @@ JL_DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b)

// object_id ------------------------------------------------------------------

static uintptr_t bits_hash(const void *b, size_t sz)
static uintptr_t bits_hash(const void *b, size_t sz) JL_NOTSAFEPOINT
{
switch (sz) {
case 1: return int32hash(*(const int8_t*)b);
Expand All @@ -219,7 +219,7 @@ static uintptr_t bits_hash(const void *b, size_t sz)
}
}

static uintptr_t NOINLINE hash_svec(jl_svec_t *v)
static uintptr_t NOINLINE hash_svec(jl_svec_t *v) JL_NOTSAFEPOINT
{
uintptr_t h = 0;
size_t i, l = jl_svec_len(v);
Expand All @@ -236,9 +236,9 @@ typedef struct _varidx {
struct _varidx *prev;
} jl_varidx_t;

static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v);
static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) JL_NOTSAFEPOINT;

static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env)
static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env) JL_NOTSAFEPOINT
{
if (v == NULL) return 0;
jl_datatype_t *tv = (jl_datatype_t*)jl_typeof(v);
Expand Down Expand Up @@ -277,7 +277,7 @@ static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env)
return jl_object_id_((jl_value_t*)tv, v);
}

static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v)
static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) JL_NOTSAFEPOINT
{
if (tv == (jl_value_t*)jl_sym_type)
return ((jl_sym_t*)v)->hash;
Expand Down Expand Up @@ -337,7 +337,7 @@ static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v)
return h;
}

JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v)
JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v) JL_NOTSAFEPOINT
{
return jl_object_id_(jl_typeof(v), v);
}
Expand Down Expand Up @@ -1132,15 +1132,15 @@ static void add_intrinsic_properties(enum intrinsic f, unsigned nargs, void (*pf
runtime_fp[f] = pfunc;
}

static void add_intrinsic(jl_module_t *inm, const char *name, enum intrinsic f)
static void add_intrinsic(jl_module_t *inm, const char *name, enum intrinsic f) JL_GC_DISABLED
{
jl_value_t *i = jl_permbox32(jl_intrinsic_type, (int32_t)f);
jl_sym_t *sym = jl_symbol(name);
jl_set_const(inm, sym, i);
jl_module_export(inm, sym);
}

void jl_init_intrinsic_properties(void)
void jl_init_intrinsic_properties(void) JL_GC_DISABLED
{
#define ADD_I(name, nargs) add_intrinsic_properties(name, nargs, (void(*)(void))&jl_##name);
#define ADD_HIDDEN ADD_I
Expand All @@ -1151,7 +1151,7 @@ void jl_init_intrinsic_properties(void)
#undef ALIAS
}

void jl_init_intrinsic_functions(void)
void jl_init_intrinsic_functions(void) JL_GC_DISABLED
{
jl_module_t *inm = jl_new_module(jl_symbol("Intrinsics"));
inm->parent = jl_core_module;
Expand Down Expand Up @@ -1183,7 +1183,7 @@ static void add_builtin_func(const char *name, jl_fptr_args_t fptr)
jl_mk_builtin_func(NULL, name, fptr);
}

void jl_init_primitives(void)
void jl_init_primitives(void) JL_GC_DISABLED
{
add_builtin_func("===", jl_f_is);
add_builtin_func("typeof", jl_f_typeof);
Expand Down
15 changes: 11 additions & 4 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,13 @@ JL_DLLEXPORT size_t jl_array_len_(jl_array_t *a);

JL_DLLEXPORT char *jl_array_typetagdata(jl_array_t *a);

STATIC_INLINE jl_value_t *jl_array_ptr_ref(void *a, size_t i) JL_NOTSAFEPOINT
#ifdef __clang_analyzer__
STATIC_INLINE jl_value_t *jl_array_ptr_ref(void *a JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT;
STATIC_INLINE jl_value_t *jl_array_ptr_set(
void *a JL_ROOTING_ARGUMENT, size_t i,
void *x JL_ROOTED_ARGUMENT) JL_NOTSAFEPOINT;
#else
STATIC_INLINE jl_value_t *jl_array_ptr_ref(void *a JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT;
{
assert(i < jl_array_len(a));
return ((jl_value_t**)(jl_array_data(a)))[i];
Expand All @@ -799,6 +805,7 @@ STATIC_INLINE jl_value_t *jl_array_ptr_set(
}
return (jl_value_t*)x;
}
#endif

STATIC_INLINE uint8_t jl_array_uint8_ref(void *a, size_t i) JL_NOTSAFEPOINT
{
Expand All @@ -813,7 +820,7 @@ STATIC_INLINE void jl_array_uint8_set(void *a, size_t i, uint8_t x) JL_NOTSAFEPO
((uint8_t*)(jl_array_data(a)))[i] = x;
}

#define jl_exprarg(e,n) (((jl_value_t**)jl_array_data(((jl_expr_t*)(e))->args))[n])
#define jl_exprarg(e,n) jl_array_ptr_ref(((jl_expr_t*)(e))->args, n)
#define jl_exprargset(e, n, v) jl_array_ptr_set(((jl_expr_t*)(e))->args, n, v)
#define jl_expr_nargs(e) jl_array_len(((jl_expr_t*)(e))->args)

Expand Down Expand Up @@ -1332,10 +1339,10 @@ JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var);
JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var);
JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT,
jl_sym_t *var,
jl_value_t *val JL_ROOTED_ARGUMENT);
jl_value_t *val JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED);
JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT,
jl_sym_t *var,
jl_value_t *val JL_ROOTED_ARGUMENT);
jl_value_t *val JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED);
JL_DLLEXPORT void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs);
JL_DLLEXPORT void jl_declare_constant(jl_binding_t *b);
JL_DLLEXPORT void jl_module_using(jl_module_t *to, jl_module_t *from);
Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ extern size_t jl_arr_xtralloc_limit;
void jl_init_types(void);
void jl_init_box_caches(void);
void jl_init_frontend(void);
void jl_init_primitives(void);
void jl_init_primitives(void) JL_GC_DISABLED;
void *jl_init_llvm(void);
void jl_init_codegen(void);
void jl_init_intrinsic_functions(void);
Expand Down
2 changes: 1 addition & 1 deletion src/support/analyzer_annotations.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#define JL_ROOTING_ARGUMENT __attribute__((annotate("julia_rooting_argument")))
#define JL_ROOTED_ARGUMENT __attribute__((annotate("julia_rooted_argument")))
#define JL_GC_DISABLED __attribute__((annotate("julia_gc_disabled")))
#define JL_ALWAYS_LEAFTYPE __attribute__((annotate("julia_always_leaftype")))
#define JL_ALWAYS_LEAFTYPE JL_GLOBALLY_ROOTED
#define JL_ROOTS_TEMPORARILY __attribute__((annotate("julia_temporarily_roots")))
#define JL_REQUIRE_ROOTED_SLOT __attribute__((annotate("julia_require_rooted_slot")))
#ifdef __cplusplus
Expand Down
21 changes: 11 additions & 10 deletions src/support/hashing.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,33 @@

#include "utils.h"
#include "dtypes.h"
#include "analyzer_annotations.h"

#ifdef __cplusplus
extern "C" {
#endif

uint_t nextipow2(uint_t i);
JL_DLLEXPORT uint32_t int32hash(uint32_t a);
JL_DLLEXPORT uint64_t int64hash(uint64_t key);
JL_DLLEXPORT uint32_t int64to32hash(uint64_t key);
uint_t nextipow2(uint_t i) JL_NOTSAFEPOINT;
JL_DLLEXPORT uint32_t int32hash(uint32_t a) JL_NOTSAFEPOINT;
JL_DLLEXPORT uint64_t int64hash(uint64_t key) JL_NOTSAFEPOINT;
JL_DLLEXPORT uint32_t int64to32hash(uint64_t key) JL_NOTSAFEPOINT;
#ifdef _P64
#define inthash int64hash
#else
#define inthash int32hash
#endif
JL_DLLEXPORT uint64_t memhash(const char *buf, size_t n);
JL_DLLEXPORT uint64_t memhash_seed(const char *buf, size_t n, uint32_t seed);
JL_DLLEXPORT uint32_t memhash32(const char *buf, size_t n);
JL_DLLEXPORT uint32_t memhash32_seed(const char *buf, size_t n, uint32_t seed);
JL_DLLEXPORT uint64_t memhash(const char *buf, size_t n) JL_NOTSAFEPOINT;
JL_DLLEXPORT uint64_t memhash_seed(const char *buf, size_t n, uint32_t seed) JL_NOTSAFEPOINT;
JL_DLLEXPORT uint32_t memhash32(const char *buf, size_t n) JL_NOTSAFEPOINT;
JL_DLLEXPORT uint32_t memhash32_seed(const char *buf, size_t n, uint32_t seed) JL_NOTSAFEPOINT;

#ifdef _P64
STATIC_INLINE uint64_t bitmix(uint64_t a, uint64_t b)
STATIC_INLINE uint64_t bitmix(uint64_t a, uint64_t b) JL_NOTSAFEPOINT
{
return int64hash(a^bswap_64(b));
}
#else
STATIC_INLINE uint32_t bitmix(uint32_t a, uint32_t b)
STATIC_INLINE uint32_t bitmix(uint32_t a, uint32_t b) JL_NOTSAFEPOINT
{
return int64to32hash((((uint64_t)a) << 32) | (uint64_t)b);
}
Expand Down

0 comments on commit 7136049

Please sign in to comment.