Skip to content
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

unroll jl_typemap_intersection_node_visitor more #16351

Merged
merged 2 commits into from
May 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1058,7 +1058,7 @@ jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types)
{
jl_typemap_entry_t *entry = NULL;
assert(jl_nparams(types) > 0);
if (!jl_is_leaf_type((jl_value_t*)types))
if (!jl_is_leaf_type((jl_value_t*)types) || jl_has_typevars((jl_value_t*)types))
return NULL;
assert(jl_is_datatype(jl_tparam0(types)));

Expand Down
49 changes: 30 additions & 19 deletions src/typemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#include <unistd.h>
#endif

#define MAX_METHLIST_COUNT 32 // this can strongly affect the sysimg size and speed!
#define INIT_CACHE_SIZE 16 // must be a power-of-two
#define MAX_METHLIST_COUNT 12 // this can strongly affect the sysimg size and speed!
#define INIT_CACHE_SIZE 8 // must be a power-of-two

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -262,7 +262,7 @@ static union jl_typemap_t *mtcache_hash_bp(jl_array_t **pa, jl_value_t *ty,
{
if (jl_is_datatype(ty)) {
uintptr_t uid = ((jl_datatype_t*)ty)->uid;
if (!uid || is_kind(ty))
if (!uid || is_kind(ty) || jl_has_typevars(ty))
// be careful not to put non-leaf types or DataType/TypeConstructor in the cache here,
// since they should have a lower priority and need to go into the sorted list
return NULL;
Expand Down Expand Up @@ -392,9 +392,16 @@ static int jl_typemap_intersection_array_visitor(jl_array_t *a, jl_value_t *ty,
if (tparam)
t = jl_tparam0(t);
}
// TODO: fast path: test key `t`
if (!jl_typemap_intersection_visitor(ml, offs+1, closure))
return 0;
if (ty == (jl_value_t*)jl_any_type || // easy case: Any always matches
(tparam ? // need to compute `ty <: Type{t}`
(jl_is_uniontype(ty) || // punt on Union{...} right now
jl_typeof(t) == ty || // deal with kinds (e.g. ty == DataType && t == Type{t})
(jl_is_type_type(ty) && (jl_is_typevar(jl_tparam0(ty)) ?
jl_subtype(t, ((jl_tvar_t*)jl_tparam0(ty))->ub, 0) : // deal with ty == Type{<:T}
jl_subtype(t, jl_tparam0(ty), 0)))) // deal with ty == Type{T{#<:T}}
: jl_subtype(t, ty, 0))) // `t` is a leaftype, so intersection test becomes subtype
if (!jl_typemap_intersection_visitor(ml, offs+1, closure))
return 0;
}
}
return 1;
Expand All @@ -409,7 +416,6 @@ static int jl_typemap_intersection_node_visitor(jl_typemap_entry_t *ml, struct t
// that can be absolutely critical for speed
register jl_typemap_intersection_visitor_fptr fptr = closure->fptr;
while (ml != (void*)jl_nothing) {
// TODO: optimize intersection test
if (closure->type == (jl_value_t*)ml->sig) {
// fast-path for the intersection of a type with itself
if (closure->env)
Expand Down Expand Up @@ -453,17 +459,21 @@ int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs,
}
if (ty) {
if (cache->targ != (void*)jl_nothing) {
if (jl_is_type_type(ty) && is_cache_leaf(jl_tparam0(ty))) {
// direct lookup of leaf types
union jl_typemap_t ml = mtcache_hash_lookup(cache->targ, jl_tparam0(ty), 1, offs);
if (ml.unknown != jl_nothing) {
if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0;
jl_value_t *typetype = jl_is_type_type(ty) ? jl_tparam0(ty) : NULL;
if (typetype && !jl_has_typevars(typetype)) {
if (is_cache_leaf(typetype)) {
// direct lookup of leaf types
union jl_typemap_t ml = mtcache_hash_lookup(cache->targ, typetype, 1, offs);
if (ml.unknown != jl_nothing) {
if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0;
}
}
}
else {
// else an array scan is required to check subtypes
// TODO: fast-path: optimized pre-intersection test
if (!jl_typemap_intersection_array_visitor(cache->targ, ty, 1, offs, closure)) return 0;
// first, fast-path: optimized pre-intersection test to see if `ty` could intersect with any Type
if (typetype || jl_type_intersection((jl_value_t*)jl_type_type, ty) != jl_bottom_type)
if (!jl_typemap_intersection_array_visitor(cache->targ, ty, 1, offs, closure)) return 0;
}
}
if (cache->arg1 != (void*)jl_nothing) {
Expand All @@ -479,10 +489,11 @@ int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs,
if (!jl_typemap_intersection_array_visitor(cache->arg1, ty, 0, offs, closure)) return 0;
}
}
if (!jl_typemap_intersection_node_visitor(map.node->linear, closure))
return 0;
return jl_typemap_intersection_visitor(map.node->any, offs+1, closure);
}
if (!jl_typemap_intersection_node_visitor(map.node->linear, closure))
return 0;
return jl_typemap_intersection_visitor(map.node->any, offs+1, closure);
return 1;
}
else {
return jl_typemap_intersection_node_visitor(map.leaf, closure);
Expand Down Expand Up @@ -548,7 +559,7 @@ static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_
// where a failure to determine the value of a
// static parameter is inconclusive.
// this is issue #3182, see test/core.jl
return NULL;
return NULL; // XXX: need a way to signal to the caller that this is an inconclusive error so it stops searching
}
ismatch = 0;
break;
Expand All @@ -563,7 +574,7 @@ static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_
ismatch = jl_types_equal(ti, (jl_value_t*)types);
JL_GC_POP();
if (!ismatch)
return NULL;
return NULL; // XXX: need a way to signal to the caller that this is an inconclusive error so it stops searching
}
}
}
Expand Down