Skip to content

Commit

Permalink
Always return valid methods from lookup_method_worldset
Browse files Browse the repository at this point in the history
  • Loading branch information
timholy committed Dec 15, 2017
2 parents dce0648 + 9d65a35 commit 600e589
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4523,7 +4523,7 @@ static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_t
// check the cache
jl_typemap_entry_t *sf = NULL;
if (jl_cfunction_list.unknown != jl_nothing) {
sf = jl_typemap_assoc_by_type(jl_cfunction_list, (jl_tupletype_t*)cfunc_sig, NULL, /*subtype*/0, /*offs*/0, /*world*/1);
sf = jl_typemap_assoc_by_type(jl_cfunction_list, (jl_tupletype_t*)cfunc_sig, NULL, /*subtype*/0, /*offs*/0, /*world*/1, /*max_world_mask*/0);
if (sf) {
jl_value_t *v = sf->func.value;
if (v) {
Expand Down
38 changes: 27 additions & 11 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -2585,29 +2585,43 @@ static void jl_update_backref_list(jl_value_t *old, jl_value_t *_new, size_t sta

// repeatedly look up older methods until we come to one that existed
// at the time this module was serialized
static jl_method_t *jl_lookup_method_worldset(jl_methtable_t *mt, jl_datatype_t *sig, arraylist_t *dependent_worlds)
static jl_method_t *jl_lookup_method_worldset(jl_methtable_t *mt, jl_datatype_t *sig, arraylist_t *dependent_worlds, size_t *max_world)
{
size_t world = jl_world_counter;
jl_typemap_entry_t *entry;
jl_method_t *_new;
while (1) {
_new = (jl_method_t*)jl_methtable_lookup(mt, sig, world);
if (!(_new && jl_is_method(_new)))
return NULL; // the method wasn't found, probably because it was disabled
entry = jl_typemap_assoc_by_type(
mt->defs, sig, NULL, /*subtype*/0, /*offs*/0, world, /*max_world_mask*/0);
if (!entry)
break;
_new = (jl_method_t*)entry->func.value;
world = lowerbound_dependent_world_set(_new->min_world, dependent_worlds);
if (world == _new->min_world)
if (world == _new->min_world) {
*max_world = entry->max_world;
return _new;
}
}
// If we failed to find a method (perhaps due to method deletion),
// grab anything
entry = jl_typemap_assoc_by_type(
mt->defs, sig, NULL, /*subtype*/0, /*offs*/0, /*world*/jl_world_counter, /*max_world_mask*/(~(size_t)0) >> 1);
assert(entry);
assert(entry->max_world != ~(size_t)0);
*max_world = entry->max_world;
return (jl_method_t*)entry->func.value;
}

static jl_method_t *jl_recache_method(jl_method_t *m, size_t start, arraylist_t *dependent_worlds)
{
jl_datatype_t *sig = (jl_datatype_t*)m->sig;
jl_datatype_t *ftype = jl_first_argument_datatype((jl_value_t*)sig);
jl_methtable_t *mt = ftype->name->mt;
size_t max_world = 0;
jl_set_typeof(m, (void*)(intptr_t)0x30); // invalidate the old value to help catch errors
jl_method_t *_new = jl_lookup_method_worldset(mt, sig, dependent_worlds);
if (!_new)
return NULL;
jl_method_t *_new = jl_lookup_method_worldset(mt, sig, dependent_worlds, &max_world);
// if (!_new)
// return NULL;
jl_update_backref_list((jl_value_t*)m, (jl_value_t*)_new, start);
return _new;
}
Expand All @@ -2618,9 +2632,10 @@ static jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *li
assert(jl_is_datatype(sig) || jl_is_unionall(sig));
jl_datatype_t *ftype = jl_first_argument_datatype((jl_value_t*)sig);
jl_methtable_t *mt = ftype->name->mt;
jl_method_t *m = jl_lookup_method_worldset(mt, sig, dependent_worlds);
if (!m)
return NULL;
size_t max_world = 0;
jl_method_t *m = jl_lookup_method_worldset(mt, sig, dependent_worlds, &max_world);
// if (!m)
// return NULL;

jl_datatype_t *argtypes = (jl_datatype_t*)li->specTypes;
jl_set_typeof(li, (void*)(intptr_t)0x40); // invalidate the old value to help catch errors
Expand All @@ -2630,6 +2645,7 @@ static jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *li
if (ti == jl_bottom_type)
env = jl_emptysvec; // the intersection may fail now if the type system had made an incorrect subtype env in the past
jl_method_instance_t *_new = jl_specializations_get_linfo(m, (jl_value_t*)argtypes, env, jl_world_counter);
_new->max_world = max_world;
jl_update_backref_list((jl_value_t*)li, (jl_value_t*)_new, start);
return _new;
}
Expand Down
20 changes: 10 additions & 10 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m,
assert(world >= m->min_world && "typemap lookup is corrupted");
JL_LOCK(&m->writelock);
jl_typemap_entry_t *sf =
jl_typemap_assoc_by_type(m->specializations, (jl_tupletype_t*)type, NULL, /*subtype*/0, /*offs*/0, world);
jl_typemap_assoc_by_type(m->specializations, (jl_tupletype_t*)type, NULL, /*subtype*/0, /*offs*/0, world, /*max_world_mask*/0);
if (sf && jl_is_method_instance(sf->func.value)) {
jl_method_instance_t *linfo = (jl_method_instance_t*)sf->func.value;
assert(linfo->min_world <= sf->min_world && linfo->max_world >= sf->max_world);
Expand Down Expand Up @@ -180,7 +180,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m,
JL_DLLEXPORT jl_value_t *jl_specializations_lookup(jl_method_t *m, jl_tupletype_t *type, size_t world)
{
jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(
m->specializations, type, NULL, /*subtype*/0, /*offs*/0, world);
m->specializations, type, NULL, /*subtype*/0, /*offs*/0, world, /*max_world_mask*/0);
if (!sf)
return jl_nothing;
return sf->func.value;
Expand All @@ -189,7 +189,7 @@ JL_DLLEXPORT jl_value_t *jl_specializations_lookup(jl_method_t *m, jl_tupletype_
JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_tupletype_t *type, size_t world)
{
jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(
mt->defs, type, NULL, /*subtype*/0, /*offs*/0, world);
mt->defs, type, NULL, /*subtype*/0, /*offs*/0, world, /*max_world_mask*/0);
if (!sf)
return jl_nothing;
return sf->func.value;
Expand Down Expand Up @@ -1070,7 +1070,7 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype
jl_method_instance_t *nf = NULL;
JL_GC_PUSH4(&env, &entry, &func, &sig);

entry = jl_typemap_assoc_by_type(mt->defs, tt, &env, /*subtype*/1, /*offs*/0, world);
entry = jl_typemap_assoc_by_type(mt->defs, tt, &env, /*subtype*/1, /*offs*/0, world, /*max_world_mask*/0);
if (entry != NULL) {
jl_method_t *m = entry->func.method;
if (!jl_has_call_ambiguities(tt, m)) {
Expand Down Expand Up @@ -1168,7 +1168,7 @@ static int check_ambiguous_visitor(jl_typemap_entry_t *oldentry, struct typemap_
// that isect == type or isect == sig and return the original match)
jl_typemap_entry_t *l = jl_typemap_assoc_by_type(
map, (jl_tupletype_t*)isect, NULL, /*subtype*/0, /*offs*/0,
closure->newentry->min_world);
closure->newentry->min_world, /*max_world_mask*/0);
if (l != NULL) // ok, intersection is covered
return 1;
jl_method_t *mambig = oldentry->func.method;
Expand Down Expand Up @@ -1636,15 +1636,15 @@ jl_tupletype_t *arg_type_tuple(jl_value_t **args, size_t nargs)
jl_method_instance_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *types,
int cache, int allow_exec, size_t world)
{
jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->cache, types, NULL, /*subtype*/1, jl_cachearg_offset(mt), world);
jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->cache, types, NULL, /*subtype*/1, jl_cachearg_offset(mt), world, /*max_world_mask*/0);
if (entry) {
jl_method_instance_t *linfo = (jl_method_instance_t*)entry->func.value;
assert(linfo->min_world <= entry->min_world && linfo->max_world >= entry->max_world &&
"typemap consistency error: MethodInstance doesn't apply to full range of its entry");
return linfo;
}
JL_LOCK(&mt->writelock);
entry = jl_typemap_assoc_by_type(mt->cache, types, NULL, /*subtype*/1, jl_cachearg_offset(mt), world);
entry = jl_typemap_assoc_by_type(mt->cache, types, NULL, /*subtype*/1, jl_cachearg_offset(mt), world, /*max_world_mask*/0);
if (entry) {
jl_method_instance_t *linfo = (jl_method_instance_t*)entry->func.value;
assert(linfo->min_world <= entry->min_world && linfo->max_world >= entry->max_world &&
Expand Down Expand Up @@ -2088,7 +2088,7 @@ JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_datatype_t *types, size_t world)
jl_svec_t *env = jl_emptysvec;
JL_GC_PUSH1(&env);
jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(
mt->defs, types, /*env*/&env, /*subtype*/1, /*offs*/0, world);
mt->defs, types, /*env*/&env, /*subtype*/1, /*offs*/0, world, /*max_world_mask*/0);
JL_GC_POP();
if (!entry)
return jl_nothing;
Expand Down Expand Up @@ -2206,7 +2206,7 @@ JL_DLLEXPORT jl_value_t *jl_get_invoke_lambda(jl_methtable_t *mt,
jl_typemap_entry_t *tm = NULL;
if (method->invokes.unknown != NULL) {
tm = jl_typemap_assoc_by_type(method->invokes, tt, NULL, /*subtype*/1,
jl_cachearg_offset(mt), world);
jl_cachearg_offset(mt), world, /*max_world_mask*/0);
if (tm) {
return (jl_value_t*)tm->func.linfo;
}
Expand All @@ -2215,7 +2215,7 @@ JL_DLLEXPORT jl_value_t *jl_get_invoke_lambda(jl_methtable_t *mt,
JL_LOCK(&method->writelock);
if (method->invokes.unknown != NULL) {
tm = jl_typemap_assoc_by_type(method->invokes, tt, NULL, /*subtype*/1,
jl_cachearg_offset(mt), world);
jl_cachearg_offset(mt), world, /*max_world_mask*/0);
if (tm) {
jl_method_instance_t *mfunc = tm->func.linfo;
JL_UNLOCK(&method->writelock);
Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par

jl_typemap_entry_t *jl_typemap_assoc_by_type(
union jl_typemap_t ml_or_cache, jl_tupletype_t *types, jl_svec_t **penv,
int8_t subtype, int8_t offs, size_t world);
int8_t subtype, int8_t offs, size_t world, size_t max_world_mask);
jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_value_t **args, size_t n, int8_t offs, size_t world);
jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *mn, jl_value_t **args, size_t n, size_t world);
STATIC_INLINE jl_typemap_entry_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_value_t **args, size_t n, int8_t offs, size_t world)
Expand Down
29 changes: 15 additions & 14 deletions src/typemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,12 +562,12 @@ int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs,
(the function) is always the same for most functions.
*/
static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_tupletype_t *types,
jl_svec_t **penv, size_t world)
jl_svec_t **penv, size_t world, size_t max_world_mask)
{
size_t n = jl_field_count(types);
int typesisva = n == 0 ? 0 : jl_is_vararg_type(jl_tparam(types, n-1));
for (; ml != (void*)jl_nothing; ml = ml->next) {
if (world < ml->min_world || world > ml->max_world)
if (world < ml->min_world || world > (ml->max_world | max_world_mask))
continue; // ignore replaced methods
size_t lensig = jl_field_count(jl_unwrap_unionall((jl_value_t*)ml->sig));
if (lensig == n || (ml->va && lensig <= n+1)) {
Expand Down Expand Up @@ -617,10 +617,11 @@ static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_

int jl_obviously_unequal(jl_value_t *a, jl_value_t *b);

static jl_typemap_entry_t *jl_typemap_lookup_by_type_(jl_typemap_entry_t *ml, jl_tupletype_t *types, size_t world)
static jl_typemap_entry_t *jl_typemap_lookup_by_type_(jl_typemap_entry_t *ml, jl_tupletype_t *types,
size_t world, size_t max_world_mask)
{
for (; ml != (void*)jl_nothing; ml = ml->next) {
if (world < ml->min_world || world > ml->max_world)
if (world < ml->min_world || world > (ml->max_world | max_world_mask))
continue;
// TODO: more efficient
jl_value_t *a = (jl_value_t*)types;
Expand Down Expand Up @@ -651,7 +652,7 @@ static jl_typemap_entry_t *jl_typemap_lookup_by_type_(jl_typemap_entry_t *ml, jl
// this is the general entry point for looking up a type in the cache
// as a subtype, or with type_equal
jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_tupletype_t *types, jl_svec_t **penv,
int8_t subtype, int8_t offs, size_t world)
int8_t subtype, int8_t offs, size_t world, size_t max_world_mask)
{
if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_level_type) {
jl_typemap_level_t *cache = ml_or_cache.node;
Expand All @@ -678,7 +679,7 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_
// If there is a type at offs, look in the optimized caches
if (!subtype) {
if (ty && jl_is_any(ty))
return jl_typemap_assoc_by_type(cache->any, types, penv, subtype, offs + 1, world);
return jl_typemap_assoc_by_type(cache->any, types, penv, subtype, offs + 1, world, max_world_mask);
if (isva) // in lookup mode, want to match Vararg exactly, not as a subtype
ty = NULL;
}
Expand All @@ -689,7 +690,7 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_
union jl_typemap_t ml = mtcache_hash_lookup(&cache->targ, a0, 1, offs);
if (ml.unknown != jl_nothing) {
jl_typemap_entry_t *li =
jl_typemap_assoc_by_type(ml, types, penv, subtype, offs + 1, world);
jl_typemap_assoc_by_type(ml, types, penv, subtype, offs + 1, world, max_world_mask);
if (li) return li;
}
}
Expand All @@ -699,26 +700,26 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_
union jl_typemap_t ml = mtcache_hash_lookup(&cache->arg1, ty, 0, offs);
if (ml.unknown != jl_nothing) {
jl_typemap_entry_t *li =
jl_typemap_assoc_by_type(ml, types, penv, subtype, offs + 1, world);
jl_typemap_assoc_by_type(ml, types, penv, subtype, offs + 1, world, max_world_mask);
if (li) return li;
}
}
if (!subtype && is_cache_leaf(ty)) return NULL;
}
// Always check the list (since offs doesn't always start at 0)
if (subtype) {
jl_typemap_entry_t *li = jl_typemap_assoc_by_type_(cache->linear, types, penv, world);
jl_typemap_entry_t *li = jl_typemap_assoc_by_type_(cache->linear, types, penv, world, max_world_mask);
if (li) return li;
return jl_typemap_assoc_by_type(cache->any, types, penv, subtype, offs + 1, world);
return jl_typemap_assoc_by_type(cache->any, types, penv, subtype, offs + 1, world, max_world_mask);
}
else {
return jl_typemap_lookup_by_type_(cache->linear, types, world);
return jl_typemap_lookup_by_type_(cache->linear, types, world, max_world_mask);
}
}
else {
return subtype ?
jl_typemap_assoc_by_type_(ml_or_cache.leaf, types, penv, world) :
jl_typemap_lookup_by_type_(ml_or_cache.leaf, types, world);
jl_typemap_assoc_by_type_(ml_or_cache.leaf, types, penv, world, max_world_mask) :
jl_typemap_lookup_by_type_(ml_or_cache.leaf, types, world, max_world_mask);
}
}

Expand Down Expand Up @@ -977,7 +978,7 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par
jl_value_t *ttype = jl_unwrap_unionall((jl_value_t*)type);

if ((jl_value_t*)simpletype == jl_nothing) {
jl_typemap_entry_t *ml = jl_typemap_assoc_by_type(*cache, type, NULL, 0, offs, min_world);
jl_typemap_entry_t *ml = jl_typemap_assoc_by_type(*cache, type, NULL, 0, offs, min_world, 0);
if (ml && ml->simplesig == (void*)jl_nothing) {
if (overwritten != NULL)
*overwritten = ml->func.value;
Expand Down

0 comments on commit 600e589

Please sign in to comment.