-
-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scary error when generating large number of RuntimeGeneratedFunctions #13
Comments
Uhh... does Julia start to discard functions if we define too many? I'll have to ask some people. This is odd to say the least. |
I spent an hour looking into this and reading the C code for method specializations in the runtime. I wasn't able to find anything obvious yet. One interesting thing I noticed was that inspecting one of the failing functions with Cthulhu.jl seemed to work fine. But then I got different inconsistent
and
which does suggest some weird corruption in the Julia runtime. I thought this might have something to do with the large number of method specializations of
|
This very much looks like an UInt16 overflow, since
65532-65537 aren't callable:
|
Jeff suggested running a debug build to check whether this code trips any assertions, and indeed, it does:
I spend a few minutes trying to adjust a bunch of Patchdiff --git a/src/ircode.c b/src/ircode.c
index 73e99f2281..05cdb02533 100644
--- a/src/ircode.c
+++ b/src/ircode.c
@@ -42,7 +42,7 @@ static void tagged_root(rle_reference *rr, jl_ircode_state *s, int i)
static void literal_val_id(rle_reference *rr, jl_ircode_state *s, jl_value_t *v) JL_GC_DISABLED
{
jl_array_t *rs = s->method->roots;
- int i, l = jl_array_len(rs);
+ size_t i, l = jl_array_len(rs);
if (jl_is_symbol(v) || jl_is_concrete_type(v)) {
for (i = 0; i < l; i++) {
if (jl_array_ptr_ref(rs, i) == v)
@@ -341,9 +341,9 @@ static void jl_encode_value_(jl_ircode_state *s, jl_value_t *v, int as_literal)
write_uint8(s->s, id);
}
else {
- assert(id <= UINT16_MAX);
+ assert(id <= UINT32_MAX);
write_uint8(s->s, TAG_LONG_METHODROOT);
- write_uint16(s->s, id);
+ write_uint32(s->s, id);
}
return;
}
@@ -603,11 +603,11 @@ static jl_value_t *jl_decode_value(jl_ircode_state *s) JL_GC_DISABLED
key = read_uint64(s->s);
tag = read_uint8(s->s);
assert(tag == TAG_METHODROOT || tag == TAG_LONG_METHODROOT);
- return lookup_root(s->method, key, tag == TAG_METHODROOT ? read_uint8(s->s) : read_uint16(s->s));
+ return lookup_root(s->method, key, tag == TAG_METHODROOT ? read_uint8(s->s) : read_uint32(s->s));
case TAG_METHODROOT:
return lookup_root(s->method, 0, read_uint8(s->s));
case TAG_LONG_METHODROOT:
- return lookup_root(s->method, 0, read_uint16(s->s));
+ return lookup_root(s->method, 0, read_uint32(s->s));
case TAG_SVEC: JL_FALLTHROUGH; case TAG_LONG_SVEC:
return jl_decode_value_svec(s, tag);
case TAG_COMMONSYM:
diff --git a/src/julia_internal.h b/src/julia_internal.h
index 21c46129b7..2ee6ed073c 100644
--- a/src/julia_internal.h
+++ b/src/julia_internal.h
@@ -538,7 +538,7 @@ void jl_resolve_globals_in_ir(jl_array_t *stmts, jl_module_t *m, jl_svec_t *spar
JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_t* root);
void jl_append_method_roots(jl_method_t *m, uint64_t modid, jl_array_t* roots);
int get_root_reference(rle_reference *rr, jl_method_t *m, size_t i);
-jl_value_t *lookup_root(jl_method_t *m, uint64_t key, int index);
+jl_value_t *lookup_root(jl_method_t *m, uint64_t key, size_t index);
int nroots_with_key(jl_method_t *m, uint64_t key);
int jl_valid_type_param(jl_value_t *v);
diff --git a/src/method.c b/src/method.c
index 7325670bd7..3df10f20fe 100644
--- a/src/method.c
+++ b/src/method.c
@@ -404,7 +404,7 @@ static void jl_code_info_set_ir(jl_code_info_t *li, jl_expr_t *ir)
// Flags that need to be copied to slotflags
const uint8_t vinfo_mask = 8 | 16 | 32 | 64;
- int i;
+ size_t i;
for (i = 0; i < nslots; i++) {
jl_value_t *vi = jl_array_ptr_ref(vis, i);
jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(vi, 0);
@@ -590,7 +590,7 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo)
// If this generated function has an opaque closure, cache it for
// correctness of method identity
- for (int i = 0; i < jl_array_len(func->code); ++i) {
+ for (size_t i = 0; i < jl_array_len(func->code); ++i) {
jl_value_t *stmt = jl_array_ptr_ref(func->code, i);
if (jl_is_expr(stmt) && ((jl_expr_t*)stmt)->head == jl_new_opaque_closure_sym) {
linfo->uninferred = jl_copy_ast((jl_value_t*)func);
@@ -1090,7 +1090,7 @@ int get_root_reference(rle_reference *rr, jl_method_t *m, size_t i)
// get a root, given its key and index relative to the key
// this is the relocatable way to get a root from m->roots
-jl_value_t *lookup_root(jl_method_t *m, uint64_t key, int index)
+jl_value_t *lookup_root(jl_method_t *m, uint64_t key, size_t index)
{
if (!m->root_blocks) {
assert(key == 0);
diff --git a/src/support/rle.h b/src/support/rle.h
index f85d9f35c4..3d47d15bb8 100644
--- a/src/support/rle.h
+++ b/src/support/rle.h
@@ -34,7 +34,7 @@ int rle_iter_increment(rle_iter_state *state, /* number of items */ size_t len,
/* indexing */
typedef struct {
uint64_t key;
- int index; // number of preceding items in the list with the same key
+ size_t index; // number of preceding items in the list with the same key
} rle_reference;
void rle_index_to_reference(rle_reference *rr, /* item index */ size_t i, uint64_t *rletable, size_t npairs, uint64_t key0); This fails with
and I didn't figure out why The more realistic and immediate solution is probably to change init to pre-create multiple generated functions based on an additional user-defined parameter. |
JuliaLang/julia#45173 fixes this for (at least) n = 2e5. |
The MWE fills an array with simple generated functions and calls them in a loop. Works for me when n=50_000, but not when n=65535.
The text was updated successfully, but these errors were encountered: